@reckona/mreact-router 0.0.86 → 0.0.88
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/bundle-pipeline.d.ts +1 -0
- package/dist/bundle-pipeline.d.ts.map +1 -1
- package/dist/bundle-pipeline.js +115 -6
- package/dist/bundle-pipeline.js.map +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +81 -20
- package/dist/client.js.map +1 -1
- package/dist/module-runner.d.ts +4 -0
- package/dist/module-runner.d.ts.map +1 -1
- package/dist/module-runner.js +448 -14
- package/dist/module-runner.js.map +1 -1
- package/dist/render.d.ts +1 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +37 -5
- package/dist/render.js.map +1 -1
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +32 -20
- package/dist/vite.js.map +1 -1
- package/package.json +11 -11
- package/src/bundle-pipeline.ts +157 -24
- package/src/client.ts +91 -37
- package/src/module-runner.ts +587 -16
- package/src/render.ts +76 -30
- package/src/vite.ts +47 -37
package/dist/module-runner.d.ts
CHANGED
|
@@ -8,7 +8,9 @@ export declare function routerModuleRunnerRuntimeCacheStats(): RouterRuntimeCach
|
|
|
8
8
|
export declare function importAppRouterSourceModule<T>(options: {
|
|
9
9
|
cacheKey?: string | undefined;
|
|
10
10
|
code: string;
|
|
11
|
+
externalizeAppSourceModuleDirs?: readonly string[] | undefined;
|
|
11
12
|
label: string;
|
|
13
|
+
plugins?: readonly RouterCompatPlugin[] | undefined;
|
|
12
14
|
resolveDir?: string | undefined;
|
|
13
15
|
serverSourceTransform?: ServerSourceTransformOptions | undefined;
|
|
14
16
|
sourcefile?: string | undefined;
|
|
@@ -21,7 +23,9 @@ export declare function importAppRouterBuiltFileModule<T>(options: {
|
|
|
21
23
|
}): Promise<T>;
|
|
22
24
|
export declare function bundleAppRouterSourceModule(options: {
|
|
23
25
|
code: string;
|
|
26
|
+
externalizeAppSourceModuleDirs?: readonly string[] | undefined;
|
|
24
27
|
label: string;
|
|
28
|
+
plugins?: readonly RouterCompatPlugin[] | undefined;
|
|
25
29
|
resolveDir?: string | undefined;
|
|
26
30
|
serverSourceTransform?: ServerSourceTransformOptions | undefined;
|
|
27
31
|
sourcefile?: string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-runner.d.ts","sourceRoot":"","sources":["../src/module-runner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"module-runner.d.ts","sourceRoot":"","sources":["../src/module-runner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAEjF,OAAO,EAKL,KAAK,YAAY,EAElB,MAAM,MAAM,CAAC;AAEd,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAKL,KAAK,sBAAsB,EAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAKL,KAAK,yBAAyB,EAC/B,MAAM,6BAA6B,CAAC;AA0BrC,wBAAgB,mCAAmC,IAAI,sBAAsB,EAAE,CAe9E;AAED,wBAAsB,2BAA2B,CAAC,CAAC,EAAE,OAAO,EAAE;IAC5D,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,SAAS,kBAAkB,EAAE,GAAG,SAAS,CAAC;IACpD,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,qBAAqB,CAAC,EAAE,4BAA4B,GAAG,SAAS,CAAC;IACjE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,WAAW,CAAC,EAAE,SAAS,YAAY,EAAE,GAAG,SAAS,CAAC;CACnD,GAAG,OAAO,CAAC,CAAC,CAAC,CA6Bb;AAiCD,wBAAsB,yBAAyB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAK3E;AAgFD,wBAAsB,8BAA8B,CAAC,CAAC,EAAE,OAAO,EAAE;IAC/D,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,CAAC,CAAC,CA6Bb;AAED,wBAAsB,2BAA2B,CAAC,OAAO,EAAE;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,SAAS,kBAAkB,EAAE,GAAG,SAAS,CAAC;IACpD,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,qBAAqB,CAAC,EAAE,4BAA4B,GAAG,SAAS,CAAC;IACjE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,WAAW,CAAC,EAAE,SAAS,YAAY,EAAE,GAAG,SAAS,CAAC;CACnD,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBlB;AAED,wBAAgB,uBAAuB,IAAI,kBAAkB,CAwB5D;AAED,UAAU,4BAA4B;IACpC,yBAAyB,CAAC,EAAE,yBAAyB,GAAG,SAAS,CAAC;IAClE,GAAG,EAAE,OAAO,CAAC;IACb,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,SAAS,CAAC;IAC3E,YAAY,EAAE,gBAAgB,CAAC;IAC/B,WAAW,CAAC,EAAE,SAAS,YAAY,EAAE,GAAG,SAAS,CAAC;CACnD"}
|
package/dist/module-runner.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
3
|
import { readFile } from "node:fs/promises";
|
|
3
|
-
import { dirname, join, sep } from "node:path";
|
|
4
|
+
import { dirname, extname, isAbsolute, join, sep } from "node:path";
|
|
4
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
6
|
import { formatDiagnostic } from "@reckona/mreact-compiler";
|
|
6
7
|
import { transformCompilerModuleContext } from "@reckona/mreact-compiler/internal";
|
|
7
|
-
import {
|
|
8
|
+
import { createRunnableDevEnvironment, mergeConfig, resolveConfig, } from "vite";
|
|
8
9
|
import { resolveWorkspacePackageFile } from "./workspace-packages.js";
|
|
9
10
|
import { bundleRouterModule, } from "./bundle-pipeline.js";
|
|
10
11
|
import { resolveRouterCacheLimit } from "./cache-config.js";
|
|
@@ -25,6 +26,10 @@ const sourceModuleCacheCounters = createRouterRuntimeCacheCounters();
|
|
|
25
26
|
const serverSourceTransformCache = new Map();
|
|
26
27
|
const maxServerSourceTransformCacheEntries = resolveRouterCacheLimit("SERVER_SOURCE_TRANSFORM", 512);
|
|
27
28
|
const serverSourceTransformCacheCounters = createRouterRuntimeCacheCounters();
|
|
29
|
+
const packageTypeCache = new Map();
|
|
30
|
+
const runnerVirtualModulePrefix = "virtual:mreact-router-source/";
|
|
31
|
+
const runnerVirtualModules = new Map();
|
|
32
|
+
let sharedRunnerEnvironment;
|
|
28
33
|
let fileImportVersion = 0;
|
|
29
34
|
export function routerModuleRunnerRuntimeCacheStats() {
|
|
30
35
|
return [
|
|
@@ -50,21 +55,88 @@ export async function importAppRouterSourceModule(options) {
|
|
|
50
55
|
}
|
|
51
56
|
async function importAppRouterSourceModuleWithoutCache(options) {
|
|
52
57
|
const code = options.resolveDir === undefined ? options.code : await bundleAppRouterSourceModule(options);
|
|
58
|
+
const sourcefile = options.sourcefile ?? join(options.resolveDir ?? process.cwd(), "module.js");
|
|
53
59
|
const executableCode = withNodeRequireShimForEsmBundle({
|
|
54
|
-
code,
|
|
60
|
+
code: withFileImportMetaUrl(code, sourcefile),
|
|
61
|
+
filename: sourcefile,
|
|
55
62
|
requireBaseDir: options.resolveDir ??
|
|
56
63
|
(options.sourcefile === undefined ? undefined : dirname(options.sourcefile)),
|
|
57
64
|
});
|
|
58
65
|
const encodedLabel = encodeURIComponent(options.label.replace(/[^A-Za-z0-9_$.-]/g, "-"));
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
const publicId = `${runnerVirtualModulePrefix}${encodedLabel}-${Date.now()}-${Math.random()}.mjs`;
|
|
67
|
+
runnerVirtualModules.set(publicId, executableCode);
|
|
68
|
+
try {
|
|
69
|
+
return await importWithSharedRunner(publicId, { invalidateEntry: true });
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
runnerVirtualModules.delete(publicId);
|
|
73
|
+
}
|
|
62
74
|
}
|
|
63
75
|
export async function importAppRouterFileModule(file) {
|
|
64
76
|
fileImportVersion += 1;
|
|
65
77
|
const url = `${pathToFileURL(file).href}?t=${Date.now()}${fileImportVersion}`;
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
return await importWithSharedRunner(url, { invalidateEntry: true });
|
|
79
|
+
}
|
|
80
|
+
async function importWithSharedRunner(moduleId, options) {
|
|
81
|
+
const environment = await getSharedRunnerEnvironment();
|
|
82
|
+
const module = (await environment.runner.import(moduleId));
|
|
83
|
+
if (options?.invalidateEntry === true) {
|
|
84
|
+
const evaluatedModule = environment.runner.evaluatedModules.getModuleByUrl(moduleId) ??
|
|
85
|
+
environment.runner.evaluatedModules.getModuleById(moduleId) ??
|
|
86
|
+
environment.runner.evaluatedModules.getModuleById(`\0${moduleId}`);
|
|
87
|
+
if (evaluatedModule !== undefined) {
|
|
88
|
+
environment.runner.evaluatedModules.invalidateModule(evaluatedModule);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return module;
|
|
92
|
+
}
|
|
93
|
+
async function getSharedRunnerEnvironment() {
|
|
94
|
+
if (sharedRunnerEnvironment !== undefined) {
|
|
95
|
+
return await sharedRunnerEnvironment;
|
|
96
|
+
}
|
|
97
|
+
sharedRunnerEnvironment = createSharedRunnerEnvironment().catch((error) => {
|
|
98
|
+
sharedRunnerEnvironment = undefined;
|
|
99
|
+
throw error;
|
|
100
|
+
});
|
|
101
|
+
return await sharedRunnerEnvironment;
|
|
102
|
+
}
|
|
103
|
+
async function createSharedRunnerEnvironment() {
|
|
104
|
+
const config = await resolveConfig(mergeConfig(runnerConfig, {
|
|
105
|
+
cacheDir: process.cwd(),
|
|
106
|
+
configFile: false,
|
|
107
|
+
envDir: false,
|
|
108
|
+
environments: {
|
|
109
|
+
mreact_router: {
|
|
110
|
+
consumer: "server",
|
|
111
|
+
dev: { moduleRunnerTransform: true },
|
|
112
|
+
resolve: {
|
|
113
|
+
conditions: ["node"],
|
|
114
|
+
external: true,
|
|
115
|
+
mainFields: [],
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
plugins: [
|
|
120
|
+
{
|
|
121
|
+
name: "mreact-router-source-module",
|
|
122
|
+
resolveId(source) {
|
|
123
|
+
return runnerVirtualModules.has(source) ? `\0${source}` : undefined;
|
|
124
|
+
},
|
|
125
|
+
load(id) {
|
|
126
|
+
const source = id.startsWith("\0") ? id.slice(1) : id;
|
|
127
|
+
return source.startsWith(runnerVirtualModulePrefix)
|
|
128
|
+
? runnerVirtualModules.get(source)
|
|
129
|
+
: undefined;
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
}), "serve");
|
|
134
|
+
const environment = createRunnableDevEnvironment("mreact_router", config, {
|
|
135
|
+
hot: false,
|
|
136
|
+
runnerOptions: { hmr: { logger: false } },
|
|
137
|
+
});
|
|
138
|
+
await environment.init();
|
|
139
|
+
return environment;
|
|
68
140
|
}
|
|
69
141
|
export async function importAppRouterBuiltFileModule(options) {
|
|
70
142
|
if (options.cacheKey !== undefined) {
|
|
@@ -85,6 +157,7 @@ export async function importAppRouterBuiltFileModule(options) {
|
|
|
85
157
|
export async function bundleAppRouterSourceModule(options) {
|
|
86
158
|
const output = await bundleRouterModule({
|
|
87
159
|
code: options.code,
|
|
160
|
+
externalizeAppSourceModuleDirs: options.externalizeAppSourceModuleDirs,
|
|
88
161
|
filename: options.sourcefile ?? join(options.resolveDir ?? process.cwd(), "module.js"),
|
|
89
162
|
platform: "node",
|
|
90
163
|
vitePlugins: options.vitePlugins,
|
|
@@ -93,6 +166,7 @@ export async function bundleAppRouterSourceModule(options) {
|
|
|
93
166
|
...(options.serverSourceTransform === undefined
|
|
94
167
|
? []
|
|
95
168
|
: [serverSourceTransformPlugin(options.serverSourceTransform)]),
|
|
169
|
+
...(options.plugins ?? []),
|
|
96
170
|
],
|
|
97
171
|
});
|
|
98
172
|
const code = output.code;
|
|
@@ -208,17 +282,349 @@ function withFileImportMetaUrl(source, filename) {
|
|
|
208
282
|
}
|
|
209
283
|
function withNodeRequireShimForEsmBundle(options) {
|
|
210
284
|
const requireBaseUrl = pathToFileURL(join(options.requireBaseDir ?? process.cwd(), "__mreact_require_shim.cjs")).href;
|
|
211
|
-
const
|
|
212
|
-
|
|
285
|
+
const rewritten = rewriteNodeModulesExternalImports(options.code);
|
|
286
|
+
const code = rewritten.code.replaceAll("createRequire(import.meta.url)", `createRequire(${JSON.stringify(requireBaseUrl)})`);
|
|
287
|
+
const needsFilenameGlobalShim = needsCommonJsFilenameGlobalShim(options.code);
|
|
288
|
+
const needsRequireShim = needsNodeRequireShim(options.code);
|
|
289
|
+
if (!rewritten.needsNativeImport &&
|
|
290
|
+
!rewritten.needsRequire &&
|
|
291
|
+
!needsFilenameGlobalShim &&
|
|
292
|
+
!needsRequireShim) {
|
|
213
293
|
return code;
|
|
214
294
|
}
|
|
215
|
-
return
|
|
216
|
-
const
|
|
217
|
-
${
|
|
295
|
+
return `${rewritten.needsNativeImport ? 'const __mreactNativeImport = Function("specifier", "return import(specifier)");\n' : ""}${needsFilenameGlobalShim ? `const __filename = ${JSON.stringify(options.filename)};
|
|
296
|
+
const __dirname = ${JSON.stringify(dirname(options.filename))};
|
|
297
|
+
` : ""}${rewritten.needsRequire || needsRequireShim ? `import { createRequire as __mreactCreateRequire } from "node:module";
|
|
298
|
+
const __mreactRequire = __mreactCreateRequire(${JSON.stringify(requireBaseUrl)});
|
|
299
|
+
const require = __mreactRequire;
|
|
300
|
+
` : ""}${code}`;
|
|
301
|
+
}
|
|
302
|
+
function needsCommonJsFilenameGlobalShim(code) {
|
|
303
|
+
return /\b__(?:filename|dirname)\b/.test(code);
|
|
218
304
|
}
|
|
219
305
|
function needsNodeRequireShim(code) {
|
|
220
306
|
return code.includes("Dynamic require of") && /\b__require\s*=/.test(code);
|
|
221
307
|
}
|
|
308
|
+
function rewriteNodeModulesExternalImports(code) {
|
|
309
|
+
const nativeImportBindings = new Map();
|
|
310
|
+
let needsNativeImport = false;
|
|
311
|
+
let needsRequire = false;
|
|
312
|
+
let importIndex = 0;
|
|
313
|
+
const importFromPattern = /^import\s+([^;\n]+?)\s+from\s+(["'])([^"']+)\2;?$/gm;
|
|
314
|
+
const sideEffectImportPattern = /^import\s+(["'])([^"']+)\1;?$/gm;
|
|
315
|
+
const withRewrittenImports = code.replace(importFromPattern, (statement, clause, _quote, specifier) => {
|
|
316
|
+
const file = nodeModulesExternalImportPath(specifier);
|
|
317
|
+
if (file === undefined || !isNodeImportableModuleFile(file)) {
|
|
318
|
+
return statement;
|
|
319
|
+
}
|
|
320
|
+
if (isNodeCommonJsModuleFile(file)) {
|
|
321
|
+
needsRequire = true;
|
|
322
|
+
const requireExpression = `__mreactRequire(${JSON.stringify(file)})`;
|
|
323
|
+
return commonJsImportClauseToRequireStatements(clause.trim(), requireExpression, importIndex++);
|
|
324
|
+
}
|
|
325
|
+
needsNativeImport = true;
|
|
326
|
+
const rewritten = esmImportClauseToNativeImportStatements(clause.trim(), specifier, importIndex++);
|
|
327
|
+
for (const [name, replacement] of rewritten.bindings) {
|
|
328
|
+
nativeImportBindings.set(name, replacement);
|
|
329
|
+
}
|
|
330
|
+
return rewritten.code;
|
|
331
|
+
});
|
|
332
|
+
const rewrittenCode = withRewrittenImports.replace(sideEffectImportPattern, (statement, _quote, specifier) => {
|
|
333
|
+
const file = nodeModulesExternalImportPath(specifier);
|
|
334
|
+
if (file === undefined || !isNodeImportableModuleFile(file)) {
|
|
335
|
+
return statement;
|
|
336
|
+
}
|
|
337
|
+
if (isNodeCommonJsModuleFile(file)) {
|
|
338
|
+
needsRequire = true;
|
|
339
|
+
return `__mreactRequire(${JSON.stringify(file)});`;
|
|
340
|
+
}
|
|
341
|
+
needsNativeImport = true;
|
|
342
|
+
return `await __mreactNativeImport(${JSON.stringify(specifier)});`;
|
|
343
|
+
});
|
|
344
|
+
return {
|
|
345
|
+
code: nativeImportBindings.size === 0
|
|
346
|
+
? rewrittenCode
|
|
347
|
+
: replaceImportedIdentifiers(rewrittenCode, nativeImportBindings),
|
|
348
|
+
needsNativeImport,
|
|
349
|
+
needsRequire,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function nodeModulesExternalImportPath(specifier) {
|
|
353
|
+
const file = externalImportFilePath(specifier);
|
|
354
|
+
if (file === undefined || !isNodeModulesPath(file)) {
|
|
355
|
+
return undefined;
|
|
356
|
+
}
|
|
357
|
+
return file;
|
|
358
|
+
}
|
|
359
|
+
function externalImportFilePath(specifier) {
|
|
360
|
+
if (specifier.startsWith("file://")) {
|
|
361
|
+
try {
|
|
362
|
+
return fileURLToPath(specifier);
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return isAbsolute(specifier) ? specifier : undefined;
|
|
369
|
+
}
|
|
370
|
+
function isNodeModulesPath(file) {
|
|
371
|
+
return file.split(sep).includes("node_modules");
|
|
372
|
+
}
|
|
373
|
+
function isNodeImportableModuleFile(file) {
|
|
374
|
+
const extension = extname(file);
|
|
375
|
+
return extension === ".cjs" || extension === ".mjs" || extension === ".js" || extension === ".node";
|
|
376
|
+
}
|
|
377
|
+
function isNodeCommonJsModuleFile(file) {
|
|
378
|
+
const extension = extname(file);
|
|
379
|
+
if (extension === ".cjs" || extension === ".cts" || extension === ".node") {
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
if (extension === ".mjs" || extension === ".mts" || extension !== ".js") {
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
return nearestPackageType(file) !== "module";
|
|
386
|
+
}
|
|
387
|
+
function nearestPackageType(file) {
|
|
388
|
+
let directory = dirname(file);
|
|
389
|
+
while (true) {
|
|
390
|
+
const packageJson = join(directory, "package.json");
|
|
391
|
+
if (packageTypeCache.has(packageJson)) {
|
|
392
|
+
return packageTypeCache.get(packageJson);
|
|
393
|
+
}
|
|
394
|
+
if (existsSync(packageJson)) {
|
|
395
|
+
const type = readPackageType(packageJson);
|
|
396
|
+
packageTypeCache.set(packageJson, type);
|
|
397
|
+
return type;
|
|
398
|
+
}
|
|
399
|
+
const parent = dirname(directory);
|
|
400
|
+
if (parent === directory) {
|
|
401
|
+
return undefined;
|
|
402
|
+
}
|
|
403
|
+
directory = parent;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
function readPackageType(packageJson) {
|
|
407
|
+
try {
|
|
408
|
+
const parsed = JSON.parse(readFileSync(packageJson, "utf8"));
|
|
409
|
+
return typeof parsed.type === "string" ? parsed.type : undefined;
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
function commonJsImportClauseToRequireStatements(clause, requireExpression, importIndex) {
|
|
416
|
+
if (clause.startsWith("* as ")) {
|
|
417
|
+
return `const ${clause.slice(5).trim()} = ${requireExpression};`;
|
|
418
|
+
}
|
|
419
|
+
if (clause.startsWith("{")) {
|
|
420
|
+
return namedCommonJsImportsToRequireStatements(clause, requireExpression);
|
|
421
|
+
}
|
|
422
|
+
const commaIndex = clause.indexOf(",");
|
|
423
|
+
if (commaIndex === -1) {
|
|
424
|
+
return `const ${clause} = ${requireExpression};`;
|
|
425
|
+
}
|
|
426
|
+
const defaultName = clause.slice(0, commaIndex).trim();
|
|
427
|
+
const namedOrNamespace = clause.slice(commaIndex + 1).trim();
|
|
428
|
+
const temporaryName = `__mreactExternalCommonJs${importIndex}`;
|
|
429
|
+
const statements = [`const ${temporaryName} = ${requireExpression};`, `const ${defaultName} = ${temporaryName};`];
|
|
430
|
+
if (namedOrNamespace.startsWith("* as ")) {
|
|
431
|
+
statements.push(`const ${namedOrNamespace.slice(5).trim()} = ${temporaryName};`);
|
|
432
|
+
}
|
|
433
|
+
else if (namedOrNamespace.startsWith("{")) {
|
|
434
|
+
statements.push(namedCommonJsImportsToRequireStatements(namedOrNamespace, temporaryName));
|
|
435
|
+
}
|
|
436
|
+
return statements.join("\n");
|
|
437
|
+
}
|
|
438
|
+
function esmImportClauseToNativeImportStatements(clause, specifier, importIndex) {
|
|
439
|
+
const bindings = new Map();
|
|
440
|
+
const temporaryName = `__mreactExternalModule${importIndex}`;
|
|
441
|
+
const statements = [
|
|
442
|
+
`const ${temporaryName} = await __mreactNativeImport(${JSON.stringify(specifier)});`,
|
|
443
|
+
];
|
|
444
|
+
if (clause.startsWith("* as ")) {
|
|
445
|
+
statements.push(`const ${clause.slice(5).trim()} = ${temporaryName};`);
|
|
446
|
+
}
|
|
447
|
+
else if (clause.startsWith("{")) {
|
|
448
|
+
collectNamedEsmImportBindings(clause, temporaryName, bindings);
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
const commaIndex = clause.indexOf(",");
|
|
452
|
+
if (commaIndex === -1) {
|
|
453
|
+
bindings.set(clause, `${temporaryName}.default`);
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
const defaultName = clause.slice(0, commaIndex).trim();
|
|
457
|
+
const namedOrNamespace = clause.slice(commaIndex + 1).trim();
|
|
458
|
+
bindings.set(defaultName, `${temporaryName}.default`);
|
|
459
|
+
if (namedOrNamespace.startsWith("* as ")) {
|
|
460
|
+
statements.push(`const ${namedOrNamespace.slice(5).trim()} = ${temporaryName};`);
|
|
461
|
+
}
|
|
462
|
+
else if (namedOrNamespace.startsWith("{")) {
|
|
463
|
+
collectNamedEsmImportBindings(namedOrNamespace, temporaryName, bindings);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
return { bindings, code: statements.join("\n") };
|
|
468
|
+
}
|
|
469
|
+
function collectNamedEsmImportBindings(clause, moduleName, bindings) {
|
|
470
|
+
for (const binding of namedImportBindings(clause)) {
|
|
471
|
+
const replacement = binding.imported === "default"
|
|
472
|
+
? `${moduleName}.default`
|
|
473
|
+
: `${moduleName}[${JSON.stringify(binding.imported)}]`;
|
|
474
|
+
bindings.set(binding.local, replacement);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
function namedCommonJsImportsToRequireStatements(clause, sourceExpression) {
|
|
478
|
+
const objectBindings = [];
|
|
479
|
+
const statements = [];
|
|
480
|
+
for (const binding of namedImportBindings(clause)) {
|
|
481
|
+
if (binding.imported === "default") {
|
|
482
|
+
statements.push(`const ${binding.local} = ${sourceExpression};`);
|
|
483
|
+
}
|
|
484
|
+
else if (binding.imported === binding.local) {
|
|
485
|
+
objectBindings.push(binding.imported);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
objectBindings.push(`${JSON.stringify(binding.imported)}: ${binding.local}`);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (objectBindings.length > 0) {
|
|
492
|
+
statements.unshift(`const { ${objectBindings.join(", ")} } = ${sourceExpression};`);
|
|
493
|
+
}
|
|
494
|
+
return statements.join("\n");
|
|
495
|
+
}
|
|
496
|
+
function namedImportBindings(clause) {
|
|
497
|
+
return clause
|
|
498
|
+
.slice(1, -1)
|
|
499
|
+
.split(",")
|
|
500
|
+
.map((binding) => binding.trim())
|
|
501
|
+
.filter((binding) => binding.length > 0)
|
|
502
|
+
.map((binding) => {
|
|
503
|
+
const alias = binding.match(/^(.+?)\s+as\s+(.+)$/);
|
|
504
|
+
const imported = alias?.[1]?.trim() ?? binding;
|
|
505
|
+
const local = alias?.[2]?.trim() ?? binding;
|
|
506
|
+
return { imported, local };
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
function replaceImportedIdentifiers(code, bindings) {
|
|
510
|
+
let rewritten = "";
|
|
511
|
+
let index = 0;
|
|
512
|
+
while (index < code.length) {
|
|
513
|
+
const char = code[index];
|
|
514
|
+
const next = code[index + 1];
|
|
515
|
+
if (char === '"' || char === "'") {
|
|
516
|
+
const end = quotedStringEnd(code, index, char);
|
|
517
|
+
rewritten += code.slice(index, end);
|
|
518
|
+
index = end;
|
|
519
|
+
continue;
|
|
520
|
+
}
|
|
521
|
+
if (char === "`") {
|
|
522
|
+
const end = templateLiteralEnd(code, index);
|
|
523
|
+
rewritten += code.slice(index, end);
|
|
524
|
+
index = end;
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
if (char === "/" && next === "/") {
|
|
528
|
+
const end = lineCommentEnd(code, index);
|
|
529
|
+
rewritten += code.slice(index, end);
|
|
530
|
+
index = end;
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
if (char === "/" && next === "*") {
|
|
534
|
+
const end = blockCommentEnd(code, index);
|
|
535
|
+
rewritten += code.slice(index, end);
|
|
536
|
+
index = end;
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
if (isIdentifierStart(char)) {
|
|
540
|
+
const end = identifierEnd(code, index);
|
|
541
|
+
const identifier = code.slice(index, end);
|
|
542
|
+
const replacement = bindings.get(identifier);
|
|
543
|
+
if (replacement !== undefined && shouldReplaceImportedIdentifier(code, index, end)) {
|
|
544
|
+
rewritten += importedIdentifierReplacement(code, index, end, identifier, replacement);
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
rewritten += identifier;
|
|
548
|
+
}
|
|
549
|
+
index = end;
|
|
550
|
+
continue;
|
|
551
|
+
}
|
|
552
|
+
rewritten += char;
|
|
553
|
+
index += 1;
|
|
554
|
+
}
|
|
555
|
+
return rewritten;
|
|
556
|
+
}
|
|
557
|
+
function shouldReplaceImportedIdentifier(code, start, end) {
|
|
558
|
+
const previous = previousNonWhitespace(code, start);
|
|
559
|
+
const next = nextNonWhitespace(code, end);
|
|
560
|
+
return previous !== "." && previous !== "?" && next !== ":";
|
|
561
|
+
}
|
|
562
|
+
function importedIdentifierReplacement(code, start, end, identifier, replacement) {
|
|
563
|
+
const previous = previousNonWhitespace(code, start);
|
|
564
|
+
const next = nextNonWhitespace(code, end);
|
|
565
|
+
return (previous === "{" || previous === ",") && (next === "," || next === "}")
|
|
566
|
+
? `${identifier}: ${replacement}`
|
|
567
|
+
: replacement;
|
|
568
|
+
}
|
|
569
|
+
function previousNonWhitespace(code, index) {
|
|
570
|
+
for (let position = index - 1; position >= 0; position -= 1) {
|
|
571
|
+
if (!/\s/u.test(code[position] ?? "")) {
|
|
572
|
+
return code[position];
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
return undefined;
|
|
576
|
+
}
|
|
577
|
+
function nextNonWhitespace(code, index) {
|
|
578
|
+
for (let position = index; position < code.length; position += 1) {
|
|
579
|
+
if (!/\s/u.test(code[position] ?? "")) {
|
|
580
|
+
return code[position];
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
return undefined;
|
|
584
|
+
}
|
|
585
|
+
function quotedStringEnd(code, start, quote) {
|
|
586
|
+
for (let index = start + 1; index < code.length; index += 1) {
|
|
587
|
+
if (code[index] === "\\") {
|
|
588
|
+
index += 1;
|
|
589
|
+
}
|
|
590
|
+
else if (code[index] === quote) {
|
|
591
|
+
return index + 1;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return code.length;
|
|
595
|
+
}
|
|
596
|
+
function templateLiteralEnd(code, start) {
|
|
597
|
+
for (let index = start + 1; index < code.length; index += 1) {
|
|
598
|
+
if (code[index] === "\\") {
|
|
599
|
+
index += 1;
|
|
600
|
+
}
|
|
601
|
+
else if (code[index] === "`") {
|
|
602
|
+
return index + 1;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
return code.length;
|
|
606
|
+
}
|
|
607
|
+
function lineCommentEnd(code, start) {
|
|
608
|
+
const end = code.indexOf("\n", start + 2);
|
|
609
|
+
return end === -1 ? code.length : end;
|
|
610
|
+
}
|
|
611
|
+
function blockCommentEnd(code, start) {
|
|
612
|
+
const end = code.indexOf("*/", start + 2);
|
|
613
|
+
return end === -1 ? code.length : end + 2;
|
|
614
|
+
}
|
|
615
|
+
function identifierEnd(code, start) {
|
|
616
|
+
let end = start + 1;
|
|
617
|
+
while (end < code.length && isIdentifierPart(code[end] ?? "")) {
|
|
618
|
+
end += 1;
|
|
619
|
+
}
|
|
620
|
+
return end;
|
|
621
|
+
}
|
|
622
|
+
function isIdentifierStart(char) {
|
|
623
|
+
return char !== undefined && /[A-Za-z_$]/u.test(char);
|
|
624
|
+
}
|
|
625
|
+
function isIdentifierPart(char) {
|
|
626
|
+
return /[A-Za-z0-9_$]/u.test(char);
|
|
627
|
+
}
|
|
222
628
|
function workspacePackageResolutionPlugin() {
|
|
223
629
|
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
224
630
|
const packageRoot = dirname(currentDir);
|
|
@@ -248,6 +654,34 @@ function workspacePackageResolutionPlugin() {
|
|
|
248
654
|
specifier,
|
|
249
655
|
});
|
|
250
656
|
const entries = new Map([
|
|
657
|
+
[
|
|
658
|
+
"react",
|
|
659
|
+
{ entry: "index", monorepoDir: "react-compat", packageName: "@reckona/mreact-compat" },
|
|
660
|
+
],
|
|
661
|
+
[
|
|
662
|
+
"react-dom",
|
|
663
|
+
{ entry: "index", monorepoDir: "react-compat", packageName: "@reckona/mreact-compat" },
|
|
664
|
+
],
|
|
665
|
+
[
|
|
666
|
+
"react-dom/client",
|
|
667
|
+
{ entry: "index", monorepoDir: "react-compat", packageName: "@reckona/mreact-compat" },
|
|
668
|
+
],
|
|
669
|
+
[
|
|
670
|
+
"react-dom/server",
|
|
671
|
+
{ entry: "index", monorepoDir: "react-compat", packageName: "@reckona/mreact-compat" },
|
|
672
|
+
],
|
|
673
|
+
[
|
|
674
|
+
"react/jsx-dev-runtime",
|
|
675
|
+
{
|
|
676
|
+
entry: "jsx-dev-runtime",
|
|
677
|
+
monorepoDir: "react-compat",
|
|
678
|
+
packageName: "@reckona/mreact-compat",
|
|
679
|
+
},
|
|
680
|
+
],
|
|
681
|
+
[
|
|
682
|
+
"react/jsx-runtime",
|
|
683
|
+
{ entry: "jsx-runtime", monorepoDir: "react-compat", packageName: "@reckona/mreact-compat" },
|
|
684
|
+
],
|
|
251
685
|
["@reckona/mreact", { entry: "index", monorepoDir: "react", packageName: "@reckona/mreact" }],
|
|
252
686
|
[
|
|
253
687
|
"@reckona/mreact/jsx-dev-runtime",
|
|
@@ -329,7 +763,7 @@ function workspacePackageResolutionPlugin() {
|
|
|
329
763
|
name: "mreact-router-workspace-packages",
|
|
330
764
|
setup(buildApi) {
|
|
331
765
|
buildApi.onResolve({
|
|
332
|
-
filter:
|
|
766
|
+
filter: /^(?:react(?:\/jsx-(?:dev-)?runtime)?|react-dom(?:\/(?:client|server))?|@reckona\/(?:mreact(?:\/(?:jsx-dev-runtime|jsx-runtime))?|mreact-(?:auth|query|reactive-core|server|router|compat)(?:\/(?:event-priority|flight|internal|jsx-dev-runtime|jsx-runtime|scheduler|app-router-globals|link|native-escape|navigation-state|session|stream-list|internal\/native-escape|internal\/session))?))$/,
|
|
333
767
|
}, (args) => {
|
|
334
768
|
const routerPath = routerEntries.get(args.path);
|
|
335
769
|
if (routerPath !== undefined) {
|