@bleedingdev/modern-js-server-utils 3.2.0-ultramodern.0
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/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/cjs/common/index.js +58 -0
- package/dist/cjs/compilers/typescript/index.js +196 -0
- package/dist/cjs/compilers/typescript/tsconfigPathsPlugin.js +148 -0
- package/dist/cjs/index.js +36 -0
- package/dist/esm/common/index.mjs +21 -0
- package/dist/esm/compilers/typescript/index.mjs +152 -0
- package/dist/esm/compilers/typescript/tsconfigPathsPlugin.mjs +101 -0
- package/dist/esm/index.mjs +1 -0
- package/dist/esm-node/common/index.mjs +22 -0
- package/dist/esm-node/compilers/typescript/index.mjs +154 -0
- package/dist/esm-node/compilers/typescript/tsconfigPathsPlugin.mjs +103 -0
- package/dist/esm-node/index.mjs +2 -0
- package/dist/types/common/index.d.ts +22 -0
- package/dist/types/compilers/typescript/index.d.ts +2 -0
- package/dist/types/compilers/typescript/tsconfigPathsPlugin.d.ts +3 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +62 -0
- package/rslib.config.mts +4 -0
- package/rstest.config.mts +6 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021-present Modern.js
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://modernjs.dev" target="blank"><img src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ylaelkeh7nuhfnuhf/modernjs-cover.png" width="300" alt="Modern.js Logo" /></a>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Modern.js</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
A Progressive React Framework for modern web development.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
Please follow [Quick Start](https://modernjs.dev/en/guides/get-started/quick-start) to get started with Modern.js.
|
|
14
|
+
|
|
15
|
+
## Documentation
|
|
16
|
+
|
|
17
|
+
- [English Documentation](https://modernjs.dev/en/)
|
|
18
|
+
- [中文文档](https://modernjs.dev)
|
|
19
|
+
|
|
20
|
+
## Contributing
|
|
21
|
+
|
|
22
|
+
Please read the [Contributing Guide](https://github.com/web-infra-dev/modern.js/blob/main/CONTRIBUTING.md).
|
|
23
|
+
|
|
24
|
+
## License
|
|
25
|
+
|
|
26
|
+
Modern.js is [MIT licensed](https://github.com/web-infra-dev/modern.js/blob/main/LICENSE).
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
FILE_EXTENSIONS: ()=>FILE_EXTENSIONS,
|
|
28
|
+
compile: ()=>compile
|
|
29
|
+
});
|
|
30
|
+
const external_path_namespaceObject = require("path");
|
|
31
|
+
const FILE_EXTENSIONS = [
|
|
32
|
+
'.js',
|
|
33
|
+
'.ts',
|
|
34
|
+
'.mjs',
|
|
35
|
+
'.ejs'
|
|
36
|
+
];
|
|
37
|
+
const validateAbsolutePath = (filename, message)=>{
|
|
38
|
+
if (!external_path_namespaceObject.isAbsolute(filename)) throw new Error(message);
|
|
39
|
+
};
|
|
40
|
+
const validateAbsolutePaths = (filenames, messageFunc)=>{
|
|
41
|
+
filenames.forEach((filename)=>validateAbsolutePath(filename, messageFunc(filename)));
|
|
42
|
+
};
|
|
43
|
+
const compile = async (appDirectory, modernConfig, compileOptions)=>{
|
|
44
|
+
const { sourceDirs, distDir, tsconfigPath } = compileOptions;
|
|
45
|
+
validateAbsolutePaths(sourceDirs, (dir)=>`source dir ${dir} is not an absolute path.`);
|
|
46
|
+
validateAbsolutePath(distDir, `dist dir ${distDir} is not an absolute path.`);
|
|
47
|
+
const { compileByTs } = await import("../compilers/typescript/index.js");
|
|
48
|
+
await compileByTs(appDirectory, modernConfig, compileOptions);
|
|
49
|
+
};
|
|
50
|
+
exports.FILE_EXTENSIONS = __webpack_exports__.FILE_EXTENSIONS;
|
|
51
|
+
exports.compile = __webpack_exports__.compile;
|
|
52
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
53
|
+
"FILE_EXTENSIONS",
|
|
54
|
+
"compile"
|
|
55
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
56
|
+
Object.defineProperty(exports, '__esModule', {
|
|
57
|
+
value: true
|
|
58
|
+
});
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.n = (module)=>{
|
|
5
|
+
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
6
|
+
__webpack_require__.d(getter, {
|
|
7
|
+
a: getter
|
|
8
|
+
});
|
|
9
|
+
return getter;
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
(()=>{
|
|
13
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
14
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: definition[key]
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
})();
|
|
20
|
+
(()=>{
|
|
21
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
22
|
+
})();
|
|
23
|
+
(()=>{
|
|
24
|
+
__webpack_require__.r = (exports1)=>{
|
|
25
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
26
|
+
value: 'Module'
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
29
|
+
value: true
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
})();
|
|
33
|
+
var __webpack_exports__ = {};
|
|
34
|
+
__webpack_require__.r(__webpack_exports__);
|
|
35
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
36
|
+
compileByTs: ()=>compileByTs
|
|
37
|
+
});
|
|
38
|
+
const utils_namespaceObject = require("@modern-js/utils");
|
|
39
|
+
const external_child_process_namespaceObject = require("child_process");
|
|
40
|
+
const external_path_namespaceObject = require("path");
|
|
41
|
+
var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
|
|
42
|
+
const external_tsconfigPathsPlugin_js_namespaceObject = require("./tsconfigPathsPlugin.js");
|
|
43
|
+
const importSpecifierRE = /((?:from\s*|import\s*\(\s*|require\s*\(\s*)['"])([^'"]+)(['"])/g;
|
|
44
|
+
const copyFiles = async (from, to, appDirectory)=>{
|
|
45
|
+
if (await utils_namespaceObject.fs.pathExists(from)) {
|
|
46
|
+
const relativePath = external_path_default().relative(appDirectory, from);
|
|
47
|
+
const targetDir = external_path_default().join(to, relativePath);
|
|
48
|
+
await utils_namespaceObject.fs.copy(from, targetDir, {
|
|
49
|
+
filter: (src)=>![
|
|
50
|
+
'.ts',
|
|
51
|
+
'.js'
|
|
52
|
+
].includes(external_path_default().extname(src)) && !src.endsWith('tsconfig.json')
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const createResolvedTsgoConfig = async (appDirectory, tsconfigPath, distDir, sourceDirs)=>{
|
|
57
|
+
const output = await runTsgo([
|
|
58
|
+
'--showConfig',
|
|
59
|
+
'-p',
|
|
60
|
+
tsconfigPath
|
|
61
|
+
], {
|
|
62
|
+
cwd: external_path_default().dirname(tsconfigPath)
|
|
63
|
+
});
|
|
64
|
+
const config = JSON.parse(output.stdout);
|
|
65
|
+
config.compilerOptions ??= {};
|
|
66
|
+
config.compilerOptions.rootDir = appDirectory;
|
|
67
|
+
config.compilerOptions.outDir = distDir;
|
|
68
|
+
config.files = filterSourceFiles(appDirectory, sourceDirs, config.files);
|
|
69
|
+
delete config.include;
|
|
70
|
+
delete config.compilerOptions.baseUrl;
|
|
71
|
+
if ([
|
|
72
|
+
'node',
|
|
73
|
+
'node10'
|
|
74
|
+
].includes(String(config.compilerOptions.moduleResolution).toLowerCase())) delete config.compilerOptions.moduleResolution;
|
|
75
|
+
const resolvedConfigPath = external_path_default().join(appDirectory, `.tsgo.${process.pid}.resolved.json`);
|
|
76
|
+
await utils_namespaceObject.fs.writeFile(resolvedConfigPath, JSON.stringify(config, null, 2));
|
|
77
|
+
return {
|
|
78
|
+
config,
|
|
79
|
+
resolvedConfigPath
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
const filterSourceFiles = (appDirectory, sourceDirs, files = [])=>{
|
|
83
|
+
const sourcePosixPaths = sourceDirs.map((sourceDir)=>sourceDir.split(external_path_default().sep).join(external_path_default().posix.sep));
|
|
84
|
+
return files.filter((fileName)=>{
|
|
85
|
+
const absoluteFileName = external_path_default().resolve(appDirectory, fileName).split(external_path_default().sep).join(external_path_default().posix.sep);
|
|
86
|
+
return fileName.endsWith('.d.ts') || sourcePosixPaths.some((sourceDir)=>absoluteFileName.includes(sourceDir));
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
const runTsgo = (args, options)=>new Promise((resolve, reject)=>{
|
|
90
|
+
const child = (0, external_child_process_namespaceObject.spawn)(process.execPath, [
|
|
91
|
+
getTsgoBinPath(),
|
|
92
|
+
...args
|
|
93
|
+
], {
|
|
94
|
+
cwd: options.cwd,
|
|
95
|
+
stdio: [
|
|
96
|
+
'ignore',
|
|
97
|
+
'pipe',
|
|
98
|
+
'pipe'
|
|
99
|
+
]
|
|
100
|
+
});
|
|
101
|
+
let stdout = '';
|
|
102
|
+
let stderr = '';
|
|
103
|
+
child.stdout.on('data', (data)=>{
|
|
104
|
+
stdout += data;
|
|
105
|
+
});
|
|
106
|
+
child.stderr.on('data', (data)=>{
|
|
107
|
+
stderr += data;
|
|
108
|
+
});
|
|
109
|
+
child.on('error', reject);
|
|
110
|
+
child.on('close', (code)=>{
|
|
111
|
+
const result = {
|
|
112
|
+
stdout,
|
|
113
|
+
stderr,
|
|
114
|
+
code: code ?? 1
|
|
115
|
+
};
|
|
116
|
+
if (false !== options.reject && 0 !== result.code) return void reject(new Error(stderr || stdout || `tsgo exited with ${result.code}`));
|
|
117
|
+
resolve(result);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
const getTsgoBinPath = ()=>external_path_default().join(external_path_default().dirname(require.resolve("@typescript/native-preview/package.json")), 'bin/tsgo.js');
|
|
121
|
+
const getSourceFileForOutput = (appDirectory, distDir, outputFile)=>{
|
|
122
|
+
const relativeOutput = external_path_default().relative(distDir, outputFile);
|
|
123
|
+
const parsed = external_path_default().parse(relativeOutput);
|
|
124
|
+
const sourceBase = external_path_default().join(appDirectory, parsed.dir, parsed.name);
|
|
125
|
+
return findExistingSource(`${sourceBase}.ts`) || findExistingSource(`${sourceBase}.tsx`) || findExistingSource(`${sourceBase}.js`) || findExistingSource(`${sourceBase}.jsx`);
|
|
126
|
+
};
|
|
127
|
+
const findExistingSource = (filePath)=>utils_namespaceObject.fs.existsSync(filePath) ? filePath : void 0;
|
|
128
|
+
const rewriteOutputSpecifiers = async (appDirectory, distDir, baseUrl, paths, moduleType)=>{
|
|
129
|
+
if (0 === Object.keys(paths).length || !await utils_namespaceObject.fs.pathExists(distDir)) return;
|
|
130
|
+
const matcher = (0, external_tsconfigPathsPlugin_js_namespaceObject.createTsconfigPathsMatcher)(baseUrl, paths);
|
|
131
|
+
if (!matcher) return;
|
|
132
|
+
const files = await collectOutputFiles(distDir);
|
|
133
|
+
await Promise.all(files.map(async (file)=>{
|
|
134
|
+
const sourceFile = getSourceFileForOutput(appDirectory, distDir, file);
|
|
135
|
+
if (!sourceFile) return;
|
|
136
|
+
const content = await utils_namespaceObject.fs.readFile(file, 'utf8');
|
|
137
|
+
let changed = false;
|
|
138
|
+
const rewritten = content.replace(importSpecifierRE, (match, prefix, specifier, suffix)=>{
|
|
139
|
+
const nextSpecifier = (0, external_tsconfigPathsPlugin_js_namespaceObject.getNotAliasedPath)(sourceFile, matcher, specifier, moduleType);
|
|
140
|
+
if (!nextSpecifier || nextSpecifier === specifier) return match;
|
|
141
|
+
changed = true;
|
|
142
|
+
return `${prefix}${nextSpecifier}${suffix}`;
|
|
143
|
+
});
|
|
144
|
+
if (changed) await utils_namespaceObject.fs.writeFile(file, rewritten);
|
|
145
|
+
}));
|
|
146
|
+
};
|
|
147
|
+
const collectOutputFiles = async (dir)=>{
|
|
148
|
+
const entries = await utils_namespaceObject.fs.readdir(dir, {
|
|
149
|
+
withFileTypes: true
|
|
150
|
+
});
|
|
151
|
+
const files = await Promise.all(entries.map(async (entry)=>{
|
|
152
|
+
const fullPath = external_path_default().join(dir, entry.name);
|
|
153
|
+
if (entry.isDirectory()) return collectOutputFiles(fullPath);
|
|
154
|
+
return /\.(?:c|m)?js$/.test(entry.name) ? [
|
|
155
|
+
fullPath
|
|
156
|
+
] : [];
|
|
157
|
+
}));
|
|
158
|
+
return files.flat();
|
|
159
|
+
};
|
|
160
|
+
const compileByTs = async (appDirectory, config, compileOptions)=>{
|
|
161
|
+
utils_namespaceObject.logger.info("Running tsgo compile...");
|
|
162
|
+
const { sourceDirs, distDir, tsconfigPath } = compileOptions;
|
|
163
|
+
if (!tsconfigPath) return;
|
|
164
|
+
const { alias } = config;
|
|
165
|
+
const aliasOption = (0, utils_namespaceObject.getAliasConfig)(alias, {
|
|
166
|
+
appDirectory,
|
|
167
|
+
tsconfigPath
|
|
168
|
+
});
|
|
169
|
+
const { paths = {}, absoluteBaseUrl = './' } = aliasOption;
|
|
170
|
+
const { config: tsgoConfig, resolvedConfigPath } = await createResolvedTsgoConfig(appDirectory, tsconfigPath, distDir, sourceDirs);
|
|
171
|
+
const result = await runTsgo([
|
|
172
|
+
'-p',
|
|
173
|
+
resolvedConfigPath
|
|
174
|
+
], {
|
|
175
|
+
cwd: appDirectory,
|
|
176
|
+
reject: false
|
|
177
|
+
});
|
|
178
|
+
await utils_namespaceObject.fs.remove(resolvedConfigPath);
|
|
179
|
+
if (result.stderr) utils_namespaceObject.logger.error(result.stderr);
|
|
180
|
+
if (result.stdout) utils_namespaceObject.logger.info(result.stdout);
|
|
181
|
+
if (0 !== result.code) {
|
|
182
|
+
const noEmitOnError = tsgoConfig.compilerOptions?.noEmitOnError;
|
|
183
|
+
if (void 0 === noEmitOnError || true === noEmitOnError) if (compileOptions.throwErrorInsteadOfExit) utils_namespaceObject.logger.error('TS-Go compilation failed');
|
|
184
|
+
else process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
await rewriteOutputSpecifiers(appDirectory, distDir, absoluteBaseUrl, paths, compileOptions.moduleType);
|
|
187
|
+
for (const source of sourceDirs)await copyFiles(source, distDir, appDirectory);
|
|
188
|
+
utils_namespaceObject.logger.info("TS-Go compile succeed");
|
|
189
|
+
};
|
|
190
|
+
exports.compileByTs = __webpack_exports__.compileByTs;
|
|
191
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
192
|
+
"compileByTs"
|
|
193
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
194
|
+
Object.defineProperty(exports, '__esModule', {
|
|
195
|
+
value: true
|
|
196
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.n = (module1)=>{
|
|
5
|
+
var getter = module1 && module1.__esModule ? ()=>module1['default'] : ()=>module1;
|
|
6
|
+
__webpack_require__.d(getter, {
|
|
7
|
+
a: getter
|
|
8
|
+
});
|
|
9
|
+
return getter;
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
(()=>{
|
|
13
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
14
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: definition[key]
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
})();
|
|
20
|
+
(()=>{
|
|
21
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
22
|
+
})();
|
|
23
|
+
(()=>{
|
|
24
|
+
__webpack_require__.r = (exports1)=>{
|
|
25
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
26
|
+
value: 'Module'
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
29
|
+
value: true
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
})();
|
|
33
|
+
var __webpack_exports__ = {};
|
|
34
|
+
__webpack_require__.r(__webpack_exports__);
|
|
35
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
36
|
+
createTsconfigPathsMatcher: ()=>createTsconfigPathsMatcher,
|
|
37
|
+
getNotAliasedPath: ()=>getNotAliasedPath
|
|
38
|
+
});
|
|
39
|
+
const utils_namespaceObject = require("@modern-js/utils");
|
|
40
|
+
const tsconfig_paths_namespaceObject = require("@modern-js/utils/tsconfig-paths");
|
|
41
|
+
const external_os_namespaceObject = require("os");
|
|
42
|
+
const external_path_namespaceObject = require("path");
|
|
43
|
+
var external_path_default = /*#__PURE__*/ __webpack_require__.n(external_path_namespaceObject);
|
|
44
|
+
const toEsmOutputPath = (resolvedPath)=>{
|
|
45
|
+
const sourcePath = (0, utils_namespaceObject.findSourceEntry)(resolvedPath) || resolvedPath;
|
|
46
|
+
const ext = external_path_default().extname(sourcePath);
|
|
47
|
+
return ext ? `${sourcePath.slice(0, -ext.length)}.js` : `${sourcePath}.js`;
|
|
48
|
+
};
|
|
49
|
+
const resolveRelativeEsmSpecifier = (sourceFile, text)=>{
|
|
50
|
+
if (!text.startsWith('./') && !text.startsWith('../')) return;
|
|
51
|
+
const importerDir = (0, external_path_namespaceObject.dirname)(sourceFile);
|
|
52
|
+
return external_path_default().resolve(importerDir, text);
|
|
53
|
+
};
|
|
54
|
+
const isRegExpKey = (str)=>str.startsWith('^') || str.endsWith('$');
|
|
55
|
+
const resolveAliasPath = (baseUrl, filePath)=>{
|
|
56
|
+
if (filePath.startsWith('.') || filePath.startsWith('..')) return external_path_default().resolve(baseUrl, filePath);
|
|
57
|
+
return filePath;
|
|
58
|
+
};
|
|
59
|
+
const createAliasMatcher = (baseUrl, alias)=>{
|
|
60
|
+
const aliasPairs = Object.keys(alias).reduce((o, key)=>{
|
|
61
|
+
if (isRegExpKey(key)) {
|
|
62
|
+
const regexp = new RegExp(key);
|
|
63
|
+
const aliasPath = resolveAliasPath(baseUrl, alias[key]);
|
|
64
|
+
o.push([
|
|
65
|
+
regexp,
|
|
66
|
+
aliasPath
|
|
67
|
+
]);
|
|
68
|
+
} else {
|
|
69
|
+
const aliasPath = resolveAliasPath(baseUrl, alias[key]);
|
|
70
|
+
o.push([
|
|
71
|
+
key,
|
|
72
|
+
aliasPath
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
return o;
|
|
76
|
+
}, []);
|
|
77
|
+
const cacheMap = new Map();
|
|
78
|
+
return (requestedModule)=>{
|
|
79
|
+
if (cacheMap.has(requestedModule)) return cacheMap.get(requestedModule);
|
|
80
|
+
for (const [key, value] of aliasPairs){
|
|
81
|
+
if (key instanceof RegExp) {
|
|
82
|
+
if (key.test(requestedModule)) {
|
|
83
|
+
cacheMap.set(requestedModule, value);
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (requestedModule === key) {
|
|
88
|
+
cacheMap.set(requestedModule, value);
|
|
89
|
+
return value;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
const createTsconfigPathsMatcher = (baseUrl, paths)=>{
|
|
95
|
+
const tsPaths = {};
|
|
96
|
+
const alias = {};
|
|
97
|
+
Object.keys(paths).forEach((key)=>{
|
|
98
|
+
if (Array.isArray(paths[key])) tsPaths[key] = paths[key];
|
|
99
|
+
else alias[key] = paths[key];
|
|
100
|
+
});
|
|
101
|
+
const matchAliasPath = createAliasMatcher(baseUrl, alias);
|
|
102
|
+
const matchTsPath = (0, tsconfig_paths_namespaceObject.createMatchPath)(baseUrl, tsPaths, [
|
|
103
|
+
'main'
|
|
104
|
+
]);
|
|
105
|
+
return (requestedModule, readJSONSync, fileExists, extensions)=>{
|
|
106
|
+
const result = matchTsPath(requestedModule, readJSONSync, fileExists, extensions);
|
|
107
|
+
if (result) return result;
|
|
108
|
+
return matchAliasPath(requestedModule);
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
function getNotAliasedPath(sourceFile, matcher, text, moduleType) {
|
|
112
|
+
let result = (0, utils_namespaceObject.findMatchedSourcePath)(matcher, text);
|
|
113
|
+
if (!result && 'module' === moduleType) result = resolveRelativeEsmSpecifier(sourceFile, text);
|
|
114
|
+
if (!result) return;
|
|
115
|
+
if ('win32' === external_os_namespaceObject.platform()) result = result.replace(/\\/g, '/');
|
|
116
|
+
if (!external_path_default().isAbsolute(result)) {
|
|
117
|
+
if (!result.startsWith('.') && !result.startsWith('..')) try {
|
|
118
|
+
const packagePath = require.resolve(result, {
|
|
119
|
+
paths: [
|
|
120
|
+
process.cwd(),
|
|
121
|
+
...module.paths
|
|
122
|
+
]
|
|
123
|
+
});
|
|
124
|
+
if (packagePath) return result;
|
|
125
|
+
} catch {}
|
|
126
|
+
try {
|
|
127
|
+
const packagePath = require.resolve(text, {
|
|
128
|
+
paths: [
|
|
129
|
+
process.cwd(),
|
|
130
|
+
...module.paths
|
|
131
|
+
]
|
|
132
|
+
});
|
|
133
|
+
if (packagePath) return text;
|
|
134
|
+
} catch {}
|
|
135
|
+
}
|
|
136
|
+
if ('module' === moduleType) result = toEsmOutputPath(result);
|
|
137
|
+
const resolvedPath = external_path_namespaceObject.posix.relative((0, external_path_namespaceObject.dirname)(sourceFile), result) || './';
|
|
138
|
+
return '.' === resolvedPath[0] ? resolvedPath : `./${resolvedPath}`;
|
|
139
|
+
}
|
|
140
|
+
exports.createTsconfigPathsMatcher = __webpack_exports__.createTsconfigPathsMatcher;
|
|
141
|
+
exports.getNotAliasedPath = __webpack_exports__.getNotAliasedPath;
|
|
142
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
143
|
+
"createTsconfigPathsMatcher",
|
|
144
|
+
"getNotAliasedPath"
|
|
145
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
146
|
+
Object.defineProperty(exports, '__esModule', {
|
|
147
|
+
value: true
|
|
148
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
compile: ()=>index_js_namespaceObject.compile
|
|
28
|
+
});
|
|
29
|
+
const index_js_namespaceObject = require("./common/index.js");
|
|
30
|
+
exports.compile = __webpack_exports__.compile;
|
|
31
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
32
|
+
"compile"
|
|
33
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
34
|
+
Object.defineProperty(exports, '__esModule', {
|
|
35
|
+
value: true
|
|
36
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as __rspack_external_path from "path";
|
|
2
|
+
const FILE_EXTENSIONS = [
|
|
3
|
+
'.js',
|
|
4
|
+
'.ts',
|
|
5
|
+
'.mjs',
|
|
6
|
+
'.ejs'
|
|
7
|
+
];
|
|
8
|
+
const validateAbsolutePath = (filename, message)=>{
|
|
9
|
+
if (!__rspack_external_path.isAbsolute(filename)) throw new Error(message);
|
|
10
|
+
};
|
|
11
|
+
const validateAbsolutePaths = (filenames, messageFunc)=>{
|
|
12
|
+
filenames.forEach((filename)=>validateAbsolutePath(filename, messageFunc(filename)));
|
|
13
|
+
};
|
|
14
|
+
const compile = async (appDirectory, modernConfig, compileOptions)=>{
|
|
15
|
+
const { sourceDirs, distDir, tsconfigPath } = compileOptions;
|
|
16
|
+
validateAbsolutePaths(sourceDirs, (dir)=>`source dir ${dir} is not an absolute path.`);
|
|
17
|
+
validateAbsolutePath(distDir, `dist dir ${distDir} is not an absolute path.`);
|
|
18
|
+
const { compileByTs } = await import("../compilers/typescript/index.mjs");
|
|
19
|
+
await compileByTs(appDirectory, modernConfig, compileOptions);
|
|
20
|
+
};
|
|
21
|
+
export { FILE_EXTENSIONS, compile };
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { fs, getAliasConfig, logger } from "@modern-js/utils";
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { createTsconfigPathsMatcher, getNotAliasedPath } from "./tsconfigPathsPlugin.mjs";
|
|
5
|
+
const importSpecifierRE = /((?:from\s*|import\s*\(\s*|require\s*\(\s*)['"])([^'"]+)(['"])/g;
|
|
6
|
+
const copyFiles = async (from, to, appDirectory)=>{
|
|
7
|
+
if (await fs.pathExists(from)) {
|
|
8
|
+
const relativePath = path.relative(appDirectory, from);
|
|
9
|
+
const targetDir = path.join(to, relativePath);
|
|
10
|
+
await fs.copy(from, targetDir, {
|
|
11
|
+
filter: (src)=>![
|
|
12
|
+
'.ts',
|
|
13
|
+
'.js'
|
|
14
|
+
].includes(path.extname(src)) && !src.endsWith('tsconfig.json')
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const createResolvedTsgoConfig = async (appDirectory, tsconfigPath, distDir, sourceDirs)=>{
|
|
19
|
+
const output = await runTsgo([
|
|
20
|
+
'--showConfig',
|
|
21
|
+
'-p',
|
|
22
|
+
tsconfigPath
|
|
23
|
+
], {
|
|
24
|
+
cwd: path.dirname(tsconfigPath)
|
|
25
|
+
});
|
|
26
|
+
const config = JSON.parse(output.stdout);
|
|
27
|
+
config.compilerOptions ??= {};
|
|
28
|
+
config.compilerOptions.rootDir = appDirectory;
|
|
29
|
+
config.compilerOptions.outDir = distDir;
|
|
30
|
+
config.files = filterSourceFiles(appDirectory, sourceDirs, config.files);
|
|
31
|
+
delete config.include;
|
|
32
|
+
delete config.compilerOptions.baseUrl;
|
|
33
|
+
if ([
|
|
34
|
+
'node',
|
|
35
|
+
'node10'
|
|
36
|
+
].includes(String(config.compilerOptions.moduleResolution).toLowerCase())) delete config.compilerOptions.moduleResolution;
|
|
37
|
+
const resolvedConfigPath = path.join(appDirectory, `.tsgo.${process.pid}.resolved.json`);
|
|
38
|
+
await fs.writeFile(resolvedConfigPath, JSON.stringify(config, null, 2));
|
|
39
|
+
return {
|
|
40
|
+
config,
|
|
41
|
+
resolvedConfigPath
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
const filterSourceFiles = (appDirectory, sourceDirs, files = [])=>{
|
|
45
|
+
const sourcePosixPaths = sourceDirs.map((sourceDir)=>sourceDir.split(path.sep).join(path.posix.sep));
|
|
46
|
+
return files.filter((fileName)=>{
|
|
47
|
+
const absoluteFileName = path.resolve(appDirectory, fileName).split(path.sep).join(path.posix.sep);
|
|
48
|
+
return fileName.endsWith('.d.ts') || sourcePosixPaths.some((sourceDir)=>absoluteFileName.includes(sourceDir));
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const runTsgo = (args, options)=>new Promise((resolve, reject)=>{
|
|
52
|
+
const child = spawn(process.execPath, [
|
|
53
|
+
getTsgoBinPath(),
|
|
54
|
+
...args
|
|
55
|
+
], {
|
|
56
|
+
cwd: options.cwd,
|
|
57
|
+
stdio: [
|
|
58
|
+
'ignore',
|
|
59
|
+
'pipe',
|
|
60
|
+
'pipe'
|
|
61
|
+
]
|
|
62
|
+
});
|
|
63
|
+
let stdout = '';
|
|
64
|
+
let stderr = '';
|
|
65
|
+
child.stdout.on('data', (data)=>{
|
|
66
|
+
stdout += data;
|
|
67
|
+
});
|
|
68
|
+
child.stderr.on('data', (data)=>{
|
|
69
|
+
stderr += data;
|
|
70
|
+
});
|
|
71
|
+
child.on('error', reject);
|
|
72
|
+
child.on('close', (code)=>{
|
|
73
|
+
const result = {
|
|
74
|
+
stdout,
|
|
75
|
+
stderr,
|
|
76
|
+
code: code ?? 1
|
|
77
|
+
};
|
|
78
|
+
if (false !== options.reject && 0 !== result.code) return void reject(new Error(stderr || stdout || `tsgo exited with ${result.code}`));
|
|
79
|
+
resolve(result);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
const getTsgoBinPath = ()=>path.join(path.dirname(require.resolve("@typescript/native-preview/package.json")), 'bin/tsgo.js');
|
|
83
|
+
const getSourceFileForOutput = (appDirectory, distDir, outputFile)=>{
|
|
84
|
+
const relativeOutput = path.relative(distDir, outputFile);
|
|
85
|
+
const parsed = path.parse(relativeOutput);
|
|
86
|
+
const sourceBase = path.join(appDirectory, parsed.dir, parsed.name);
|
|
87
|
+
return findExistingSource(`${sourceBase}.ts`) || findExistingSource(`${sourceBase}.tsx`) || findExistingSource(`${sourceBase}.js`) || findExistingSource(`${sourceBase}.jsx`);
|
|
88
|
+
};
|
|
89
|
+
const findExistingSource = (filePath)=>fs.existsSync(filePath) ? filePath : void 0;
|
|
90
|
+
const rewriteOutputSpecifiers = async (appDirectory, distDir, baseUrl, paths, moduleType)=>{
|
|
91
|
+
if (0 === Object.keys(paths).length || !await fs.pathExists(distDir)) return;
|
|
92
|
+
const matcher = createTsconfigPathsMatcher(baseUrl, paths);
|
|
93
|
+
if (!matcher) return;
|
|
94
|
+
const files = await collectOutputFiles(distDir);
|
|
95
|
+
await Promise.all(files.map(async (file)=>{
|
|
96
|
+
const sourceFile = getSourceFileForOutput(appDirectory, distDir, file);
|
|
97
|
+
if (!sourceFile) return;
|
|
98
|
+
const content = await fs.readFile(file, 'utf8');
|
|
99
|
+
let changed = false;
|
|
100
|
+
const rewritten = content.replace(importSpecifierRE, (match, prefix, specifier, suffix)=>{
|
|
101
|
+
const nextSpecifier = getNotAliasedPath(sourceFile, matcher, specifier, moduleType);
|
|
102
|
+
if (!nextSpecifier || nextSpecifier === specifier) return match;
|
|
103
|
+
changed = true;
|
|
104
|
+
return `${prefix}${nextSpecifier}${suffix}`;
|
|
105
|
+
});
|
|
106
|
+
if (changed) await fs.writeFile(file, rewritten);
|
|
107
|
+
}));
|
|
108
|
+
};
|
|
109
|
+
const collectOutputFiles = async (dir)=>{
|
|
110
|
+
const entries = await fs.readdir(dir, {
|
|
111
|
+
withFileTypes: true
|
|
112
|
+
});
|
|
113
|
+
const files = await Promise.all(entries.map(async (entry)=>{
|
|
114
|
+
const fullPath = path.join(dir, entry.name);
|
|
115
|
+
if (entry.isDirectory()) return collectOutputFiles(fullPath);
|
|
116
|
+
return /\.(?:c|m)?js$/.test(entry.name) ? [
|
|
117
|
+
fullPath
|
|
118
|
+
] : [];
|
|
119
|
+
}));
|
|
120
|
+
return files.flat();
|
|
121
|
+
};
|
|
122
|
+
const compileByTs = async (appDirectory, config, compileOptions)=>{
|
|
123
|
+
logger.info("Running tsgo compile...");
|
|
124
|
+
const { sourceDirs, distDir, tsconfigPath } = compileOptions;
|
|
125
|
+
if (!tsconfigPath) return;
|
|
126
|
+
const { alias } = config;
|
|
127
|
+
const aliasOption = getAliasConfig(alias, {
|
|
128
|
+
appDirectory,
|
|
129
|
+
tsconfigPath
|
|
130
|
+
});
|
|
131
|
+
const { paths = {}, absoluteBaseUrl = './' } = aliasOption;
|
|
132
|
+
const { config: tsgoConfig, resolvedConfigPath } = await createResolvedTsgoConfig(appDirectory, tsconfigPath, distDir, sourceDirs);
|
|
133
|
+
const result = await runTsgo([
|
|
134
|
+
'-p',
|
|
135
|
+
resolvedConfigPath
|
|
136
|
+
], {
|
|
137
|
+
cwd: appDirectory,
|
|
138
|
+
reject: false
|
|
139
|
+
});
|
|
140
|
+
await fs.remove(resolvedConfigPath);
|
|
141
|
+
if (result.stderr) logger.error(result.stderr);
|
|
142
|
+
if (result.stdout) logger.info(result.stdout);
|
|
143
|
+
if (0 !== result.code) {
|
|
144
|
+
const noEmitOnError = tsgoConfig.compilerOptions?.noEmitOnError;
|
|
145
|
+
if (void 0 === noEmitOnError || true === noEmitOnError) if (compileOptions.throwErrorInsteadOfExit) logger.error('TS-Go compilation failed');
|
|
146
|
+
else process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
await rewriteOutputSpecifiers(appDirectory, distDir, absoluteBaseUrl, paths, compileOptions.moduleType);
|
|
149
|
+
for (const source of sourceDirs)await copyFiles(source, distDir, appDirectory);
|
|
150
|
+
logger.info("TS-Go compile succeed");
|
|
151
|
+
};
|
|
152
|
+
export { compileByTs };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { findMatchedSourcePath, findSourceEntry } from "@modern-js/utils";
|
|
2
|
+
import { createMatchPath } from "@modern-js/utils/tsconfig-paths";
|
|
3
|
+
import path, { dirname, posix } from "path";
|
|
4
|
+
import * as __rspack_external_os from "os";
|
|
5
|
+
const toEsmOutputPath = (resolvedPath)=>{
|
|
6
|
+
const sourcePath = findSourceEntry(resolvedPath) || resolvedPath;
|
|
7
|
+
const ext = path.extname(sourcePath);
|
|
8
|
+
return ext ? `${sourcePath.slice(0, -ext.length)}.js` : `${sourcePath}.js`;
|
|
9
|
+
};
|
|
10
|
+
const resolveRelativeEsmSpecifier = (sourceFile, text)=>{
|
|
11
|
+
if (!text.startsWith('./') && !text.startsWith('../')) return;
|
|
12
|
+
const importerDir = dirname(sourceFile);
|
|
13
|
+
return path.resolve(importerDir, text);
|
|
14
|
+
};
|
|
15
|
+
const isRegExpKey = (str)=>str.startsWith('^') || str.endsWith('$');
|
|
16
|
+
const resolveAliasPath = (baseUrl, filePath)=>{
|
|
17
|
+
if (filePath.startsWith('.') || filePath.startsWith('..')) return path.resolve(baseUrl, filePath);
|
|
18
|
+
return filePath;
|
|
19
|
+
};
|
|
20
|
+
const createAliasMatcher = (baseUrl, alias)=>{
|
|
21
|
+
const aliasPairs = Object.keys(alias).reduce((o, key)=>{
|
|
22
|
+
if (isRegExpKey(key)) {
|
|
23
|
+
const regexp = new RegExp(key);
|
|
24
|
+
const aliasPath = resolveAliasPath(baseUrl, alias[key]);
|
|
25
|
+
o.push([
|
|
26
|
+
regexp,
|
|
27
|
+
aliasPath
|
|
28
|
+
]);
|
|
29
|
+
} else {
|
|
30
|
+
const aliasPath = resolveAliasPath(baseUrl, alias[key]);
|
|
31
|
+
o.push([
|
|
32
|
+
key,
|
|
33
|
+
aliasPath
|
|
34
|
+
]);
|
|
35
|
+
}
|
|
36
|
+
return o;
|
|
37
|
+
}, []);
|
|
38
|
+
const cacheMap = new Map();
|
|
39
|
+
return (requestedModule)=>{
|
|
40
|
+
if (cacheMap.has(requestedModule)) return cacheMap.get(requestedModule);
|
|
41
|
+
for (const [key, value] of aliasPairs){
|
|
42
|
+
if (key instanceof RegExp) {
|
|
43
|
+
if (key.test(requestedModule)) {
|
|
44
|
+
cacheMap.set(requestedModule, value);
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (requestedModule === key) {
|
|
49
|
+
cacheMap.set(requestedModule, value);
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
const createTsconfigPathsMatcher = (baseUrl, paths)=>{
|
|
56
|
+
const tsPaths = {};
|
|
57
|
+
const alias = {};
|
|
58
|
+
Object.keys(paths).forEach((key)=>{
|
|
59
|
+
if (Array.isArray(paths[key])) tsPaths[key] = paths[key];
|
|
60
|
+
else alias[key] = paths[key];
|
|
61
|
+
});
|
|
62
|
+
const matchAliasPath = createAliasMatcher(baseUrl, alias);
|
|
63
|
+
const matchTsPath = createMatchPath(baseUrl, tsPaths, [
|
|
64
|
+
'main'
|
|
65
|
+
]);
|
|
66
|
+
return (requestedModule, readJSONSync, fileExists, extensions)=>{
|
|
67
|
+
const result = matchTsPath(requestedModule, readJSONSync, fileExists, extensions);
|
|
68
|
+
if (result) return result;
|
|
69
|
+
return matchAliasPath(requestedModule);
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
function getNotAliasedPath(sourceFile, matcher, text, moduleType) {
|
|
73
|
+
let result = findMatchedSourcePath(matcher, text);
|
|
74
|
+
if (!result && 'module' === moduleType) result = resolveRelativeEsmSpecifier(sourceFile, text);
|
|
75
|
+
if (!result) return;
|
|
76
|
+
if ('win32' === __rspack_external_os.platform()) result = result.replace(/\\/g, '/');
|
|
77
|
+
if (!path.isAbsolute(result)) {
|
|
78
|
+
if (!result.startsWith('.') && !result.startsWith('..')) try {
|
|
79
|
+
const packagePath = require.resolve(result, {
|
|
80
|
+
paths: [
|
|
81
|
+
process.cwd(),
|
|
82
|
+
...module.paths
|
|
83
|
+
]
|
|
84
|
+
});
|
|
85
|
+
if (packagePath) return result;
|
|
86
|
+
} catch {}
|
|
87
|
+
try {
|
|
88
|
+
const packagePath = require.resolve(text, {
|
|
89
|
+
paths: [
|
|
90
|
+
process.cwd(),
|
|
91
|
+
...module.paths
|
|
92
|
+
]
|
|
93
|
+
});
|
|
94
|
+
if (packagePath) return text;
|
|
95
|
+
} catch {}
|
|
96
|
+
}
|
|
97
|
+
if ('module' === moduleType) result = toEsmOutputPath(result);
|
|
98
|
+
const resolvedPath = posix.relative(dirname(sourceFile), result) || './';
|
|
99
|
+
return '.' === resolvedPath[0] ? resolvedPath : `./${resolvedPath}`;
|
|
100
|
+
}
|
|
101
|
+
export { createTsconfigPathsMatcher, getNotAliasedPath };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { compile } from "./common/index.mjs";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import * as __rspack_external_path from "path";
|
|
3
|
+
const FILE_EXTENSIONS = [
|
|
4
|
+
'.js',
|
|
5
|
+
'.ts',
|
|
6
|
+
'.mjs',
|
|
7
|
+
'.ejs'
|
|
8
|
+
];
|
|
9
|
+
const validateAbsolutePath = (filename, message)=>{
|
|
10
|
+
if (!__rspack_external_path.isAbsolute(filename)) throw new Error(message);
|
|
11
|
+
};
|
|
12
|
+
const validateAbsolutePaths = (filenames, messageFunc)=>{
|
|
13
|
+
filenames.forEach((filename)=>validateAbsolutePath(filename, messageFunc(filename)));
|
|
14
|
+
};
|
|
15
|
+
const compile = async (appDirectory, modernConfig, compileOptions)=>{
|
|
16
|
+
const { sourceDirs, distDir, tsconfigPath } = compileOptions;
|
|
17
|
+
validateAbsolutePaths(sourceDirs, (dir)=>`source dir ${dir} is not an absolute path.`);
|
|
18
|
+
validateAbsolutePath(distDir, `dist dir ${distDir} is not an absolute path.`);
|
|
19
|
+
const { compileByTs } = await import("../compilers/typescript/index.mjs");
|
|
20
|
+
await compileByTs(appDirectory, modernConfig, compileOptions);
|
|
21
|
+
};
|
|
22
|
+
export { FILE_EXTENSIONS, compile };
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import __rslib_shim_module__ from "node:module";
|
|
2
|
+
const require = /*#__PURE__*/ __rslib_shim_module__.createRequire(/*#__PURE__*/ (()=>import.meta.url)());
|
|
3
|
+
import { fs, getAliasConfig, logger } from "@modern-js/utils";
|
|
4
|
+
import { spawn } from "child_process";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { createTsconfigPathsMatcher, getNotAliasedPath } from "./tsconfigPathsPlugin.mjs";
|
|
7
|
+
const importSpecifierRE = /((?:from\s*|import\s*\(\s*|require\s*\(\s*)['"])([^'"]+)(['"])/g;
|
|
8
|
+
const copyFiles = async (from, to, appDirectory)=>{
|
|
9
|
+
if (await fs.pathExists(from)) {
|
|
10
|
+
const relativePath = path.relative(appDirectory, from);
|
|
11
|
+
const targetDir = path.join(to, relativePath);
|
|
12
|
+
await fs.copy(from, targetDir, {
|
|
13
|
+
filter: (src)=>![
|
|
14
|
+
'.ts',
|
|
15
|
+
'.js'
|
|
16
|
+
].includes(path.extname(src)) && !src.endsWith('tsconfig.json')
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const createResolvedTsgoConfig = async (appDirectory, tsconfigPath, distDir, sourceDirs)=>{
|
|
21
|
+
const output = await runTsgo([
|
|
22
|
+
'--showConfig',
|
|
23
|
+
'-p',
|
|
24
|
+
tsconfigPath
|
|
25
|
+
], {
|
|
26
|
+
cwd: path.dirname(tsconfigPath)
|
|
27
|
+
});
|
|
28
|
+
const config = JSON.parse(output.stdout);
|
|
29
|
+
config.compilerOptions ??= {};
|
|
30
|
+
config.compilerOptions.rootDir = appDirectory;
|
|
31
|
+
config.compilerOptions.outDir = distDir;
|
|
32
|
+
config.files = filterSourceFiles(appDirectory, sourceDirs, config.files);
|
|
33
|
+
delete config.include;
|
|
34
|
+
delete config.compilerOptions.baseUrl;
|
|
35
|
+
if ([
|
|
36
|
+
'node',
|
|
37
|
+
'node10'
|
|
38
|
+
].includes(String(config.compilerOptions.moduleResolution).toLowerCase())) delete config.compilerOptions.moduleResolution;
|
|
39
|
+
const resolvedConfigPath = path.join(appDirectory, `.tsgo.${process.pid}.resolved.json`);
|
|
40
|
+
await fs.writeFile(resolvedConfigPath, JSON.stringify(config, null, 2));
|
|
41
|
+
return {
|
|
42
|
+
config,
|
|
43
|
+
resolvedConfigPath
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
const filterSourceFiles = (appDirectory, sourceDirs, files = [])=>{
|
|
47
|
+
const sourcePosixPaths = sourceDirs.map((sourceDir)=>sourceDir.split(path.sep).join(path.posix.sep));
|
|
48
|
+
return files.filter((fileName)=>{
|
|
49
|
+
const absoluteFileName = path.resolve(appDirectory, fileName).split(path.sep).join(path.posix.sep);
|
|
50
|
+
return fileName.endsWith('.d.ts') || sourcePosixPaths.some((sourceDir)=>absoluteFileName.includes(sourceDir));
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const runTsgo = (args, options)=>new Promise((resolve, reject)=>{
|
|
54
|
+
const child = spawn(process.execPath, [
|
|
55
|
+
getTsgoBinPath(),
|
|
56
|
+
...args
|
|
57
|
+
], {
|
|
58
|
+
cwd: options.cwd,
|
|
59
|
+
stdio: [
|
|
60
|
+
'ignore',
|
|
61
|
+
'pipe',
|
|
62
|
+
'pipe'
|
|
63
|
+
]
|
|
64
|
+
});
|
|
65
|
+
let stdout = '';
|
|
66
|
+
let stderr = '';
|
|
67
|
+
child.stdout.on('data', (data)=>{
|
|
68
|
+
stdout += data;
|
|
69
|
+
});
|
|
70
|
+
child.stderr.on('data', (data)=>{
|
|
71
|
+
stderr += data;
|
|
72
|
+
});
|
|
73
|
+
child.on('error', reject);
|
|
74
|
+
child.on('close', (code)=>{
|
|
75
|
+
const result = {
|
|
76
|
+
stdout,
|
|
77
|
+
stderr,
|
|
78
|
+
code: code ?? 1
|
|
79
|
+
};
|
|
80
|
+
if (false !== options.reject && 0 !== result.code) return void reject(new Error(stderr || stdout || `tsgo exited with ${result.code}`));
|
|
81
|
+
resolve(result);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
const getTsgoBinPath = ()=>path.join(path.dirname(require.resolve("@typescript/native-preview/package.json")), 'bin/tsgo.js');
|
|
85
|
+
const getSourceFileForOutput = (appDirectory, distDir, outputFile)=>{
|
|
86
|
+
const relativeOutput = path.relative(distDir, outputFile);
|
|
87
|
+
const parsed = path.parse(relativeOutput);
|
|
88
|
+
const sourceBase = path.join(appDirectory, parsed.dir, parsed.name);
|
|
89
|
+
return findExistingSource(`${sourceBase}.ts`) || findExistingSource(`${sourceBase}.tsx`) || findExistingSource(`${sourceBase}.js`) || findExistingSource(`${sourceBase}.jsx`);
|
|
90
|
+
};
|
|
91
|
+
const findExistingSource = (filePath)=>fs.existsSync(filePath) ? filePath : void 0;
|
|
92
|
+
const rewriteOutputSpecifiers = async (appDirectory, distDir, baseUrl, paths, moduleType)=>{
|
|
93
|
+
if (0 === Object.keys(paths).length || !await fs.pathExists(distDir)) return;
|
|
94
|
+
const matcher = createTsconfigPathsMatcher(baseUrl, paths);
|
|
95
|
+
if (!matcher) return;
|
|
96
|
+
const files = await collectOutputFiles(distDir);
|
|
97
|
+
await Promise.all(files.map(async (file)=>{
|
|
98
|
+
const sourceFile = getSourceFileForOutput(appDirectory, distDir, file);
|
|
99
|
+
if (!sourceFile) return;
|
|
100
|
+
const content = await fs.readFile(file, 'utf8');
|
|
101
|
+
let changed = false;
|
|
102
|
+
const rewritten = content.replace(importSpecifierRE, (match, prefix, specifier, suffix)=>{
|
|
103
|
+
const nextSpecifier = getNotAliasedPath(sourceFile, matcher, specifier, moduleType);
|
|
104
|
+
if (!nextSpecifier || nextSpecifier === specifier) return match;
|
|
105
|
+
changed = true;
|
|
106
|
+
return `${prefix}${nextSpecifier}${suffix}`;
|
|
107
|
+
});
|
|
108
|
+
if (changed) await fs.writeFile(file, rewritten);
|
|
109
|
+
}));
|
|
110
|
+
};
|
|
111
|
+
const collectOutputFiles = async (dir)=>{
|
|
112
|
+
const entries = await fs.readdir(dir, {
|
|
113
|
+
withFileTypes: true
|
|
114
|
+
});
|
|
115
|
+
const files = await Promise.all(entries.map(async (entry)=>{
|
|
116
|
+
const fullPath = path.join(dir, entry.name);
|
|
117
|
+
if (entry.isDirectory()) return collectOutputFiles(fullPath);
|
|
118
|
+
return /\.(?:c|m)?js$/.test(entry.name) ? [
|
|
119
|
+
fullPath
|
|
120
|
+
] : [];
|
|
121
|
+
}));
|
|
122
|
+
return files.flat();
|
|
123
|
+
};
|
|
124
|
+
const compileByTs = async (appDirectory, config, compileOptions)=>{
|
|
125
|
+
logger.info("Running tsgo compile...");
|
|
126
|
+
const { sourceDirs, distDir, tsconfigPath } = compileOptions;
|
|
127
|
+
if (!tsconfigPath) return;
|
|
128
|
+
const { alias } = config;
|
|
129
|
+
const aliasOption = getAliasConfig(alias, {
|
|
130
|
+
appDirectory,
|
|
131
|
+
tsconfigPath
|
|
132
|
+
});
|
|
133
|
+
const { paths = {}, absoluteBaseUrl = './' } = aliasOption;
|
|
134
|
+
const { config: tsgoConfig, resolvedConfigPath } = await createResolvedTsgoConfig(appDirectory, tsconfigPath, distDir, sourceDirs);
|
|
135
|
+
const result = await runTsgo([
|
|
136
|
+
'-p',
|
|
137
|
+
resolvedConfigPath
|
|
138
|
+
], {
|
|
139
|
+
cwd: appDirectory,
|
|
140
|
+
reject: false
|
|
141
|
+
});
|
|
142
|
+
await fs.remove(resolvedConfigPath);
|
|
143
|
+
if (result.stderr) logger.error(result.stderr);
|
|
144
|
+
if (result.stdout) logger.info(result.stdout);
|
|
145
|
+
if (0 !== result.code) {
|
|
146
|
+
const noEmitOnError = tsgoConfig.compilerOptions?.noEmitOnError;
|
|
147
|
+
if (void 0 === noEmitOnError || true === noEmitOnError) if (compileOptions.throwErrorInsteadOfExit) logger.error('TS-Go compilation failed');
|
|
148
|
+
else process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
await rewriteOutputSpecifiers(appDirectory, distDir, absoluteBaseUrl, paths, compileOptions.moduleType);
|
|
151
|
+
for (const source of sourceDirs)await copyFiles(source, distDir, appDirectory);
|
|
152
|
+
logger.info("TS-Go compile succeed");
|
|
153
|
+
};
|
|
154
|
+
export { compileByTs };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import __rslib_shim_module__ from "node:module";
|
|
2
|
+
const require = /*#__PURE__*/ __rslib_shim_module__.createRequire(/*#__PURE__*/ (()=>import.meta.url)());
|
|
3
|
+
import { findMatchedSourcePath, findSourceEntry } from "@modern-js/utils";
|
|
4
|
+
import { createMatchPath } from "@modern-js/utils/tsconfig-paths";
|
|
5
|
+
import path, { dirname, posix } from "path";
|
|
6
|
+
import * as __rspack_external_os from "os";
|
|
7
|
+
const toEsmOutputPath = (resolvedPath)=>{
|
|
8
|
+
const sourcePath = findSourceEntry(resolvedPath) || resolvedPath;
|
|
9
|
+
const ext = path.extname(sourcePath);
|
|
10
|
+
return ext ? `${sourcePath.slice(0, -ext.length)}.js` : `${sourcePath}.js`;
|
|
11
|
+
};
|
|
12
|
+
const resolveRelativeEsmSpecifier = (sourceFile, text)=>{
|
|
13
|
+
if (!text.startsWith('./') && !text.startsWith('../')) return;
|
|
14
|
+
const importerDir = dirname(sourceFile);
|
|
15
|
+
return path.resolve(importerDir, text);
|
|
16
|
+
};
|
|
17
|
+
const isRegExpKey = (str)=>str.startsWith('^') || str.endsWith('$');
|
|
18
|
+
const resolveAliasPath = (baseUrl, filePath)=>{
|
|
19
|
+
if (filePath.startsWith('.') || filePath.startsWith('..')) return path.resolve(baseUrl, filePath);
|
|
20
|
+
return filePath;
|
|
21
|
+
};
|
|
22
|
+
const createAliasMatcher = (baseUrl, alias)=>{
|
|
23
|
+
const aliasPairs = Object.keys(alias).reduce((o, key)=>{
|
|
24
|
+
if (isRegExpKey(key)) {
|
|
25
|
+
const regexp = new RegExp(key);
|
|
26
|
+
const aliasPath = resolveAliasPath(baseUrl, alias[key]);
|
|
27
|
+
o.push([
|
|
28
|
+
regexp,
|
|
29
|
+
aliasPath
|
|
30
|
+
]);
|
|
31
|
+
} else {
|
|
32
|
+
const aliasPath = resolveAliasPath(baseUrl, alias[key]);
|
|
33
|
+
o.push([
|
|
34
|
+
key,
|
|
35
|
+
aliasPath
|
|
36
|
+
]);
|
|
37
|
+
}
|
|
38
|
+
return o;
|
|
39
|
+
}, []);
|
|
40
|
+
const cacheMap = new Map();
|
|
41
|
+
return (requestedModule)=>{
|
|
42
|
+
if (cacheMap.has(requestedModule)) return cacheMap.get(requestedModule);
|
|
43
|
+
for (const [key, value] of aliasPairs){
|
|
44
|
+
if (key instanceof RegExp) {
|
|
45
|
+
if (key.test(requestedModule)) {
|
|
46
|
+
cacheMap.set(requestedModule, value);
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (requestedModule === key) {
|
|
51
|
+
cacheMap.set(requestedModule, value);
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
const createTsconfigPathsMatcher = (baseUrl, paths)=>{
|
|
58
|
+
const tsPaths = {};
|
|
59
|
+
const alias = {};
|
|
60
|
+
Object.keys(paths).forEach((key)=>{
|
|
61
|
+
if (Array.isArray(paths[key])) tsPaths[key] = paths[key];
|
|
62
|
+
else alias[key] = paths[key];
|
|
63
|
+
});
|
|
64
|
+
const matchAliasPath = createAliasMatcher(baseUrl, alias);
|
|
65
|
+
const matchTsPath = createMatchPath(baseUrl, tsPaths, [
|
|
66
|
+
'main'
|
|
67
|
+
]);
|
|
68
|
+
return (requestedModule, readJSONSync, fileExists, extensions)=>{
|
|
69
|
+
const result = matchTsPath(requestedModule, readJSONSync, fileExists, extensions);
|
|
70
|
+
if (result) return result;
|
|
71
|
+
return matchAliasPath(requestedModule);
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
function getNotAliasedPath(sourceFile, matcher, text, moduleType) {
|
|
75
|
+
let result = findMatchedSourcePath(matcher, text);
|
|
76
|
+
if (!result && 'module' === moduleType) result = resolveRelativeEsmSpecifier(sourceFile, text);
|
|
77
|
+
if (!result) return;
|
|
78
|
+
if ('win32' === __rspack_external_os.platform()) result = result.replace(/\\/g, '/');
|
|
79
|
+
if (!path.isAbsolute(result)) {
|
|
80
|
+
if (!result.startsWith('.') && !result.startsWith('..')) try {
|
|
81
|
+
const packagePath = require.resolve(result, {
|
|
82
|
+
paths: [
|
|
83
|
+
process.cwd(),
|
|
84
|
+
...module.paths
|
|
85
|
+
]
|
|
86
|
+
});
|
|
87
|
+
if (packagePath) return result;
|
|
88
|
+
} catch {}
|
|
89
|
+
try {
|
|
90
|
+
const packagePath = require.resolve(text, {
|
|
91
|
+
paths: [
|
|
92
|
+
process.cwd(),
|
|
93
|
+
...module.paths
|
|
94
|
+
]
|
|
95
|
+
});
|
|
96
|
+
if (packagePath) return text;
|
|
97
|
+
} catch {}
|
|
98
|
+
}
|
|
99
|
+
if ('module' === moduleType) result = toEsmOutputPath(result);
|
|
100
|
+
const resolvedPath = posix.relative(dirname(sourceFile), result) || './';
|
|
101
|
+
return '.' === resolvedPath[0] ? resolvedPath : `./${resolvedPath}`;
|
|
102
|
+
}
|
|
103
|
+
export { createTsconfigPathsMatcher, getNotAliasedPath };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SourceNormalizedConfig } from '@modern-js/server-core';
|
|
2
|
+
export interface Pattern {
|
|
3
|
+
from: string;
|
|
4
|
+
to: string;
|
|
5
|
+
tsconfigPath?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface IConfig {
|
|
8
|
+
alias?: SourceNormalizedConfig['alias'];
|
|
9
|
+
server?: {
|
|
10
|
+
compiler?: 'typescript';
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export interface CompileOptions {
|
|
14
|
+
sourceDirs: string[];
|
|
15
|
+
distDir: string;
|
|
16
|
+
tsconfigPath?: string;
|
|
17
|
+
moduleType?: 'module' | 'commonjs';
|
|
18
|
+
throwErrorInsteadOfExit?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export type CompileFunc = (appDirectory: string, modernConfig: IConfig, compileOptions: CompileOptions) => Promise<void>;
|
|
21
|
+
export declare const FILE_EXTENSIONS: string[];
|
|
22
|
+
export declare const compile: CompileFunc;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { MatchPath } from '@modern-js/utils/tsconfig-paths';
|
|
2
|
+
export declare const createTsconfigPathsMatcher: (baseUrl: string, paths: Record<string, string[] | string>) => MatchPath | undefined;
|
|
3
|
+
export declare function getNotAliasedPath(sourceFile: string, matcher: MatchPath, text: string, moduleType?: 'module' | 'commonjs'): string | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { compile } from './common';
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bleedingdev/modern-js-server-utils",
|
|
3
|
+
"description": "A Progressive React Framework for modern web development.",
|
|
4
|
+
"homepage": "https://github.com/BleedingDev/ultramodern.js#readme",
|
|
5
|
+
"bugs": {
|
|
6
|
+
"url": "https://github.com/BleedingDev/ultramodern.js/issues"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/BleedingDev/ultramodern.js.git",
|
|
11
|
+
"directory": "packages/server/utils"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"react",
|
|
16
|
+
"framework",
|
|
17
|
+
"modern",
|
|
18
|
+
"modern.js"
|
|
19
|
+
],
|
|
20
|
+
"version": "3.2.0-ultramodern.0",
|
|
21
|
+
"types": "./dist/types/index.d.ts",
|
|
22
|
+
"main": "./dist/cjs/index.js",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/types/index.d.ts",
|
|
26
|
+
"modern:source": "./src/index.ts",
|
|
27
|
+
"node": {
|
|
28
|
+
"import": "./dist/esm-node/index.mjs",
|
|
29
|
+
"require": "./dist/cjs/index.js"
|
|
30
|
+
},
|
|
31
|
+
"default": "./dist/cjs/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"typesVersions": {
|
|
35
|
+
"*": {
|
|
36
|
+
".": [
|
|
37
|
+
"./dist/types/index.d.ts"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@swc/helpers": "^0.5.21",
|
|
43
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.2.0-ultramodern.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@rslib/core": "0.21.5",
|
|
47
|
+
"@types/node": "^25.8.0",
|
|
48
|
+
"@typescript/native-preview": "7.0.0-dev.20260516.1",
|
|
49
|
+
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.2.0-ultramodern.0",
|
|
50
|
+
"@scripts/rstest-config": "2.66.0"
|
|
51
|
+
},
|
|
52
|
+
"sideEffects": false,
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"registry": "https://registry.npmjs.org/",
|
|
55
|
+
"access": "public"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"dev": "rslib build --watch",
|
|
59
|
+
"build": "rslib build && pnpm -w tsgo:dts \"$PWD\"",
|
|
60
|
+
"test": "rstest --passWithNoTests"
|
|
61
|
+
}
|
|
62
|
+
}
|
package/rslib.config.mts
ADDED