@nasti-toolchain/nasti 2.3.1 → 2.4.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/README.md +64 -1
- package/bin/nasti.js +0 -0
- package/client/hmr.ts +4 -3
- package/dist/cli.cjs +957 -269
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +951 -264
- package/dist/cli.js.map +1 -1
- package/dist/client/hmr.cjs.map +1 -1
- package/dist/client/hmr.d.cts +4 -3
- package/dist/client/hmr.d.ts +4 -3
- package/dist/index.cjs +1054 -366
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -8
- package/dist/index.d.ts +64 -8
- package/dist/index.js +1048 -361
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,10 +10,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
10
10
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
11
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
12
|
});
|
|
13
|
-
var __glob = (map) => (
|
|
14
|
-
var fn = map[
|
|
13
|
+
var __glob = (map) => (path19) => {
|
|
14
|
+
var fn = map[path19];
|
|
15
15
|
if (fn) return fn();
|
|
16
|
-
throw new Error("Module not found in bundle: " +
|
|
16
|
+
throw new Error("Module not found in bundle: " + path19);
|
|
17
17
|
};
|
|
18
18
|
var __esm = (fn, res) => function __init() {
|
|
19
19
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -481,6 +481,7 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
481
481
|
if (envOptions.build) Object.assign(resolved.build, envOptions.build);
|
|
482
482
|
resolved.environments.client = {
|
|
483
483
|
consumer,
|
|
484
|
+
buildEnabled: envOptions.buildEnabled ?? true,
|
|
484
485
|
entry: normalizeEnvironmentEntries(envOptions.entry, root),
|
|
485
486
|
html: path.resolve(
|
|
486
487
|
root,
|
|
@@ -495,6 +496,7 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
495
496
|
}
|
|
496
497
|
resolved.environments[name] = {
|
|
497
498
|
consumer,
|
|
499
|
+
buildEnabled: envOptions.buildEnabled ?? true,
|
|
498
500
|
entry: normalizeEnvironmentEntries(envOptions.entry, root),
|
|
499
501
|
html: envOptions.consumer === "client" && envOptions.html ? path.resolve(root, envOptions.html) : void 0,
|
|
500
502
|
driver: envOptions.driver,
|
|
@@ -721,6 +723,7 @@ function resolvePlugin(config) {
|
|
|
721
723
|
}
|
|
722
724
|
if (!source.startsWith("/") && !source.startsWith(".")) {
|
|
723
725
|
if (vueRuntimeEntry && source === "vue") return vueRuntimeEntry;
|
|
726
|
+
if (config.command === "build") return null;
|
|
724
727
|
try {
|
|
725
728
|
const resolved = require2.resolve(source, {
|
|
726
729
|
paths: [importer ? path2.dirname(importer) : config.root]
|
|
@@ -852,27 +855,27 @@ var require_process = __commonJS({
|
|
|
852
855
|
var require_filesystem = __commonJS({
|
|
853
856
|
"node_modules/detect-libc/lib/filesystem.js"(exports, module) {
|
|
854
857
|
"use strict";
|
|
855
|
-
var
|
|
858
|
+
var fs14 = __require("fs");
|
|
856
859
|
var LDD_PATH = "/usr/bin/ldd";
|
|
857
860
|
var SELF_PATH = "/proc/self/exe";
|
|
858
861
|
var MAX_LENGTH = 2048;
|
|
859
|
-
var readFileSync = (
|
|
860
|
-
const fd =
|
|
862
|
+
var readFileSync = (path19) => {
|
|
863
|
+
const fd = fs14.openSync(path19, "r");
|
|
861
864
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
862
|
-
const bytesRead =
|
|
863
|
-
|
|
865
|
+
const bytesRead = fs14.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
866
|
+
fs14.close(fd, () => {
|
|
864
867
|
});
|
|
865
868
|
return buffer.subarray(0, bytesRead);
|
|
866
869
|
};
|
|
867
|
-
var readFile = (
|
|
868
|
-
|
|
870
|
+
var readFile = (path19) => new Promise((resolve, reject) => {
|
|
871
|
+
fs14.open(path19, "r", (err, fd) => {
|
|
869
872
|
if (err) {
|
|
870
873
|
reject(err);
|
|
871
874
|
} else {
|
|
872
875
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
873
|
-
|
|
876
|
+
fs14.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
|
|
874
877
|
resolve(buffer.subarray(0, bytesRead));
|
|
875
|
-
|
|
878
|
+
fs14.close(fd, () => {
|
|
876
879
|
});
|
|
877
880
|
});
|
|
878
881
|
}
|
|
@@ -984,11 +987,11 @@ var require_detect_libc = __commonJS({
|
|
|
984
987
|
}
|
|
985
988
|
return null;
|
|
986
989
|
};
|
|
987
|
-
var familyFromInterpreterPath = (
|
|
988
|
-
if (
|
|
989
|
-
if (
|
|
990
|
+
var familyFromInterpreterPath = (path19) => {
|
|
991
|
+
if (path19) {
|
|
992
|
+
if (path19.includes("/ld-musl-")) {
|
|
990
993
|
return MUSL;
|
|
991
|
-
} else if (
|
|
994
|
+
} else if (path19.includes("/ld-linux-")) {
|
|
992
995
|
return GLIBC;
|
|
993
996
|
}
|
|
994
997
|
}
|
|
@@ -1035,8 +1038,8 @@ var require_detect_libc = __commonJS({
|
|
|
1035
1038
|
cachedFamilyInterpreter = null;
|
|
1036
1039
|
try {
|
|
1037
1040
|
const selfContent = await readFile(SELF_PATH);
|
|
1038
|
-
const
|
|
1039
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
1041
|
+
const path19 = interpreterPath(selfContent);
|
|
1042
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path19);
|
|
1040
1043
|
} catch (e) {
|
|
1041
1044
|
}
|
|
1042
1045
|
return cachedFamilyInterpreter;
|
|
@@ -1048,8 +1051,8 @@ var require_detect_libc = __commonJS({
|
|
|
1048
1051
|
cachedFamilyInterpreter = null;
|
|
1049
1052
|
try {
|
|
1050
1053
|
const selfContent = readFileSync(SELF_PATH);
|
|
1051
|
-
const
|
|
1052
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
1054
|
+
const path19 = interpreterPath(selfContent);
|
|
1055
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path19);
|
|
1053
1056
|
} catch (e) {
|
|
1054
1057
|
}
|
|
1055
1058
|
return cachedFamilyInterpreter;
|
|
@@ -2113,8 +2116,8 @@ function vuePlugin(config) {
|
|
|
2113
2116
|
let descriptor = descriptorCache.get(filePath);
|
|
2114
2117
|
if (!descriptor) {
|
|
2115
2118
|
try {
|
|
2116
|
-
const
|
|
2117
|
-
const source =
|
|
2119
|
+
const fs14 = await import("fs");
|
|
2120
|
+
const source = fs14.readFileSync(filePath, "utf-8");
|
|
2118
2121
|
const parsed = sfc.parse(source, { filename: filePath });
|
|
2119
2122
|
if (parsed.errors.length) return null;
|
|
2120
2123
|
descriptor = parsed.descriptor;
|
|
@@ -2335,16 +2338,27 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
2335
2338
|
// src/plugins/builtins.ts
|
|
2336
2339
|
function resolvePluginList(config, userPlugins, opts = {}) {
|
|
2337
2340
|
const isServe = config.command === "serve";
|
|
2341
|
+
let environmentOptions;
|
|
2342
|
+
if (opts.environmentName) {
|
|
2343
|
+
environmentOptions = config.environments[opts.environmentName];
|
|
2344
|
+
if (!environmentOptions) {
|
|
2345
|
+
throw new Error(
|
|
2346
|
+
`[nasti] unknown environment "${opts.environmentName}" \u2014 declare it in config.environments`
|
|
2347
|
+
);
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
const pluginConfig = environmentOptions ? { ...config, resolve: environmentOptions.resolve, build: environmentOptions.build } : config;
|
|
2351
|
+
const consumer = opts.consumer ?? environmentOptions?.consumer;
|
|
2338
2352
|
return [
|
|
2339
2353
|
// vuePlugin 排最前(enforce: 'pre' 语义):.vue 先编译成 JS 再走后续管道
|
|
2340
|
-
...config.framework === "vue" ? [vuePlugin(
|
|
2341
|
-
resolvePlugin(
|
|
2342
|
-
cssPlugin(
|
|
2343
|
-
assetsPlugin(
|
|
2344
|
-
...isServe ? [htmlPlugin(
|
|
2354
|
+
...config.framework === "vue" ? [vuePlugin(pluginConfig)] : [],
|
|
2355
|
+
resolvePlugin(pluginConfig),
|
|
2356
|
+
cssPlugin(pluginConfig, opts.cssEngine, consumer),
|
|
2357
|
+
assetsPlugin(pluginConfig),
|
|
2358
|
+
...isServe ? [htmlPlugin(pluginConfig)] : [],
|
|
2345
2359
|
...userPlugins,
|
|
2346
2360
|
// cssPostPlugin 最后(enforce: 'post' 语义):renderChunk 聚合抽取
|
|
2347
|
-
...!isServe && opts.cssEngine ? [cssPostPlugin(
|
|
2361
|
+
...!isServe && opts.cssEngine ? [cssPostPlugin(pluginConfig, opts.cssEngine)] : []
|
|
2348
2362
|
];
|
|
2349
2363
|
}
|
|
2350
2364
|
var init_builtins = __esm({
|
|
@@ -2474,17 +2488,35 @@ var init_plugin_container = __esm({
|
|
|
2474
2488
|
}
|
|
2475
2489
|
});
|
|
2476
2490
|
|
|
2491
|
+
// src/core/url.ts
|
|
2492
|
+
function removeTimestampQuery(url) {
|
|
2493
|
+
const hashIndex = url.indexOf("#");
|
|
2494
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
|
|
2495
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
2496
|
+
const queryIndex = withoutHash.indexOf("?");
|
|
2497
|
+
if (queryIndex < 0) return url;
|
|
2498
|
+
const pathname = withoutHash.slice(0, queryIndex);
|
|
2499
|
+
const query = withoutHash.slice(queryIndex + 1).split("&").filter((part) => !/^t=\d+$/.test(part)).join("&");
|
|
2500
|
+
return pathname + (query ? `?${query}` : "") + hash;
|
|
2501
|
+
}
|
|
2502
|
+
var init_url = __esm({
|
|
2503
|
+
"src/core/url.ts"() {
|
|
2504
|
+
"use strict";
|
|
2505
|
+
}
|
|
2506
|
+
});
|
|
2507
|
+
|
|
2477
2508
|
// src/core/module-graph.ts
|
|
2478
2509
|
var ModuleGraph;
|
|
2479
2510
|
var init_module_graph = __esm({
|
|
2480
2511
|
"src/core/module-graph.ts"() {
|
|
2481
2512
|
"use strict";
|
|
2513
|
+
init_url();
|
|
2482
2514
|
ModuleGraph = class {
|
|
2483
2515
|
urlToModuleMap = /* @__PURE__ */ new Map();
|
|
2484
2516
|
idToModuleMap = /* @__PURE__ */ new Map();
|
|
2485
2517
|
fileToModulesMap = /* @__PURE__ */ new Map();
|
|
2486
2518
|
getModuleByUrl(url) {
|
|
2487
|
-
return this.urlToModuleMap.get(url);
|
|
2519
|
+
return this.urlToModuleMap.get(removeTimestampQuery(url));
|
|
2488
2520
|
}
|
|
2489
2521
|
getModuleById(id) {
|
|
2490
2522
|
return this.idToModuleMap.get(id);
|
|
@@ -2493,10 +2525,11 @@ var init_module_graph = __esm({
|
|
|
2493
2525
|
return this.fileToModulesMap.get(file);
|
|
2494
2526
|
}
|
|
2495
2527
|
async ensureEntryFromUrl(url) {
|
|
2496
|
-
|
|
2528
|
+
const normalizedUrl = removeTimestampQuery(url);
|
|
2529
|
+
let mod = this.urlToModuleMap.get(normalizedUrl);
|
|
2497
2530
|
if (mod) return mod;
|
|
2498
|
-
mod = this.createModule(
|
|
2499
|
-
this.urlToModuleMap.set(
|
|
2531
|
+
mod = this.createModule(normalizedUrl);
|
|
2532
|
+
this.urlToModuleMap.set(normalizedUrl, mod);
|
|
2500
2533
|
return mod;
|
|
2501
2534
|
}
|
|
2502
2535
|
createModule(url, id) {
|
|
@@ -2510,6 +2543,7 @@ var init_module_graph = __esm({
|
|
|
2510
2543
|
acceptedHmrDeps: /* @__PURE__ */ new Set(),
|
|
2511
2544
|
transformResult: null,
|
|
2512
2545
|
lastHMRTimestamp: 0,
|
|
2546
|
+
invalidationVersion: 0,
|
|
2513
2547
|
isSelfAccepting: false
|
|
2514
2548
|
};
|
|
2515
2549
|
this.idToModuleMap.set(mod.id, mod);
|
|
@@ -2552,10 +2586,64 @@ var init_module_graph = __esm({
|
|
|
2552
2586
|
}
|
|
2553
2587
|
}
|
|
2554
2588
|
}
|
|
2589
|
+
/**
|
|
2590
|
+
* 用一次转换得到的信息原子更新 import 与 HMR accept 关系。
|
|
2591
|
+
* 依赖节点会在真正被浏览器请求前预先创建,这样入口模块先转换时也能建立完整图。
|
|
2592
|
+
*/
|
|
2593
|
+
async updateModuleInfo(mod, importedUrls, acceptedUrls, isSelfAccepting, expectedInvalidationVersion) {
|
|
2594
|
+
const importedModules = await Promise.all(
|
|
2595
|
+
[...importedUrls].map((url) => this.ensureEntryFromUrl(url))
|
|
2596
|
+
);
|
|
2597
|
+
const acceptedModules = await Promise.all(
|
|
2598
|
+
[...acceptedUrls].map((url) => this.ensureEntryFromUrl(url))
|
|
2599
|
+
);
|
|
2600
|
+
if (expectedInvalidationVersion !== void 0 && mod.invalidationVersion !== expectedInvalidationVersion) {
|
|
2601
|
+
return null;
|
|
2602
|
+
}
|
|
2603
|
+
const previousImports = new Set(mod.importedModules);
|
|
2604
|
+
for (const imported of previousImports) {
|
|
2605
|
+
imported.importers.delete(mod);
|
|
2606
|
+
}
|
|
2607
|
+
mod.importedModules.clear();
|
|
2608
|
+
mod.acceptedHmrDeps.clear();
|
|
2609
|
+
for (const imported of importedModules) {
|
|
2610
|
+
mod.importedModules.add(imported);
|
|
2611
|
+
imported.importers.add(mod);
|
|
2612
|
+
}
|
|
2613
|
+
for (const accepted of acceptedModules) {
|
|
2614
|
+
mod.acceptedHmrDeps.add(accepted);
|
|
2615
|
+
}
|
|
2616
|
+
mod.isSelfAccepting = isSelfAccepting;
|
|
2617
|
+
const pruned = /* @__PURE__ */ new Set();
|
|
2618
|
+
for (const imported of previousImports) {
|
|
2619
|
+
if (!mod.importedModules.has(imported) && imported.importers.size === 0) {
|
|
2620
|
+
pruned.add(imported);
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
return pruned;
|
|
2624
|
+
}
|
|
2555
2625
|
/** 使模块的转换缓存失效 */
|
|
2556
|
-
invalidateModule(mod) {
|
|
2626
|
+
invalidateModule(mod, timestamp = Date.now()) {
|
|
2557
2627
|
mod.transformResult = null;
|
|
2558
|
-
mod.lastHMRTimestamp =
|
|
2628
|
+
mod.lastHMRTimestamp = timestamp;
|
|
2629
|
+
mod.invalidationVersion++;
|
|
2630
|
+
}
|
|
2631
|
+
/**
|
|
2632
|
+
* 仅失效到 HMR 边界:显式接受依赖的模块本身不会重执行;自接受模块需要失效,
|
|
2633
|
+
* 但不再继续影响其 importer。这样既能传播依赖时间戳,也不会隐式重复副作用。
|
|
2634
|
+
*/
|
|
2635
|
+
invalidateModuleAndImporters(mod, timestamp = Date.now(), seen = /* @__PURE__ */ new Set()) {
|
|
2636
|
+
if (seen.has(mod)) return;
|
|
2637
|
+
seen.add(mod);
|
|
2638
|
+
this.invalidateModule(mod, timestamp);
|
|
2639
|
+
for (const importer of mod.importers) {
|
|
2640
|
+
if (importer.acceptedHmrDeps.has(mod)) continue;
|
|
2641
|
+
if (importer.isSelfAccepting) {
|
|
2642
|
+
this.invalidateModule(importer, timestamp);
|
|
2643
|
+
continue;
|
|
2644
|
+
}
|
|
2645
|
+
this.invalidateModuleAndImporters(importer, timestamp, seen);
|
|
2646
|
+
}
|
|
2559
2647
|
}
|
|
2560
2648
|
/** 使所有模块缓存失效 */
|
|
2561
2649
|
invalidateAll() {
|
|
@@ -2566,34 +2654,32 @@ var init_module_graph = __esm({
|
|
|
2566
2654
|
/** 获取 HMR 传播边界 - 从变更模块向上遍历找到接受更新的边界 */
|
|
2567
2655
|
getHmrBoundaries(mod) {
|
|
2568
2656
|
const boundaries = [];
|
|
2569
|
-
const
|
|
2570
|
-
const
|
|
2571
|
-
if (
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
boundaries.push({ boundary
|
|
2575
|
-
return true;
|
|
2657
|
+
const traversed = /* @__PURE__ */ new Set();
|
|
2658
|
+
const addBoundary = (boundary, acceptedVia) => {
|
|
2659
|
+
if (!boundaries.some(
|
|
2660
|
+
(item) => item.boundary === boundary && item.acceptedVia === acceptedVia
|
|
2661
|
+
)) {
|
|
2662
|
+
boundaries.push({ boundary, acceptedVia });
|
|
2576
2663
|
}
|
|
2577
|
-
|
|
2578
|
-
|
|
2664
|
+
};
|
|
2665
|
+
const propagate = (node) => {
|
|
2666
|
+
if (traversed.has(node)) return true;
|
|
2667
|
+
traversed.add(node);
|
|
2668
|
+
if (node.isSelfAccepting) {
|
|
2669
|
+
addBoundary(node, node);
|
|
2579
2670
|
return true;
|
|
2580
2671
|
}
|
|
2581
2672
|
if (node.importers.size === 0) return false;
|
|
2582
2673
|
for (const importer of node.importers) {
|
|
2583
|
-
if (
|
|
2674
|
+
if (importer.acceptedHmrDeps.has(node)) {
|
|
2675
|
+
addBoundary(importer, node);
|
|
2676
|
+
continue;
|
|
2677
|
+
}
|
|
2678
|
+
if (!propagate(importer)) return false;
|
|
2584
2679
|
}
|
|
2585
2680
|
return true;
|
|
2586
2681
|
};
|
|
2587
|
-
|
|
2588
|
-
boundaries.push({ boundary: mod, acceptedVia: mod });
|
|
2589
|
-
return boundaries;
|
|
2590
|
-
}
|
|
2591
|
-
for (const importer of mod.importers) {
|
|
2592
|
-
if (!propagate(importer, mod)) {
|
|
2593
|
-
return [];
|
|
2594
|
-
}
|
|
2595
|
-
}
|
|
2596
|
-
return boundaries;
|
|
2682
|
+
return propagate(mod) ? boundaries : [];
|
|
2597
2683
|
}
|
|
2598
2684
|
};
|
|
2599
2685
|
}
|
|
@@ -2689,6 +2775,7 @@ var init_environment = __esm({
|
|
|
2689
2775
|
moduleGraph;
|
|
2690
2776
|
candidatePlugins;
|
|
2691
2777
|
pluginApi;
|
|
2778
|
+
buildMetadata = {};
|
|
2692
2779
|
initialized = false;
|
|
2693
2780
|
constructor(name, config, init = {}) {
|
|
2694
2781
|
const options = config.environments[name];
|
|
@@ -2745,6 +2832,22 @@ var init_environment = __esm({
|
|
|
2745
2832
|
logger: this.config.logger
|
|
2746
2833
|
};
|
|
2747
2834
|
}
|
|
2835
|
+
setBuildMetadata(metadata) {
|
|
2836
|
+
const { entries: currentEntries, ...currentMetadata } = this.buildMetadata;
|
|
2837
|
+
const { entries, ...nextMetadata } = metadata;
|
|
2838
|
+
this.buildMetadata = {
|
|
2839
|
+
...currentMetadata,
|
|
2840
|
+
...nextMetadata,
|
|
2841
|
+
...currentEntries || entries ? { entries: { ...currentEntries, ...entries } } : {}
|
|
2842
|
+
};
|
|
2843
|
+
}
|
|
2844
|
+
getBuildMetadata() {
|
|
2845
|
+
const { entries, ...metadata } = this.buildMetadata;
|
|
2846
|
+
return {
|
|
2847
|
+
...metadata,
|
|
2848
|
+
...entries ? { entries: { ...entries } } : {}
|
|
2849
|
+
};
|
|
2850
|
+
}
|
|
2748
2851
|
async close() {
|
|
2749
2852
|
try {
|
|
2750
2853
|
await this.driver?.close?.(this.getDriverContext());
|
|
@@ -2909,6 +3012,134 @@ var init_reporter = __esm({
|
|
|
2909
3012
|
}
|
|
2910
3013
|
});
|
|
2911
3014
|
|
|
3015
|
+
// src/core/build-app-context.ts
|
|
3016
|
+
import fs6 from "fs";
|
|
3017
|
+
import path9 from "path";
|
|
3018
|
+
function createBuildAppContext(config, results) {
|
|
3019
|
+
const output = [];
|
|
3020
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
3021
|
+
const outDir = path9.resolve(config.root, config.build.outDir);
|
|
3022
|
+
let environmentArtifacts;
|
|
3023
|
+
return {
|
|
3024
|
+
config,
|
|
3025
|
+
results,
|
|
3026
|
+
get output() {
|
|
3027
|
+
return Object.freeze([...output]);
|
|
3028
|
+
},
|
|
3029
|
+
getResult(environmentName) {
|
|
3030
|
+
return results[environmentName];
|
|
3031
|
+
},
|
|
3032
|
+
getArtifact(environmentName, fileName) {
|
|
3033
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
3034
|
+
return results[environmentName]?.output.find(
|
|
3035
|
+
(artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalized
|
|
3036
|
+
);
|
|
3037
|
+
},
|
|
3038
|
+
getEntry(environmentName, entryName) {
|
|
3039
|
+
const result = results[environmentName];
|
|
3040
|
+
const fileName = result?.entries?.[entryName];
|
|
3041
|
+
if (!fileName) return void 0;
|
|
3042
|
+
return result.output.find(
|
|
3043
|
+
(artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalizeEnvironmentFileName(fileName)
|
|
3044
|
+
);
|
|
3045
|
+
},
|
|
3046
|
+
getManifest(environmentName) {
|
|
3047
|
+
return results[environmentName]?.manifest;
|
|
3048
|
+
},
|
|
3049
|
+
emitFile(file) {
|
|
3050
|
+
const fileName = normalizeAppFileName(file.fileName);
|
|
3051
|
+
const collisionKey = artifactCollisionKey(fileName);
|
|
3052
|
+
if (emitted.has(collisionKey)) {
|
|
3053
|
+
throw new Error(`[nasti] app artifact already emitted: ${fileName}`);
|
|
3054
|
+
}
|
|
3055
|
+
environmentArtifacts ??= collectEnvironmentArtifacts(config, results, outDir);
|
|
3056
|
+
if (environmentArtifacts.has(collisionKey)) {
|
|
3057
|
+
throw new Error(`[nasti] app artifact conflicts with environment output: ${fileName}`);
|
|
3058
|
+
}
|
|
3059
|
+
const target = path9.resolve(outDir, ...fileName.split("/"));
|
|
3060
|
+
const relative = path9.relative(outDir, target);
|
|
3061
|
+
if (relative.startsWith("..") || path9.isAbsolute(relative)) {
|
|
3062
|
+
throw new Error(`[nasti] app artifact must stay inside build.outDir: ${file.fileName}`);
|
|
3063
|
+
}
|
|
3064
|
+
assertNoSymlinkComponents(outDir, fileName);
|
|
3065
|
+
fs6.mkdirSync(path9.dirname(target), { recursive: true });
|
|
3066
|
+
fs6.writeFileSync(target, file.source);
|
|
3067
|
+
const artifact = {
|
|
3068
|
+
...file,
|
|
3069
|
+
fileName,
|
|
3070
|
+
type: "asset"
|
|
3071
|
+
};
|
|
3072
|
+
emitted.add(collisionKey);
|
|
3073
|
+
output.push(artifact);
|
|
3074
|
+
return fileName;
|
|
3075
|
+
}
|
|
3076
|
+
};
|
|
3077
|
+
}
|
|
3078
|
+
function normalizeEnvironmentFileName(fileName) {
|
|
3079
|
+
return path9.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
|
|
3080
|
+
}
|
|
3081
|
+
function isInvalidEnvironmentFileName(fileName) {
|
|
3082
|
+
return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || path9.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
|
|
3083
|
+
}
|
|
3084
|
+
function normalizeAppFileName(fileName) {
|
|
3085
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
3086
|
+
if (isInvalidEnvironmentFileName(normalized)) {
|
|
3087
|
+
throw new Error(`[nasti] invalid app artifact fileName: ${fileName}`);
|
|
3088
|
+
}
|
|
3089
|
+
return normalized;
|
|
3090
|
+
}
|
|
3091
|
+
function artifactCollisionKey(fileName) {
|
|
3092
|
+
return normalizeEnvironmentFileName(fileName).toLowerCase();
|
|
3093
|
+
}
|
|
3094
|
+
function collectEnvironmentArtifacts(config, results, appOutDir) {
|
|
3095
|
+
const occupied = /* @__PURE__ */ new Set();
|
|
3096
|
+
for (const [environmentName, result] of Object.entries(results)) {
|
|
3097
|
+
const environment = config.environments[environmentName];
|
|
3098
|
+
if (!environment) continue;
|
|
3099
|
+
const environmentOutDir = path9.resolve(config.root, environment.build.outDir);
|
|
3100
|
+
for (const artifact of result.output) {
|
|
3101
|
+
const artifactPath = path9.resolve(
|
|
3102
|
+
environmentOutDir,
|
|
3103
|
+
...normalizeEnvironmentFileName(artifact.fileName).split("/")
|
|
3104
|
+
);
|
|
3105
|
+
const relative = path9.relative(appOutDir, artifactPath);
|
|
3106
|
+
if (!relative.startsWith("..") && !path9.isAbsolute(relative)) {
|
|
3107
|
+
occupied.add(artifactCollisionKey(relative));
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
return occupied;
|
|
3112
|
+
}
|
|
3113
|
+
function assertNoSymlinkComponents(outDir, fileName) {
|
|
3114
|
+
let current = outDir;
|
|
3115
|
+
for (const segment of fileName.split("/")) {
|
|
3116
|
+
current = path9.join(current, segment);
|
|
3117
|
+
let stats;
|
|
3118
|
+
try {
|
|
3119
|
+
stats = fs6.lstatSync(current);
|
|
3120
|
+
} catch (error) {
|
|
3121
|
+
if (error.code === "ENOENT") continue;
|
|
3122
|
+
throw error;
|
|
3123
|
+
}
|
|
3124
|
+
if (stats.isSymbolicLink()) {
|
|
3125
|
+
throw new Error(`[nasti] app artifact path cannot traverse a symlink: ${fileName}`);
|
|
3126
|
+
}
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3129
|
+
function inferEnvironmentEntries(output) {
|
|
3130
|
+
const entries = {};
|
|
3131
|
+
for (const artifact of output) {
|
|
3132
|
+
if (artifact.type !== "chunk" || !artifact.isEntry || !artifact.name) continue;
|
|
3133
|
+
entries[artifact.name] = normalizeEnvironmentFileName(artifact.fileName);
|
|
3134
|
+
}
|
|
3135
|
+
return Object.keys(entries).length > 0 ? entries : void 0;
|
|
3136
|
+
}
|
|
3137
|
+
var init_build_app_context = __esm({
|
|
3138
|
+
"src/core/build-app-context.ts"() {
|
|
3139
|
+
"use strict";
|
|
3140
|
+
}
|
|
3141
|
+
});
|
|
3142
|
+
|
|
2912
3143
|
// src/build/index.ts
|
|
2913
3144
|
var build_exports = {};
|
|
2914
3145
|
__export(build_exports, {
|
|
@@ -2918,8 +3149,8 @@ __export(build_exports, {
|
|
|
2918
3149
|
resolveClientEntries: () => resolveClientEntries,
|
|
2919
3150
|
toRolldownPlugins: () => toRolldownPlugins
|
|
2920
3151
|
});
|
|
2921
|
-
import
|
|
2922
|
-
import
|
|
3152
|
+
import path10 from "path";
|
|
3153
|
+
import fs7 from "fs";
|
|
2923
3154
|
import { builtinModules } from "module";
|
|
2924
3155
|
import { rolldown } from "rolldown";
|
|
2925
3156
|
import pc4 from "picocolors";
|
|
@@ -2927,9 +3158,14 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
2927
3158
|
const config = environment.config;
|
|
2928
3159
|
const envOptions = environment.options;
|
|
2929
3160
|
const isServer = environment.consumer === "server";
|
|
2930
|
-
const outDir =
|
|
3161
|
+
const outDir = path10.resolve(config.root, envOptions.build.outDir);
|
|
2931
3162
|
const assetsDir = envOptions.build.assetsDir;
|
|
2932
|
-
const {
|
|
3163
|
+
const {
|
|
3164
|
+
output: userOutput,
|
|
3165
|
+
transform: userTransform,
|
|
3166
|
+
resolve: userResolve,
|
|
3167
|
+
...restInputOptions
|
|
3168
|
+
} = envOptions.build.rolldownOptions;
|
|
2933
3169
|
const vueDefine = config.framework === "vue" ? {
|
|
2934
3170
|
__VUE_OPTIONS_API__: "true",
|
|
2935
3171
|
__VUE_PROD_DEVTOOLS__: "false",
|
|
@@ -2943,19 +3179,22 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
2943
3179
|
input: entryPoints,
|
|
2944
3180
|
transform: { ...userTransform, define: mergedDefine },
|
|
2945
3181
|
plugins: rolldownPlugins,
|
|
3182
|
+
// client/server consumer 都必须使用当前环境的 conditions/mainFields;Lynx
|
|
3183
|
+
// BG/MT 通常同为 client consumer,但仍可能声明不同的运行时条件。
|
|
3184
|
+
resolve: {
|
|
3185
|
+
...userResolve ?? {},
|
|
3186
|
+
// Environment API 是条件解析的唯一高层入口,优先于继承来的底层选项。
|
|
3187
|
+
conditionNames: envOptions.resolve.conditions,
|
|
3188
|
+
mainFields: envOptions.resolve.mainFields
|
|
3189
|
+
},
|
|
2946
3190
|
...isServer ? {
|
|
2947
3191
|
platform: restInputOptions.platform ?? "node",
|
|
2948
|
-
resolve: {
|
|
2949
|
-
conditionNames: envOptions.resolve.conditions,
|
|
2950
|
-
mainFields: envOptions.resolve.mainFields,
|
|
2951
|
-
...restInputOptions.resolve
|
|
2952
|
-
},
|
|
2953
3192
|
// server 产物:node 内建恒外部化;bare specifier 默认外部化
|
|
2954
3193
|
//(同 Vite ssr.external 默认 —— 依赖由 node_modules 运行时解析),
|
|
2955
3194
|
// 相对/绝对/虚拟模块照常打包。需要内联依赖时经 rolldownOptions.external 覆盖。
|
|
2956
3195
|
external: restInputOptions.external ?? ((id) => {
|
|
2957
3196
|
if (NODE_BUILTINS.has(id)) return true;
|
|
2958
|
-
return !id.startsWith(".") && !
|
|
3197
|
+
return !id.startsWith(".") && !path10.isAbsolute(id) && !id.startsWith("\0");
|
|
2959
3198
|
})
|
|
2960
3199
|
} : {}
|
|
2961
3200
|
};
|
|
@@ -2982,27 +3221,122 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
2982
3221
|
};
|
|
2983
3222
|
return { inputOptions, outputOptions, outDir };
|
|
2984
3223
|
}
|
|
2985
|
-
function toRolldownPlugins(plugins) {
|
|
3224
|
+
function toRolldownPlugins(plugins, environment) {
|
|
3225
|
+
const wrap = (hook) => {
|
|
3226
|
+
if (!hook) return hook;
|
|
3227
|
+
return function(...args) {
|
|
3228
|
+
return hook.apply(attachEnvironment(this, environment), args);
|
|
3229
|
+
};
|
|
3230
|
+
};
|
|
2986
3231
|
return plugins.map((p) => ({
|
|
2987
3232
|
name: p.name,
|
|
2988
|
-
resolveId: p.resolveId,
|
|
2989
|
-
load: p.load,
|
|
2990
|
-
transform: p.transform,
|
|
2991
|
-
buildStart: p.buildStart,
|
|
2992
|
-
buildEnd: p.buildEnd,
|
|
3233
|
+
resolveId: wrap(p.resolveId),
|
|
3234
|
+
load: wrap(p.load),
|
|
3235
|
+
transform: wrap(p.transform),
|
|
3236
|
+
buildStart: wrap(p.buildStart),
|
|
3237
|
+
buildEnd: wrap(p.buildEnd),
|
|
2993
3238
|
// closeBundle 在 bundle.close() 时触发 —— PWA manifest/SW 等终态产物依赖
|
|
2994
|
-
closeBundle: p.closeBundle,
|
|
2995
|
-
renderChunk: p.renderChunk,
|
|
2996
|
-
augmentChunkHash: p.augmentChunkHash,
|
|
2997
|
-
generateBundle: p.generateBundle
|
|
3239
|
+
closeBundle: wrap(p.closeBundle),
|
|
3240
|
+
renderChunk: wrap(p.renderChunk),
|
|
3241
|
+
augmentChunkHash: wrap(p.augmentChunkHash),
|
|
3242
|
+
generateBundle: wrap(p.generateBundle)
|
|
2998
3243
|
}));
|
|
2999
3244
|
}
|
|
3245
|
+
function attachEnvironment(context, environment) {
|
|
3246
|
+
if (context?.environment === environment) return context;
|
|
3247
|
+
try {
|
|
3248
|
+
Object.defineProperty(context, "environment", {
|
|
3249
|
+
configurable: true,
|
|
3250
|
+
enumerable: false,
|
|
3251
|
+
writable: false,
|
|
3252
|
+
value: environment
|
|
3253
|
+
});
|
|
3254
|
+
return context;
|
|
3255
|
+
} catch {
|
|
3256
|
+
return new Proxy(context, {
|
|
3257
|
+
get(target, property) {
|
|
3258
|
+
if (property === "environment") return environment;
|
|
3259
|
+
const value = Reflect.get(target, property, target);
|
|
3260
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
3261
|
+
},
|
|
3262
|
+
set(target, property, value) {
|
|
3263
|
+
return Reflect.set(target, property, value, target);
|
|
3264
|
+
}
|
|
3265
|
+
});
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
function finalizeEnvironmentResult(environment, result) {
|
|
3269
|
+
const metadata = environment.getBuildMetadata();
|
|
3270
|
+
const inferredEntries = inferEnvironmentEntries(result.output);
|
|
3271
|
+
const entries = {
|
|
3272
|
+
...inferredEntries,
|
|
3273
|
+
...metadata.entries,
|
|
3274
|
+
...result.entries
|
|
3275
|
+
};
|
|
3276
|
+
const normalizedEntries = Object.fromEntries(
|
|
3277
|
+
Object.entries(entries).map(([name, fileName]) => {
|
|
3278
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
3279
|
+
if (isInvalidEnvironmentFileName(normalized)) {
|
|
3280
|
+
throw new Error(
|
|
3281
|
+
`[nasti] environment "${environment.name}" returned invalid entry "${name}": ${fileName}`
|
|
3282
|
+
);
|
|
3283
|
+
}
|
|
3284
|
+
return [name, normalized];
|
|
3285
|
+
})
|
|
3286
|
+
);
|
|
3287
|
+
return {
|
|
3288
|
+
...metadata,
|
|
3289
|
+
...result,
|
|
3290
|
+
output: result.output,
|
|
3291
|
+
...Object.keys(normalizedEntries).length > 0 ? { entries: normalizedEntries } : {}
|
|
3292
|
+
};
|
|
3293
|
+
}
|
|
3294
|
+
function prepareBuildOutputDirectories(config, buildableNames) {
|
|
3295
|
+
const directories = /* @__PURE__ */ new Set();
|
|
3296
|
+
const protectedPaths = /* @__PURE__ */ new Set();
|
|
3297
|
+
const clientIsBuilt = buildableNames.includes("client");
|
|
3298
|
+
if (!clientIsBuilt && config.build.emptyOutDir) {
|
|
3299
|
+
directories.add(path10.resolve(config.root, config.build.outDir));
|
|
3300
|
+
}
|
|
3301
|
+
for (const name of buildableNames) {
|
|
3302
|
+
const environment = config.environments[name];
|
|
3303
|
+
const outDir = path10.resolve(config.root, environment.build.outDir);
|
|
3304
|
+
if (!environment.build.emptyOutDir) {
|
|
3305
|
+
protectedPaths.add(outDir);
|
|
3306
|
+
continue;
|
|
3307
|
+
}
|
|
3308
|
+
if (!environment.driver) directories.add(outDir);
|
|
3309
|
+
}
|
|
3310
|
+
const containsPath = (parent, child) => {
|
|
3311
|
+
const relative = path10.relative(parent, child);
|
|
3312
|
+
return relative === "" || !relative.startsWith("..") && !path10.isAbsolute(relative);
|
|
3313
|
+
};
|
|
3314
|
+
const roots = [...directories].filter(
|
|
3315
|
+
(directory) => ![...protectedPaths].some((protectedPath) => containsPath(directory, protectedPath))
|
|
3316
|
+
).sort((a, b) => a.length - b.length).filter(
|
|
3317
|
+
(directory, index2, all) => !all.slice(0, index2).some((parent) => containsPath(parent, directory))
|
|
3318
|
+
);
|
|
3319
|
+
for (const directory of roots) {
|
|
3320
|
+
if (fs7.existsSync(directory)) fs7.rmSync(directory, { recursive: true, force: true });
|
|
3321
|
+
}
|
|
3322
|
+
}
|
|
3323
|
+
function assertDriverBuildResult(environment, result) {
|
|
3324
|
+
const output = result != null && typeof result === "object" ? result.output : void 0;
|
|
3325
|
+
const hasValidOutput = Array.isArray(output) && output.every(
|
|
3326
|
+
(artifact) => artifact != null && typeof artifact === "object" && typeof artifact.fileName === "string" && typeof artifact.type === "string"
|
|
3327
|
+
);
|
|
3328
|
+
if (!hasValidOutput) {
|
|
3329
|
+
throw new Error(
|
|
3330
|
+
`[nasti] environment "${environment.name}" driver "${environment.driver?.name}" returned an invalid build result; expected { output: EnvironmentBuildOutput[] }`
|
|
3331
|
+
);
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3000
3334
|
function resolveClientEntries(config, html) {
|
|
3001
3335
|
const configuredEntries = config.environments.client?.entry ?? [];
|
|
3002
3336
|
if (configuredEntries.length > 0) return configuredEntries;
|
|
3003
3337
|
const entryPoints = [];
|
|
3004
3338
|
const htmlFile = config.environments.client?.html;
|
|
3005
|
-
const htmlDir = htmlFile ?
|
|
3339
|
+
const htmlDir = htmlFile ? path10.dirname(htmlFile) : config.root;
|
|
3006
3340
|
if (html) {
|
|
3007
3341
|
const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
|
|
3008
3342
|
for (const match of scriptMatches) {
|
|
@@ -3010,7 +3344,7 @@ function resolveClientEntries(config, html) {
|
|
|
3010
3344
|
if (src && !src.startsWith("http")) {
|
|
3011
3345
|
const cleanSrc = src.split(/[?#]/, 1)[0];
|
|
3012
3346
|
entryPoints.push(
|
|
3013
|
-
cleanSrc.startsWith("/") ?
|
|
3347
|
+
cleanSrc.startsWith("/") ? path10.resolve(config.root, cleanSrc.replace(/^\//, "")) : path10.resolve(htmlDir, cleanSrc)
|
|
3014
3348
|
);
|
|
3015
3349
|
}
|
|
3016
3350
|
}
|
|
@@ -3018,8 +3352,8 @@ function resolveClientEntries(config, html) {
|
|
|
3018
3352
|
if (entryPoints.length === 0) {
|
|
3019
3353
|
const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
|
|
3020
3354
|
for (const entry of fallbackEntries) {
|
|
3021
|
-
const fullPath =
|
|
3022
|
-
if (
|
|
3355
|
+
const fullPath = path10.resolve(config.root, entry);
|
|
3356
|
+
if (fs7.existsSync(fullPath)) {
|
|
3023
3357
|
entryPoints.push(fullPath);
|
|
3024
3358
|
break;
|
|
3025
3359
|
}
|
|
@@ -3047,16 +3381,20 @@ async function build(inlineConfig = {}) {
|
|
|
3047
3381
|
const startTime = performance.now();
|
|
3048
3382
|
logger.info(
|
|
3049
3383
|
pc4.cyan(`
|
|
3050
|
-
nasti v${"2.
|
|
3384
|
+
nasti v${"2.4.0"} `) + pc4.green(`building for ${config.mode}...`)
|
|
3051
3385
|
);
|
|
3052
3386
|
debug4?.(`root: ${config.root}`);
|
|
3053
|
-
const buildableNames = Object.keys(config.environments).filter(
|
|
3054
|
-
|
|
3055
|
-
|
|
3387
|
+
const buildableNames = Object.keys(config.environments).filter((name) => {
|
|
3388
|
+
const environment = config.environments[name];
|
|
3389
|
+
if (!environment.buildEnabled) return false;
|
|
3390
|
+
return name === "client" || environment.entry.length > 0 || !!environment.driver;
|
|
3391
|
+
});
|
|
3056
3392
|
buildableNames.sort((a, b) => a === "client" ? -1 : b === "client" ? 1 : 0);
|
|
3393
|
+
prepareBuildOutputDirectories(config, buildableNames);
|
|
3057
3394
|
const environments = {};
|
|
3058
3395
|
const environmentResults = {};
|
|
3059
3396
|
const initializedEnvironments = [];
|
|
3397
|
+
const buildAppContext = createBuildAppContext(config, environmentResults);
|
|
3060
3398
|
let clientOutput = [];
|
|
3061
3399
|
let buildFailed = false;
|
|
3062
3400
|
try {
|
|
@@ -3072,7 +3410,7 @@ nasti v${"2.3.1"} `) + pc4.green(`building for ${config.mode}...`)
|
|
|
3072
3410
|
}
|
|
3073
3411
|
const pluginApi = getPluginApi(config);
|
|
3074
3412
|
for (const plugin of config.plugins) {
|
|
3075
|
-
await plugin.afterBuildApp?.(environmentResults, pluginApi);
|
|
3413
|
+
await plugin.afterBuildApp?.(environmentResults, pluginApi, buildAppContext);
|
|
3076
3414
|
}
|
|
3077
3415
|
} catch (error) {
|
|
3078
3416
|
buildFailed = true;
|
|
@@ -3099,22 +3437,31 @@ nasti v${"2.3.1"} `) + pc4.green(`building for ${config.mode}...`)
|
|
|
3099
3437
|
}
|
|
3100
3438
|
}
|
|
3101
3439
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
3102
|
-
const
|
|
3440
|
+
const allOutput = [...Object.values(environments).flat(), ...buildAppContext.output];
|
|
3441
|
+
const totalSize = allOutput.reduce((sum, chunk) => {
|
|
3103
3442
|
const content = chunk.type === "chunk" ? chunk.code : chunk.source;
|
|
3104
3443
|
if (content == null) return sum;
|
|
3105
3444
|
return sum + (typeof content === "string" ? Buffer.byteLength(content) : content.byteLength);
|
|
3106
3445
|
}, 0);
|
|
3107
|
-
const fileCount =
|
|
3446
|
+
const fileCount = allOutput.length;
|
|
3108
3447
|
const envSuffix = buildableNames.length > 1 ? ` (${buildableNames.join(" + ")})` : "";
|
|
3109
3448
|
logger.info(pc4.green(`\u2713 built in ${elapsed}s`) + pc4.dim(envSuffix));
|
|
3110
3449
|
logger.info(pc4.dim(` ${fileCount} files, ${displaySize(totalSize)} total \u2192 ${config.build.outDir}/`));
|
|
3111
|
-
return {
|
|
3450
|
+
return {
|
|
3451
|
+
output: clientOutput,
|
|
3452
|
+
environments,
|
|
3453
|
+
environmentResults,
|
|
3454
|
+
appOutput: [...buildAppContext.output]
|
|
3455
|
+
};
|
|
3112
3456
|
}
|
|
3113
3457
|
async function buildClientEnvironment(config) {
|
|
3114
3458
|
const logger = config.logger;
|
|
3115
|
-
const outDir =
|
|
3459
|
+
const outDir = path10.resolve(config.root, config.build.outDir);
|
|
3116
3460
|
const cssEngine = createCssEngine();
|
|
3117
|
-
const pluginList = resolvePluginList(config, config.plugins, {
|
|
3461
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
3462
|
+
cssEngine,
|
|
3463
|
+
environmentName: "client"
|
|
3464
|
+
});
|
|
3118
3465
|
const clientEnv = new NastiEnvironment("client", config, {
|
|
3119
3466
|
mode: "build",
|
|
3120
3467
|
plugins: pluginList,
|
|
@@ -3129,13 +3476,11 @@ async function buildClientEnvironment(config) {
|
|
|
3129
3476
|
);
|
|
3130
3477
|
}
|
|
3131
3478
|
const result = await clientEnv.driver.build(clientEnv.getDriverContext());
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
if (config.build.emptyOutDir && fs6.existsSync(outDir)) {
|
|
3135
|
-
fs6.rmSync(outDir, { recursive: true, force: true });
|
|
3479
|
+
assertDriverBuildResult(clientEnv, result);
|
|
3480
|
+
return { environment: clientEnv, result: finalizeEnvironmentResult(clientEnv, result) };
|
|
3136
3481
|
}
|
|
3137
|
-
|
|
3138
|
-
const htmlFile = config.environments.client.html ??
|
|
3482
|
+
fs7.mkdirSync(outDir, { recursive: true });
|
|
3483
|
+
const htmlFile = config.environments.client.html ?? path10.resolve(config.root, "index.html");
|
|
3139
3484
|
const html = await readHtmlFile(config.root, htmlFile);
|
|
3140
3485
|
const entryPoints = resolveClientEntries(config, html);
|
|
3141
3486
|
if (entryPoints.length === 0) {
|
|
@@ -3145,7 +3490,7 @@ async function buildClientEnvironment(config) {
|
|
|
3145
3490
|
const nativeReporter = config.logLevel === "silent" ? null : await tryNativeReporterPlugin(config, logger);
|
|
3146
3491
|
const rolldownPlugins = [
|
|
3147
3492
|
createOxcTransformPlugin(config, clientEnv),
|
|
3148
|
-
...toRolldownPlugins(allPlugins),
|
|
3493
|
+
...toRolldownPlugins(allPlugins, clientEnv),
|
|
3149
3494
|
...nativeReporter ? [nativeReporter] : []
|
|
3150
3495
|
];
|
|
3151
3496
|
const { inputOptions, outputOptions } = getRolldownOptions(
|
|
@@ -3182,13 +3527,16 @@ async function buildClientEnvironment(config) {
|
|
|
3182
3527
|
);
|
|
3183
3528
|
}
|
|
3184
3529
|
}
|
|
3185
|
-
|
|
3530
|
+
fs7.writeFileSync(path10.resolve(outDir, "index.html"), processedHtml);
|
|
3186
3531
|
}
|
|
3187
3532
|
if (!nativeReporter && config.logLevel !== "silent") {
|
|
3188
3533
|
reportBuildOutput(output, config, logger);
|
|
3189
3534
|
}
|
|
3190
3535
|
warnLargeChunks(output, config, logger);
|
|
3191
|
-
return {
|
|
3536
|
+
return {
|
|
3537
|
+
environment: clientEnv,
|
|
3538
|
+
result: finalizeEnvironmentResult(clientEnv, { output })
|
|
3539
|
+
};
|
|
3192
3540
|
} catch (error) {
|
|
3193
3541
|
try {
|
|
3194
3542
|
await clientEnv.close();
|
|
@@ -3204,7 +3552,10 @@ async function buildClientEnvironment(config) {
|
|
|
3204
3552
|
async function buildServerEnvironment(config, name) {
|
|
3205
3553
|
const envOptions = config.environments[name];
|
|
3206
3554
|
const logger = config.logger;
|
|
3207
|
-
const pluginList = resolvePluginList(config, config.plugins, {
|
|
3555
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
3556
|
+
consumer: envOptions.consumer,
|
|
3557
|
+
environmentName: name
|
|
3558
|
+
});
|
|
3208
3559
|
const environment = new NastiEnvironment(name, config, {
|
|
3209
3560
|
mode: "build",
|
|
3210
3561
|
plugins: pluginList,
|
|
@@ -3220,38 +3571,39 @@ async function buildServerEnvironment(config, name) {
|
|
|
3220
3571
|
}
|
|
3221
3572
|
try {
|
|
3222
3573
|
const result = await environment.driver.build(environment.getDriverContext());
|
|
3223
|
-
|
|
3574
|
+
assertDriverBuildResult(environment, result);
|
|
3575
|
+
return { environment, result: finalizeEnvironmentResult(environment, result) };
|
|
3224
3576
|
} catch (error) {
|
|
3225
3577
|
await environment.close();
|
|
3226
3578
|
throw error;
|
|
3227
3579
|
}
|
|
3228
3580
|
}
|
|
3229
3581
|
for (const entry of envOptions.entry) {
|
|
3230
|
-
if (!
|
|
3582
|
+
if (!fs7.existsSync(entry)) {
|
|
3231
3583
|
await environment.close();
|
|
3232
3584
|
throw new Error(`[nasti] environment "${name}" entry not found: ${entry}`);
|
|
3233
3585
|
}
|
|
3234
3586
|
}
|
|
3235
3587
|
const rolldownPlugins = [
|
|
3236
3588
|
createOxcTransformPlugin(config, environment),
|
|
3237
|
-
...toRolldownPlugins(environment.plugins)
|
|
3589
|
+
...toRolldownPlugins(environment.plugins, environment)
|
|
3238
3590
|
];
|
|
3239
3591
|
const { inputOptions, outputOptions, outDir } = getRolldownOptions(
|
|
3240
3592
|
environment,
|
|
3241
3593
|
envOptions.entry,
|
|
3242
3594
|
rolldownPlugins
|
|
3243
3595
|
);
|
|
3244
|
-
|
|
3245
|
-
fs6.rmSync(outDir, { recursive: true, force: true });
|
|
3246
|
-
}
|
|
3247
|
-
fs6.mkdirSync(outDir, { recursive: true });
|
|
3596
|
+
fs7.mkdirSync(outDir, { recursive: true });
|
|
3248
3597
|
const bundle2 = await rolldown(inputOptions);
|
|
3249
3598
|
const { output } = await bundle2.write(outputOptions);
|
|
3250
3599
|
await bundle2.close();
|
|
3251
3600
|
logger.info(
|
|
3252
|
-
pc4.dim(` [${name}] `) + output.map((o) =>
|
|
3601
|
+
pc4.dim(` [${name}] `) + output.map((o) => path10.join(envOptions.build.outDir, o.fileName)).join(pc4.dim(", "))
|
|
3253
3602
|
);
|
|
3254
|
-
return {
|
|
3603
|
+
return {
|
|
3604
|
+
environment,
|
|
3605
|
+
result: finalizeEnvironmentResult(environment, { output })
|
|
3606
|
+
};
|
|
3255
3607
|
}
|
|
3256
3608
|
function injectCssLinks(html, cssEngine, config) {
|
|
3257
3609
|
const cssLinkTags = [];
|
|
@@ -3278,9 +3630,9 @@ function escapeRegExp(string) {
|
|
|
3278
3630
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3279
3631
|
}
|
|
3280
3632
|
function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, urlPrefix) {
|
|
3281
|
-
const rootRelative =
|
|
3282
|
-
const resolvedHtmlFile =
|
|
3283
|
-
const htmlRelative =
|
|
3633
|
+
const rootRelative = path10.relative(config.root, facadeModuleId).split(path10.sep).join("/");
|
|
3634
|
+
const resolvedHtmlFile = path10.resolve(config.root, htmlFile);
|
|
3635
|
+
const htmlRelative = path10.relative(path10.dirname(resolvedHtmlFile), facadeModuleId).split(path10.sep).join("/");
|
|
3284
3636
|
const candidates = /* @__PURE__ */ new Set([
|
|
3285
3637
|
rootRelative,
|
|
3286
3638
|
`/${rootRelative}`,
|
|
@@ -3310,6 +3662,7 @@ var init_build = __esm({
|
|
|
3310
3662
|
init_reporter();
|
|
3311
3663
|
init_debug();
|
|
3312
3664
|
init_plugin_api();
|
|
3665
|
+
init_build_app_context();
|
|
3313
3666
|
debug4 = createDebugger("nasti:build");
|
|
3314
3667
|
NODE_BUILTINS = /* @__PURE__ */ new Set([...builtinModules, ...builtinModules.map((m) => `node:${m}`)]);
|
|
3315
3668
|
}
|
|
@@ -3367,20 +3720,22 @@ __export(middleware_exports, {
|
|
|
3367
3720
|
transformMiddleware: () => transformMiddleware,
|
|
3368
3721
|
transformRequest: () => transformRequest
|
|
3369
3722
|
});
|
|
3370
|
-
import
|
|
3371
|
-
import
|
|
3723
|
+
import path12 from "path";
|
|
3724
|
+
import fs9 from "fs";
|
|
3372
3725
|
import { createRequire as createRequire3 } from "module";
|
|
3373
3726
|
import { fileURLToPath, pathToFileURL as pathToFileURL3 } from "url";
|
|
3374
3727
|
import pc6 from "picocolors";
|
|
3375
|
-
function getReactRefreshRuntimeEsm() {
|
|
3376
|
-
if (__refreshRuntimeCache)
|
|
3728
|
+
function getReactRefreshRuntimeEsm(includeBoundaryHelpers = false) {
|
|
3729
|
+
if (__refreshRuntimeCache) {
|
|
3730
|
+
return includeBoundaryHelpers ? __refreshRuntimeCache + REACT_REFRESH_BOUNDARY_HELPERS : __refreshRuntimeCache;
|
|
3731
|
+
}
|
|
3377
3732
|
let cjsPath;
|
|
3378
3733
|
try {
|
|
3379
3734
|
const pkgPath = __require2.resolve("react-refresh/package.json");
|
|
3380
|
-
cjsPath =
|
|
3735
|
+
cjsPath = path12.join(path12.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
|
|
3381
3736
|
} catch (err) {
|
|
3382
|
-
cjsPath =
|
|
3383
|
-
if (!
|
|
3737
|
+
cjsPath = path12.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
|
|
3738
|
+
if (!fs9.existsSync(cjsPath)) {
|
|
3384
3739
|
const origMsg = err instanceof Error ? err.message : String(err);
|
|
3385
3740
|
throw new Error(
|
|
3386
3741
|
`[nasti] Missing dependency "react-refresh". Install it with: npm install react-refresh
|
|
@@ -3388,7 +3743,7 @@ Original resolve error: ${origMsg}`
|
|
|
3388
3743
|
);
|
|
3389
3744
|
}
|
|
3390
3745
|
}
|
|
3391
|
-
const cjsSource =
|
|
3746
|
+
const cjsSource = fs9.readFileSync(cjsPath, "utf-8");
|
|
3392
3747
|
__refreshRuntimeCache = `// Wrapped react-refresh runtime -> ESM
|
|
3393
3748
|
const exports = {};
|
|
3394
3749
|
const module = { exports };
|
|
@@ -3408,7 +3763,7 @@ export const findAffectedHostInstances = __rt.findAffectedHostInstances;
|
|
|
3408
3763
|
export const collectCustomHooksForSignature = __rt.collectCustomHooksForSignature;
|
|
3409
3764
|
export default __rt;
|
|
3410
3765
|
`;
|
|
3411
|
-
return __refreshRuntimeCache;
|
|
3766
|
+
return includeBoundaryHelpers ? __refreshRuntimeCache + REACT_REFRESH_BOUNDARY_HELPERS : __refreshRuntimeCache;
|
|
3412
3767
|
}
|
|
3413
3768
|
function buildReactRefreshWrapper(moduleUrl, transformedCode) {
|
|
3414
3769
|
const urlLit = JSON.stringify(moduleUrl);
|
|
@@ -3434,22 +3789,40 @@ window.$RefreshReg$ = prevRefreshReg;
|
|
|
3434
3789
|
window.$RefreshSig$ = prevRefreshSig;
|
|
3435
3790
|
|
|
3436
3791
|
if (__nasti_hot__) {
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3792
|
+
let __nasti_current_exports__;
|
|
3793
|
+
__nasti_hot__.accept((nextExports) => {
|
|
3794
|
+
if (!nextExports) return;
|
|
3795
|
+
if (!__nasti_current_exports__) {
|
|
3796
|
+
__nasti_hot__.invalidate('Could not Fast Refresh (previous exports unavailable)');
|
|
3797
|
+
return;
|
|
3798
|
+
}
|
|
3799
|
+
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(
|
|
3800
|
+
${urlLit},
|
|
3801
|
+
__nasti_current_exports__,
|
|
3802
|
+
nextExports,
|
|
3803
|
+
);
|
|
3804
|
+
if (invalidateMessage) __nasti_hot__.invalidate(invalidateMessage);
|
|
3805
|
+
});
|
|
3806
|
+
RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
|
|
3807
|
+
__nasti_current_exports__ = currentExports;
|
|
3808
|
+
RefreshRuntime.registerExportsForReactRefresh(${urlLit}, currentExports);
|
|
3442
3809
|
});
|
|
3443
3810
|
}
|
|
3444
3811
|
`;
|
|
3445
3812
|
}
|
|
3446
3813
|
function injectImportMetaHot(code, moduleUrl) {
|
|
3447
|
-
|
|
3814
|
+
const hotRE = /\bimport\.meta\.hot\b/g;
|
|
3815
|
+
const matches = [...maskStringsAndComments(code).matchAll(hotRE)];
|
|
3816
|
+
if (matches.length === 0) return code;
|
|
3817
|
+
for (const match of matches.reverse()) {
|
|
3818
|
+
const start = match.index;
|
|
3819
|
+
code = code.slice(0, start) + "__nasti_hot__" + code.slice(start + match[0].length);
|
|
3820
|
+
}
|
|
3448
3821
|
const urlLit = JSON.stringify(moduleUrl);
|
|
3449
3822
|
const header = `import { createHotContext as __nasti_createHotContext__ } from "/@nasti/client";
|
|
3450
3823
|
const __nasti_hot__ = __nasti_createHotContext__(${urlLit});
|
|
3451
3824
|
`;
|
|
3452
|
-
return header + code
|
|
3825
|
+
return header + code;
|
|
3453
3826
|
}
|
|
3454
3827
|
function transformMiddleware(ctx) {
|
|
3455
3828
|
ctx.envDefine = buildEnvDefine(
|
|
@@ -3525,13 +3898,14 @@ function transformMiddleware(ctx) {
|
|
|
3525
3898
|
}
|
|
3526
3899
|
async function transformRequest(url, ctx) {
|
|
3527
3900
|
const { config, pluginContainer, moduleGraph } = ctx;
|
|
3901
|
+
url = removeTimestampQuery(url);
|
|
3528
3902
|
const cleanReqUrl = url.split("?")[0];
|
|
3529
3903
|
const cached2 = moduleGraph.getModuleByUrl(url);
|
|
3530
3904
|
if (cached2?.transformResult) {
|
|
3531
3905
|
return cached2.transformResult;
|
|
3532
3906
|
}
|
|
3533
3907
|
if (cleanReqUrl === "/@react-refresh") {
|
|
3534
|
-
return { code: getReactRefreshRuntimeEsm() };
|
|
3908
|
+
return { code: getReactRefreshRuntimeEsm(true) };
|
|
3535
3909
|
}
|
|
3536
3910
|
if (cleanReqUrl.startsWith("/@modules/") && url.includes("?")) {
|
|
3537
3911
|
const idParam = new URLSearchParams(url.slice(url.indexOf("?") + 1)).get("id");
|
|
@@ -3539,8 +3913,8 @@ async function transformRequest(url, ctx) {
|
|
|
3539
3913
|
let realIdValid = false;
|
|
3540
3914
|
try {
|
|
3541
3915
|
if (idParam) {
|
|
3542
|
-
realId =
|
|
3543
|
-
realIdValid =
|
|
3916
|
+
realId = fs9.realpathSync(idParam);
|
|
3917
|
+
realIdValid = fs9.statSync(realId).isFile() && (realId.includes(`${path12.sep}node_modules${path12.sep}`) || isUnderRoot(realId, config.root));
|
|
3544
3918
|
}
|
|
3545
3919
|
} catch {
|
|
3546
3920
|
realId = null;
|
|
@@ -3567,6 +3941,8 @@ async function transformRequest(url, ctx) {
|
|
|
3567
3941
|
}
|
|
3568
3942
|
const rawQuery = url.includes("?") ? url.slice(url.indexOf("?") + 1) : "";
|
|
3569
3943
|
if (rawQuery && !/^t=\d+$/.test(rawQuery)) {
|
|
3944
|
+
const mod2 = await moduleGraph.ensureEntryFromUrl(url);
|
|
3945
|
+
const transformVersion2 = mod2.invalidationVersion;
|
|
3570
3946
|
const loaded = await pluginContainer.load(url);
|
|
3571
3947
|
if (loaded != null) {
|
|
3572
3948
|
let code2 = typeof loaded === "string" ? loaded : loaded.code;
|
|
@@ -3574,30 +3950,43 @@ async function transformRequest(url, ctx) {
|
|
|
3574
3950
|
if (transformed != null) {
|
|
3575
3951
|
code2 = typeof transformed === "string" ? transformed : transformed.code;
|
|
3576
3952
|
}
|
|
3577
|
-
const
|
|
3578
|
-
moduleGraph.registerModule(mod2,
|
|
3579
|
-
|
|
3953
|
+
const parentFile = resolveUrlToFile(cleanReqUrl, config.root) ?? cleanReqUrl;
|
|
3954
|
+
moduleGraph.registerModule(mod2, parentFile);
|
|
3955
|
+
const hotInfo2 = rewriteHotAcceptDeps(code2, config, parentFile);
|
|
3956
|
+
code2 = injectImportMetaHot(hotInfo2.code, url);
|
|
3580
3957
|
code2 = replaceEnvInCode(code2, ctx.envDefine ?? buildEnvDefine(
|
|
3581
3958
|
loadEnv(config.mode, config.root, config.envPrefix),
|
|
3582
3959
|
config.mode
|
|
3583
3960
|
));
|
|
3584
|
-
|
|
3961
|
+
const importedUrls2 = /* @__PURE__ */ new Set();
|
|
3962
|
+
code2 = rewriteImports(code2, config, parentFile, importedUrls2, moduleGraph);
|
|
3963
|
+
const pruned2 = await moduleGraph.updateModuleInfo(
|
|
3964
|
+
mod2,
|
|
3965
|
+
importedUrls2,
|
|
3966
|
+
hotInfo2.acceptedUrls,
|
|
3967
|
+
hotInfo2.isSelfAccepting,
|
|
3968
|
+
transformVersion2
|
|
3969
|
+
);
|
|
3585
3970
|
const transformResult2 = { code: code2 };
|
|
3586
|
-
|
|
3971
|
+
if (pruned2) {
|
|
3972
|
+
if (pruned2.size > 0) ctx.onPrune?.([...pruned2].map((item) => item.url));
|
|
3973
|
+
mod2.transformResult = transformResult2;
|
|
3974
|
+
}
|
|
3587
3975
|
return transformResult2;
|
|
3588
3976
|
}
|
|
3589
3977
|
}
|
|
3590
3978
|
const filePath = resolveUrlToFile(url, config.root);
|
|
3591
|
-
if (!filePath || !
|
|
3979
|
+
if (!filePath || !fs9.existsSync(filePath)) return null;
|
|
3592
3980
|
const mod = await moduleGraph.ensureEntryFromUrl(url);
|
|
3593
3981
|
moduleGraph.registerModule(mod, filePath);
|
|
3982
|
+
const transformVersion = mod.invalidationVersion;
|
|
3594
3983
|
if (cleanReqUrl.startsWith("/@modules/")) {
|
|
3595
3984
|
const code2 = await bundlePackageAsEsm(filePath, config.root);
|
|
3596
3985
|
const transformResult2 = { code: code2 };
|
|
3597
3986
|
mod.transformResult = transformResult2;
|
|
3598
3987
|
return transformResult2;
|
|
3599
3988
|
}
|
|
3600
|
-
let code =
|
|
3989
|
+
let code = fs9.readFileSync(filePath, "utf-8");
|
|
3601
3990
|
const pluginResult = await pluginContainer.transform(code, filePath);
|
|
3602
3991
|
if (pluginResult) {
|
|
3603
3992
|
code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
|
|
@@ -3617,9 +4006,10 @@ async function transformRequest(url, ctx) {
|
|
|
3617
4006
|
if (useRefresh) {
|
|
3618
4007
|
code = buildReactRefreshWrapper(stableUrl, code);
|
|
3619
4008
|
wrappedWithRefresh = true;
|
|
3620
|
-
mod.isSelfAccepting = true;
|
|
3621
4009
|
}
|
|
3622
4010
|
}
|
|
4011
|
+
const hotInfo = rewriteHotAcceptDeps(code, config, filePath);
|
|
4012
|
+
code = hotInfo.code;
|
|
3623
4013
|
if (!wrappedWithRefresh) {
|
|
3624
4014
|
code = injectImportMetaHot(code, stableUrl);
|
|
3625
4015
|
}
|
|
@@ -3628,9 +4018,20 @@ async function transformRequest(url, ctx) {
|
|
|
3628
4018
|
config.mode
|
|
3629
4019
|
);
|
|
3630
4020
|
code = replaceEnvInCode(code, envDefine);
|
|
3631
|
-
|
|
4021
|
+
const importedUrls = /* @__PURE__ */ new Set();
|
|
4022
|
+
code = rewriteImports(code, config, filePath, importedUrls, moduleGraph);
|
|
4023
|
+
const pruned = await moduleGraph.updateModuleInfo(
|
|
4024
|
+
mod,
|
|
4025
|
+
importedUrls,
|
|
4026
|
+
hotInfo.acceptedUrls,
|
|
4027
|
+
wrappedWithRefresh || hotInfo.isSelfAccepting,
|
|
4028
|
+
transformVersion
|
|
4029
|
+
);
|
|
3632
4030
|
const transformResult = { code };
|
|
3633
|
-
|
|
4031
|
+
if (pruned) {
|
|
4032
|
+
if (pruned.size > 0) ctx.onPrune?.([...pruned].map((item) => item.url));
|
|
4033
|
+
mod.transformResult = transformResult;
|
|
4034
|
+
}
|
|
3634
4035
|
return transformResult;
|
|
3635
4036
|
}
|
|
3636
4037
|
async function loadVirtualModule(spec, ctx) {
|
|
@@ -3638,7 +4039,7 @@ async function loadVirtualModule(spec, ctx) {
|
|
|
3638
4039
|
const resolved = await pluginContainer.resolveId(spec);
|
|
3639
4040
|
if (resolved == null) return null;
|
|
3640
4041
|
const resolvedId = typeof resolved === "string" ? resolved : resolved.id;
|
|
3641
|
-
const looksVirtual = resolvedId.startsWith("\0") || !
|
|
4042
|
+
const looksVirtual = resolvedId.startsWith("\0") || !fs9.existsSync(resolvedId);
|
|
3642
4043
|
if (!looksVirtual) return null;
|
|
3643
4044
|
const loadResult = await pluginContainer.load(resolvedId);
|
|
3644
4045
|
if (loadResult == null) return null;
|
|
@@ -3651,7 +4052,7 @@ async function loadVirtualModule(spec, ctx) {
|
|
|
3651
4052
|
loadEnv(config.mode, config.root, config.envPrefix),
|
|
3652
4053
|
config.mode
|
|
3653
4054
|
));
|
|
3654
|
-
const anchor =
|
|
4055
|
+
const anchor = path12.join(config.root, "__nasti_virtual__.ts");
|
|
3655
4056
|
code = rewriteImports(code, config, anchor);
|
|
3656
4057
|
return { id: resolvedId, result: { code } };
|
|
3657
4058
|
}
|
|
@@ -3677,7 +4078,7 @@ async function doBundlePackage(entryFile, root) {
|
|
|
3677
4078
|
await bundle2.close();
|
|
3678
4079
|
let code = result.output[0].code;
|
|
3679
4080
|
code = code.replace(/process\.env\.NODE_ENV/g, '"development"');
|
|
3680
|
-
const externalBaseDir =
|
|
4081
|
+
const externalBaseDir = path12.dirname(entryFile);
|
|
3681
4082
|
code = code.replace(
|
|
3682
4083
|
/^(import\b[^;'"]*?\bfrom\s+)(['"])([^'"./][^'"]*)(\2)/gm,
|
|
3683
4084
|
(_, prefix, q, spec) => `${prefix}${q}${externalSpecToModuleUrl(spec, externalBaseDir, root)}${q}`
|
|
@@ -3695,16 +4096,16 @@ async function doBundlePackage(entryFile, root) {
|
|
|
3695
4096
|
return code;
|
|
3696
4097
|
}
|
|
3697
4098
|
async function tryGenerateSubpathShim(entryFile, root) {
|
|
3698
|
-
const NM = `${
|
|
4099
|
+
const NM = `${path12.sep}node_modules${path12.sep}`;
|
|
3699
4100
|
if (!entryFile.includes(NM)) return null;
|
|
3700
4101
|
let pkgDir = null;
|
|
3701
4102
|
let pkgName = null;
|
|
3702
|
-
let dir =
|
|
4103
|
+
let dir = path12.dirname(entryFile);
|
|
3703
4104
|
while (true) {
|
|
3704
|
-
const pkgJsonPath =
|
|
3705
|
-
if (
|
|
4105
|
+
const pkgJsonPath = path12.join(dir, "package.json");
|
|
4106
|
+
if (fs9.existsSync(pkgJsonPath)) {
|
|
3706
4107
|
try {
|
|
3707
|
-
const pkg = JSON.parse(
|
|
4108
|
+
const pkg = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
|
|
3708
4109
|
if (typeof pkg?.name === "string" && pkg.name) {
|
|
3709
4110
|
pkgDir = dir;
|
|
3710
4111
|
pkgName = pkg.name;
|
|
@@ -3713,16 +4114,16 @@ async function tryGenerateSubpathShim(entryFile, root) {
|
|
|
3713
4114
|
} catch {
|
|
3714
4115
|
}
|
|
3715
4116
|
}
|
|
3716
|
-
const parent =
|
|
4117
|
+
const parent = path12.dirname(dir);
|
|
3717
4118
|
if (parent === dir) return null;
|
|
3718
4119
|
dir = parent;
|
|
3719
4120
|
if (!dir.includes(NM)) return null;
|
|
3720
4121
|
}
|
|
3721
4122
|
if (!pkgDir || !pkgName) return null;
|
|
3722
|
-
const entryExt =
|
|
4123
|
+
const entryExt = path12.extname(entryFile);
|
|
3723
4124
|
const mainEntry = pickMainEntryByExtension(pkgDir, entryExt);
|
|
3724
4125
|
if (!mainEntry) return null;
|
|
3725
|
-
if (
|
|
4126
|
+
if (path12.resolve(mainEntry) === path12.resolve(entryFile)) return null;
|
|
3726
4127
|
let mainNs;
|
|
3727
4128
|
let subNs;
|
|
3728
4129
|
try {
|
|
@@ -3746,7 +4147,7 @@ async function tryGenerateSubpathShim(entryFile, root) {
|
|
|
3746
4147
|
if (mainNs["default"] !== subNs["default"]) return null;
|
|
3747
4148
|
}
|
|
3748
4149
|
const rootMain = resolveNodeModule(root, pkgName);
|
|
3749
|
-
const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir +
|
|
4150
|
+
const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir + path12.sep) ? `/@modules/${pkgName}` : `/@modules/${pkgName}?id=${encodeURIComponent(mainEntry)}`;
|
|
3750
4151
|
const lines = [
|
|
3751
4152
|
`// Nasti subpath shim \u2192 ${pkgName} (avoid duplicate bundling)`,
|
|
3752
4153
|
`import * as __pkg from "${mainEntryUrl}";`
|
|
@@ -3760,10 +4161,10 @@ async function tryGenerateSubpathShim(entryFile, root) {
|
|
|
3760
4161
|
return lines.join("\n") + "\n";
|
|
3761
4162
|
}
|
|
3762
4163
|
function pickMainEntryByExtension(pkgDir, preferredExt) {
|
|
3763
|
-
const pkgJsonPath =
|
|
4164
|
+
const pkgJsonPath = path12.join(pkgDir, "package.json");
|
|
3764
4165
|
let pkg;
|
|
3765
4166
|
try {
|
|
3766
|
-
pkg = JSON.parse(
|
|
4167
|
+
pkg = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
|
|
3767
4168
|
} catch {
|
|
3768
4169
|
return null;
|
|
3769
4170
|
}
|
|
@@ -3782,14 +4183,14 @@ function pickMainEntryByExtension(pkgDir, preferredExt) {
|
|
|
3782
4183
|
if (typeof pkg.module === "string") candidates.push(pkg.module);
|
|
3783
4184
|
if (typeof pkg.main === "string") candidates.push(pkg.main);
|
|
3784
4185
|
for (const cand of candidates) {
|
|
3785
|
-
if (
|
|
3786
|
-
const full =
|
|
3787
|
-
if (
|
|
4186
|
+
if (path12.extname(cand) === preferredExt) {
|
|
4187
|
+
const full = path12.resolve(pkgDir, cand);
|
|
4188
|
+
if (fs9.existsSync(full)) return full;
|
|
3788
4189
|
}
|
|
3789
4190
|
}
|
|
3790
4191
|
for (const cand of candidates) {
|
|
3791
|
-
const full =
|
|
3792
|
-
if (
|
|
4192
|
+
const full = path12.resolve(pkgDir, cand);
|
|
4193
|
+
if (fs9.existsSync(full)) return full;
|
|
3793
4194
|
}
|
|
3794
4195
|
return null;
|
|
3795
4196
|
}
|
|
@@ -3835,72 +4236,231 @@ async function injectCjsNamedExports(code, entryFile) {
|
|
|
3835
4236
|
return code;
|
|
3836
4237
|
}
|
|
3837
4238
|
}
|
|
3838
|
-
function rewriteImports(code, config, filePath) {
|
|
4239
|
+
function rewriteImports(code, config, filePath, importedUrls, moduleGraph) {
|
|
4240
|
+
const resolveSpec = createModuleSpecifierResolver(config, filePath);
|
|
4241
|
+
const transformSpec = (spec) => {
|
|
4242
|
+
const resolved = removeTimestampQuery(resolveSpec(spec));
|
|
4243
|
+
importedUrls?.add(resolved);
|
|
4244
|
+
const timestamp = moduleGraph?.getModuleByUrl(resolved)?.lastHMRTimestamp ?? 0;
|
|
4245
|
+
return timestamp > 0 ? appendTimestampQuery(resolved, timestamp) : resolved;
|
|
4246
|
+
};
|
|
4247
|
+
return code.replace(
|
|
4248
|
+
/\bfrom\s+(['"])([^'"]+)\1/g,
|
|
4249
|
+
(_m, q, s) => `from ${q}${transformSpec(s)}${q}`
|
|
4250
|
+
).replace(
|
|
4251
|
+
/\bimport\s+(['"])([^'"]+)\1/g,
|
|
4252
|
+
(_m, q, s) => `import ${q}${transformSpec(s)}${q}`
|
|
4253
|
+
).replace(
|
|
4254
|
+
/\bimport\s*\(\s*(['"])([^'"]+)\1\s*\)/g,
|
|
4255
|
+
(_m, q, s) => `import(${q}${transformSpec(s)}${q})`
|
|
4256
|
+
);
|
|
4257
|
+
}
|
|
4258
|
+
function createModuleSpecifierResolver(config, filePath) {
|
|
3839
4259
|
const root = config.root;
|
|
3840
|
-
const fileDir =
|
|
4260
|
+
const fileDir = path12.dirname(filePath);
|
|
3841
4261
|
const aliasEntries = Object.entries(config.resolve.alias).sort(
|
|
3842
4262
|
([a], [b]) => b.length - a.length
|
|
3843
4263
|
);
|
|
3844
|
-
const toRootUrl = (abs) => "/" +
|
|
3845
|
-
|
|
3846
|
-
const suffixMatch =
|
|
4264
|
+
const toRootUrl = (abs) => "/" + path12.relative(root, abs).replace(/\\/g, "/");
|
|
4265
|
+
return (specifier) => {
|
|
4266
|
+
const suffixMatch = specifier.match(/[?#].*$/);
|
|
3847
4267
|
const suffix = suffixMatch ? suffixMatch[0] : "";
|
|
3848
|
-
const baseSpec = suffix ?
|
|
4268
|
+
const baseSpec = suffix ? specifier.slice(0, -suffix.length) : specifier;
|
|
3849
4269
|
for (const [key, value] of aliasEntries) {
|
|
3850
4270
|
if (baseSpec === key || baseSpec.startsWith(key + "/")) {
|
|
3851
4271
|
const aliasBase = resolveAliasTarget2(value, root);
|
|
3852
4272
|
const sub = baseSpec.slice(key.length).replace(/^\//, "");
|
|
3853
|
-
const target = sub ?
|
|
4273
|
+
const target = sub ? path12.join(aliasBase, sub) : aliasBase;
|
|
3854
4274
|
const resolved = tryResolveDiskPath(target);
|
|
3855
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix :
|
|
4275
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
3856
4276
|
}
|
|
3857
4277
|
}
|
|
3858
4278
|
if (baseSpec.startsWith("./") || baseSpec.startsWith("../")) {
|
|
3859
|
-
const
|
|
3860
|
-
|
|
3861
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
|
|
4279
|
+
const resolved = tryResolveDiskPath(path12.resolve(fileDir, baseSpec));
|
|
4280
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
3862
4281
|
}
|
|
3863
4282
|
if (baseSpec.startsWith("/") && !baseSpec.startsWith("/@")) {
|
|
3864
|
-
const
|
|
3865
|
-
|
|
3866
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
|
|
4283
|
+
const resolved = tryResolveDiskPath(path12.join(root, baseSpec.replace(/^\//, "")));
|
|
4284
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
3867
4285
|
}
|
|
3868
|
-
if (baseSpec.startsWith("/")) return
|
|
3869
|
-
return `/@modules/${
|
|
4286
|
+
if (baseSpec.startsWith("/")) return specifier;
|
|
4287
|
+
return `/@modules/${specifier}`;
|
|
3870
4288
|
};
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
)
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
)
|
|
4289
|
+
}
|
|
4290
|
+
function rewriteHotAcceptDeps(code, config, filePath) {
|
|
4291
|
+
const acceptedUrls = /* @__PURE__ */ new Set();
|
|
4292
|
+
const edits = [];
|
|
4293
|
+
const resolveSpec = createModuleSpecifierResolver(config, filePath);
|
|
4294
|
+
const acceptRE = /(?:\bimport\.meta\.hot|\b__nasti_hot__)(?:(?:\?\.)|\.)accept\s*\(/g;
|
|
4295
|
+
const searchableCode = maskStringsAndComments(code);
|
|
4296
|
+
let isSelfAccepting = false;
|
|
4297
|
+
let match;
|
|
4298
|
+
while (match = acceptRE.exec(searchableCode)) {
|
|
4299
|
+
let cursor = match.index + match[0].length;
|
|
4300
|
+
const skipTrivia = () => {
|
|
4301
|
+
while (cursor < code.length) {
|
|
4302
|
+
if (/\s/.test(code[cursor])) {
|
|
4303
|
+
cursor++;
|
|
4304
|
+
continue;
|
|
4305
|
+
}
|
|
4306
|
+
if (code[cursor] === "/" && code[cursor + 1] === "/") {
|
|
4307
|
+
cursor += 2;
|
|
4308
|
+
while (cursor < code.length && code[cursor] !== "\n") cursor++;
|
|
4309
|
+
continue;
|
|
4310
|
+
}
|
|
4311
|
+
if (code[cursor] === "/" && code[cursor + 1] === "*") {
|
|
4312
|
+
cursor += 2;
|
|
4313
|
+
while (cursor < code.length && !(code[cursor] === "*" && code[cursor + 1] === "/")) cursor++;
|
|
4314
|
+
cursor += 2;
|
|
4315
|
+
continue;
|
|
4316
|
+
}
|
|
4317
|
+
break;
|
|
4318
|
+
}
|
|
4319
|
+
};
|
|
4320
|
+
skipTrivia();
|
|
4321
|
+
const first = code[cursor];
|
|
4322
|
+
if (!first || first === ")" || first !== "[" && first !== "'" && first !== '"' && first !== "`") {
|
|
4323
|
+
isSelfAccepting = true;
|
|
4324
|
+
continue;
|
|
4325
|
+
}
|
|
4326
|
+
const readLiteral = () => {
|
|
4327
|
+
const quote = code[cursor];
|
|
4328
|
+
if (quote !== "'" && quote !== '"' && quote !== "`") return;
|
|
4329
|
+
const start = cursor;
|
|
4330
|
+
cursor++;
|
|
4331
|
+
let raw = "";
|
|
4332
|
+
while (cursor < code.length) {
|
|
4333
|
+
const char = code[cursor];
|
|
4334
|
+
if (char === "\\") {
|
|
4335
|
+
raw += code[cursor + 1] ?? "";
|
|
4336
|
+
cursor += 2;
|
|
4337
|
+
continue;
|
|
4338
|
+
}
|
|
4339
|
+
if (char === quote) {
|
|
4340
|
+
cursor++;
|
|
4341
|
+
const resolved = removeTimestampQuery(resolveSpec(raw));
|
|
4342
|
+
acceptedUrls.add(resolved);
|
|
4343
|
+
edits.push({ start, end: cursor, value: JSON.stringify(resolved) });
|
|
4344
|
+
return;
|
|
4345
|
+
}
|
|
4346
|
+
if (quote === "`" && char === "$" && code[cursor + 1] === "{") return;
|
|
4347
|
+
raw += char;
|
|
4348
|
+
cursor++;
|
|
4349
|
+
}
|
|
4350
|
+
};
|
|
4351
|
+
if (first === "[") {
|
|
4352
|
+
cursor++;
|
|
4353
|
+
while (cursor < code.length) {
|
|
4354
|
+
skipTrivia();
|
|
4355
|
+
if (code[cursor] === ",") {
|
|
4356
|
+
cursor++;
|
|
4357
|
+
skipTrivia();
|
|
4358
|
+
}
|
|
4359
|
+
if (code[cursor] === "]") break;
|
|
4360
|
+
const before = cursor;
|
|
4361
|
+
readLiteral();
|
|
4362
|
+
if (cursor === before) break;
|
|
4363
|
+
}
|
|
4364
|
+
} else {
|
|
4365
|
+
readLiteral();
|
|
4366
|
+
}
|
|
4367
|
+
}
|
|
4368
|
+
for (const edit of edits.sort((a, b) => b.start - a.start)) {
|
|
4369
|
+
code = code.slice(0, edit.start) + edit.value + code.slice(edit.end);
|
|
4370
|
+
}
|
|
4371
|
+
return { code, acceptedUrls, isSelfAccepting };
|
|
4372
|
+
}
|
|
4373
|
+
function maskStringsAndComments(code) {
|
|
4374
|
+
const masked = code.split("");
|
|
4375
|
+
let state = "code";
|
|
4376
|
+
const isRegexStart = (index2) => {
|
|
4377
|
+
let previous = index2 - 1;
|
|
4378
|
+
while (previous >= 0 && /\s/.test(code[previous])) previous--;
|
|
4379
|
+
return previous < 0 || "=(:,!&|?{};[]+-*%^~<>".includes(code[previous]);
|
|
4380
|
+
};
|
|
4381
|
+
for (let i = 0; i < code.length; i++) {
|
|
4382
|
+
const char = code[i];
|
|
4383
|
+
const next = code[i + 1];
|
|
4384
|
+
if (state === "code") {
|
|
4385
|
+
if (char === "'") state = "single";
|
|
4386
|
+
else if (char === '"') state = "double";
|
|
4387
|
+
else if (char === "`") state = "template";
|
|
4388
|
+
else if (char === "/" && next === "/") state = "line-comment";
|
|
4389
|
+
else if (char === "/" && next === "*") state = "block-comment";
|
|
4390
|
+
else if (char === "/" && isRegexStart(i)) state = "regex";
|
|
4391
|
+
else continue;
|
|
4392
|
+
masked[i] = " ";
|
|
4393
|
+
continue;
|
|
4394
|
+
}
|
|
4395
|
+
if (state === "line-comment") {
|
|
4396
|
+
if (char === "\n") {
|
|
4397
|
+
state = "code";
|
|
4398
|
+
} else {
|
|
4399
|
+
masked[i] = " ";
|
|
4400
|
+
}
|
|
4401
|
+
continue;
|
|
4402
|
+
}
|
|
4403
|
+
if (state === "block-comment") {
|
|
4404
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
4405
|
+
if (char === "*" && next === "/") {
|
|
4406
|
+
masked[i + 1] = " ";
|
|
4407
|
+
i++;
|
|
4408
|
+
state = "code";
|
|
4409
|
+
}
|
|
4410
|
+
continue;
|
|
4411
|
+
}
|
|
4412
|
+
if (state === "regex" || state === "regex-class") {
|
|
4413
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
4414
|
+
if (char === "\\") {
|
|
4415
|
+
if (i + 1 < code.length) masked[++i] = " ";
|
|
4416
|
+
} else if (state === "regex" && char === "[") {
|
|
4417
|
+
state = "regex-class";
|
|
4418
|
+
} else if (state === "regex-class" && char === "]") {
|
|
4419
|
+
state = "regex";
|
|
4420
|
+
} else if (state === "regex" && char === "/") {
|
|
4421
|
+
state = "code";
|
|
4422
|
+
}
|
|
4423
|
+
continue;
|
|
4424
|
+
}
|
|
4425
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
4426
|
+
if (char === "\\") {
|
|
4427
|
+
if (i + 1 < code.length) masked[++i] = " ";
|
|
4428
|
+
continue;
|
|
4429
|
+
}
|
|
4430
|
+
if (state === "single" && char === "'" || state === "double" && char === '"' || state === "template" && char === "`") {
|
|
4431
|
+
state = "code";
|
|
4432
|
+
}
|
|
4433
|
+
}
|
|
4434
|
+
return masked.join("");
|
|
3881
4435
|
}
|
|
3882
4436
|
function resolveAliasTarget2(value, root) {
|
|
3883
|
-
if (
|
|
3884
|
-
if (value.startsWith("/")) return
|
|
3885
|
-
return
|
|
4437
|
+
if (path12.isAbsolute(value) && fs9.existsSync(value)) return value;
|
|
4438
|
+
if (value.startsWith("/")) return path12.join(root, value.slice(1));
|
|
4439
|
+
return path12.resolve(root, value);
|
|
3886
4440
|
}
|
|
3887
4441
|
function tryResolveDiskPath(target) {
|
|
3888
|
-
if (
|
|
4442
|
+
if (fs9.existsSync(target) && fs9.statSync(target).isFile()) return target;
|
|
3889
4443
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
3890
4444
|
const withExt = target + ext;
|
|
3891
|
-
if (
|
|
4445
|
+
if (fs9.existsSync(withExt) && fs9.statSync(withExt).isFile()) return withExt;
|
|
3892
4446
|
}
|
|
3893
|
-
if (
|
|
4447
|
+
if (fs9.existsSync(target) && fs9.statSync(target).isDirectory()) {
|
|
3894
4448
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
3895
|
-
const idx =
|
|
3896
|
-
if (
|
|
4449
|
+
const idx = path12.join(target, "index" + ext);
|
|
4450
|
+
if (fs9.existsSync(idx) && fs9.statSync(idx).isFile()) return idx;
|
|
3897
4451
|
}
|
|
3898
4452
|
}
|
|
3899
4453
|
return null;
|
|
3900
4454
|
}
|
|
3901
4455
|
function isUnderRoot(abs, root) {
|
|
3902
|
-
const rel =
|
|
3903
|
-
return !!rel && !rel.startsWith("..") && !
|
|
4456
|
+
const rel = path12.relative(root, abs);
|
|
4457
|
+
return !!rel && !rel.startsWith("..") && !path12.isAbsolute(rel);
|
|
4458
|
+
}
|
|
4459
|
+
function appendTimestampQuery(url, timestamp) {
|
|
4460
|
+
const hashIndex = url.indexOf("#");
|
|
4461
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
|
|
4462
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
4463
|
+
return `${withoutHash}${withoutHash.includes("?") ? "&" : "?"}t=${timestamp}${hash}`;
|
|
3904
4464
|
}
|
|
3905
4465
|
function externalSpecToModuleUrl(spec, baseDir, root) {
|
|
3906
4466
|
const resolved = resolveNodeModule(baseDir, spec);
|
|
@@ -3913,7 +4473,7 @@ function resolveNodeModule(baseDir, moduleName) {
|
|
|
3913
4473
|
const resolved = resolveNodeModuleEntry(baseDir, moduleName);
|
|
3914
4474
|
if (!resolved) return null;
|
|
3915
4475
|
try {
|
|
3916
|
-
return
|
|
4476
|
+
return fs9.realpathSync(resolved);
|
|
3917
4477
|
} catch {
|
|
3918
4478
|
return resolved;
|
|
3919
4479
|
}
|
|
@@ -3933,21 +4493,21 @@ function resolveNodeModuleEntry(root, moduleName) {
|
|
|
3933
4493
|
let pkgDir = null;
|
|
3934
4494
|
let dir = root;
|
|
3935
4495
|
for (; ; ) {
|
|
3936
|
-
const candidate =
|
|
3937
|
-
if (
|
|
4496
|
+
const candidate = path12.join(dir, "node_modules", pkgName);
|
|
4497
|
+
if (fs9.existsSync(candidate)) {
|
|
3938
4498
|
pkgDir = candidate;
|
|
3939
4499
|
break;
|
|
3940
4500
|
}
|
|
3941
|
-
const parent =
|
|
4501
|
+
const parent = path12.dirname(dir);
|
|
3942
4502
|
if (parent === dir) break;
|
|
3943
4503
|
dir = parent;
|
|
3944
4504
|
}
|
|
3945
4505
|
if (!pkgDir) return null;
|
|
3946
|
-
const pkgJsonPath =
|
|
3947
|
-
if (!
|
|
4506
|
+
const pkgJsonPath = path12.join(pkgDir, "package.json");
|
|
4507
|
+
if (!fs9.existsSync(pkgJsonPath)) return null;
|
|
3948
4508
|
let pkg;
|
|
3949
4509
|
try {
|
|
3950
|
-
pkg = JSON.parse(
|
|
4510
|
+
pkg = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
|
|
3951
4511
|
} catch {
|
|
3952
4512
|
return null;
|
|
3953
4513
|
}
|
|
@@ -3960,32 +4520,32 @@ function resolveNodeModuleEntry(root, moduleName) {
|
|
|
3960
4520
|
const subDirs = [""];
|
|
3961
4521
|
for (const field of ["module", "main"]) {
|
|
3962
4522
|
if (typeof pkg[field] === "string") {
|
|
3963
|
-
const dir2 =
|
|
4523
|
+
const dir2 = path12.dirname(pkg[field]);
|
|
3964
4524
|
if (dir2 && dir2 !== "." && !subDirs.includes(dir2)) subDirs.push(dir2);
|
|
3965
4525
|
}
|
|
3966
4526
|
}
|
|
3967
4527
|
for (const dir2 of subDirs) {
|
|
3968
|
-
const direct =
|
|
3969
|
-
if (
|
|
4528
|
+
const direct = path12.join(pkgDir, dir2, subpath);
|
|
4529
|
+
if (fs9.existsSync(direct) && fs9.statSync(direct).isFile()) return direct;
|
|
3970
4530
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
3971
|
-
if (
|
|
4531
|
+
if (fs9.existsSync(direct + ext)) return direct + ext;
|
|
3972
4532
|
}
|
|
3973
4533
|
}
|
|
3974
4534
|
return null;
|
|
3975
4535
|
}
|
|
3976
4536
|
for (const field of ["module", "jsnext:main", "jsnext", "main"]) {
|
|
3977
4537
|
if (typeof pkg[field] === "string") {
|
|
3978
|
-
const entry =
|
|
3979
|
-
if (
|
|
4538
|
+
const entry = path12.join(pkgDir, pkg[field]);
|
|
4539
|
+
if (fs9.existsSync(entry)) return entry;
|
|
3980
4540
|
}
|
|
3981
4541
|
}
|
|
3982
|
-
const indexFallback =
|
|
3983
|
-
if (
|
|
4542
|
+
const indexFallback = path12.join(pkgDir, "index.js");
|
|
4543
|
+
if (fs9.existsSync(indexFallback)) return indexFallback;
|
|
3984
4544
|
return null;
|
|
3985
4545
|
}
|
|
3986
4546
|
function resolvePackageExports(exports, key, pkgDir) {
|
|
3987
4547
|
if (typeof exports === "string") {
|
|
3988
|
-
return key === "." ?
|
|
4548
|
+
return key === "." ? path12.join(pkgDir, exports) : null;
|
|
3989
4549
|
}
|
|
3990
4550
|
const entry = exports[key];
|
|
3991
4551
|
if (entry === void 0) {
|
|
@@ -3997,7 +4557,7 @@ function resolvePackageExports(exports, key, pkgDir) {
|
|
|
3997
4557
|
return resolveExportValue(entry, pkgDir);
|
|
3998
4558
|
}
|
|
3999
4559
|
function resolveExportValue(value, pkgDir) {
|
|
4000
|
-
if (typeof value === "string") return
|
|
4560
|
+
if (typeof value === "string") return path12.join(pkgDir, value);
|
|
4001
4561
|
if (Array.isArray(value)) {
|
|
4002
4562
|
for (const item of value) {
|
|
4003
4563
|
const r = resolveExportValue(item, pkgDir);
|
|
@@ -4021,17 +4581,17 @@ function resolveUrlToFile(url, root) {
|
|
|
4021
4581
|
const moduleName = cleanUrl.slice("/@modules/".length);
|
|
4022
4582
|
return resolveNodeModule(root, moduleName);
|
|
4023
4583
|
}
|
|
4024
|
-
const filePath =
|
|
4025
|
-
if (
|
|
4584
|
+
const filePath = path12.resolve(root, cleanUrl.replace(/^\//, ""));
|
|
4585
|
+
if (fs9.existsSync(filePath) && fs9.statSync(filePath).isFile()) {
|
|
4026
4586
|
return filePath;
|
|
4027
4587
|
}
|
|
4028
4588
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
4029
4589
|
const withExt = filePath + ext;
|
|
4030
|
-
if (
|
|
4590
|
+
if (fs9.existsSync(withExt)) return withExt;
|
|
4031
4591
|
}
|
|
4032
4592
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
4033
|
-
const indexFile =
|
|
4034
|
-
if (
|
|
4593
|
+
const indexFile = path12.join(filePath, "index" + ext);
|
|
4594
|
+
if (fs9.existsSync(indexFile)) return indexFile;
|
|
4035
4595
|
}
|
|
4036
4596
|
return null;
|
|
4037
4597
|
}
|
|
@@ -4039,36 +4599,35 @@ function isModuleRequest(url) {
|
|
|
4039
4599
|
const cleanUrl = url.split("?")[0];
|
|
4040
4600
|
if (/\.(ts|tsx|jsx|js|mjs|vue|css|json)$/.test(cleanUrl)) return true;
|
|
4041
4601
|
if (cleanUrl.startsWith("/@modules/")) return true;
|
|
4042
|
-
if (!
|
|
4602
|
+
if (!path12.extname(cleanUrl)) return true;
|
|
4043
4603
|
return false;
|
|
4044
4604
|
}
|
|
4045
4605
|
function getHmrClientCode() {
|
|
4046
4606
|
return `
|
|
4047
4607
|
// Nasti HMR Client
|
|
4048
|
-
const
|
|
4608
|
+
const socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws';
|
|
4609
|
+
const socket = new WebSocket(socketProtocol + '://' + location.host, 'nasti-hmr');
|
|
4049
4610
|
const hotModulesMap = new Map();
|
|
4050
4611
|
const disposeMap = new Map();
|
|
4051
4612
|
const pruneMap = new Map();
|
|
4613
|
+
const dataMap = new Map();
|
|
4614
|
+
let updateQueue = [];
|
|
4615
|
+
let pendingUpdateQueue = false;
|
|
4052
4616
|
|
|
4053
4617
|
socket.addEventListener('message', async ({ data }) => {
|
|
4054
4618
|
const payload = JSON.parse(data);
|
|
4055
4619
|
switch (payload.type) {
|
|
4056
4620
|
case 'connected':
|
|
4057
|
-
console.
|
|
4621
|
+
console.debug('[nasti] connected.');
|
|
4058
4622
|
clearErrorOverlay();
|
|
4059
4623
|
break;
|
|
4060
4624
|
case 'update':
|
|
4061
4625
|
try {
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
} else if (update.type === 'css-update') {
|
|
4066
|
-
return updateCss(update.path);
|
|
4067
|
-
}
|
|
4068
|
-
}));
|
|
4626
|
+
// CSS \u5728 unbundled \u6A21\u5F0F\u4E0B\u4E5F\u662F\u4F1A\u6CE8\u5165 <style> \u7684 JS \u6A21\u5757\uFF0C\u548C\u666E\u901A JS
|
|
4627
|
+
// \u4E00\u6837\u91CD\u65B0 import \u624D\u80FD\u6267\u884C dispose/accept \u5E76\u4FDD\u6301\u9875\u9762\u72B6\u6001\u3002
|
|
4628
|
+
await Promise.all(payload.updates.map(queueUpdate));
|
|
4069
4629
|
clearErrorOverlay();
|
|
4070
|
-
console.
|
|
4071
|
-
location.reload();
|
|
4630
|
+
console.debug('[nasti] HMR update complete.');
|
|
4072
4631
|
} catch (err) {
|
|
4073
4632
|
console.error('[nasti] HMR update failed:', err);
|
|
4074
4633
|
showErrorOverlay(err);
|
|
@@ -4079,10 +4638,17 @@ socket.addEventListener('message', async ({ data }) => {
|
|
|
4079
4638
|
location.reload();
|
|
4080
4639
|
break;
|
|
4081
4640
|
case 'prune':
|
|
4082
|
-
payload.paths.
|
|
4083
|
-
const
|
|
4084
|
-
|
|
4085
|
-
|
|
4641
|
+
await Promise.all(payload.paths.map(async (path) => {
|
|
4642
|
+
const data = dataMap.get(path);
|
|
4643
|
+
const dispose = disposeMap.get(path);
|
|
4644
|
+
const prune = pruneMap.get(path);
|
|
4645
|
+
if (dispose) await dispose(data);
|
|
4646
|
+
if (prune) await prune(data);
|
|
4647
|
+
hotModulesMap.delete(path);
|
|
4648
|
+
disposeMap.delete(path);
|
|
4649
|
+
pruneMap.delete(path);
|
|
4650
|
+
dataMap.delete(path);
|
|
4651
|
+
}));
|
|
4086
4652
|
break;
|
|
4087
4653
|
case 'error':
|
|
4088
4654
|
console.error('[nasti] error:', payload.err.message);
|
|
@@ -4091,33 +4657,64 @@ socket.addEventListener('message', async ({ data }) => {
|
|
|
4091
4657
|
}
|
|
4092
4658
|
});
|
|
4093
4659
|
|
|
4094
|
-
// \
|
|
4660
|
+
// \u670D\u52A1\u91CD\u542F\u540E\u65E7\u6A21\u5757\u56FE\u5DF2\u5931\u6548\uFF0C\u91CD\u8FDE\u65F6\u6574\u9875\u5237\u65B0\u662F\u5FC5\u8981\u515C\u5E95\uFF1B\u6B63\u5E38 update \u4E0D\u518D\u5237\u65B0\u3002
|
|
4095
4661
|
let reconnectTimer = 0;
|
|
4096
4662
|
socket.addEventListener('close', () => {
|
|
4097
4663
|
clearTimeout(reconnectTimer);
|
|
4098
4664
|
reconnectTimer = setTimeout(() => location.reload(), 1000);
|
|
4099
4665
|
});
|
|
4100
4666
|
|
|
4667
|
+
/**
|
|
4668
|
+
* \u540C\u4E00\u6279\u66F4\u65B0\u5148\u5168\u90E8\u62C9\u53D6\uFF0C\u518D\u6309\u670D\u52A1\u7AEF\u6D88\u606F\u987A\u5E8F\u6267\u884C accept \u56DE\u8C03\uFF0C\u907F\u514D HTTP \u5F80\u8FD4\u901F\u5EA6
|
|
4669
|
+
* \u6539\u53D8\u6A21\u5757\u5E94\u7528\u987A\u5E8F\u3002\u8FD9\u4E0E Vite HMRClient \u7684 fetch/apply \u4E24\u9636\u6BB5\u4E00\u81F4\u3002
|
|
4670
|
+
*/
|
|
4671
|
+
async function queueUpdate(update) {
|
|
4672
|
+
updateQueue.push(fetchUpdate(update));
|
|
4673
|
+
if (pendingUpdateQueue) return;
|
|
4674
|
+
|
|
4675
|
+
pendingUpdateQueue = true;
|
|
4676
|
+
await Promise.resolve();
|
|
4677
|
+
pendingUpdateQueue = false;
|
|
4678
|
+
const loading = updateQueue;
|
|
4679
|
+
updateQueue = [];
|
|
4680
|
+
const applyUpdates = await Promise.all(loading);
|
|
4681
|
+
for (const apply of applyUpdates) {
|
|
4682
|
+
if (apply) apply();
|
|
4683
|
+
}
|
|
4684
|
+
}
|
|
4685
|
+
|
|
4101
4686
|
async function fetchUpdate(update) {
|
|
4102
4687
|
const mod = hotModulesMap.get(update.path);
|
|
4103
|
-
// \
|
|
4104
|
-
|
|
4105
|
-
if (dispose) dispose();
|
|
4688
|
+
// \u5C1A\u672A\u5728\u5F53\u524D\u9875\u9762\u52A0\u8F7D\u7684\u52A8\u6001\u6A21\u5757\u4E0D\u9700\u8981\u66F4\u65B0\u3002
|
|
4689
|
+
if (!mod) return;
|
|
4106
4690
|
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4691
|
+
// \u5FC5\u987B\u5728\u91CD\u65B0 import \u524D\u786E\u5B9A\u65E7\u56DE\u8C03\uFF1B\u65B0\u6A21\u5757\u6267\u884C createHotContext \u65F6\u4F1A\u6E05\u7A7A\u5E76\u6CE8\u518C\u65B0\u56DE\u8C03\u3002
|
|
4692
|
+
const qualifiedCallbacks = mod.callbacks.filter(({ deps }) =>
|
|
4693
|
+
deps.includes(update.acceptedPath)
|
|
4694
|
+
);
|
|
4695
|
+
const isSelfUpdate = update.path === update.acceptedPath;
|
|
4696
|
+
if (!isSelfUpdate && qualifiedCallbacks.length === 0) return;
|
|
4697
|
+
|
|
4698
|
+
const dispose = disposeMap.get(update.acceptedPath);
|
|
4699
|
+
if (dispose) await dispose(dataMap.get(update.acceptedPath));
|
|
4700
|
+
const newMod = await import(appendTimestampQuery(update.acceptedPath, update.timestamp));
|
|
4701
|
+
|
|
4702
|
+
return () => {
|
|
4703
|
+
for (const { deps, fn } of qualifiedCallbacks) {
|
|
4704
|
+
fn(deps.map((dep) => dep === update.acceptedPath ? newMod : undefined));
|
|
4705
|
+
}
|
|
4706
|
+
const detail = isSelfUpdate
|
|
4707
|
+
? update.path
|
|
4708
|
+
: update.acceptedPath + ' via ' + update.path;
|
|
4709
|
+
console.debug('[nasti] hot updated:', detail);
|
|
4710
|
+
};
|
|
4112
4711
|
}
|
|
4113
4712
|
|
|
4114
|
-
function
|
|
4115
|
-
const
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
.then(css => { el.textContent = css; });
|
|
4120
|
-
}
|
|
4713
|
+
function appendTimestampQuery(url, timestamp) {
|
|
4714
|
+
const hashIndex = url.indexOf('#');
|
|
4715
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : '';
|
|
4716
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
4717
|
+
return withoutHash + (withoutHash.includes('?') ? '&' : '?') + 't=' + timestamp + hash;
|
|
4121
4718
|
}
|
|
4122
4719
|
|
|
4123
4720
|
function clearErrorOverlay() {
|
|
@@ -4145,23 +4742,30 @@ function showErrorOverlay(err) {
|
|
|
4145
4742
|
document.body.appendChild(overlay);
|
|
4146
4743
|
}
|
|
4147
4744
|
|
|
4148
|
-
/**
|
|
4149
|
-
* \u751F\u6210 import.meta.hot \u7684 hot context\u3002
|
|
4150
|
-
* \u5173\u952E\u7EA6\u675F\uFF1A\u540C\u4E00 ownerPath \u7684 accept \u56DE\u8C03\u5FC5\u987B\u66FF\u6362\uFF08\u4E0D\u662F append\uFF09\u3002
|
|
4151
|
-
* \u6BCF\u6B21\u6A21\u5757\u91CD\u65B0 import \u90FD\u4F1A\u8C03\u7528 createHotContext\uFF0C\u65E7\u56DE\u8C03\u4F1A\u88AB fetchUpdate \u8C03\u7528\u540E\u7ACB\u5373\u88AB\u65B0 import
|
|
4152
|
-
* \u91CC\u7684 accept \u66FF\u6362\u3002\u4E0D\u66FF\u6362\u7684\u8BDD\u6BCF\u7F16\u8F91\u4E00\u6B21\u5C31\u591A\u4E00\u4E2A\u56DE\u8C03\uFF0C\u8D8A\u8DD1\u8D8A\u6162\u3002
|
|
4153
|
-
*/
|
|
4154
4745
|
export function createHotContext(ownerPath) {
|
|
4746
|
+
if (!dataMap.has(ownerPath)) dataMap.set(ownerPath, {});
|
|
4747
|
+
|
|
4748
|
+
// \u6A21\u5757\u91CD\u65B0\u6267\u884C\u65F6\u4E22\u5F03\u65E7 accept \u56DE\u8C03\uFF0C\u4F46\u4FDD\u7559\u540C\u4E00\u4E2A hot.data \u5BF9\u8C61\u3002
|
|
4749
|
+
const existing = hotModulesMap.get(ownerPath);
|
|
4750
|
+
if (existing) existing.callbacks = [];
|
|
4751
|
+
|
|
4752
|
+
const acceptDeps = (deps, callback = () => {}) => {
|
|
4753
|
+
const mod = hotModulesMap.get(ownerPath) || { id: ownerPath, callbacks: [] };
|
|
4754
|
+
mod.callbacks.push({ deps, fn: callback });
|
|
4755
|
+
hotModulesMap.set(ownerPath, mod);
|
|
4756
|
+
};
|
|
4757
|
+
|
|
4155
4758
|
return {
|
|
4156
4759
|
accept(deps, callback) {
|
|
4157
|
-
// \u81EA\u63A5\u53D7: hot.accept() \u6216 hot.accept(callback)
|
|
4158
4760
|
if (typeof deps === 'function' || deps === undefined) {
|
|
4159
|
-
|
|
4160
|
-
|
|
4761
|
+
acceptDeps([ownerPath], ([mod]) => deps?.(mod));
|
|
4762
|
+
} else if (typeof deps === 'string') {
|
|
4763
|
+
acceptDeps([deps], ([mod]) => callback?.(mod));
|
|
4764
|
+
} else if (Array.isArray(deps)) {
|
|
4765
|
+
acceptDeps(deps, callback);
|
|
4766
|
+
} else {
|
|
4767
|
+
throw new Error('invalid hot.accept() usage');
|
|
4161
4768
|
}
|
|
4162
|
-
// \u4F9D\u8D56\u63A5\u53D7: hot.accept(deps, callback)\uFF0C\u591A\u6B21\u8C03\u7528\u8FFD\u52A0
|
|
4163
|
-
const existing = hotModulesMap.get(ownerPath)?.callbacks ?? [];
|
|
4164
|
-
hotModulesMap.set(ownerPath, { callbacks: [...existing, callback] });
|
|
4165
4769
|
},
|
|
4166
4770
|
prune(callback) {
|
|
4167
4771
|
pruneMap.set(ownerPath, callback);
|
|
@@ -4172,21 +4776,85 @@ export function createHotContext(ownerPath) {
|
|
|
4172
4776
|
invalidate() {
|
|
4173
4777
|
location.reload();
|
|
4174
4778
|
},
|
|
4175
|
-
data:
|
|
4779
|
+
data: dataMap.get(ownerPath),
|
|
4176
4780
|
};
|
|
4177
4781
|
}
|
|
4178
4782
|
`;
|
|
4179
4783
|
}
|
|
4180
|
-
var __dirname_esm, __require2, __refreshRuntimeCache, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
|
|
4784
|
+
var __dirname_esm, __require2, __refreshRuntimeCache, REACT_REFRESH_BOUNDARY_HELPERS, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
|
|
4181
4785
|
var init_middleware = __esm({
|
|
4182
4786
|
"src/server/middleware.ts"() {
|
|
4183
4787
|
"use strict";
|
|
4184
4788
|
init_transformer();
|
|
4185
4789
|
init_html();
|
|
4186
4790
|
init_env();
|
|
4187
|
-
|
|
4791
|
+
init_url();
|
|
4792
|
+
__dirname_esm = path12.dirname(fileURLToPath(import.meta.url));
|
|
4188
4793
|
__require2 = createRequire3(import.meta.url);
|
|
4189
4794
|
__refreshRuntimeCache = null;
|
|
4795
|
+
REACT_REFRESH_BOUNDARY_HELPERS = `
|
|
4796
|
+
function __nastiIsPlainObject(obj) {
|
|
4797
|
+
return Object.prototype.toString.call(obj) === '[object Object]' &&
|
|
4798
|
+
(obj.constructor === Object || obj.constructor === undefined);
|
|
4799
|
+
}
|
|
4800
|
+
function __nastiIsCompoundComponent(type) {
|
|
4801
|
+
if (!__nastiIsPlainObject(type)) return false;
|
|
4802
|
+
for (const key in type) {
|
|
4803
|
+
if (!isLikelyComponentType(type[key])) return false;
|
|
4804
|
+
}
|
|
4805
|
+
return true;
|
|
4806
|
+
}
|
|
4807
|
+
export function registerExportsForReactRefresh(filename, moduleExports) {
|
|
4808
|
+
for (const key in moduleExports) {
|
|
4809
|
+
if (key === '__esModule') continue;
|
|
4810
|
+
const value = moduleExports[key];
|
|
4811
|
+
if (isLikelyComponentType(value)) {
|
|
4812
|
+
register(value, filename + ' export ' + key);
|
|
4813
|
+
} else if (__nastiIsCompoundComponent(value)) {
|
|
4814
|
+
for (const subKey in value) {
|
|
4815
|
+
register(value[subKey], filename + ' export ' + key + '-' + subKey);
|
|
4816
|
+
}
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
let __nastiRefreshTimer;
|
|
4821
|
+
function __nastiEnqueueRefresh() {
|
|
4822
|
+
clearTimeout(__nastiRefreshTimer);
|
|
4823
|
+
__nastiRefreshTimer = setTimeout(() => performReactRefresh(), 16);
|
|
4824
|
+
}
|
|
4825
|
+
function __nastiCheckExports(ignored, exports, predicate) {
|
|
4826
|
+
for (const key in exports) {
|
|
4827
|
+
if (ignored.includes(key)) continue;
|
|
4828
|
+
if (!predicate(key, exports[key])) return key;
|
|
4829
|
+
}
|
|
4830
|
+
return true;
|
|
4831
|
+
}
|
|
4832
|
+
export function validateRefreshBoundaryAndEnqueueUpdate(id, prevExports, nextExports) {
|
|
4833
|
+
const ignored = window.__getReactRefreshIgnoredExports?.({ id }) ?? [];
|
|
4834
|
+
if (__nastiCheckExports(ignored, prevExports, (key) => key in nextExports) !== true) {
|
|
4835
|
+
return 'Could not Fast Refresh (export removed)';
|
|
4836
|
+
}
|
|
4837
|
+
if (__nastiCheckExports(ignored, nextExports, (key) => key in prevExports) !== true) {
|
|
4838
|
+
return 'Could not Fast Refresh (new export)';
|
|
4839
|
+
}
|
|
4840
|
+
let hasExports = false;
|
|
4841
|
+
const compatible = __nastiCheckExports(ignored, nextExports, (key, value) => {
|
|
4842
|
+
hasExports = true;
|
|
4843
|
+
return isLikelyComponentType(value) ||
|
|
4844
|
+
__nastiIsCompoundComponent(value) ||
|
|
4845
|
+
prevExports[key] === value;
|
|
4846
|
+
});
|
|
4847
|
+
if (!hasExports) {
|
|
4848
|
+
return 'Could not Fast Refresh (no exports)';
|
|
4849
|
+
}
|
|
4850
|
+
if (compatible === true) {
|
|
4851
|
+
__nastiEnqueueRefresh();
|
|
4852
|
+
return;
|
|
4853
|
+
}
|
|
4854
|
+
return 'Could not Fast Refresh ("' + compatible + '" export is incompatible)';
|
|
4855
|
+
}
|
|
4856
|
+
export const __hmr_import = (module) => import(module);
|
|
4857
|
+
`;
|
|
4190
4858
|
REACT_REFRESH_GLOBAL_PREAMBLE = `
|
|
4191
4859
|
import RefreshRuntime from "/@react-refresh";
|
|
4192
4860
|
RefreshRuntime.injectIntoGlobalHook(window);
|
|
@@ -4202,27 +4870,29 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
4202
4870
|
});
|
|
4203
4871
|
|
|
4204
4872
|
// src/server/hmr.ts
|
|
4205
|
-
import
|
|
4206
|
-
import
|
|
4873
|
+
import path13 from "path";
|
|
4874
|
+
import fs10 from "fs";
|
|
4207
4875
|
import pc7 from "picocolors";
|
|
4208
4876
|
async function handleFileChange(file, server) {
|
|
4209
4877
|
const { moduleGraph, ws, config } = server;
|
|
4210
4878
|
const logger = config.logger;
|
|
4211
|
-
const relativePath = "/" +
|
|
4212
|
-
const shortFile =
|
|
4879
|
+
const relativePath = "/" + path13.relative(config.root, file);
|
|
4880
|
+
const shortFile = path13.relative(config.root, file);
|
|
4213
4881
|
const mods = moduleGraph.getModulesByFile(file);
|
|
4214
4882
|
if (!mods || mods.size === 0) {
|
|
4215
4883
|
return;
|
|
4216
4884
|
}
|
|
4217
4885
|
const updates = [];
|
|
4218
4886
|
const timestamp = Date.now();
|
|
4887
|
+
const graph = moduleGraph;
|
|
4888
|
+
const invalidatedModules = /* @__PURE__ */ new Set();
|
|
4219
4889
|
for (const mod of mods) {
|
|
4220
|
-
|
|
4890
|
+
graph.invalidateModuleAndImporters(mod, timestamp, invalidatedModules);
|
|
4221
4891
|
const ctx = {
|
|
4222
4892
|
file,
|
|
4223
4893
|
timestamp,
|
|
4224
4894
|
modules: [mod],
|
|
4225
|
-
read: () =>
|
|
4895
|
+
read: () => fs10.readFileSync(file, "utf-8"),
|
|
4226
4896
|
server
|
|
4227
4897
|
};
|
|
4228
4898
|
let affectedModules = [mod];
|
|
@@ -4235,19 +4905,25 @@ async function handleFileChange(file, server) {
|
|
|
4235
4905
|
}
|
|
4236
4906
|
}
|
|
4237
4907
|
for (const affected of affectedModules) {
|
|
4238
|
-
|
|
4908
|
+
graph.invalidateModuleAndImporters(affected, timestamp, invalidatedModules);
|
|
4909
|
+
const boundaries = graph.getHmrBoundaries(affected);
|
|
4239
4910
|
if (boundaries.length === 0) {
|
|
4240
4911
|
logger.info(pc7.green("page reload ") + pc7.dim(shortFile), { timestamp: true });
|
|
4241
4912
|
ws.send({ type: "full-reload", path: relativePath });
|
|
4242
4913
|
return;
|
|
4243
4914
|
}
|
|
4244
|
-
for (const { boundary } of boundaries) {
|
|
4245
|
-
|
|
4915
|
+
for (const { boundary, acceptedVia } of boundaries) {
|
|
4916
|
+
const update = {
|
|
4246
4917
|
type: boundary.type === "css" ? "css-update" : "js-update",
|
|
4247
4918
|
path: boundary.url,
|
|
4248
|
-
acceptedPath:
|
|
4919
|
+
acceptedPath: acceptedVia.url,
|
|
4249
4920
|
timestamp
|
|
4250
|
-
}
|
|
4921
|
+
};
|
|
4922
|
+
if (!updates.some(
|
|
4923
|
+
(existing) => existing.type === update.type && existing.path === update.path && existing.acceptedPath === update.acceptedPath
|
|
4924
|
+
)) {
|
|
4925
|
+
updates.push(update);
|
|
4926
|
+
}
|
|
4251
4927
|
}
|
|
4252
4928
|
}
|
|
4253
4929
|
}
|
|
@@ -4271,8 +4947,8 @@ __export(runnable_environment_exports, {
|
|
|
4271
4947
|
NastiModuleRunner: () => NastiModuleRunner,
|
|
4272
4948
|
createModuleRunner: () => createModuleRunner
|
|
4273
4949
|
});
|
|
4274
|
-
import
|
|
4275
|
-
import
|
|
4950
|
+
import path14 from "path";
|
|
4951
|
+
import fs11 from "fs";
|
|
4276
4952
|
import { builtinModules as builtinModules3, createRequire as createRequire4 } from "module";
|
|
4277
4953
|
import { pathToFileURL as pathToFileURL4 } from "url";
|
|
4278
4954
|
function createModuleRunner(environment) {
|
|
@@ -4306,7 +4982,7 @@ var init_runnable_environment = __esm({
|
|
|
4306
4982
|
this.config.mode,
|
|
4307
4983
|
ssrDefineOverrides(environment.consumer)
|
|
4308
4984
|
);
|
|
4309
|
-
this.require = createRequire4(
|
|
4985
|
+
this.require = createRequire4(path14.join(this.config.root, "package.json"));
|
|
4310
4986
|
const handlers = {
|
|
4311
4987
|
fetchModule: async (id, importer) => this.fetchModule(id, importer),
|
|
4312
4988
|
getBuiltins: () => [/^node:/, ...builtinModules3]
|
|
@@ -4330,9 +5006,9 @@ var init_runnable_environment = __esm({
|
|
|
4330
5006
|
this.cache.clear();
|
|
4331
5007
|
}
|
|
4332
5008
|
resolveToId(rawUrl) {
|
|
4333
|
-
if (
|
|
5009
|
+
if (path14.isAbsolute(rawUrl) && fs11.existsSync(rawUrl.split("?")[0])) return rawUrl;
|
|
4334
5010
|
const clean = rawUrl.replace(/^\//, "");
|
|
4335
|
-
return
|
|
5011
|
+
return path14.resolve(this.config.root, clean);
|
|
4336
5012
|
}
|
|
4337
5013
|
/**
|
|
4338
5014
|
* fetchModule(invoke 契约方法):环境管线产出 runner 可执行代码。
|
|
@@ -4341,14 +5017,14 @@ var init_runnable_environment = __esm({
|
|
|
4341
5017
|
*/
|
|
4342
5018
|
async fetchModule(id, importer) {
|
|
4343
5019
|
if (NODE_BUILTINS3.has(id)) return { externalize: id };
|
|
4344
|
-
if (!id.startsWith(".") && !
|
|
5020
|
+
if (!id.startsWith(".") && !path14.isAbsolute(id) && !id.startsWith("\0")) {
|
|
4345
5021
|
return { externalize: id };
|
|
4346
5022
|
}
|
|
4347
5023
|
const container = this.environment.pluginContainer;
|
|
4348
5024
|
let resolvedId = id;
|
|
4349
5025
|
if (id.startsWith(".") && importer) {
|
|
4350
5026
|
const resolved = await container.resolveId(id, importer);
|
|
4351
|
-
resolvedId = resolved ? typeof resolved === "string" ? resolved : resolved.id :
|
|
5027
|
+
resolvedId = resolved ? typeof resolved === "string" ? resolved : resolved.id : path14.resolve(path14.dirname(importer.split("?")[0]), id);
|
|
4352
5028
|
}
|
|
4353
5029
|
resolvedId = this.completeExtension(resolvedId);
|
|
4354
5030
|
const cleanId = resolvedId.split("?")[0];
|
|
@@ -4356,8 +5032,8 @@ var init_runnable_environment = __esm({
|
|
|
4356
5032
|
const loaded = await container.load(resolvedId);
|
|
4357
5033
|
if (loaded != null) {
|
|
4358
5034
|
code = typeof loaded === "string" ? loaded : loaded.code;
|
|
4359
|
-
} else if (
|
|
4360
|
-
code =
|
|
5035
|
+
} else if (fs11.existsSync(cleanId)) {
|
|
5036
|
+
code = fs11.readFileSync(cleanId, "utf-8");
|
|
4361
5037
|
} else {
|
|
4362
5038
|
throw new Error(`[nasti:ssr] cannot load module: ${resolvedId}`);
|
|
4363
5039
|
}
|
|
@@ -4390,19 +5066,19 @@ var init_runnable_environment = __esm({
|
|
|
4390
5066
|
completeExtension(id) {
|
|
4391
5067
|
const clean = id.split("?")[0];
|
|
4392
5068
|
const query = id.includes("?") ? id.slice(id.indexOf("?")) : "";
|
|
4393
|
-
if (
|
|
5069
|
+
if (fs11.existsSync(clean) && fs11.statSync(clean).isFile()) return id;
|
|
4394
5070
|
const jsMatch = clean.match(/^(.*)\.([mc]?)jsx?$/);
|
|
4395
5071
|
if (jsMatch) {
|
|
4396
5072
|
for (const tsExt of [`.${jsMatch[2]}ts`, `.${jsMatch[2]}tsx`]) {
|
|
4397
|
-
if (
|
|
5073
|
+
if (fs11.existsSync(jsMatch[1] + tsExt)) return jsMatch[1] + tsExt + query;
|
|
4398
5074
|
}
|
|
4399
5075
|
}
|
|
4400
5076
|
for (const ext of this.config.resolve.extensions) {
|
|
4401
|
-
if (
|
|
5077
|
+
if (fs11.existsSync(clean + ext)) return clean + ext + query;
|
|
4402
5078
|
}
|
|
4403
5079
|
for (const ext of this.config.resolve.extensions) {
|
|
4404
|
-
const indexPath =
|
|
4405
|
-
if (
|
|
5080
|
+
const indexPath = path14.join(clean, `index${ext}`);
|
|
5081
|
+
if (fs11.existsSync(indexPath)) return indexPath;
|
|
4406
5082
|
}
|
|
4407
5083
|
return id;
|
|
4408
5084
|
}
|
|
@@ -4429,10 +5105,10 @@ var init_runnable_environment = __esm({
|
|
|
4429
5105
|
return;
|
|
4430
5106
|
}
|
|
4431
5107
|
const ssrImport = async (dep) => {
|
|
4432
|
-
if (NODE_BUILTINS3.has(dep) || !dep.startsWith(".") && !
|
|
5108
|
+
if (NODE_BUILTINS3.has(dep) || !dep.startsWith(".") && !path14.isAbsolute(dep) && !dep.startsWith("\0")) {
|
|
4433
5109
|
return this.importExternal(dep);
|
|
4434
5110
|
}
|
|
4435
|
-
const depId = dep.startsWith(".") ? this.completeExtension(
|
|
5111
|
+
const depId = dep.startsWith(".") ? this.completeExtension(path14.resolve(path14.dirname(fetched.id.split("?")[0]), dep)) : this.completeExtension(dep);
|
|
4436
5112
|
return this.instantiate(depId);
|
|
4437
5113
|
};
|
|
4438
5114
|
const ssrExportAll = (sourceModule) => {
|
|
@@ -4464,7 +5140,7 @@ var init_runnable_environment = __esm({
|
|
|
4464
5140
|
}
|
|
4465
5141
|
async importExternal(spec) {
|
|
4466
5142
|
try {
|
|
4467
|
-
return await (spec.startsWith("node:") || !
|
|
5143
|
+
return await (spec.startsWith("node:") || !path14.isAbsolute(spec) ? import(this.resolveExternalSpecifier(spec)) : import(pathToFileURL4(spec).href));
|
|
4468
5144
|
} catch (err) {
|
|
4469
5145
|
throw new Error(`[nasti:ssr] failed to import external "${spec}": ${err.message}`);
|
|
4470
5146
|
}
|
|
@@ -4490,7 +5166,7 @@ var dev_engine_exports = {};
|
|
|
4490
5166
|
__export(dev_engine_exports, {
|
|
4491
5167
|
createBundledDevServer: () => createBundledDevServer
|
|
4492
5168
|
});
|
|
4493
|
-
import
|
|
5169
|
+
import path15 from "path";
|
|
4494
5170
|
import crypto3 from "crypto";
|
|
4495
5171
|
import { WebSocketServer as WsServer2 } from "ws";
|
|
4496
5172
|
import pc8 from "picocolors";
|
|
@@ -4526,7 +5202,7 @@ async function createBundledDevServer(opts) {
|
|
|
4526
5202
|
createReactRefreshRuntimePlugin(entryPoints),
|
|
4527
5203
|
createBundledOxcRefreshPlugin()
|
|
4528
5204
|
] : [],
|
|
4529
|
-
...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins)),
|
|
5205
|
+
...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins, clientEnv)),
|
|
4530
5206
|
...useReactRefresh ? [
|
|
4531
5207
|
refreshWrapperFn({
|
|
4532
5208
|
cwd: config.root,
|
|
@@ -4575,7 +5251,7 @@ async function createBundledDevServer(opts) {
|
|
|
4575
5251
|
}
|
|
4576
5252
|
const url = `/${patchPath}`;
|
|
4577
5253
|
logger.info(
|
|
4578
|
-
pc8.green("hmr update ") + pc8.dim(changedFiles.map((f) =>
|
|
5254
|
+
pc8.green("hmr update ") + pc8.dim(changedFiles.map((f) => path15.relative(config.root, f)).join(", ")),
|
|
4579
5255
|
{ timestamp: true }
|
|
4580
5256
|
);
|
|
4581
5257
|
sendTo(clientId, { type: "hmr:update", path: url, url });
|
|
@@ -4711,7 +5387,7 @@ async function createBundledDevServer(opts) {
|
|
|
4711
5387
|
return;
|
|
4712
5388
|
}
|
|
4713
5389
|
res.setHeader("ETag", hit.etag);
|
|
4714
|
-
res.setHeader("Content-Type", MIME_TYPES[
|
|
5390
|
+
res.setHeader("Content-Type", MIME_TYPES[path15.extname(fileName)] ?? "application/octet-stream");
|
|
4715
5391
|
res.setHeader("Cache-Control", "no-cache");
|
|
4716
5392
|
res.end(hit.content);
|
|
4717
5393
|
return;
|
|
@@ -4747,7 +5423,7 @@ function stripCatchAllLoad(plugins) {
|
|
|
4747
5423
|
);
|
|
4748
5424
|
}
|
|
4749
5425
|
function createReactRefreshRuntimePlugin(entryPoints) {
|
|
4750
|
-
const entryIds = new Set(entryPoints.map((p) =>
|
|
5426
|
+
const entryIds = new Set(entryPoints.map((p) => path15.resolve(p)));
|
|
4751
5427
|
return {
|
|
4752
5428
|
name: "nasti:bundled-react-refresh",
|
|
4753
5429
|
resolveId(source) {
|
|
@@ -4765,7 +5441,7 @@ function createReactRefreshRuntimePlugin(entryPoints) {
|
|
|
4765
5441
|
return null;
|
|
4766
5442
|
},
|
|
4767
5443
|
transform(code, id) {
|
|
4768
|
-
if (!entryIds.has(
|
|
5444
|
+
if (!entryIds.has(path15.resolve(id.split("?")[0]))) return null;
|
|
4769
5445
|
return { code: `import ${JSON.stringify(PREAMBLE_SPEC)};
|
|
4770
5446
|
${code}`, map: null };
|
|
4771
5447
|
}
|
|
@@ -4936,7 +5612,7 @@ __export(server_exports, {
|
|
|
4936
5612
|
createServer: () => createServer
|
|
4937
5613
|
});
|
|
4938
5614
|
import http from "http";
|
|
4939
|
-
import
|
|
5615
|
+
import path16 from "path";
|
|
4940
5616
|
import os from "os";
|
|
4941
5617
|
import connect from "connect";
|
|
4942
5618
|
import sirv from "sirv";
|
|
@@ -4946,7 +5622,9 @@ async function createServer(inlineConfig = {}) {
|
|
|
4946
5622
|
const startTime = performance.now();
|
|
4947
5623
|
const config = await resolveConfig(inlineConfig, "serve");
|
|
4948
5624
|
const logger = config.logger;
|
|
4949
|
-
const allPlugins = resolvePluginList(config, config.plugins
|
|
5625
|
+
const allPlugins = resolvePluginList(config, config.plugins, {
|
|
5626
|
+
environmentName: "client"
|
|
5627
|
+
});
|
|
4950
5628
|
const configWithPlugins = { ...config, plugins: allPlugins };
|
|
4951
5629
|
const app = connect();
|
|
4952
5630
|
const httpServer = http.createServer(app);
|
|
@@ -4963,7 +5641,10 @@ async function createServer(inlineConfig = {}) {
|
|
|
4963
5641
|
for (const name of Object.keys(config.environments)) {
|
|
4964
5642
|
if (name === "client") continue;
|
|
4965
5643
|
const consumer = config.environments[name].consumer;
|
|
4966
|
-
const envPlugins = resolvePluginList(config, config.plugins, {
|
|
5644
|
+
const envPlugins = resolvePluginList(config, config.plugins, {
|
|
5645
|
+
consumer,
|
|
5646
|
+
environmentName: name
|
|
5647
|
+
});
|
|
4967
5648
|
environments[name] = new NastiEnvironment(name, config, {
|
|
4968
5649
|
mode: "dev",
|
|
4969
5650
|
plugins: envPlugins,
|
|
@@ -4998,14 +5679,14 @@ async function createServer(inlineConfig = {}) {
|
|
|
4998
5679
|
app.use(bundledServer.middleware);
|
|
4999
5680
|
}
|
|
5000
5681
|
const ignoredSegments = /* @__PURE__ */ new Set(["node_modules", ".git", ".nasti"]);
|
|
5001
|
-
const outDirAbs =
|
|
5682
|
+
const outDirAbs = path16.resolve(config.root, config.build.outDir);
|
|
5002
5683
|
const watcher = watch(config.root, {
|
|
5003
5684
|
ignored: (filePath) => {
|
|
5004
5685
|
if (filePath === config.root) return false;
|
|
5005
|
-
if (filePath === outDirAbs || filePath.startsWith(outDirAbs +
|
|
5006
|
-
const rel =
|
|
5007
|
-
if (!rel || rel.startsWith("..") ||
|
|
5008
|
-
for (const seg of rel.split(
|
|
5686
|
+
if (filePath === outDirAbs || filePath.startsWith(outDirAbs + path16.sep)) return true;
|
|
5687
|
+
const rel = path16.relative(config.root, filePath);
|
|
5688
|
+
if (!rel || rel.startsWith("..") || path16.isAbsolute(rel)) return false;
|
|
5689
|
+
for (const seg of rel.split(path16.sep)) {
|
|
5009
5690
|
if (ignoredSegments.has(seg)) return true;
|
|
5010
5691
|
}
|
|
5011
5692
|
return false;
|
|
@@ -5106,7 +5787,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
5106
5787
|
const readyIn = Math.ceil(performance.now() - startTime);
|
|
5107
5788
|
logger.info(
|
|
5108
5789
|
`
|
|
5109
|
-
${pc9.cyan(pc9.bold("NASTI"))} ${pc9.cyan(`v${"2.
|
|
5790
|
+
${pc9.cyan(pc9.bold("NASTI"))} ${pc9.cyan(`v${"2.4.0"}`)} ${pc9.dim("ready in")} ${pc9.bold(readyIn)} ${pc9.dim("ms")}
|
|
5110
5791
|
`
|
|
5111
5792
|
);
|
|
5112
5793
|
printServerUrls(
|
|
@@ -5134,7 +5815,12 @@ async function createServer(inlineConfig = {}) {
|
|
|
5134
5815
|
},
|
|
5135
5816
|
async transformRequest(url) {
|
|
5136
5817
|
const { transformRequest: transformRequest2 } = await Promise.resolve().then(() => (init_middleware(), middleware_exports));
|
|
5137
|
-
return transformRequest2(url, {
|
|
5818
|
+
return transformRequest2(url, {
|
|
5819
|
+
config: configWithPlugins,
|
|
5820
|
+
pluginContainer,
|
|
5821
|
+
moduleGraph,
|
|
5822
|
+
onPrune: (paths) => ws.send({ type: "prune", paths })
|
|
5823
|
+
});
|
|
5138
5824
|
},
|
|
5139
5825
|
async ssrLoadModule(url) {
|
|
5140
5826
|
const runner = await getSsrRunner();
|
|
@@ -5194,9 +5880,10 @@ async function createServer(inlineConfig = {}) {
|
|
|
5194
5880
|
app.use(transformMiddleware({
|
|
5195
5881
|
config: configWithPlugins,
|
|
5196
5882
|
pluginContainer,
|
|
5197
|
-
moduleGraph
|
|
5883
|
+
moduleGraph,
|
|
5884
|
+
onPrune: (paths) => ws.send({ type: "prune", paths })
|
|
5198
5885
|
}));
|
|
5199
|
-
const publicDir =
|
|
5886
|
+
const publicDir = path16.resolve(config.root, "public");
|
|
5200
5887
|
app.use(sirv(publicDir, { dev: true, etag: true }));
|
|
5201
5888
|
app.use(sirv(config.root, { dev: true, etag: true }));
|
|
5202
5889
|
const postMiddlewares = [];
|
|
@@ -5244,8 +5931,8 @@ init_build();
|
|
|
5244
5931
|
// src/build/electron.ts
|
|
5245
5932
|
init_config();
|
|
5246
5933
|
init_resolve();
|
|
5247
|
-
import
|
|
5248
|
-
import
|
|
5934
|
+
import path11 from "path";
|
|
5935
|
+
import fs8 from "fs";
|
|
5249
5936
|
import { rolldown as rolldown2 } from "rolldown";
|
|
5250
5937
|
import pc5 from "picocolors";
|
|
5251
5938
|
|
|
@@ -5289,16 +5976,16 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5289
5976
|
const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
|
|
5290
5977
|
const startTime = performance.now();
|
|
5291
5978
|
assertElectronVersion(config);
|
|
5292
|
-
console.log(pc5.cyan("\n\u26A1 nasti build (electron)") + pc5.dim(` v${"2.
|
|
5979
|
+
console.log(pc5.cyan("\n\u26A1 nasti build (electron)") + pc5.dim(` v${"2.4.0"}`));
|
|
5293
5980
|
console.log(pc5.dim(` root: ${config.root}`));
|
|
5294
5981
|
console.log(pc5.dim(` mode: ${config.mode}`));
|
|
5295
5982
|
console.log(pc5.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
|
|
5296
|
-
const outDir =
|
|
5297
|
-
if (config.build.emptyOutDir &&
|
|
5298
|
-
|
|
5983
|
+
const outDir = path11.resolve(config.root, config.build.outDir);
|
|
5984
|
+
if (config.build.emptyOutDir && fs8.existsSync(outDir)) {
|
|
5985
|
+
fs8.rmSync(outDir, { recursive: true, force: true });
|
|
5299
5986
|
}
|
|
5300
|
-
|
|
5301
|
-
const rendererOutDir =
|
|
5987
|
+
fs8.mkdirSync(outDir, { recursive: true });
|
|
5988
|
+
const rendererOutDir = path11.join(outDir, "renderer");
|
|
5302
5989
|
const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
|
|
5303
5990
|
await build2(createElectronRendererConfig(config, inlineConfig, {
|
|
5304
5991
|
build: {
|
|
@@ -5307,8 +5994,8 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5307
5994
|
emptyOutDir: false
|
|
5308
5995
|
}
|
|
5309
5996
|
}));
|
|
5310
|
-
const mainEntry =
|
|
5311
|
-
if (!
|
|
5997
|
+
const mainEntry = path11.resolve(config.root, config.electron.main);
|
|
5998
|
+
if (!fs8.existsSync(mainEntry)) {
|
|
5312
5999
|
throw new Error(
|
|
5313
6000
|
`Electron main entry not found: ${config.electron.main}
|
|
5314
6001
|
\u5728 nasti.config.ts \u7684 electron.main \u6307\u5B9A\u4E3B\u8FDB\u7A0B\u5165\u53E3\u6587\u4EF6\u3002`
|
|
@@ -5322,11 +6009,11 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5322
6009
|
const preloadEntries = normalizePreload(config.electron.preload, config.root);
|
|
5323
6010
|
const preloadFiles = [];
|
|
5324
6011
|
for (const entry of preloadEntries) {
|
|
5325
|
-
if (!
|
|
6012
|
+
if (!fs8.existsSync(entry)) {
|
|
5326
6013
|
console.warn(pc5.yellow(` \u26A0 preload entry not found, skipped: ${entry}`));
|
|
5327
6014
|
continue;
|
|
5328
6015
|
}
|
|
5329
|
-
const base =
|
|
6016
|
+
const base = path11.basename(entry).replace(/\.[^.]+$/, "");
|
|
5330
6017
|
const out = outFileName(outDir, base, config.electron.preloadFormat);
|
|
5331
6018
|
await bundleNode(config, entry, {
|
|
5332
6019
|
outFile: out,
|
|
@@ -5338,10 +6025,10 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5338
6025
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
5339
6026
|
console.log(pc5.green(`
|
|
5340
6027
|
\u2713 Electron build complete in ${elapsed}s`));
|
|
5341
|
-
console.log(pc5.dim(` renderer: ${
|
|
5342
|
-
console.log(pc5.dim(` main: ${
|
|
6028
|
+
console.log(pc5.dim(` renderer: ${path11.relative(config.root, rendererOutDir)}/`));
|
|
6029
|
+
console.log(pc5.dim(` main: ${path11.relative(config.root, mainFile)}`));
|
|
5343
6030
|
for (const pf of preloadFiles) {
|
|
5344
|
-
console.log(pc5.dim(` preload: ${
|
|
6031
|
+
console.log(pc5.dim(` preload: ${path11.relative(config.root, pf)}`));
|
|
5345
6032
|
}
|
|
5346
6033
|
console.log();
|
|
5347
6034
|
return { rendererOutDir, mainFile, preloadFiles };
|
|
@@ -5379,7 +6066,7 @@ async function bundleNode(config, entry, opts) {
|
|
|
5379
6066
|
},
|
|
5380
6067
|
plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
|
|
5381
6068
|
});
|
|
5382
|
-
|
|
6069
|
+
fs8.mkdirSync(path11.dirname(opts.outFile), { recursive: true });
|
|
5383
6070
|
await bundle2.write({
|
|
5384
6071
|
sourcemap: !!config.build.sourcemap,
|
|
5385
6072
|
minify: !!config.build.minify,
|
|
@@ -5390,7 +6077,7 @@ async function bundleNode(config, entry, opts) {
|
|
|
5390
6077
|
codeSplitting: false
|
|
5391
6078
|
});
|
|
5392
6079
|
await bundle2.close();
|
|
5393
|
-
console.log(pc5.dim(` \u2713 ${opts.label} \u2192 ${
|
|
6080
|
+
console.log(pc5.dim(` \u2713 ${opts.label} \u2192 ${path11.relative(config.root, opts.outFile)}`));
|
|
5394
6081
|
return opts.outFile;
|
|
5395
6082
|
}
|
|
5396
6083
|
function createElectronRendererConfig(config, inlineConfig = {}, overrides = {}) {
|
|
@@ -5414,11 +6101,11 @@ function createElectronRendererConfig(config, inlineConfig = {}, overrides = {})
|
|
|
5414
6101
|
}
|
|
5415
6102
|
function outFileName(outDir, base, format) {
|
|
5416
6103
|
const ext = format === "cjs" ? ".cjs" : ".mjs";
|
|
5417
|
-
return
|
|
6104
|
+
return path11.join(outDir, base + ext);
|
|
5418
6105
|
}
|
|
5419
6106
|
function normalizePreload(preload, root) {
|
|
5420
6107
|
const list = Array.isArray(preload) ? preload : preload ? [preload] : [];
|
|
5421
|
-
return list.map((p) =>
|
|
6108
|
+
return list.map((p) => path11.resolve(root, p));
|
|
5422
6109
|
}
|
|
5423
6110
|
function assertElectronVersion(config) {
|
|
5424
6111
|
const min = config.electron.minVersion;
|
|
@@ -5433,9 +6120,9 @@ function assertElectronVersion(config) {
|
|
|
5433
6120
|
}
|
|
5434
6121
|
function detectInstalledElectron(root) {
|
|
5435
6122
|
try {
|
|
5436
|
-
const pkgPath =
|
|
5437
|
-
if (!
|
|
5438
|
-
const pkg = JSON.parse(
|
|
6123
|
+
const pkgPath = path11.resolve(root, "node_modules/electron/package.json");
|
|
6124
|
+
if (!fs8.existsSync(pkgPath)) return null;
|
|
6125
|
+
const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
|
|
5439
6126
|
const major = parseInt(String(pkg.version).split(".")[0], 10);
|
|
5440
6127
|
return Number.isFinite(major) ? major : null;
|
|
5441
6128
|
} catch {
|
|
@@ -5448,8 +6135,8 @@ init_server();
|
|
|
5448
6135
|
|
|
5449
6136
|
// src/server/electron-dev.ts
|
|
5450
6137
|
init_config();
|
|
5451
|
-
import
|
|
5452
|
-
import
|
|
6138
|
+
import path17 from "path";
|
|
6139
|
+
import fs12 from "fs";
|
|
5453
6140
|
import { createRequire as createRequire5 } from "module";
|
|
5454
6141
|
import { spawn } from "child_process";
|
|
5455
6142
|
import chokidar from "chokidar";
|
|
@@ -5462,7 +6149,7 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5462
6149
|
const { noSpawn, ...rest } = inlineConfig;
|
|
5463
6150
|
const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
|
|
5464
6151
|
warnElectronVersion(config);
|
|
5465
|
-
console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.
|
|
6152
|
+
console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.4.0"}`));
|
|
5466
6153
|
const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
5467
6154
|
const server = await createServer2({
|
|
5468
6155
|
...rest,
|
|
@@ -5472,11 +6159,11 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5472
6159
|
await server.listen();
|
|
5473
6160
|
const devUrl = `http://localhost:${server.config.server.port}` + electronRendererDevPath(config.electron.renderer);
|
|
5474
6161
|
console.log(pc10.dim(` renderer: ${devUrl}`));
|
|
5475
|
-
const stageDir =
|
|
5476
|
-
|
|
5477
|
-
const mainEntry =
|
|
6162
|
+
const stageDir = path17.resolve(config.root, ".nasti");
|
|
6163
|
+
fs12.mkdirSync(stageDir, { recursive: true });
|
|
6164
|
+
const mainEntry = path17.resolve(config.root, config.electron.main);
|
|
5478
6165
|
const preloadEntries = normalizePreload(config.electron.preload, config.root);
|
|
5479
|
-
const builtMainFile =
|
|
6166
|
+
const builtMainFile = path17.join(stageDir, "main" + extFor(config.electron.mainFormat));
|
|
5480
6167
|
const builtPreloadFiles = [];
|
|
5481
6168
|
const compileAll = async () => {
|
|
5482
6169
|
await compileNode(config, mainEntry, {
|
|
@@ -5486,9 +6173,9 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5486
6173
|
});
|
|
5487
6174
|
builtPreloadFiles.length = 0;
|
|
5488
6175
|
for (const entry of preloadEntries) {
|
|
5489
|
-
if (!
|
|
5490
|
-
const base =
|
|
5491
|
-
const out =
|
|
6176
|
+
if (!fs12.existsSync(entry)) continue;
|
|
6177
|
+
const base = path17.basename(entry).replace(/\.[^.]+$/, "");
|
|
6178
|
+
const out = path17.join(stageDir, base + extFor(config.electron.preloadFormat));
|
|
5492
6179
|
await compileNode(config, entry, {
|
|
5493
6180
|
outFile: out,
|
|
5494
6181
|
format: config.electron.preloadFormat,
|
|
@@ -5527,7 +6214,7 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5527
6214
|
};
|
|
5528
6215
|
spawnElectron();
|
|
5529
6216
|
if (config.electron.autoRestart) {
|
|
5530
|
-
const watchTargets = [mainEntry, ...preloadEntries].filter(
|
|
6217
|
+
const watchTargets = [mainEntry, ...preloadEntries].filter(fs12.existsSync);
|
|
5531
6218
|
const watcher = chokidar.watch(watchTargets, { ignoreInitial: true });
|
|
5532
6219
|
let restarting = null;
|
|
5533
6220
|
let pending = false;
|
|
@@ -5607,7 +6294,7 @@ async function compileNode(config, entry, opts) {
|
|
|
5607
6294
|
platform: "node",
|
|
5608
6295
|
plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
|
|
5609
6296
|
});
|
|
5610
|
-
|
|
6297
|
+
fs12.mkdirSync(path17.dirname(opts.outFile), { recursive: true });
|
|
5611
6298
|
await bundle2.write({
|
|
5612
6299
|
file: opts.outFile,
|
|
5613
6300
|
format: opts.format === "cjs" ? "cjs" : "esm",
|
|
@@ -5620,18 +6307,18 @@ async function compileNode(config, entry, opts) {
|
|
|
5620
6307
|
await bundle2.close();
|
|
5621
6308
|
}
|
|
5622
6309
|
function electronRendererDevPath(renderer) {
|
|
5623
|
-
const normalized = renderer.split(
|
|
6310
|
+
const normalized = renderer.split(path17.sep).join("/").replace(/^\.?\//, "");
|
|
5624
6311
|
return normalized === "index.html" ? "/" : `/${normalized}`;
|
|
5625
6312
|
}
|
|
5626
6313
|
function resolveElectronBinary(config) {
|
|
5627
|
-
if (config.electron.electronPath &&
|
|
6314
|
+
if (config.electron.electronPath && fs12.existsSync(config.electron.electronPath)) {
|
|
5628
6315
|
return config.electron.electronPath;
|
|
5629
6316
|
}
|
|
5630
6317
|
try {
|
|
5631
|
-
const require2 = createRequire5(
|
|
6318
|
+
const require2 = createRequire5(path17.resolve(config.root, "package.json"));
|
|
5632
6319
|
const pathFile = require2.resolve("electron");
|
|
5633
6320
|
const electronModule = require2(pathFile);
|
|
5634
|
-
if (typeof electronModule === "string" &&
|
|
6321
|
+
if (typeof electronModule === "string" && fs12.existsSync(electronModule)) {
|
|
5635
6322
|
return electronModule;
|
|
5636
6323
|
}
|
|
5637
6324
|
} catch {
|
|
@@ -5658,8 +6345,8 @@ function warnElectronVersion(config) {
|
|
|
5658
6345
|
}
|
|
5659
6346
|
|
|
5660
6347
|
// src/plugins/monaco-editor.ts
|
|
5661
|
-
import
|
|
5662
|
-
import
|
|
6348
|
+
import path18 from "path";
|
|
6349
|
+
import fs13 from "fs";
|
|
5663
6350
|
import crypto4 from "crypto";
|
|
5664
6351
|
import { createRequire as createRequire6 } from "module";
|
|
5665
6352
|
var DEFAULT_WORKERS = {
|
|
@@ -5680,9 +6367,9 @@ function normalizePublicPath(p) {
|
|
|
5680
6367
|
}
|
|
5681
6368
|
function readMonacoVersion(root) {
|
|
5682
6369
|
try {
|
|
5683
|
-
const require2 = createRequire6(
|
|
6370
|
+
const require2 = createRequire6(path18.resolve(root, "package.json"));
|
|
5684
6371
|
const pkgJsonPath = require2.resolve("monaco-editor/package.json", { paths: [root] });
|
|
5685
|
-
const pkg = JSON.parse(
|
|
6372
|
+
const pkg = JSON.parse(fs13.readFileSync(pkgJsonPath, "utf-8"));
|
|
5686
6373
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
5687
6374
|
} catch {
|
|
5688
6375
|
return "unknown";
|
|
@@ -5702,20 +6389,20 @@ function monacoEditorPlugin(options = {}) {
|
|
|
5702
6389
|
let cacheDir = "";
|
|
5703
6390
|
const building = /* @__PURE__ */ new Map();
|
|
5704
6391
|
async function buildWorker(worker) {
|
|
5705
|
-
const cacheFile =
|
|
5706
|
-
if (
|
|
6392
|
+
const cacheFile = path18.join(cacheDir, `${worker.label}.worker.js`);
|
|
6393
|
+
if (fs13.existsSync(cacheFile)) return cacheFile;
|
|
5707
6394
|
const existing = building.get(worker.label);
|
|
5708
6395
|
if (existing) return existing;
|
|
5709
6396
|
const task = (async () => {
|
|
5710
6397
|
const { rolldown: rolldown4 } = await import("rolldown");
|
|
5711
|
-
const require2 = createRequire6(
|
|
6398
|
+
const require2 = createRequire6(path18.resolve(resolvedConfig.root, "package.json"));
|
|
5712
6399
|
let entry;
|
|
5713
6400
|
try {
|
|
5714
6401
|
entry = require2.resolve(worker.entry, { paths: [resolvedConfig.root] });
|
|
5715
6402
|
} catch {
|
|
5716
6403
|
entry = require2.resolve(worker.entry + ".js", { paths: [resolvedConfig.root] });
|
|
5717
6404
|
}
|
|
5718
|
-
|
|
6405
|
+
fs13.mkdirSync(cacheDir, { recursive: true });
|
|
5719
6406
|
const bundle2 = await rolldown4({
|
|
5720
6407
|
input: entry,
|
|
5721
6408
|
platform: "browser"
|
|
@@ -5775,12 +6462,12 @@ function monacoEditorPlugin(options = {}) {
|
|
|
5775
6462
|
resolvedConfig = config;
|
|
5776
6463
|
const version = readMonacoVersion(config.root);
|
|
5777
6464
|
const key = crypto4.createHash("sha1").update(version + "|" + publicPath).digest("hex").slice(0, 8);
|
|
5778
|
-
cacheDir =
|
|
6465
|
+
cacheDir = path18.resolve(config.root, "node_modules/.nasti/monaco", key);
|
|
5779
6466
|
},
|
|
5780
6467
|
async configureServer(server) {
|
|
5781
6468
|
const shouldBuild = !isCDN(publicPath) || forceBuildCDN;
|
|
5782
6469
|
const watcher = server.watcher;
|
|
5783
|
-
const monacoDir =
|
|
6470
|
+
const monacoDir = path18.resolve(resolvedConfig.root, "node_modules/monaco-editor");
|
|
5784
6471
|
try {
|
|
5785
6472
|
watcher?.unwatch?.(monacoDir);
|
|
5786
6473
|
} catch {
|
|
@@ -5810,7 +6497,7 @@ function monacoEditorPlugin(options = {}) {
|
|
|
5810
6497
|
const file = await buildWorker(worker);
|
|
5811
6498
|
res.setHeader("Content-Type", "application/javascript; charset=utf-8");
|
|
5812
6499
|
res.setHeader("Cache-Control", "public, max-age=604800, immutable");
|
|
5813
|
-
|
|
6500
|
+
fs13.createReadStream(file).pipe(res);
|
|
5814
6501
|
} catch (e) {
|
|
5815
6502
|
res.statusCode = 500;
|
|
5816
6503
|
res.end(`Monaco worker build failed: ${e.message}`);
|
|
@@ -5845,16 +6532,16 @@ self.monaco = monaco;`,
|
|
|
5845
6532
|
resolvedConfig.root,
|
|
5846
6533
|
resolvedConfig.build.outDir,
|
|
5847
6534
|
resolvedConfig.base
|
|
5848
|
-
) : isCDN(publicPath) ?
|
|
6535
|
+
) : isCDN(publicPath) ? path18.resolve(resolvedConfig.root, resolvedConfig.build.outDir, "monaco") : path18.resolve(
|
|
5849
6536
|
resolvedConfig.root,
|
|
5850
6537
|
resolvedConfig.build.outDir,
|
|
5851
6538
|
publicPath.replace(/^\//, "")
|
|
5852
6539
|
);
|
|
5853
|
-
|
|
6540
|
+
fs13.mkdirSync(outDir, { recursive: true });
|
|
5854
6541
|
for (const worker of workers) {
|
|
5855
6542
|
try {
|
|
5856
6543
|
const cacheFile = await buildWorker(worker);
|
|
5857
|
-
|
|
6544
|
+
fs13.copyFileSync(cacheFile, path18.join(outDir, `${worker.label}.worker.js`));
|
|
5858
6545
|
} catch (e) {
|
|
5859
6546
|
throw new Error(
|
|
5860
6547
|
`[nasti:monaco-editor] worker build failed for "${worker.label}": ${e.message}
|