@reliverse/dler 1.2.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 +312 -0
- package/bin/cli/args/agg/main.js +0 -0
- package/bin/cli/args/conv/README.md +3 -0
- package/bin/cli/args/conv/main.js +0 -0
- package/bin/cli/args/deps/analyzer.js +42 -0
- package/bin/cli/args/deps/filesystem.js +42 -0
- package/bin/cli/args/deps/formatter.js +65 -0
- package/bin/cli/args/deps/mod.js +48 -0
- package/bin/cli/args/deps/parser.js +59 -0
- package/bin/cli/args/deps/types.js +0 -0
- package/bin/cli/args/init/README.md +121 -0
- package/bin/cli/args/init/libs/reinit/reinit-main.js +5 -0
- package/bin/cli/args/init/libs/reinit/reint-impl/const.js +26 -0
- package/bin/cli/args/init/libs/reinit/reint-impl/mod.txt +395 -0
- package/bin/cli/args/init/libs/reinit/reint-impl/templates/t-gitignore.js +9 -0
- package/bin/cli/args/init/libs/reinit/reint-impl/templates/t-license.js +22 -0
- package/bin/cli/args/init/libs/reinit/reint-impl/templates/t-readme.js +59 -0
- package/bin/cli/args/init/libs/reinit/reint-impl/types.js +0 -0
- package/bin/cli/args/init/libs/reinit/reint-impl/utils.js +3 -0
- package/bin/cli/args/init/main.txt +121 -0
- package/bin/cli/args/init/types.js +1 -0
- package/bin/cli/args/inject/README.md +148 -0
- package/bin/cli/args/inject/arg-ts-expect-error.txt +49 -0
- package/bin/cli/args/inject/cli-mod.js +32 -0
- package/bin/cli/args/inject/main.txt +28 -0
- package/bin/cli/args/inject/reinject.config.js +4 -0
- package/bin/cli/args/inject/ts-expect-error.txt +277 -0
- package/bin/cli/args/merger/README.md +125 -0
- package/bin/cli/args/merger/main.txt +306 -0
- package/bin/cli/args/mono/main.js +0 -0
- package/bin/cli/args/spells/mod.js +44 -0
- package/bin/cli/args/split/README.md +13 -0
- package/bin/cli/args/split/split-main.js +26 -0
- package/bin/cli/args/split/split-mod.js +117 -0
- package/bin/cli/args/tools/index.js +81 -0
- package/bin/cli/args/tools/tools-impl.js +296 -0
- package/bin/cli.js +111 -0
- package/bin/init.js +157 -0
- package/bin/libs/cfg/cfg-default.js +50 -0
- package/bin/libs/cfg/cfg-main.js +1 -0
- package/bin/libs/cfg/cfg-mod.js +4 -0
- package/bin/libs/cfg/cfg-types.js +1 -0
- package/bin/libs/sdk/sdk-impl/build/build-library.js +865 -0
- package/bin/libs/sdk/sdk-impl/build/build-regular.js +373 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/auto.js +110 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/build.js +322 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/copy/copy.js +62 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/copy/types.js +0 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/mkdist/mkdist.js +57 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/mkdist/types.js +0 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/build.js +104 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/config.js +124 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/plugins/cjs.js +48 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/plugins/esbuild.js +91 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/plugins/json.js +17 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/plugins/raw.js +20 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/plugins/shebang.js +42 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/stub.js +137 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/types.js +0 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/utils.js +41 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/rollup/watch.js +33 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/types.js +6 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/untyped/index.js +125 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/untyped/types.js +0 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/utils.js +158 -0
- package/bin/libs/sdk/sdk-impl/build/bundlers/unified/validate.js +68 -0
- package/bin/libs/sdk/sdk-impl/library-flow.js +169 -0
- package/bin/libs/sdk/sdk-impl/pub/pub-library.js +132 -0
- package/bin/libs/sdk/sdk-impl/pub/pub-regular.js +69 -0
- package/bin/libs/sdk/sdk-impl/regular-flow.js +219 -0
- package/bin/libs/sdk/sdk-impl/spells/spells-executors.js +307 -0
- package/bin/libs/sdk/sdk-impl/spells/spells-filesystem.js +72 -0
- package/bin/libs/sdk/sdk-impl/spells/spells-main.js +87 -0
- package/bin/libs/sdk/sdk-impl/spells/spells-parser.js +60 -0
- package/bin/libs/sdk/sdk-impl/spells/spells-types.js +0 -0
- package/bin/libs/sdk/sdk-impl/utils/tools/tools-agg.js +149 -0
- package/bin/libs/sdk/sdk-impl/utils/tools/tools-impl.js +21 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-build.js +102 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-bump.js +238 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-clean.js +35 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-consts.js +17 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-cwd.js +36 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-deps.js +73 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-determine.js +25 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-error.js +17 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-fs.js +202 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-info.js +42 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-jsr-json.js +51 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-paths.js +658 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-perf.js +22 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-pkg-json-libs.js +259 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-pkg-json-reg.js +207 -0
- package/bin/libs/sdk/sdk-impl/utils/utils-tsconfig.js +44 -0
- package/bin/libs/sdk/sdk-main.js +114 -0
- package/bin/libs/sdk/sdk-types.js +1 -0
- package/bin/load.js +27 -0
- package/bin/main.js +46 -0
- package/bin/tools.txt +92 -0
- package/bin/types.js +0 -0
- package/package.json +93 -0
|
@@ -0,0 +1,658 @@
|
|
|
1
|
+
import { relinka } from "@reliverse/relinka";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import MagicString from "magic-string";
|
|
4
|
+
import pMap from "p-map";
|
|
5
|
+
import path from "pathe";
|
|
6
|
+
import { CONCURRENCY_DEFAULT } from "./utils-consts.js";
|
|
7
|
+
const DEBUG_MODE = false;
|
|
8
|
+
const CWD = process.cwd();
|
|
9
|
+
const STATIC_IMPORT_REGEX = /(import|export)[\s\S]*?from\s+(['"])([^'"]+)\2/g;
|
|
10
|
+
const DYNAMIC_IMPORT_REGEX = /import\s*\(\s*(['"])([^'"]+)\1\s*\)/g;
|
|
11
|
+
const DEFAULT_FILE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"];
|
|
12
|
+
export function extractPackageName(importPath) {
|
|
13
|
+
if (!importPath || importPath.startsWith(".") || importPath.startsWith("/")) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const match = importPath.match(/^(@[^/]+\/[^/]+|[^/]+)/);
|
|
17
|
+
return match ? match[0] : null;
|
|
18
|
+
}
|
|
19
|
+
function normalizeAliasPrefix(prefix) {
|
|
20
|
+
return prefix.endsWith("/") ? prefix : `${prefix}/`;
|
|
21
|
+
}
|
|
22
|
+
function getBareImportUrl(importStr, requireFromKeyword = false) {
|
|
23
|
+
const regex = requireFromKeyword ? /from\s+(['"])(https?:\/\/[^'"]+)\1/ : /(['"])(https?:\/\/[^'"]+)\1/;
|
|
24
|
+
const match = regex.exec(importStr);
|
|
25
|
+
return match?.[2] ?? null;
|
|
26
|
+
}
|
|
27
|
+
function isLibraryImport(relativePathToRoot, libName, libConfig, currentLibName) {
|
|
28
|
+
if (currentLibName && libName === currentLibName) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const libMainDir = path.dirname(libConfig.libMainFile).replace(/\\/g, "/");
|
|
32
|
+
return relativePathToRoot.startsWith(`${libMainDir}/`);
|
|
33
|
+
}
|
|
34
|
+
function matchLibraryImport(relativeToRoot, libsList, currentLibName) {
|
|
35
|
+
for (const [libName, libConfig] of Object.entries(libsList)) {
|
|
36
|
+
if (libConfig?.libMainFile && isLibraryImport(relativeToRoot, libName, libConfig, currentLibName)) {
|
|
37
|
+
return libName;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
function replaceJsExtension(importPath) {
|
|
43
|
+
if (importPath.endsWith(".js")) {
|
|
44
|
+
return `${importPath.slice(0, -3)}.ts`;
|
|
45
|
+
}
|
|
46
|
+
return importPath;
|
|
47
|
+
}
|
|
48
|
+
function convertAbsoluteToAlias(ip, opts) {
|
|
49
|
+
const relativePath = path.relative(opts.baseDir, ip).replace(/\\/g, "/");
|
|
50
|
+
return `${opts.aliasPrefix}${relativePath}`;
|
|
51
|
+
}
|
|
52
|
+
function convertAbsoluteToBare(ip) {
|
|
53
|
+
relinka(
|
|
54
|
+
"warn",
|
|
55
|
+
`Ambiguous conversion: absolute:bare for ${ip}. Using path relative to CWD.`
|
|
56
|
+
);
|
|
57
|
+
return path.relative(CWD, ip).replace(/\\/g, "/");
|
|
58
|
+
}
|
|
59
|
+
function convertAbsoluteToModule(ip, opts) {
|
|
60
|
+
const relativeToRoot = path.relative(CWD, ip).replace(/\\/g, "/");
|
|
61
|
+
const libName = matchLibraryImport(
|
|
62
|
+
relativeToRoot,
|
|
63
|
+
opts.libsList,
|
|
64
|
+
opts.currentLibName
|
|
65
|
+
);
|
|
66
|
+
if (libName) {
|
|
67
|
+
relinka("verbose", `Converted absolute ${ip} to module ${libName}`);
|
|
68
|
+
return libName;
|
|
69
|
+
}
|
|
70
|
+
return ip;
|
|
71
|
+
}
|
|
72
|
+
function convertAbsoluteToRelative(ip, opts) {
|
|
73
|
+
let relativePath = path.relative(path.dirname(opts.sourceFile), ip).replace(/\\/g, "/");
|
|
74
|
+
if (!relativePath.startsWith(".") && !path.isAbsolute(relativePath)) {
|
|
75
|
+
relativePath = `./${relativePath}`;
|
|
76
|
+
}
|
|
77
|
+
return relativePath;
|
|
78
|
+
}
|
|
79
|
+
function convertAliasToAbsolute(ip, opts) {
|
|
80
|
+
if (!ip.startsWith(opts.aliasPrefix)) return ip;
|
|
81
|
+
const subPath = ip.slice(opts.aliasPrefix.length);
|
|
82
|
+
return path.resolve(opts.baseDir, subPath);
|
|
83
|
+
}
|
|
84
|
+
function convertAliasToBare(ip, opts) {
|
|
85
|
+
if (!ip.startsWith(opts.aliasPrefix)) return ip;
|
|
86
|
+
const absolutePath = convertAliasToAbsolute(ip, opts);
|
|
87
|
+
return convertAbsoluteToBare(absolutePath);
|
|
88
|
+
}
|
|
89
|
+
function convertAliasToModule(ip, opts) {
|
|
90
|
+
if (!ip.startsWith(opts.aliasPrefix)) return ip;
|
|
91
|
+
const absolutePath = convertAliasToAbsolute(ip, opts);
|
|
92
|
+
return convertAbsoluteToModule(absolutePath, opts);
|
|
93
|
+
}
|
|
94
|
+
function convertAliasToRelative(ip, opts) {
|
|
95
|
+
if (!ip.startsWith(opts.aliasPrefix)) return ip;
|
|
96
|
+
const absolutePath = convertAliasToAbsolute(ip, opts);
|
|
97
|
+
return convertAbsoluteToRelative(absolutePath, opts);
|
|
98
|
+
}
|
|
99
|
+
function convertBareToAbsolute(ip, opts) {
|
|
100
|
+
const url = getBareImportUrl(ip);
|
|
101
|
+
if (url && opts.urlMap[url]) {
|
|
102
|
+
const localPath = opts.urlMap[url];
|
|
103
|
+
relinka("verbose", `Mapping URL ${url} to local path ${localPath}`);
|
|
104
|
+
return path.resolve(CWD, localPath);
|
|
105
|
+
}
|
|
106
|
+
const packageName = extractPackageName(ip);
|
|
107
|
+
const libConfig = packageName ? opts.libsList[packageName] : void 0;
|
|
108
|
+
if (libConfig?.libMainFile) {
|
|
109
|
+
const libEntryPoint = path.resolve(CWD, libConfig.libMainFile);
|
|
110
|
+
relinka(
|
|
111
|
+
"verbose",
|
|
112
|
+
`Mapping package ${packageName} to absolute path ${libEntryPoint}`
|
|
113
|
+
);
|
|
114
|
+
return libEntryPoint;
|
|
115
|
+
}
|
|
116
|
+
relinka(
|
|
117
|
+
"verbose",
|
|
118
|
+
`Cannot convert bare import to absolute: ${ip}. No mapping found.`
|
|
119
|
+
);
|
|
120
|
+
return ip;
|
|
121
|
+
}
|
|
122
|
+
function convertBareToAlias(ip, opts) {
|
|
123
|
+
const absolutePath = convertBareToAbsolute(ip, opts);
|
|
124
|
+
if (absolutePath !== ip) {
|
|
125
|
+
return convertAbsoluteToAlias(absolutePath, opts);
|
|
126
|
+
}
|
|
127
|
+
return ip;
|
|
128
|
+
}
|
|
129
|
+
function convertBareToDynamic(ip) {
|
|
130
|
+
relinka(
|
|
131
|
+
"warn",
|
|
132
|
+
"bare:dynamic conversion requires special handling of the full import statement."
|
|
133
|
+
);
|
|
134
|
+
return ip;
|
|
135
|
+
}
|
|
136
|
+
function convertBareToModule(ip, opts) {
|
|
137
|
+
const url = getBareImportUrl(ip);
|
|
138
|
+
if (url && opts.urlMap[url]) {
|
|
139
|
+
const localPath = opts.urlMap[url];
|
|
140
|
+
const absolutePath = path.resolve(CWD, localPath);
|
|
141
|
+
return convertAbsoluteToModule(absolutePath, opts);
|
|
142
|
+
}
|
|
143
|
+
const packageName = extractPackageName(ip);
|
|
144
|
+
if (packageName && opts.libsList[packageName]) {
|
|
145
|
+
relinka("verbose", `Bare import ${packageName} is already a module.`);
|
|
146
|
+
return packageName;
|
|
147
|
+
}
|
|
148
|
+
return ip;
|
|
149
|
+
}
|
|
150
|
+
function convertBareToRelative(ip, opts) {
|
|
151
|
+
const absolutePath = convertBareToAbsolute(ip, opts);
|
|
152
|
+
if (absolutePath !== ip) {
|
|
153
|
+
return convertAbsoluteToRelative(absolutePath, opts);
|
|
154
|
+
}
|
|
155
|
+
return ip;
|
|
156
|
+
}
|
|
157
|
+
function convertDynamicToAbsolute(ip, opts) {
|
|
158
|
+
return path.resolve(path.dirname(opts.sourceFile), ip);
|
|
159
|
+
}
|
|
160
|
+
function convertDynamicToAlias(ip, opts) {
|
|
161
|
+
const absolutePath = convertDynamicToAbsolute(ip, opts);
|
|
162
|
+
return convertAbsoluteToAlias(absolutePath, opts);
|
|
163
|
+
}
|
|
164
|
+
function convertDynamicToBare(ip, opts) {
|
|
165
|
+
const absolutePath = convertDynamicToAbsolute(ip, opts);
|
|
166
|
+
return convertAbsoluteToBare(absolutePath);
|
|
167
|
+
}
|
|
168
|
+
function convertDynamicToModule(ip, opts) {
|
|
169
|
+
const absolutePath = convertDynamicToAbsolute(ip, opts);
|
|
170
|
+
return convertAbsoluteToModule(absolutePath, opts);
|
|
171
|
+
}
|
|
172
|
+
function convertDynamicToRelative(ip, opts) {
|
|
173
|
+
const absolutePath = convertDynamicToAbsolute(ip, opts);
|
|
174
|
+
return convertAbsoluteToRelative(absolutePath, opts);
|
|
175
|
+
}
|
|
176
|
+
function convertModuleToAbsolute(ip, opts) {
|
|
177
|
+
const packageName = extractPackageName(ip);
|
|
178
|
+
const libConfig = packageName ? opts.libsList[packageName] : void 0;
|
|
179
|
+
if (!libConfig?.libMainFile) return ip;
|
|
180
|
+
const libMainDir = path.dirname(path.resolve(CWD, libConfig.libMainFile));
|
|
181
|
+
relinka(
|
|
182
|
+
"verbose",
|
|
183
|
+
`Converted module ${packageName} to absolute path ${libMainDir}`
|
|
184
|
+
);
|
|
185
|
+
return libMainDir;
|
|
186
|
+
}
|
|
187
|
+
function convertModuleToAlias(ip, opts) {
|
|
188
|
+
const absolutePath = convertModuleToAbsolute(ip, opts);
|
|
189
|
+
if (absolutePath !== ip) {
|
|
190
|
+
return convertAbsoluteToAlias(absolutePath, opts);
|
|
191
|
+
}
|
|
192
|
+
return ip;
|
|
193
|
+
}
|
|
194
|
+
function convertModuleToBare(ip, opts) {
|
|
195
|
+
const absolutePath = convertModuleToAbsolute(ip, opts);
|
|
196
|
+
if (absolutePath !== ip) {
|
|
197
|
+
return convertAbsoluteToBare(absolutePath);
|
|
198
|
+
}
|
|
199
|
+
return ip;
|
|
200
|
+
}
|
|
201
|
+
function convertModuleToRelative(ip, opts) {
|
|
202
|
+
const absolutePath = convertModuleToAbsolute(ip, opts);
|
|
203
|
+
if (absolutePath !== ip) {
|
|
204
|
+
return convertAbsoluteToRelative(absolutePath, opts);
|
|
205
|
+
}
|
|
206
|
+
return ip;
|
|
207
|
+
}
|
|
208
|
+
function convertRelativeToAbsolute(ip, opts) {
|
|
209
|
+
return path.resolve(path.dirname(opts.sourceFile), ip);
|
|
210
|
+
}
|
|
211
|
+
function convertRelativeToAlias(ip, opts) {
|
|
212
|
+
const absolutePath = convertRelativeToAbsolute(ip, opts);
|
|
213
|
+
return convertAbsoluteToAlias(absolutePath, opts);
|
|
214
|
+
}
|
|
215
|
+
function convertRelativeToBare(ip, opts) {
|
|
216
|
+
const absolutePath = convertRelativeToAbsolute(ip, opts);
|
|
217
|
+
return convertAbsoluteToBare(absolutePath);
|
|
218
|
+
}
|
|
219
|
+
function convertRelativeToModule(ip, opts) {
|
|
220
|
+
const absolutePath = convertRelativeToAbsolute(ip, opts);
|
|
221
|
+
return convertAbsoluteToModule(absolutePath, opts);
|
|
222
|
+
}
|
|
223
|
+
const conversionMapping = {
|
|
224
|
+
// Route all conversions through the specific functions defined above.
|
|
225
|
+
// The `opts` object contains all necessary context.
|
|
226
|
+
"absolute:alias": convertAbsoluteToAlias,
|
|
227
|
+
"absolute:bare": convertAbsoluteToBare,
|
|
228
|
+
"absolute:module": convertAbsoluteToModule,
|
|
229
|
+
"absolute:relative": convertAbsoluteToRelative,
|
|
230
|
+
"alias:absolute": convertAliasToAbsolute,
|
|
231
|
+
// alias:alias is identity if prefix/base match (handled in dispatcher)
|
|
232
|
+
"alias:bare": convertAliasToBare,
|
|
233
|
+
"alias:module": convertAliasToModule,
|
|
234
|
+
"alias:relative": convertAliasToRelative,
|
|
235
|
+
"bare:absolute": convertBareToAbsolute,
|
|
236
|
+
"bare:alias": convertBareToAlias,
|
|
237
|
+
"bare:dynamic": convertBareToDynamic,
|
|
238
|
+
// Placeholder, logic elsewhere
|
|
239
|
+
"bare:module": convertBareToModule,
|
|
240
|
+
"bare:relative": convertBareToRelative,
|
|
241
|
+
"dynamic:absolute": convertDynamicToAbsolute,
|
|
242
|
+
"dynamic:alias": convertDynamicToAlias,
|
|
243
|
+
"dynamic:bare": convertDynamicToBare,
|
|
244
|
+
"dynamic:module": convertDynamicToModule,
|
|
245
|
+
"dynamic:relative": convertDynamicToRelative,
|
|
246
|
+
"module:absolute": convertModuleToAbsolute,
|
|
247
|
+
"module:alias": convertModuleToAlias,
|
|
248
|
+
"module:bare": convertModuleToBare,
|
|
249
|
+
"module:relative": convertModuleToRelative,
|
|
250
|
+
"relative:absolute": convertRelativeToAbsolute,
|
|
251
|
+
"relative:alias": convertRelativeToAlias,
|
|
252
|
+
"relative:bare": convertRelativeToBare,
|
|
253
|
+
"relative:module": convertRelativeToModule
|
|
254
|
+
};
|
|
255
|
+
function convertSingleImportPath(fromType, toType, importPath, options) {
|
|
256
|
+
const fullOptions = {
|
|
257
|
+
baseDir: options.baseDir ?? CWD,
|
|
258
|
+
// Default baseDir if not provided
|
|
259
|
+
libsList: options.libsList ?? {},
|
|
260
|
+
sourceFile: options.sourceFile,
|
|
261
|
+
urlMap: options.urlMap ?? {},
|
|
262
|
+
strip: options.strip ?? [],
|
|
263
|
+
currentLibName: options.currentLibName,
|
|
264
|
+
// Normalize alias prefix only if provided, default to empty string
|
|
265
|
+
aliasPrefix: options.aliasPrefix ? normalizeAliasPrefix(options.aliasPrefix) : ""
|
|
266
|
+
};
|
|
267
|
+
if (fromType === toType) {
|
|
268
|
+
return importPath;
|
|
269
|
+
}
|
|
270
|
+
const conversionKey = `${fromType}:${toType}`;
|
|
271
|
+
const converter = conversionMapping[conversionKey];
|
|
272
|
+
let convertedPath;
|
|
273
|
+
if (converter) {
|
|
274
|
+
convertedPath = converter(importPath, fullOptions);
|
|
275
|
+
} else {
|
|
276
|
+
relinka(
|
|
277
|
+
"verbose",
|
|
278
|
+
`No converter found for ${conversionKey} on path "${importPath}". Returning original.`
|
|
279
|
+
);
|
|
280
|
+
convertedPath = importPath;
|
|
281
|
+
}
|
|
282
|
+
if (fullOptions.strip.length > 0 && convertedPath !== importPath) {
|
|
283
|
+
let processedPath = convertedPath;
|
|
284
|
+
for (const stripSegment of fullOptions.strip) {
|
|
285
|
+
const normalizedStripSegment = stripSegment.endsWith("/") ? stripSegment : `${stripSegment}/`;
|
|
286
|
+
if (processedPath.startsWith(normalizedStripSegment)) {
|
|
287
|
+
processedPath = processedPath.slice(normalizedStripSegment.length);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
convertedPath = processedPath;
|
|
291
|
+
}
|
|
292
|
+
return convertedPath;
|
|
293
|
+
}
|
|
294
|
+
async function processFileContent(filePath, processLogic, options) {
|
|
295
|
+
const { distJsrDryRun = false, generateSourceMap = false } = options;
|
|
296
|
+
try {
|
|
297
|
+
const originalContent = await fs.readFile(filePath, "utf-8");
|
|
298
|
+
const s = new MagicString(originalContent);
|
|
299
|
+
const changesMade = await processLogic(originalContent, s);
|
|
300
|
+
if (!changesMade) {
|
|
301
|
+
return {
|
|
302
|
+
filePath,
|
|
303
|
+
message: `No changes needed for ${path.basename(filePath)}`,
|
|
304
|
+
success: true
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
const newContent = s.toString();
|
|
308
|
+
let map;
|
|
309
|
+
if (originalContent === newContent) {
|
|
310
|
+
return {
|
|
311
|
+
filePath,
|
|
312
|
+
message: `No effective changes for ${path.basename(filePath)}`,
|
|
313
|
+
success: true
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
if (generateSourceMap) {
|
|
317
|
+
map = s.generateMap({
|
|
318
|
+
file: `${path.basename(filePath)}.map`,
|
|
319
|
+
// Map file named relative to source
|
|
320
|
+
includeContent: true,
|
|
321
|
+
source: path.basename(filePath)
|
|
322
|
+
// Source file named relative to map
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
if (!distJsrDryRun) {
|
|
326
|
+
await fs.writeFile(filePath, newContent, "utf-8");
|
|
327
|
+
if (map) {
|
|
328
|
+
await fs.writeFile(`${filePath}.map`, map.toString(), "utf-8");
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
const message = `Processed ${path.basename(filePath)}${distJsrDryRun ? " (dry run)" : ""}${map ? " + sourcemap" : ""}`;
|
|
332
|
+
if (DEBUG_MODE || distJsrDryRun) {
|
|
333
|
+
relinka("verbose", message);
|
|
334
|
+
}
|
|
335
|
+
return { filePath, message, success: true };
|
|
336
|
+
} catch (error) {
|
|
337
|
+
const errorMessage = `Error processing file ${filePath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
338
|
+
relinka("error", errorMessage);
|
|
339
|
+
return { filePath, message: errorMessage, success: false };
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
async function processDirectoryRecursively(dirPath, fileExtensions, fileProcessor, concurrency) {
|
|
343
|
+
let results = [];
|
|
344
|
+
try {
|
|
345
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
346
|
+
const filesToProcess = [];
|
|
347
|
+
const directoriesToRecurse = [];
|
|
348
|
+
for (const entry of entries) {
|
|
349
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
350
|
+
if (entry.isFile()) {
|
|
351
|
+
if (fileExtensions.some((ext) => entry.name.endsWith(ext))) {
|
|
352
|
+
filesToProcess.push(fullPath);
|
|
353
|
+
}
|
|
354
|
+
} else if (entry.isDirectory()) {
|
|
355
|
+
if (entry.name !== "node_modules" && !entry.name.startsWith(".")) {
|
|
356
|
+
directoriesToRecurse.push(fullPath);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (filesToProcess.length > 0) {
|
|
361
|
+
const fileResults = await pMap(filesToProcess, fileProcessor, {
|
|
362
|
+
concurrency
|
|
363
|
+
});
|
|
364
|
+
results = results.concat(fileResults);
|
|
365
|
+
}
|
|
366
|
+
for (const subDirPath of directoriesToRecurse) {
|
|
367
|
+
const subDirResults = await processDirectoryRecursively(
|
|
368
|
+
subDirPath,
|
|
369
|
+
fileExtensions,
|
|
370
|
+
fileProcessor,
|
|
371
|
+
concurrency
|
|
372
|
+
);
|
|
373
|
+
results = results.concat(subDirResults);
|
|
374
|
+
}
|
|
375
|
+
} catch (error) {
|
|
376
|
+
const errorMessage = `Error reading directory ${dirPath}: ${error instanceof Error ? error.message : String(error)}`;
|
|
377
|
+
relinka("error", errorMessage);
|
|
378
|
+
}
|
|
379
|
+
return results;
|
|
380
|
+
}
|
|
381
|
+
async function transformImportPathsLogic(content, s, options) {
|
|
382
|
+
let changesMade = false;
|
|
383
|
+
const { fromType, toType, filePath, ...conversionArgs } = options;
|
|
384
|
+
const converterOptions = {
|
|
385
|
+
...conversionArgs,
|
|
386
|
+
sourceFile: filePath,
|
|
387
|
+
// Pass the absolute file path
|
|
388
|
+
strip: conversionArgs.strip ?? [],
|
|
389
|
+
// Provide default empty array
|
|
390
|
+
urlMap: conversionArgs.urlMap ?? {}
|
|
391
|
+
// Provide default empty object
|
|
392
|
+
};
|
|
393
|
+
for (const match of content.matchAll(STATIC_IMPORT_REGEX)) {
|
|
394
|
+
const fullMatch = match[0];
|
|
395
|
+
const importPath = match[3];
|
|
396
|
+
if (typeof match.index !== "number" || !importPath) continue;
|
|
397
|
+
const quoteChar = match[2];
|
|
398
|
+
const pathStartIndex = match.index + fullMatch.lastIndexOf(importPath) - 1;
|
|
399
|
+
const pathEndIndex = pathStartIndex + importPath.length + 2;
|
|
400
|
+
const bareUrl = getBareImportUrl(
|
|
401
|
+
fullMatch,
|
|
402
|
+
true
|
|
403
|
+
/* require 'from' */
|
|
404
|
+
);
|
|
405
|
+
if (fromType === "bare" && toType === "dynamic" && bareUrl) {
|
|
406
|
+
const localPath = converterOptions.urlMap?.[bareUrl];
|
|
407
|
+
if (localPath) {
|
|
408
|
+
const dynamicImportStatement = `await import(${quoteChar}${localPath}${quoteChar})`;
|
|
409
|
+
const fromIndex = fullMatch.toLowerCase().lastIndexOf(" from ");
|
|
410
|
+
if (fromIndex > 0) {
|
|
411
|
+
const replacementStart = match.index + fromIndex;
|
|
412
|
+
const replacementEnd = match.index + fullMatch.length;
|
|
413
|
+
s.overwrite(
|
|
414
|
+
replacementStart,
|
|
415
|
+
replacementEnd,
|
|
416
|
+
` = ${dynamicImportStatement}`
|
|
417
|
+
);
|
|
418
|
+
changesMade = true;
|
|
419
|
+
if (DEBUG_MODE)
|
|
420
|
+
relinka(
|
|
421
|
+
"verbose",
|
|
422
|
+
`Converted bare URL import to dynamic: ${bareUrl} -> ${localPath}`
|
|
423
|
+
);
|
|
424
|
+
} else {
|
|
425
|
+
relinka(
|
|
426
|
+
"warn",
|
|
427
|
+
`Could not find ' from ' in statement for bare:dynamic conversion: ${fullMatch}`
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
} else {
|
|
431
|
+
relinka(
|
|
432
|
+
"verbose",
|
|
433
|
+
`No local mapping found for URL: ${bareUrl} in bare:dynamic conversion.`
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
const convertedPath = convertSingleImportPath(
|
|
439
|
+
fromType,
|
|
440
|
+
toType,
|
|
441
|
+
importPath,
|
|
442
|
+
converterOptions
|
|
443
|
+
);
|
|
444
|
+
if (convertedPath !== importPath) {
|
|
445
|
+
s.overwrite(pathStartIndex + 1, pathEndIndex - 1, convertedPath);
|
|
446
|
+
changesMade = true;
|
|
447
|
+
if (DEBUG_MODE)
|
|
448
|
+
relinka(
|
|
449
|
+
"verbose",
|
|
450
|
+
`Converted path: ${importPath} -> ${convertedPath} (${fromType} -> ${toType})`
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
const dynamicImportRegexLocal = new RegExp(DYNAMIC_IMPORT_REGEX.source, "g");
|
|
455
|
+
for (const match of content.matchAll(dynamicImportRegexLocal)) {
|
|
456
|
+
const fullMatch = match[0];
|
|
457
|
+
const importPath = match[2];
|
|
458
|
+
if (typeof match.index !== "number" || !importPath) continue;
|
|
459
|
+
const quoteChar = match[1];
|
|
460
|
+
const pathStartIndex = match.index + fullMatch.indexOf(quoteChar + importPath + quoteChar) + 1;
|
|
461
|
+
const pathEndIndex = pathStartIndex + importPath.length;
|
|
462
|
+
const effectiveFromType = fromType === "dynamic" ? "dynamic" : fromType;
|
|
463
|
+
const convertedPath = convertSingleImportPath(
|
|
464
|
+
effectiveFromType,
|
|
465
|
+
// Use determined 'from' type
|
|
466
|
+
toType,
|
|
467
|
+
importPath,
|
|
468
|
+
// The path string from inside import()
|
|
469
|
+
converterOptions
|
|
470
|
+
);
|
|
471
|
+
if (convertedPath !== importPath) {
|
|
472
|
+
s.overwrite(pathStartIndex, pathEndIndex, convertedPath);
|
|
473
|
+
changesMade = true;
|
|
474
|
+
if (DEBUG_MODE)
|
|
475
|
+
relinka(
|
|
476
|
+
"verbose",
|
|
477
|
+
`Converted dynamic path: ${importPath} -> ${convertedPath} (${effectiveFromType} -> ${toType})`
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return changesMade;
|
|
482
|
+
}
|
|
483
|
+
async function transformJsToTsExtensionLogic(content, s) {
|
|
484
|
+
let changesMade = false;
|
|
485
|
+
const processMatches = (regex, pathGroupIndex) => {
|
|
486
|
+
const localRegex = new RegExp(
|
|
487
|
+
regex.source,
|
|
488
|
+
regex.flags.includes("g") ? regex.flags : `${regex.flags}g`
|
|
489
|
+
);
|
|
490
|
+
for (const match of content.matchAll(localRegex)) {
|
|
491
|
+
const fullMatch = match[0];
|
|
492
|
+
const importPath = match[pathGroupIndex];
|
|
493
|
+
if (typeof match.index !== "number" || !importPath) continue;
|
|
494
|
+
const replacedPath = replaceJsExtension(importPath);
|
|
495
|
+
if (replacedPath !== importPath) {
|
|
496
|
+
const quoteChar = match[pathGroupIndex - 1];
|
|
497
|
+
const pathStartIndex = match.index + fullMatch.lastIndexOf(quoteChar + importPath + quoteChar) + 1;
|
|
498
|
+
const pathEndIndex = pathStartIndex + importPath.length;
|
|
499
|
+
s.overwrite(pathStartIndex, pathEndIndex, replacedPath);
|
|
500
|
+
changesMade = true;
|
|
501
|
+
if (DEBUG_MODE)
|
|
502
|
+
relinka(
|
|
503
|
+
"verbose",
|
|
504
|
+
`Changed extension: ${importPath} -> ${replacedPath}`
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
processMatches(STATIC_IMPORT_REGEX, 3);
|
|
510
|
+
processMatches(DYNAMIC_IMPORT_REGEX, 2);
|
|
511
|
+
return changesMade;
|
|
512
|
+
}
|
|
513
|
+
export async function convertImportPaths(options) {
|
|
514
|
+
const {
|
|
515
|
+
baseDir: rawBaseDir,
|
|
516
|
+
fromType,
|
|
517
|
+
toType,
|
|
518
|
+
libsList,
|
|
519
|
+
aliasPrefix: rawAliasPrefix,
|
|
520
|
+
currentLibName,
|
|
521
|
+
distJsrDryRun = false,
|
|
522
|
+
fileExtensions = DEFAULT_FILE_EXTENSIONS,
|
|
523
|
+
generateSourceMap = false,
|
|
524
|
+
strip = [],
|
|
525
|
+
urlMap = {}
|
|
526
|
+
} = options;
|
|
527
|
+
if (!rawBaseDir) {
|
|
528
|
+
throw new Error("`baseDir` option is required.");
|
|
529
|
+
}
|
|
530
|
+
const baseDir = path.resolve(CWD, rawBaseDir);
|
|
531
|
+
if ((fromType === "alias" || toType === "alias") && !rawAliasPrefix) {
|
|
532
|
+
throw new Error(
|
|
533
|
+
"`aliasPrefix` is required when converting from/to 'alias' type."
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
try {
|
|
537
|
+
const stats = await fs.stat(baseDir);
|
|
538
|
+
if (!stats.isDirectory()) {
|
|
539
|
+
throw new Error(`Specified baseDir is not a directory: ${baseDir}`);
|
|
540
|
+
}
|
|
541
|
+
} catch (error) {
|
|
542
|
+
if (error instanceof Error && error.code === "ENOENT") {
|
|
543
|
+
throw new Error(`Specified baseDir does not exist: ${baseDir}`);
|
|
544
|
+
}
|
|
545
|
+
throw error;
|
|
546
|
+
}
|
|
547
|
+
relinka(
|
|
548
|
+
"info",
|
|
549
|
+
`Starting import path conversion (${fromType} -> ${toType}) in directory: ${baseDir}`
|
|
550
|
+
);
|
|
551
|
+
if (distJsrDryRun) {
|
|
552
|
+
relinka("info", "Dry run mode enabled: No files will be modified.");
|
|
553
|
+
}
|
|
554
|
+
const fileProcessor = async (filePath) => {
|
|
555
|
+
return processFileContent(
|
|
556
|
+
filePath,
|
|
557
|
+
(content, s) => transformImportPathsLogic(content, s, {
|
|
558
|
+
// Pass necessary context for the transformation
|
|
559
|
+
fromType,
|
|
560
|
+
toType,
|
|
561
|
+
filePath,
|
|
562
|
+
// Pass the absolute file path
|
|
563
|
+
aliasPrefix: rawAliasPrefix,
|
|
564
|
+
// Pass raw prefix, normalization happens inside
|
|
565
|
+
baseDir,
|
|
566
|
+
// Pass the resolved absolute baseDir
|
|
567
|
+
currentLibName,
|
|
568
|
+
libsList,
|
|
569
|
+
strip,
|
|
570
|
+
urlMap
|
|
571
|
+
}),
|
|
572
|
+
{ distJsrDryRun, generateSourceMap }
|
|
573
|
+
// Pass options for file writing
|
|
574
|
+
);
|
|
575
|
+
};
|
|
576
|
+
const results = await processDirectoryRecursively(
|
|
577
|
+
baseDir,
|
|
578
|
+
fileExtensions,
|
|
579
|
+
fileProcessor,
|
|
580
|
+
CONCURRENCY_DEFAULT
|
|
581
|
+
);
|
|
582
|
+
const successCount = results.filter((r) => r.success).length;
|
|
583
|
+
const changedCount = results.filter(
|
|
584
|
+
(r) => r.message.startsWith("Processed")
|
|
585
|
+
).length;
|
|
586
|
+
const errorResults = results.filter((r) => !r.success);
|
|
587
|
+
relinka(
|
|
588
|
+
"info",
|
|
589
|
+
`Import path conversion finished. ${successCount} files processed successfully (${changedCount} modified), ${errorResults.length} errors.`
|
|
590
|
+
);
|
|
591
|
+
for (const result of errorResults) {
|
|
592
|
+
relinka("error", result.message);
|
|
593
|
+
}
|
|
594
|
+
return results;
|
|
595
|
+
}
|
|
596
|
+
export async function convertImportExtensionsJsToTs(options) {
|
|
597
|
+
const {
|
|
598
|
+
dirPath: rawDirPath,
|
|
599
|
+
distJsrDryRun = false,
|
|
600
|
+
fileExtensions = DEFAULT_FILE_EXTENSIONS,
|
|
601
|
+
generateSourceMap = false
|
|
602
|
+
} = options;
|
|
603
|
+
if (!rawDirPath) {
|
|
604
|
+
throw new Error("`dirPath` option is required.");
|
|
605
|
+
}
|
|
606
|
+
const absoluteDirPath = path.resolve(CWD, rawDirPath);
|
|
607
|
+
try {
|
|
608
|
+
const stats = await fs.stat(absoluteDirPath);
|
|
609
|
+
if (!stats.isDirectory()) {
|
|
610
|
+
throw new Error(
|
|
611
|
+
`Specified dirPath is not a directory: ${absoluteDirPath}`
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
} catch (error) {
|
|
615
|
+
if (error instanceof Error && error.code === "ENOENT") {
|
|
616
|
+
throw new Error(`Specified dirPath does not exist: ${absoluteDirPath}`);
|
|
617
|
+
}
|
|
618
|
+
throw error;
|
|
619
|
+
}
|
|
620
|
+
relinka(
|
|
621
|
+
"info",
|
|
622
|
+
`Starting .js -> .ts import extension conversion in directory: ${absoluteDirPath}`
|
|
623
|
+
);
|
|
624
|
+
if (distJsrDryRun) {
|
|
625
|
+
relinka("info", "Dry run mode enabled: No files will be modified.");
|
|
626
|
+
}
|
|
627
|
+
const fileProcessor = async (filePath) => {
|
|
628
|
+
return processFileContent(
|
|
629
|
+
filePath,
|
|
630
|
+
transformJsToTsExtensionLogic,
|
|
631
|
+
// Pass the dedicated logic function
|
|
632
|
+
{ distJsrDryRun, generateSourceMap }
|
|
633
|
+
// Pass options for file writing
|
|
634
|
+
);
|
|
635
|
+
};
|
|
636
|
+
const results = await processDirectoryRecursively(
|
|
637
|
+
absoluteDirPath,
|
|
638
|
+
fileExtensions,
|
|
639
|
+
fileProcessor,
|
|
640
|
+
CONCURRENCY_DEFAULT
|
|
641
|
+
);
|
|
642
|
+
const successCount = results.filter((r) => r.success).length;
|
|
643
|
+
const changedCount = results.filter(
|
|
644
|
+
(r) => r.message.startsWith("Processed")
|
|
645
|
+
).length;
|
|
646
|
+
const errorResults = results.filter((r) => !r.success);
|
|
647
|
+
relinka(
|
|
648
|
+
"info",
|
|
649
|
+
`Extension conversion finished. ${successCount} files processed successfully (${changedCount} modified), ${errorResults.length} errors.`
|
|
650
|
+
);
|
|
651
|
+
for (const result of errorResults) {
|
|
652
|
+
relinka("error", result.message);
|
|
653
|
+
}
|
|
654
|
+
return results;
|
|
655
|
+
}
|
|
656
|
+
export function normalizeQuotes(str) {
|
|
657
|
+
return str.replace(/['"]/g, '"');
|
|
658
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function createPerfTimer() {
|
|
2
|
+
return {
|
|
3
|
+
pausedAt: null,
|
|
4
|
+
pausedDuration: 0,
|
|
5
|
+
startTime: performance.now()
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export function getElapsedPerfTime(timer) {
|
|
9
|
+
const currentPausedTime = timer.pausedAt !== null ? performance.now() - timer.pausedAt : 0;
|
|
10
|
+
return performance.now() - timer.startTime - timer.pausedDuration - currentPausedTime;
|
|
11
|
+
}
|
|
12
|
+
export function pausePerfTimer(timer) {
|
|
13
|
+
if (timer.pausedAt === null) {
|
|
14
|
+
timer.pausedAt = performance.now();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function resumePerfTimer(timer) {
|
|
18
|
+
if (timer.pausedAt !== null) {
|
|
19
|
+
timer.pausedDuration += performance.now() - timer.pausedAt;
|
|
20
|
+
timer.pausedAt = null;
|
|
21
|
+
}
|
|
22
|
+
}
|