@nasti-toolchain/nasti 2.3.1 → 2.4.1
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 +97 -1
- package/bin/nasti.js +0 -0
- package/client/hmr.ts +4 -3
- package/dist/cli.cjs +1896 -583
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1891 -575
- 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 +1810 -497
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +233 -18
- package/dist/index.d.ts +233 -18
- package/dist/index.js +1810 -494
- package/dist/index.js.map +1 -1
- package/package.json +8 -4
package/dist/cli.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) => (path18) => {
|
|
14
|
+
var fn = map[path18];
|
|
15
15
|
if (fn) return fn();
|
|
16
|
-
throw new Error("Module not found in bundle: " +
|
|
16
|
+
throw new Error("Module not found in bundle: " + path18);
|
|
17
17
|
};
|
|
18
18
|
var __esm = (fn, res) => function __init() {
|
|
19
19
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -189,7 +189,10 @@ var init_defaults = __esm({
|
|
|
189
189
|
target: "es2022",
|
|
190
190
|
rolldownOptions: {},
|
|
191
191
|
emptyOutDir: true,
|
|
192
|
-
css: {
|
|
192
|
+
css: {
|
|
193
|
+
inject: true,
|
|
194
|
+
emit: true
|
|
195
|
+
},
|
|
193
196
|
reportCompressedSize: true,
|
|
194
197
|
chunkSizeWarningLimit: 500,
|
|
195
198
|
cssCodeSplit: true,
|
|
@@ -428,7 +431,11 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
428
431
|
allowClearScreen: clearScreen2,
|
|
429
432
|
customLogger: merged.customLogger
|
|
430
433
|
});
|
|
431
|
-
const mergedBuild = {
|
|
434
|
+
const mergedBuild = {
|
|
435
|
+
...defaults.build,
|
|
436
|
+
...merged.build,
|
|
437
|
+
css: { ...defaults.build.css, ...merged.build?.css }
|
|
438
|
+
};
|
|
432
439
|
if (merged.build?.cssMinify === void 0) {
|
|
433
440
|
mergedBuild.cssMinify = !!mergedBuild.minify;
|
|
434
441
|
}
|
|
@@ -459,11 +466,17 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
459
466
|
bundledDev: merged.experimental?.bundledDev ?? defaults.experimental.bundledDev
|
|
460
467
|
}
|
|
461
468
|
};
|
|
462
|
-
const
|
|
469
|
+
const rawUserEnvironments = {
|
|
463
470
|
client: {},
|
|
464
471
|
ssr: {},
|
|
465
472
|
...merged.environments ?? {}
|
|
466
473
|
};
|
|
474
|
+
const userEnvironments = Object.fromEntries(
|
|
475
|
+
Object.entries(rawUserEnvironments).map(([name, options]) => [
|
|
476
|
+
name,
|
|
477
|
+
deepMerge({}, options)
|
|
478
|
+
])
|
|
479
|
+
);
|
|
467
480
|
for (const [name, envOptions] of Object.entries(userEnvironments)) {
|
|
468
481
|
for (const plugin of rawPlugins) {
|
|
469
482
|
if (plugin.configEnvironment) {
|
|
@@ -474,6 +487,7 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
474
487
|
}
|
|
475
488
|
for (const [name, envOptions] of Object.entries(userEnvironments)) {
|
|
476
489
|
const consumer = envOptions.consumer ?? (name === "client" ? "client" : "server");
|
|
490
|
+
const vueOptions = deepMerge({}, envOptions.vue ?? {});
|
|
477
491
|
if (name === "client") {
|
|
478
492
|
if (envOptions.resolve) {
|
|
479
493
|
Object.assign(resolved.resolve, {
|
|
@@ -481,9 +495,14 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
481
495
|
alias: { ...resolved.resolve.alias, ...envOptions.resolve.alias }
|
|
482
496
|
});
|
|
483
497
|
}
|
|
484
|
-
if (envOptions.build)
|
|
498
|
+
if (envOptions.build) {
|
|
499
|
+
const { css, ...environmentBuild } = envOptions.build;
|
|
500
|
+
Object.assign(resolved.build, environmentBuild);
|
|
501
|
+
if (css) resolved.build.css = { ...resolved.build.css, ...css };
|
|
502
|
+
}
|
|
485
503
|
resolved.environments.client = {
|
|
486
504
|
consumer,
|
|
505
|
+
buildEnabled: envOptions.buildEnabled ?? true,
|
|
487
506
|
entry: normalizeEnvironmentEntries(envOptions.entry, root),
|
|
488
507
|
html: path.resolve(
|
|
489
508
|
root,
|
|
@@ -492,15 +511,18 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
492
511
|
driver: envOptions.driver,
|
|
493
512
|
// 同引用 —— 精确镜像(assertClientEnvironmentMirror 校验)
|
|
494
513
|
resolve: resolved.resolve,
|
|
495
|
-
build: resolved.build
|
|
514
|
+
build: resolved.build,
|
|
515
|
+
vue: vueOptions
|
|
496
516
|
};
|
|
497
517
|
continue;
|
|
498
518
|
}
|
|
499
519
|
resolved.environments[name] = {
|
|
500
520
|
consumer,
|
|
521
|
+
buildEnabled: envOptions.buildEnabled ?? true,
|
|
501
522
|
entry: normalizeEnvironmentEntries(envOptions.entry, root),
|
|
502
523
|
html: envOptions.consumer === "client" && envOptions.html ? path.resolve(root, envOptions.html) : void 0,
|
|
503
524
|
driver: envOptions.driver,
|
|
525
|
+
vue: vueOptions,
|
|
504
526
|
resolve: {
|
|
505
527
|
alias: { ...resolved.resolve.alias, ...envOptions.resolve?.alias },
|
|
506
528
|
extensions: envOptions.resolve?.extensions ?? [...resolved.resolve.extensions],
|
|
@@ -511,6 +533,7 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
511
533
|
build: {
|
|
512
534
|
...resolved.build,
|
|
513
535
|
...envOptions.build,
|
|
536
|
+
css: { ...resolved.build.css, ...envOptions.build?.css },
|
|
514
537
|
// 非 client 环境默认产出到 <outDir>/<envName>(如 dist/ssr),可显式覆盖
|
|
515
538
|
outDir: envOptions.build?.outDir ?? path.join(resolved.build.outDir, name),
|
|
516
539
|
// server 产物默认不压缩(可调试性优先,与 Vite SSR 默认一致),可显式覆盖
|
|
@@ -754,17 +777,23 @@ var init_plugin_container = __esm({
|
|
|
754
777
|
}
|
|
755
778
|
async transform(code, id) {
|
|
756
779
|
let currentCode = code;
|
|
780
|
+
let lastResult;
|
|
757
781
|
for (const plugin of this.plugins) {
|
|
758
782
|
if (!plugin.transform) continue;
|
|
759
783
|
const result = await plugin.transform.call(this.ctx, currentCode, id);
|
|
760
784
|
if (result == null) continue;
|
|
761
785
|
if (typeof result === "string") {
|
|
762
786
|
currentCode = result;
|
|
787
|
+
lastResult = void 0;
|
|
763
788
|
} else {
|
|
764
789
|
currentCode = result.code;
|
|
790
|
+
lastResult = result;
|
|
765
791
|
}
|
|
766
792
|
}
|
|
767
|
-
return currentCode === code ? null : {
|
|
793
|
+
return currentCode === code ? null : {
|
|
794
|
+
...lastResult,
|
|
795
|
+
code: currentCode
|
|
796
|
+
};
|
|
768
797
|
}
|
|
769
798
|
/** 完整的模块处理管道: resolveId → load → transform */
|
|
770
799
|
async processModule(source, importer) {
|
|
@@ -787,17 +816,39 @@ var init_plugin_container = __esm({
|
|
|
787
816
|
}
|
|
788
817
|
});
|
|
789
818
|
|
|
819
|
+
// src/core/url.ts
|
|
820
|
+
function removeTimestampQuery(url) {
|
|
821
|
+
const hashIndex = url.indexOf("#");
|
|
822
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
|
|
823
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
824
|
+
const queryIndex = withoutHash.indexOf("?");
|
|
825
|
+
if (queryIndex < 0) return url;
|
|
826
|
+
const pathname = withoutHash.slice(0, queryIndex);
|
|
827
|
+
const query = withoutHash.slice(queryIndex + 1).split("&").filter((part) => !/^t=\d+$/.test(part)).join("&");
|
|
828
|
+
return pathname + (query ? `?${query}` : "") + hash;
|
|
829
|
+
}
|
|
830
|
+
var init_url = __esm({
|
|
831
|
+
"src/core/url.ts"() {
|
|
832
|
+
"use strict";
|
|
833
|
+
}
|
|
834
|
+
});
|
|
835
|
+
|
|
790
836
|
// src/core/module-graph.ts
|
|
791
837
|
var ModuleGraph;
|
|
792
838
|
var init_module_graph = __esm({
|
|
793
839
|
"src/core/module-graph.ts"() {
|
|
794
840
|
"use strict";
|
|
841
|
+
init_url();
|
|
795
842
|
ModuleGraph = class {
|
|
843
|
+
environmentName;
|
|
796
844
|
urlToModuleMap = /* @__PURE__ */ new Map();
|
|
797
845
|
idToModuleMap = /* @__PURE__ */ new Map();
|
|
798
846
|
fileToModulesMap = /* @__PURE__ */ new Map();
|
|
847
|
+
constructor(environmentName = "client") {
|
|
848
|
+
this.environmentName = environmentName;
|
|
849
|
+
}
|
|
799
850
|
getModuleByUrl(url) {
|
|
800
|
-
return this.urlToModuleMap.get(url);
|
|
851
|
+
return this.urlToModuleMap.get(removeTimestampQuery(url));
|
|
801
852
|
}
|
|
802
853
|
getModuleById(id) {
|
|
803
854
|
return this.idToModuleMap.get(id);
|
|
@@ -806,10 +857,11 @@ var init_module_graph = __esm({
|
|
|
806
857
|
return this.fileToModulesMap.get(file);
|
|
807
858
|
}
|
|
808
859
|
async ensureEntryFromUrl(url) {
|
|
809
|
-
|
|
860
|
+
const normalizedUrl = removeTimestampQuery(url);
|
|
861
|
+
let mod = this.urlToModuleMap.get(normalizedUrl);
|
|
810
862
|
if (mod) return mod;
|
|
811
|
-
mod = this.createModule(
|
|
812
|
-
this.urlToModuleMap.set(
|
|
863
|
+
mod = this.createModule(normalizedUrl);
|
|
864
|
+
this.urlToModuleMap.set(normalizedUrl, mod);
|
|
813
865
|
return mod;
|
|
814
866
|
}
|
|
815
867
|
createModule(url, id) {
|
|
@@ -823,7 +875,9 @@ var init_module_graph = __esm({
|
|
|
823
875
|
acceptedHmrDeps: /* @__PURE__ */ new Set(),
|
|
824
876
|
transformResult: null,
|
|
825
877
|
lastHMRTimestamp: 0,
|
|
826
|
-
|
|
878
|
+
invalidationVersion: 0,
|
|
879
|
+
isSelfAccepting: false,
|
|
880
|
+
environment: this.environmentName
|
|
827
881
|
};
|
|
828
882
|
this.idToModuleMap.set(mod.id, mod);
|
|
829
883
|
return mod;
|
|
@@ -865,10 +919,64 @@ var init_module_graph = __esm({
|
|
|
865
919
|
}
|
|
866
920
|
}
|
|
867
921
|
}
|
|
922
|
+
/**
|
|
923
|
+
* 用一次转换得到的信息原子更新 import 与 HMR accept 关系。
|
|
924
|
+
* 依赖节点会在真正被浏览器请求前预先创建,这样入口模块先转换时也能建立完整图。
|
|
925
|
+
*/
|
|
926
|
+
async updateModuleInfo(mod, importedUrls, acceptedUrls, isSelfAccepting, expectedInvalidationVersion) {
|
|
927
|
+
const importedModules = await Promise.all(
|
|
928
|
+
[...importedUrls].map((url) => this.ensureEntryFromUrl(url))
|
|
929
|
+
);
|
|
930
|
+
const acceptedModules = await Promise.all(
|
|
931
|
+
[...acceptedUrls].map((url) => this.ensureEntryFromUrl(url))
|
|
932
|
+
);
|
|
933
|
+
if (expectedInvalidationVersion !== void 0 && mod.invalidationVersion !== expectedInvalidationVersion) {
|
|
934
|
+
return null;
|
|
935
|
+
}
|
|
936
|
+
const previousImports = new Set(mod.importedModules);
|
|
937
|
+
for (const imported of previousImports) {
|
|
938
|
+
imported.importers.delete(mod);
|
|
939
|
+
}
|
|
940
|
+
mod.importedModules.clear();
|
|
941
|
+
mod.acceptedHmrDeps.clear();
|
|
942
|
+
for (const imported of importedModules) {
|
|
943
|
+
mod.importedModules.add(imported);
|
|
944
|
+
imported.importers.add(mod);
|
|
945
|
+
}
|
|
946
|
+
for (const accepted of acceptedModules) {
|
|
947
|
+
mod.acceptedHmrDeps.add(accepted);
|
|
948
|
+
}
|
|
949
|
+
mod.isSelfAccepting = isSelfAccepting;
|
|
950
|
+
const pruned = /* @__PURE__ */ new Set();
|
|
951
|
+
for (const imported of previousImports) {
|
|
952
|
+
if (!mod.importedModules.has(imported) && imported.importers.size === 0) {
|
|
953
|
+
pruned.add(imported);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
return pruned;
|
|
957
|
+
}
|
|
868
958
|
/** 使模块的转换缓存失效 */
|
|
869
|
-
invalidateModule(mod) {
|
|
959
|
+
invalidateModule(mod, timestamp = Date.now()) {
|
|
870
960
|
mod.transformResult = null;
|
|
871
|
-
mod.lastHMRTimestamp =
|
|
961
|
+
mod.lastHMRTimestamp = timestamp;
|
|
962
|
+
mod.invalidationVersion++;
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* 仅失效到 HMR 边界:显式接受依赖的模块本身不会重执行;自接受模块需要失效,
|
|
966
|
+
* 但不再继续影响其 importer。这样既能传播依赖时间戳,也不会隐式重复副作用。
|
|
967
|
+
*/
|
|
968
|
+
invalidateModuleAndImporters(mod, timestamp = Date.now(), seen = /* @__PURE__ */ new Set()) {
|
|
969
|
+
if (seen.has(mod)) return;
|
|
970
|
+
seen.add(mod);
|
|
971
|
+
this.invalidateModule(mod, timestamp);
|
|
972
|
+
for (const importer of mod.importers) {
|
|
973
|
+
if (importer.acceptedHmrDeps.has(mod)) continue;
|
|
974
|
+
if (importer.isSelfAccepting) {
|
|
975
|
+
this.invalidateModule(importer, timestamp);
|
|
976
|
+
continue;
|
|
977
|
+
}
|
|
978
|
+
this.invalidateModuleAndImporters(importer, timestamp, seen);
|
|
979
|
+
}
|
|
872
980
|
}
|
|
873
981
|
/** 使所有模块缓存失效 */
|
|
874
982
|
invalidateAll() {
|
|
@@ -879,34 +987,32 @@ var init_module_graph = __esm({
|
|
|
879
987
|
/** 获取 HMR 传播边界 - 从变更模块向上遍历找到接受更新的边界 */
|
|
880
988
|
getHmrBoundaries(mod) {
|
|
881
989
|
const boundaries = [];
|
|
882
|
-
const
|
|
883
|
-
const
|
|
884
|
-
if (
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
boundaries.push({ boundary
|
|
888
|
-
return true;
|
|
990
|
+
const traversed = /* @__PURE__ */ new Set();
|
|
991
|
+
const addBoundary = (boundary, acceptedVia) => {
|
|
992
|
+
if (!boundaries.some(
|
|
993
|
+
(item) => item.boundary === boundary && item.acceptedVia === acceptedVia
|
|
994
|
+
)) {
|
|
995
|
+
boundaries.push({ boundary, acceptedVia });
|
|
889
996
|
}
|
|
890
|
-
|
|
891
|
-
|
|
997
|
+
};
|
|
998
|
+
const propagate = (node) => {
|
|
999
|
+
if (traversed.has(node)) return true;
|
|
1000
|
+
traversed.add(node);
|
|
1001
|
+
if (node.isSelfAccepting) {
|
|
1002
|
+
addBoundary(node, node);
|
|
892
1003
|
return true;
|
|
893
1004
|
}
|
|
894
1005
|
if (node.importers.size === 0) return false;
|
|
895
1006
|
for (const importer of node.importers) {
|
|
896
|
-
if (
|
|
1007
|
+
if (importer.acceptedHmrDeps.has(node)) {
|
|
1008
|
+
addBoundary(importer, node);
|
|
1009
|
+
continue;
|
|
1010
|
+
}
|
|
1011
|
+
if (!propagate(importer)) return false;
|
|
897
1012
|
}
|
|
898
1013
|
return true;
|
|
899
1014
|
};
|
|
900
|
-
|
|
901
|
-
boundaries.push({ boundary: mod, acceptedVia: mod });
|
|
902
|
-
return boundaries;
|
|
903
|
-
}
|
|
904
|
-
for (const importer of mod.importers) {
|
|
905
|
-
if (!propagate(importer, mod)) {
|
|
906
|
-
return [];
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
return boundaries;
|
|
1015
|
+
return propagate(mod) ? boundaries : [];
|
|
910
1016
|
}
|
|
911
1017
|
};
|
|
912
1018
|
}
|
|
@@ -929,12 +1035,12 @@ function createNoopHotChannel() {
|
|
|
929
1035
|
}
|
|
930
1036
|
};
|
|
931
1037
|
}
|
|
932
|
-
function createWsHotChannel(ws) {
|
|
1038
|
+
function createWsHotChannel(ws, environmentName = "client") {
|
|
933
1039
|
const listeners = /* @__PURE__ */ new Map();
|
|
934
1040
|
let invokeHandlers;
|
|
935
1041
|
return {
|
|
936
1042
|
send(payload) {
|
|
937
|
-
ws.send(payload);
|
|
1043
|
+
ws.send({ ...payload, environment: payload.environment ?? environmentName });
|
|
938
1044
|
},
|
|
939
1045
|
on(event, listener) {
|
|
940
1046
|
let set = listeners.get(event);
|
|
@@ -946,8 +1052,8 @@ function createWsHotChannel(ws) {
|
|
|
946
1052
|
},
|
|
947
1053
|
listen() {
|
|
948
1054
|
},
|
|
1055
|
+
// 多个 environment 共享底层 WebSocket server;它由 DevServer.close() 统一关闭。
|
|
949
1056
|
close() {
|
|
950
|
-
ws.close();
|
|
951
1057
|
},
|
|
952
1058
|
setInvokeHandler(handlers) {
|
|
953
1059
|
invokeHandlers = handlers;
|
|
@@ -1045,6 +1151,10 @@ var init_environment = __esm({
|
|
|
1045
1151
|
moduleGraph;
|
|
1046
1152
|
candidatePlugins;
|
|
1047
1153
|
pluginApi;
|
|
1154
|
+
buildMetadata = {};
|
|
1155
|
+
cssModules = /* @__PURE__ */ new Map();
|
|
1156
|
+
assetModules = /* @__PURE__ */ new Map();
|
|
1157
|
+
transformRequestHandler;
|
|
1048
1158
|
initialized = false;
|
|
1049
1159
|
constructor(name, config, init = {}) {
|
|
1050
1160
|
const options = config.environments[name];
|
|
@@ -1059,7 +1169,7 @@ var init_environment = __esm({
|
|
|
1059
1169
|
this.config = config;
|
|
1060
1170
|
this.options = options;
|
|
1061
1171
|
this.hot = init.hot ?? createNoopHotChannel();
|
|
1062
|
-
this.moduleGraph = new ModuleGraph();
|
|
1172
|
+
this.moduleGraph = new ModuleGraph(name);
|
|
1063
1173
|
this.candidatePlugins = init.plugins ?? config.plugins;
|
|
1064
1174
|
this.pluginApi = init.pluginApi ?? getPluginApi(config);
|
|
1065
1175
|
}
|
|
@@ -1101,6 +1211,53 @@ var init_environment = __esm({
|
|
|
1101
1211
|
logger: this.config.logger
|
|
1102
1212
|
};
|
|
1103
1213
|
}
|
|
1214
|
+
configureDevPipeline(transformRequest2) {
|
|
1215
|
+
this.transformRequestHandler = transformRequest2;
|
|
1216
|
+
}
|
|
1217
|
+
async transformRequest(url) {
|
|
1218
|
+
if (!this.transformRequestHandler) {
|
|
1219
|
+
throw new Error(
|
|
1220
|
+
`[nasti] environment "${this.name}" does not have an initialized dev transform pipeline`
|
|
1221
|
+
);
|
|
1222
|
+
}
|
|
1223
|
+
return this.transformRequestHandler(url);
|
|
1224
|
+
}
|
|
1225
|
+
setCssModule(module) {
|
|
1226
|
+
this.cssModules.set(module.id, { ...module });
|
|
1227
|
+
}
|
|
1228
|
+
getCssModule(id) {
|
|
1229
|
+
const module = this.cssModules.get(id);
|
|
1230
|
+
return module ? { ...module } : void 0;
|
|
1231
|
+
}
|
|
1232
|
+
getCssModules() {
|
|
1233
|
+
return Object.freeze(
|
|
1234
|
+
Object.fromEntries(
|
|
1235
|
+
[...this.cssModules].map(([id, module]) => [id, { ...module }])
|
|
1236
|
+
)
|
|
1237
|
+
);
|
|
1238
|
+
}
|
|
1239
|
+
setAssetModule(id, fileName) {
|
|
1240
|
+
this.assetModules.set(id, fileName);
|
|
1241
|
+
}
|
|
1242
|
+
getAssetModules() {
|
|
1243
|
+
return Object.freeze(Object.fromEntries(this.assetModules));
|
|
1244
|
+
}
|
|
1245
|
+
setBuildMetadata(metadata) {
|
|
1246
|
+
const { entries: currentEntries, ...currentMetadata } = this.buildMetadata;
|
|
1247
|
+
const { entries, ...nextMetadata } = metadata;
|
|
1248
|
+
this.buildMetadata = {
|
|
1249
|
+
...currentMetadata,
|
|
1250
|
+
...nextMetadata,
|
|
1251
|
+
...currentEntries || entries ? { entries: { ...currentEntries, ...entries } } : {}
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
getBuildMetadata() {
|
|
1255
|
+
const { entries, ...metadata } = this.buildMetadata;
|
|
1256
|
+
return {
|
|
1257
|
+
...metadata,
|
|
1258
|
+
...entries ? { entries: { ...entries } } : {}
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1104
1261
|
async close() {
|
|
1105
1262
|
try {
|
|
1106
1263
|
await this.driver?.close?.(this.getDriverContext());
|
|
@@ -1341,28 +1498,111 @@ var init_env = __esm({
|
|
|
1341
1498
|
}
|
|
1342
1499
|
});
|
|
1343
1500
|
|
|
1344
|
-
// src/
|
|
1345
|
-
var middleware_exports = {};
|
|
1346
|
-
__export(middleware_exports, {
|
|
1347
|
-
REACT_REFRESH_GLOBAL_PREAMBLE: () => REACT_REFRESH_GLOBAL_PREAMBLE,
|
|
1348
|
-
getReactRefreshRuntimeEsm: () => getReactRefreshRuntimeEsm,
|
|
1349
|
-
transformMiddleware: () => transformMiddleware,
|
|
1350
|
-
transformRequest: () => transformRequest
|
|
1351
|
-
});
|
|
1501
|
+
// src/plugins/assets.ts
|
|
1352
1502
|
import path4 from "path";
|
|
1353
1503
|
import fs4 from "fs";
|
|
1504
|
+
import crypto from "crypto";
|
|
1505
|
+
function assetsPlugin(config) {
|
|
1506
|
+
const emittedAssets = /* @__PURE__ */ new Set();
|
|
1507
|
+
return {
|
|
1508
|
+
name: "nasti:assets",
|
|
1509
|
+
resolveId(source) {
|
|
1510
|
+
if (source.endsWith("?url") || source.endsWith("?raw")) {
|
|
1511
|
+
return source;
|
|
1512
|
+
}
|
|
1513
|
+
return null;
|
|
1514
|
+
},
|
|
1515
|
+
load(id) {
|
|
1516
|
+
const ext = path4.extname(id.replace(/\?.*$/, ""));
|
|
1517
|
+
if (id.endsWith("?raw")) {
|
|
1518
|
+
const file = id.slice(0, -4);
|
|
1519
|
+
if (fs4.existsSync(file)) {
|
|
1520
|
+
const content = fs4.readFileSync(file, "utf-8");
|
|
1521
|
+
return `export default ${JSON.stringify(content)}`;
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
if (id.endsWith("?url") || ASSET_EXTENSIONS.has(ext)) {
|
|
1525
|
+
const file = id.replace(/\?.*$/, "");
|
|
1526
|
+
if (!fs4.existsSync(file)) return null;
|
|
1527
|
+
if (config.command === "serve") {
|
|
1528
|
+
const url = "/" + path4.relative(config.root, file);
|
|
1529
|
+
return `export default ${JSON.stringify(url)}`;
|
|
1530
|
+
}
|
|
1531
|
+
const content = fs4.readFileSync(file);
|
|
1532
|
+
const hash = crypto.createHash("sha256").update(content).digest("hex").slice(0, 8);
|
|
1533
|
+
const basename = path4.basename(file, ext);
|
|
1534
|
+
const hashedName = `${config.build.assetsDir}/${basename}.${hash}${ext}`;
|
|
1535
|
+
const environment = this.environment;
|
|
1536
|
+
if (!environment) {
|
|
1537
|
+
throw new Error("[nasti:assets] build environment is not initialized");
|
|
1538
|
+
}
|
|
1539
|
+
if (!emittedAssets.has(hashedName)) {
|
|
1540
|
+
this.emitFile({
|
|
1541
|
+
type: "asset",
|
|
1542
|
+
fileName: hashedName,
|
|
1543
|
+
source: content
|
|
1544
|
+
});
|
|
1545
|
+
emittedAssets.add(hashedName);
|
|
1546
|
+
}
|
|
1547
|
+
environment.setAssetModule(file, hashedName);
|
|
1548
|
+
return `export default ${JSON.stringify(config.base + hashedName)}`;
|
|
1549
|
+
}
|
|
1550
|
+
return null;
|
|
1551
|
+
}
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
function isAssetFile(id) {
|
|
1555
|
+
const ext = path4.extname(id.replace(/\?.*$/, ""));
|
|
1556
|
+
return ASSET_EXTENSIONS.has(ext);
|
|
1557
|
+
}
|
|
1558
|
+
var ASSET_EXTENSIONS;
|
|
1559
|
+
var init_assets = __esm({
|
|
1560
|
+
"src/plugins/assets.ts"() {
|
|
1561
|
+
"use strict";
|
|
1562
|
+
ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
1563
|
+
".png",
|
|
1564
|
+
".jpg",
|
|
1565
|
+
".jpeg",
|
|
1566
|
+
".gif",
|
|
1567
|
+
".svg",
|
|
1568
|
+
".ico",
|
|
1569
|
+
".webp",
|
|
1570
|
+
".avif",
|
|
1571
|
+
".mp4",
|
|
1572
|
+
".webm",
|
|
1573
|
+
".ogg",
|
|
1574
|
+
".mp3",
|
|
1575
|
+
".wav",
|
|
1576
|
+
".flac",
|
|
1577
|
+
".aac",
|
|
1578
|
+
".woff",
|
|
1579
|
+
".woff2",
|
|
1580
|
+
".eot",
|
|
1581
|
+
".ttf",
|
|
1582
|
+
".otf",
|
|
1583
|
+
".pdf",
|
|
1584
|
+
".txt"
|
|
1585
|
+
]);
|
|
1586
|
+
}
|
|
1587
|
+
});
|
|
1588
|
+
|
|
1589
|
+
// src/server/middleware.ts
|
|
1590
|
+
import path5 from "path";
|
|
1591
|
+
import fs5 from "fs";
|
|
1354
1592
|
import { createRequire } from "module";
|
|
1355
1593
|
import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "url";
|
|
1356
1594
|
import pc3 from "picocolors";
|
|
1357
|
-
function getReactRefreshRuntimeEsm() {
|
|
1358
|
-
if (__refreshRuntimeCache)
|
|
1595
|
+
function getReactRefreshRuntimeEsm(includeBoundaryHelpers = false) {
|
|
1596
|
+
if (__refreshRuntimeCache) {
|
|
1597
|
+
return includeBoundaryHelpers ? __refreshRuntimeCache + REACT_REFRESH_BOUNDARY_HELPERS : __refreshRuntimeCache;
|
|
1598
|
+
}
|
|
1359
1599
|
let cjsPath;
|
|
1360
1600
|
try {
|
|
1361
1601
|
const pkgPath = __require2.resolve("react-refresh/package.json");
|
|
1362
|
-
cjsPath =
|
|
1602
|
+
cjsPath = path5.join(path5.dirname(pkgPath), "cjs", "react-refresh-runtime.development.js");
|
|
1363
1603
|
} catch (err) {
|
|
1364
|
-
cjsPath =
|
|
1365
|
-
if (!
|
|
1604
|
+
cjsPath = path5.resolve(__dirname_esm, "../../node_modules/react-refresh/cjs/react-refresh-runtime.development.js");
|
|
1605
|
+
if (!fs5.existsSync(cjsPath)) {
|
|
1366
1606
|
const origMsg = err instanceof Error ? err.message : String(err);
|
|
1367
1607
|
throw new Error(
|
|
1368
1608
|
`[nasti] Missing dependency "react-refresh". Install it with: npm install react-refresh
|
|
@@ -1370,7 +1610,7 @@ Original resolve error: ${origMsg}`
|
|
|
1370
1610
|
);
|
|
1371
1611
|
}
|
|
1372
1612
|
}
|
|
1373
|
-
const cjsSource =
|
|
1613
|
+
const cjsSource = fs5.readFileSync(cjsPath, "utf-8");
|
|
1374
1614
|
__refreshRuntimeCache = `// Wrapped react-refresh runtime -> ESM
|
|
1375
1615
|
const exports = {};
|
|
1376
1616
|
const module = { exports };
|
|
@@ -1390,7 +1630,7 @@ export const findAffectedHostInstances = __rt.findAffectedHostInstances;
|
|
|
1390
1630
|
export const collectCustomHooksForSignature = __rt.collectCustomHooksForSignature;
|
|
1391
1631
|
export default __rt;
|
|
1392
1632
|
`;
|
|
1393
|
-
return __refreshRuntimeCache;
|
|
1633
|
+
return includeBoundaryHelpers ? __refreshRuntimeCache + REACT_REFRESH_BOUNDARY_HELPERS : __refreshRuntimeCache;
|
|
1394
1634
|
}
|
|
1395
1635
|
function buildReactRefreshWrapper(moduleUrl, transformedCode) {
|
|
1396
1636
|
const urlLit = JSON.stringify(moduleUrl);
|
|
@@ -1416,27 +1656,46 @@ window.$RefreshReg$ = prevRefreshReg;
|
|
|
1416
1656
|
window.$RefreshSig$ = prevRefreshSig;
|
|
1417
1657
|
|
|
1418
1658
|
if (__nasti_hot__) {
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1659
|
+
let __nasti_current_exports__;
|
|
1660
|
+
__nasti_hot__.accept((nextExports) => {
|
|
1661
|
+
if (!nextExports) return;
|
|
1662
|
+
if (!__nasti_current_exports__) {
|
|
1663
|
+
__nasti_hot__.invalidate('Could not Fast Refresh (previous exports unavailable)');
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(
|
|
1667
|
+
${urlLit},
|
|
1668
|
+
__nasti_current_exports__,
|
|
1669
|
+
nextExports,
|
|
1670
|
+
);
|
|
1671
|
+
if (invalidateMessage) __nasti_hot__.invalidate(invalidateMessage);
|
|
1672
|
+
});
|
|
1673
|
+
RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
|
|
1674
|
+
__nasti_current_exports__ = currentExports;
|
|
1675
|
+
RefreshRuntime.registerExportsForReactRefresh(${urlLit}, currentExports);
|
|
1424
1676
|
});
|
|
1425
1677
|
}
|
|
1426
1678
|
`;
|
|
1427
1679
|
}
|
|
1428
1680
|
function injectImportMetaHot(code, moduleUrl) {
|
|
1429
|
-
|
|
1681
|
+
const hotRE = /\bimport\.meta\.hot\b/g;
|
|
1682
|
+
const matches = [...maskStringsAndComments(code).matchAll(hotRE)];
|
|
1683
|
+
if (matches.length === 0) return code;
|
|
1684
|
+
for (const match of matches.reverse()) {
|
|
1685
|
+
const start = match.index;
|
|
1686
|
+
code = code.slice(0, start) + "__nasti_hot__" + code.slice(start + match[0].length);
|
|
1687
|
+
}
|
|
1430
1688
|
const urlLit = JSON.stringify(moduleUrl);
|
|
1431
1689
|
const header = `import { createHotContext as __nasti_createHotContext__ } from "/@nasti/client";
|
|
1432
1690
|
const __nasti_hot__ = __nasti_createHotContext__(${urlLit});
|
|
1433
1691
|
`;
|
|
1434
|
-
return header + code
|
|
1692
|
+
return header + code;
|
|
1435
1693
|
}
|
|
1436
1694
|
function transformMiddleware(ctx) {
|
|
1437
1695
|
ctx.envDefine = buildEnvDefine(
|
|
1438
1696
|
loadEnv(ctx.config.mode, ctx.config.root, ctx.config.envPrefix),
|
|
1439
|
-
ctx.config.mode
|
|
1697
|
+
ctx.config.mode,
|
|
1698
|
+
ssrDefineOverrides(ctx.environment?.consumer ?? "client")
|
|
1440
1699
|
);
|
|
1441
1700
|
return async (req, res, next) => {
|
|
1442
1701
|
const url = req.url ?? "/";
|
|
@@ -1481,7 +1740,7 @@ function transformMiddleware(ctx) {
|
|
|
1481
1740
|
return;
|
|
1482
1741
|
}
|
|
1483
1742
|
}
|
|
1484
|
-
if (isModuleRequest(url)) {
|
|
1743
|
+
if (isModuleRequest(url, req.headers["sec-fetch-dest"])) {
|
|
1485
1744
|
try {
|
|
1486
1745
|
const result = await transformRequest(url, ctx);
|
|
1487
1746
|
if (result) {
|
|
@@ -1507,13 +1766,14 @@ function transformMiddleware(ctx) {
|
|
|
1507
1766
|
}
|
|
1508
1767
|
async function transformRequest(url, ctx) {
|
|
1509
1768
|
const { config, pluginContainer, moduleGraph } = ctx;
|
|
1769
|
+
url = removeTimestampQuery(url);
|
|
1510
1770
|
const cleanReqUrl = url.split("?")[0];
|
|
1511
1771
|
const cached2 = moduleGraph.getModuleByUrl(url);
|
|
1512
1772
|
if (cached2?.transformResult) {
|
|
1513
1773
|
return cached2.transformResult;
|
|
1514
1774
|
}
|
|
1515
1775
|
if (cleanReqUrl === "/@react-refresh") {
|
|
1516
|
-
return { code: getReactRefreshRuntimeEsm() };
|
|
1776
|
+
return { code: getReactRefreshRuntimeEsm(true) };
|
|
1517
1777
|
}
|
|
1518
1778
|
if (cleanReqUrl.startsWith("/@modules/") && url.includes("?")) {
|
|
1519
1779
|
const idParam = new URLSearchParams(url.slice(url.indexOf("?") + 1)).get("id");
|
|
@@ -1521,8 +1781,8 @@ async function transformRequest(url, ctx) {
|
|
|
1521
1781
|
let realIdValid = false;
|
|
1522
1782
|
try {
|
|
1523
1783
|
if (idParam) {
|
|
1524
|
-
realId =
|
|
1525
|
-
realIdValid =
|
|
1784
|
+
realId = fs5.realpathSync(idParam);
|
|
1785
|
+
realIdValid = fs5.statSync(realId).isFile() && (realId.includes(`${path5.sep}node_modules${path5.sep}`) || isUnderRoot(realId, config.root));
|
|
1526
1786
|
}
|
|
1527
1787
|
} catch {
|
|
1528
1788
|
realId = null;
|
|
@@ -1549,40 +1809,63 @@ async function transformRequest(url, ctx) {
|
|
|
1549
1809
|
}
|
|
1550
1810
|
const rawQuery = url.includes("?") ? url.slice(url.indexOf("?") + 1) : "";
|
|
1551
1811
|
if (rawQuery && !/^t=\d+$/.test(rawQuery)) {
|
|
1552
|
-
const
|
|
1553
|
-
|
|
1554
|
-
|
|
1812
|
+
const mod2 = await moduleGraph.ensureEntryFromUrl(url);
|
|
1813
|
+
const transformVersion2 = mod2.invalidationVersion;
|
|
1814
|
+
const loaded2 = await pluginContainer.load(url);
|
|
1815
|
+
if (loaded2 != null) {
|
|
1816
|
+
let code2 = typeof loaded2 === "string" ? loaded2 : loaded2.code;
|
|
1817
|
+
let map2 = typeof loaded2 === "string" ? void 0 : loaded2.map;
|
|
1555
1818
|
const transformed = await pluginContainer.transform(code2, url);
|
|
1556
1819
|
if (transformed != null) {
|
|
1557
1820
|
code2 = typeof transformed === "string" ? transformed : transformed.code;
|
|
1821
|
+
if (typeof transformed !== "string" && transformed.map != null) {
|
|
1822
|
+
map2 = transformed.map;
|
|
1823
|
+
}
|
|
1558
1824
|
}
|
|
1559
|
-
const
|
|
1560
|
-
moduleGraph.registerModule(mod2,
|
|
1561
|
-
|
|
1825
|
+
const parentFile = resolveUrlToFile(cleanReqUrl, config.root) ?? cleanReqUrl;
|
|
1826
|
+
moduleGraph.registerModule(mod2, parentFile);
|
|
1827
|
+
const hotInfo2 = rewriteHotAcceptDeps(code2, config, parentFile);
|
|
1828
|
+
code2 = injectImportMetaHot(hotInfo2.code, url);
|
|
1562
1829
|
code2 = replaceEnvInCode(code2, ctx.envDefine ?? buildEnvDefine(
|
|
1563
1830
|
loadEnv(config.mode, config.root, config.envPrefix),
|
|
1564
|
-
config.mode
|
|
1831
|
+
config.mode,
|
|
1832
|
+
ssrDefineOverrides(ctx.environment?.consumer ?? "client")
|
|
1565
1833
|
));
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1834
|
+
const importedUrls2 = /* @__PURE__ */ new Set();
|
|
1835
|
+
code2 = rewriteImports(code2, config, parentFile, importedUrls2, moduleGraph);
|
|
1836
|
+
const pruned2 = await moduleGraph.updateModuleInfo(
|
|
1837
|
+
mod2,
|
|
1838
|
+
importedUrls2,
|
|
1839
|
+
hotInfo2.acceptedUrls,
|
|
1840
|
+
hotInfo2.isSelfAccepting,
|
|
1841
|
+
transformVersion2
|
|
1842
|
+
);
|
|
1843
|
+
const transformResult2 = { code: code2, map: map2 };
|
|
1844
|
+
if (pruned2) {
|
|
1845
|
+
if (pruned2.size > 0) ctx.onPrune?.([...pruned2].map((item) => item.url));
|
|
1846
|
+
mod2.transformResult = transformResult2;
|
|
1847
|
+
}
|
|
1569
1848
|
return transformResult2;
|
|
1570
1849
|
}
|
|
1571
1850
|
}
|
|
1572
1851
|
const filePath = resolveUrlToFile(url, config.root);
|
|
1573
|
-
if (!filePath || !
|
|
1852
|
+
if (!filePath || !fs5.existsSync(filePath)) return null;
|
|
1574
1853
|
const mod = await moduleGraph.ensureEntryFromUrl(url);
|
|
1575
1854
|
moduleGraph.registerModule(mod, filePath);
|
|
1855
|
+
const transformVersion = mod.invalidationVersion;
|
|
1576
1856
|
if (cleanReqUrl.startsWith("/@modules/")) {
|
|
1577
1857
|
const code2 = await bundlePackageAsEsm(filePath, config.root);
|
|
1578
1858
|
const transformResult2 = { code: code2 };
|
|
1579
1859
|
mod.transformResult = transformResult2;
|
|
1580
1860
|
return transformResult2;
|
|
1581
1861
|
}
|
|
1582
|
-
|
|
1862
|
+
const loaded = await pluginContainer.load(filePath);
|
|
1863
|
+
let code = loaded == null ? fs5.readFileSync(filePath, "utf-8") : typeof loaded === "string" ? loaded : loaded.code;
|
|
1864
|
+
let map = loaded && typeof loaded !== "string" ? loaded.map : void 0;
|
|
1583
1865
|
const pluginResult = await pluginContainer.transform(code, filePath);
|
|
1584
1866
|
if (pluginResult) {
|
|
1585
1867
|
code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
|
|
1868
|
+
if (typeof pluginResult !== "string") map = pluginResult.map;
|
|
1586
1869
|
}
|
|
1587
1870
|
const stableUrl = cleanReqUrl;
|
|
1588
1871
|
let wrappedWithRefresh = false;
|
|
@@ -1593,26 +1876,41 @@ async function transformRequest(url, ctx) {
|
|
|
1593
1876
|
sourcemap: true,
|
|
1594
1877
|
jsxRuntime: "automatic",
|
|
1595
1878
|
jsxImportSource: config.framework === "vue" ? "vue" : "react",
|
|
1596
|
-
reactRefresh: useRefresh
|
|
1879
|
+
reactRefresh: useRefresh,
|
|
1880
|
+
target: ctx.environment?.options.build.target ?? config.build.target
|
|
1597
1881
|
});
|
|
1598
1882
|
code = result.code;
|
|
1883
|
+
if (result.map) map = JSON.parse(result.map);
|
|
1599
1884
|
if (useRefresh) {
|
|
1600
1885
|
code = buildReactRefreshWrapper(stableUrl, code);
|
|
1601
1886
|
wrappedWithRefresh = true;
|
|
1602
|
-
mod.isSelfAccepting = true;
|
|
1603
1887
|
}
|
|
1604
1888
|
}
|
|
1889
|
+
const hotInfo = rewriteHotAcceptDeps(code, config, filePath);
|
|
1890
|
+
code = hotInfo.code;
|
|
1605
1891
|
if (!wrappedWithRefresh) {
|
|
1606
1892
|
code = injectImportMetaHot(code, stableUrl);
|
|
1607
1893
|
}
|
|
1608
1894
|
const envDefine = ctx.envDefine ?? buildEnvDefine(
|
|
1609
1895
|
loadEnv(config.mode, config.root, config.envPrefix),
|
|
1610
|
-
config.mode
|
|
1896
|
+
config.mode,
|
|
1897
|
+
ssrDefineOverrides(ctx.environment?.consumer ?? "client")
|
|
1611
1898
|
);
|
|
1612
1899
|
code = replaceEnvInCode(code, envDefine);
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1900
|
+
const importedUrls = /* @__PURE__ */ new Set();
|
|
1901
|
+
code = rewriteImports(code, config, filePath, importedUrls, moduleGraph);
|
|
1902
|
+
const pruned = await moduleGraph.updateModuleInfo(
|
|
1903
|
+
mod,
|
|
1904
|
+
importedUrls,
|
|
1905
|
+
hotInfo.acceptedUrls,
|
|
1906
|
+
wrappedWithRefresh || hotInfo.isSelfAccepting,
|
|
1907
|
+
transformVersion
|
|
1908
|
+
);
|
|
1909
|
+
const transformResult = { code, map };
|
|
1910
|
+
if (pruned) {
|
|
1911
|
+
if (pruned.size > 0) ctx.onPrune?.([...pruned].map((item) => item.url));
|
|
1912
|
+
mod.transformResult = transformResult;
|
|
1913
|
+
}
|
|
1616
1914
|
return transformResult;
|
|
1617
1915
|
}
|
|
1618
1916
|
async function loadVirtualModule(spec, ctx) {
|
|
@@ -1620,7 +1918,7 @@ async function loadVirtualModule(spec, ctx) {
|
|
|
1620
1918
|
const resolved = await pluginContainer.resolveId(spec);
|
|
1621
1919
|
if (resolved == null) return null;
|
|
1622
1920
|
const resolvedId = typeof resolved === "string" ? resolved : resolved.id;
|
|
1623
|
-
const looksVirtual = resolvedId.startsWith("\0") || !
|
|
1921
|
+
const looksVirtual = resolvedId.startsWith("\0") || !fs5.existsSync(resolvedId);
|
|
1624
1922
|
if (!looksVirtual) return null;
|
|
1625
1923
|
const loadResult = await pluginContainer.load(resolvedId);
|
|
1626
1924
|
if (loadResult == null) return null;
|
|
@@ -1631,9 +1929,10 @@ async function loadVirtualModule(spec, ctx) {
|
|
|
1631
1929
|
}
|
|
1632
1930
|
code = replaceEnvInCode(code, ctx.envDefine ?? buildEnvDefine(
|
|
1633
1931
|
loadEnv(config.mode, config.root, config.envPrefix),
|
|
1634
|
-
config.mode
|
|
1932
|
+
config.mode,
|
|
1933
|
+
ssrDefineOverrides(ctx.environment?.consumer ?? "client")
|
|
1635
1934
|
));
|
|
1636
|
-
const anchor =
|
|
1935
|
+
const anchor = path5.join(config.root, "__nasti_virtual__.ts");
|
|
1637
1936
|
code = rewriteImports(code, config, anchor);
|
|
1638
1937
|
return { id: resolvedId, result: { code } };
|
|
1639
1938
|
}
|
|
@@ -1659,7 +1958,7 @@ async function doBundlePackage(entryFile, root) {
|
|
|
1659
1958
|
await bundle2.close();
|
|
1660
1959
|
let code = result.output[0].code;
|
|
1661
1960
|
code = code.replace(/process\.env\.NODE_ENV/g, '"development"');
|
|
1662
|
-
const externalBaseDir =
|
|
1961
|
+
const externalBaseDir = path5.dirname(entryFile);
|
|
1663
1962
|
code = code.replace(
|
|
1664
1963
|
/^(import\b[^;'"]*?\bfrom\s+)(['"])([^'"./][^'"]*)(\2)/gm,
|
|
1665
1964
|
(_, prefix, q, spec) => `${prefix}${q}${externalSpecToModuleUrl(spec, externalBaseDir, root)}${q}`
|
|
@@ -1677,16 +1976,16 @@ async function doBundlePackage(entryFile, root) {
|
|
|
1677
1976
|
return code;
|
|
1678
1977
|
}
|
|
1679
1978
|
async function tryGenerateSubpathShim(entryFile, root) {
|
|
1680
|
-
const NM = `${
|
|
1979
|
+
const NM = `${path5.sep}node_modules${path5.sep}`;
|
|
1681
1980
|
if (!entryFile.includes(NM)) return null;
|
|
1682
1981
|
let pkgDir = null;
|
|
1683
1982
|
let pkgName = null;
|
|
1684
|
-
let dir =
|
|
1983
|
+
let dir = path5.dirname(entryFile);
|
|
1685
1984
|
while (true) {
|
|
1686
|
-
const pkgJsonPath =
|
|
1687
|
-
if (
|
|
1985
|
+
const pkgJsonPath = path5.join(dir, "package.json");
|
|
1986
|
+
if (fs5.existsSync(pkgJsonPath)) {
|
|
1688
1987
|
try {
|
|
1689
|
-
const pkg = JSON.parse(
|
|
1988
|
+
const pkg = JSON.parse(fs5.readFileSync(pkgJsonPath, "utf-8"));
|
|
1690
1989
|
if (typeof pkg?.name === "string" && pkg.name) {
|
|
1691
1990
|
pkgDir = dir;
|
|
1692
1991
|
pkgName = pkg.name;
|
|
@@ -1695,16 +1994,16 @@ async function tryGenerateSubpathShim(entryFile, root) {
|
|
|
1695
1994
|
} catch {
|
|
1696
1995
|
}
|
|
1697
1996
|
}
|
|
1698
|
-
const parent =
|
|
1997
|
+
const parent = path5.dirname(dir);
|
|
1699
1998
|
if (parent === dir) return null;
|
|
1700
1999
|
dir = parent;
|
|
1701
2000
|
if (!dir.includes(NM)) return null;
|
|
1702
2001
|
}
|
|
1703
2002
|
if (!pkgDir || !pkgName) return null;
|
|
1704
|
-
const entryExt =
|
|
2003
|
+
const entryExt = path5.extname(entryFile);
|
|
1705
2004
|
const mainEntry = pickMainEntryByExtension(pkgDir, entryExt);
|
|
1706
2005
|
if (!mainEntry) return null;
|
|
1707
|
-
if (
|
|
2006
|
+
if (path5.resolve(mainEntry) === path5.resolve(entryFile)) return null;
|
|
1708
2007
|
let mainNs;
|
|
1709
2008
|
let subNs;
|
|
1710
2009
|
try {
|
|
@@ -1728,7 +2027,7 @@ async function tryGenerateSubpathShim(entryFile, root) {
|
|
|
1728
2027
|
if (mainNs["default"] !== subNs["default"]) return null;
|
|
1729
2028
|
}
|
|
1730
2029
|
const rootMain = resolveNodeModule(root, pkgName);
|
|
1731
|
-
const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir +
|
|
2030
|
+
const mainEntryUrl = rootMain && rootMain.startsWith(pkgDir + path5.sep) ? `/@modules/${pkgName}` : `/@modules/${pkgName}?id=${encodeURIComponent(mainEntry)}`;
|
|
1732
2031
|
const lines = [
|
|
1733
2032
|
`// Nasti subpath shim \u2192 ${pkgName} (avoid duplicate bundling)`,
|
|
1734
2033
|
`import * as __pkg from "${mainEntryUrl}";`
|
|
@@ -1742,10 +2041,10 @@ async function tryGenerateSubpathShim(entryFile, root) {
|
|
|
1742
2041
|
return lines.join("\n") + "\n";
|
|
1743
2042
|
}
|
|
1744
2043
|
function pickMainEntryByExtension(pkgDir, preferredExt) {
|
|
1745
|
-
const pkgJsonPath =
|
|
2044
|
+
const pkgJsonPath = path5.join(pkgDir, "package.json");
|
|
1746
2045
|
let pkg;
|
|
1747
2046
|
try {
|
|
1748
|
-
pkg = JSON.parse(
|
|
2047
|
+
pkg = JSON.parse(fs5.readFileSync(pkgJsonPath, "utf-8"));
|
|
1749
2048
|
} catch {
|
|
1750
2049
|
return null;
|
|
1751
2050
|
}
|
|
@@ -1764,14 +2063,14 @@ function pickMainEntryByExtension(pkgDir, preferredExt) {
|
|
|
1764
2063
|
if (typeof pkg.module === "string") candidates.push(pkg.module);
|
|
1765
2064
|
if (typeof pkg.main === "string") candidates.push(pkg.main);
|
|
1766
2065
|
for (const cand of candidates) {
|
|
1767
|
-
if (
|
|
1768
|
-
const full =
|
|
1769
|
-
if (
|
|
2066
|
+
if (path5.extname(cand) === preferredExt) {
|
|
2067
|
+
const full = path5.resolve(pkgDir, cand);
|
|
2068
|
+
if (fs5.existsSync(full)) return full;
|
|
1770
2069
|
}
|
|
1771
2070
|
}
|
|
1772
2071
|
for (const cand of candidates) {
|
|
1773
|
-
const full =
|
|
1774
|
-
if (
|
|
2072
|
+
const full = path5.resolve(pkgDir, cand);
|
|
2073
|
+
if (fs5.existsSync(full)) return full;
|
|
1775
2074
|
}
|
|
1776
2075
|
return null;
|
|
1777
2076
|
}
|
|
@@ -1817,72 +2116,231 @@ async function injectCjsNamedExports(code, entryFile) {
|
|
|
1817
2116
|
return code;
|
|
1818
2117
|
}
|
|
1819
2118
|
}
|
|
1820
|
-
function rewriteImports(code, config, filePath) {
|
|
2119
|
+
function rewriteImports(code, config, filePath, importedUrls, moduleGraph) {
|
|
2120
|
+
const resolveSpec = createModuleSpecifierResolver(config, filePath);
|
|
2121
|
+
const transformSpec = (spec) => {
|
|
2122
|
+
const resolved = removeTimestampQuery(resolveSpec(spec));
|
|
2123
|
+
importedUrls?.add(resolved);
|
|
2124
|
+
const timestamp = moduleGraph?.getModuleByUrl(resolved)?.lastHMRTimestamp ?? 0;
|
|
2125
|
+
return timestamp > 0 ? appendTimestampQuery(resolved, timestamp) : resolved;
|
|
2126
|
+
};
|
|
2127
|
+
return code.replace(
|
|
2128
|
+
/\bfrom\s+(['"])([^'"]+)\1/g,
|
|
2129
|
+
(_m, q, s) => `from ${q}${transformSpec(s)}${q}`
|
|
2130
|
+
).replace(
|
|
2131
|
+
/\bimport\s+(['"])([^'"]+)\1/g,
|
|
2132
|
+
(_m, q, s) => `import ${q}${transformSpec(s)}${q}`
|
|
2133
|
+
).replace(
|
|
2134
|
+
/\bimport\s*\(\s*(['"])([^'"]+)\1\s*\)/g,
|
|
2135
|
+
(_m, q, s) => `import(${q}${transformSpec(s)}${q})`
|
|
2136
|
+
);
|
|
2137
|
+
}
|
|
2138
|
+
function createModuleSpecifierResolver(config, filePath) {
|
|
1821
2139
|
const root = config.root;
|
|
1822
|
-
const fileDir =
|
|
2140
|
+
const fileDir = path5.dirname(filePath);
|
|
1823
2141
|
const aliasEntries = Object.entries(config.resolve.alias).sort(
|
|
1824
2142
|
([a], [b]) => b.length - a.length
|
|
1825
2143
|
);
|
|
1826
|
-
const toRootUrl = (abs) => "/" +
|
|
1827
|
-
|
|
1828
|
-
const suffixMatch =
|
|
2144
|
+
const toRootUrl = (abs) => "/" + path5.relative(root, abs).replace(/\\/g, "/");
|
|
2145
|
+
return (specifier) => {
|
|
2146
|
+
const suffixMatch = specifier.match(/[?#].*$/);
|
|
1829
2147
|
const suffix = suffixMatch ? suffixMatch[0] : "";
|
|
1830
|
-
const baseSpec = suffix ?
|
|
2148
|
+
const baseSpec = suffix ? specifier.slice(0, -suffix.length) : specifier;
|
|
1831
2149
|
for (const [key, value] of aliasEntries) {
|
|
1832
2150
|
if (baseSpec === key || baseSpec.startsWith(key + "/")) {
|
|
1833
2151
|
const aliasBase = resolveAliasTarget(value, root);
|
|
1834
2152
|
const sub = baseSpec.slice(key.length).replace(/^\//, "");
|
|
1835
|
-
const target = sub ?
|
|
2153
|
+
const target = sub ? path5.join(aliasBase, sub) : aliasBase;
|
|
1836
2154
|
const resolved = tryResolveDiskPath(target);
|
|
1837
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix :
|
|
2155
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
1838
2156
|
}
|
|
1839
2157
|
}
|
|
1840
2158
|
if (baseSpec.startsWith("./") || baseSpec.startsWith("../")) {
|
|
1841
|
-
const
|
|
1842
|
-
|
|
1843
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
|
|
2159
|
+
const resolved = tryResolveDiskPath(path5.resolve(fileDir, baseSpec));
|
|
2160
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
1844
2161
|
}
|
|
1845
2162
|
if (baseSpec.startsWith("/") && !baseSpec.startsWith("/@")) {
|
|
1846
|
-
const
|
|
1847
|
-
|
|
1848
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
|
|
2163
|
+
const resolved = tryResolveDiskPath(path5.join(root, baseSpec.replace(/^\//, "")));
|
|
2164
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
1849
2165
|
}
|
|
1850
|
-
if (baseSpec.startsWith("/")) return
|
|
1851
|
-
return `/@modules/${
|
|
2166
|
+
if (baseSpec.startsWith("/")) return specifier;
|
|
2167
|
+
return `/@modules/${specifier}`;
|
|
1852
2168
|
};
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
)
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
)
|
|
2169
|
+
}
|
|
2170
|
+
function rewriteHotAcceptDeps(code, config, filePath) {
|
|
2171
|
+
const acceptedUrls = /* @__PURE__ */ new Set();
|
|
2172
|
+
const edits = [];
|
|
2173
|
+
const resolveSpec = createModuleSpecifierResolver(config, filePath);
|
|
2174
|
+
const acceptRE = /(?:\bimport\.meta\.hot|\b__nasti_hot__)(?:(?:\?\.)|\.)accept\s*\(/g;
|
|
2175
|
+
const searchableCode = maskStringsAndComments(code);
|
|
2176
|
+
let isSelfAccepting = false;
|
|
2177
|
+
let match;
|
|
2178
|
+
while (match = acceptRE.exec(searchableCode)) {
|
|
2179
|
+
let cursor = match.index + match[0].length;
|
|
2180
|
+
const skipTrivia = () => {
|
|
2181
|
+
while (cursor < code.length) {
|
|
2182
|
+
if (/\s/.test(code[cursor])) {
|
|
2183
|
+
cursor++;
|
|
2184
|
+
continue;
|
|
2185
|
+
}
|
|
2186
|
+
if (code[cursor] === "/" && code[cursor + 1] === "/") {
|
|
2187
|
+
cursor += 2;
|
|
2188
|
+
while (cursor < code.length && code[cursor] !== "\n") cursor++;
|
|
2189
|
+
continue;
|
|
2190
|
+
}
|
|
2191
|
+
if (code[cursor] === "/" && code[cursor + 1] === "*") {
|
|
2192
|
+
cursor += 2;
|
|
2193
|
+
while (cursor < code.length && !(code[cursor] === "*" && code[cursor + 1] === "/")) cursor++;
|
|
2194
|
+
cursor += 2;
|
|
2195
|
+
continue;
|
|
2196
|
+
}
|
|
2197
|
+
break;
|
|
2198
|
+
}
|
|
2199
|
+
};
|
|
2200
|
+
skipTrivia();
|
|
2201
|
+
const first = code[cursor];
|
|
2202
|
+
if (!first || first === ")" || first !== "[" && first !== "'" && first !== '"' && first !== "`") {
|
|
2203
|
+
isSelfAccepting = true;
|
|
2204
|
+
continue;
|
|
2205
|
+
}
|
|
2206
|
+
const readLiteral = () => {
|
|
2207
|
+
const quote = code[cursor];
|
|
2208
|
+
if (quote !== "'" && quote !== '"' && quote !== "`") return;
|
|
2209
|
+
const start = cursor;
|
|
2210
|
+
cursor++;
|
|
2211
|
+
let raw = "";
|
|
2212
|
+
while (cursor < code.length) {
|
|
2213
|
+
const char = code[cursor];
|
|
2214
|
+
if (char === "\\") {
|
|
2215
|
+
raw += code[cursor + 1] ?? "";
|
|
2216
|
+
cursor += 2;
|
|
2217
|
+
continue;
|
|
2218
|
+
}
|
|
2219
|
+
if (char === quote) {
|
|
2220
|
+
cursor++;
|
|
2221
|
+
const resolved = removeTimestampQuery(resolveSpec(raw));
|
|
2222
|
+
acceptedUrls.add(resolved);
|
|
2223
|
+
edits.push({ start, end: cursor, value: JSON.stringify(resolved) });
|
|
2224
|
+
return;
|
|
2225
|
+
}
|
|
2226
|
+
if (quote === "`" && char === "$" && code[cursor + 1] === "{") return;
|
|
2227
|
+
raw += char;
|
|
2228
|
+
cursor++;
|
|
2229
|
+
}
|
|
2230
|
+
};
|
|
2231
|
+
if (first === "[") {
|
|
2232
|
+
cursor++;
|
|
2233
|
+
while (cursor < code.length) {
|
|
2234
|
+
skipTrivia();
|
|
2235
|
+
if (code[cursor] === ",") {
|
|
2236
|
+
cursor++;
|
|
2237
|
+
skipTrivia();
|
|
2238
|
+
}
|
|
2239
|
+
if (code[cursor] === "]") break;
|
|
2240
|
+
const before = cursor;
|
|
2241
|
+
readLiteral();
|
|
2242
|
+
if (cursor === before) break;
|
|
2243
|
+
}
|
|
2244
|
+
} else {
|
|
2245
|
+
readLiteral();
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
for (const edit of edits.sort((a, b) => b.start - a.start)) {
|
|
2249
|
+
code = code.slice(0, edit.start) + edit.value + code.slice(edit.end);
|
|
2250
|
+
}
|
|
2251
|
+
return { code, acceptedUrls, isSelfAccepting };
|
|
2252
|
+
}
|
|
2253
|
+
function maskStringsAndComments(code) {
|
|
2254
|
+
const masked = code.split("");
|
|
2255
|
+
let state = "code";
|
|
2256
|
+
const isRegexStart = (index2) => {
|
|
2257
|
+
let previous = index2 - 1;
|
|
2258
|
+
while (previous >= 0 && /\s/.test(code[previous])) previous--;
|
|
2259
|
+
return previous < 0 || "=(:,!&|?{};[]+-*%^~<>".includes(code[previous]);
|
|
2260
|
+
};
|
|
2261
|
+
for (let i = 0; i < code.length; i++) {
|
|
2262
|
+
const char = code[i];
|
|
2263
|
+
const next = code[i + 1];
|
|
2264
|
+
if (state === "code") {
|
|
2265
|
+
if (char === "'") state = "single";
|
|
2266
|
+
else if (char === '"') state = "double";
|
|
2267
|
+
else if (char === "`") state = "template";
|
|
2268
|
+
else if (char === "/" && next === "/") state = "line-comment";
|
|
2269
|
+
else if (char === "/" && next === "*") state = "block-comment";
|
|
2270
|
+
else if (char === "/" && isRegexStart(i)) state = "regex";
|
|
2271
|
+
else continue;
|
|
2272
|
+
masked[i] = " ";
|
|
2273
|
+
continue;
|
|
2274
|
+
}
|
|
2275
|
+
if (state === "line-comment") {
|
|
2276
|
+
if (char === "\n") {
|
|
2277
|
+
state = "code";
|
|
2278
|
+
} else {
|
|
2279
|
+
masked[i] = " ";
|
|
2280
|
+
}
|
|
2281
|
+
continue;
|
|
2282
|
+
}
|
|
2283
|
+
if (state === "block-comment") {
|
|
2284
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
2285
|
+
if (char === "*" && next === "/") {
|
|
2286
|
+
masked[i + 1] = " ";
|
|
2287
|
+
i++;
|
|
2288
|
+
state = "code";
|
|
2289
|
+
}
|
|
2290
|
+
continue;
|
|
2291
|
+
}
|
|
2292
|
+
if (state === "regex" || state === "regex-class") {
|
|
2293
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
2294
|
+
if (char === "\\") {
|
|
2295
|
+
if (i + 1 < code.length) masked[++i] = " ";
|
|
2296
|
+
} else if (state === "regex" && char === "[") {
|
|
2297
|
+
state = "regex-class";
|
|
2298
|
+
} else if (state === "regex-class" && char === "]") {
|
|
2299
|
+
state = "regex";
|
|
2300
|
+
} else if (state === "regex" && char === "/") {
|
|
2301
|
+
state = "code";
|
|
2302
|
+
}
|
|
2303
|
+
continue;
|
|
2304
|
+
}
|
|
2305
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
2306
|
+
if (char === "\\") {
|
|
2307
|
+
if (i + 1 < code.length) masked[++i] = " ";
|
|
2308
|
+
continue;
|
|
2309
|
+
}
|
|
2310
|
+
if (state === "single" && char === "'" || state === "double" && char === '"' || state === "template" && char === "`") {
|
|
2311
|
+
state = "code";
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
return masked.join("");
|
|
1863
2315
|
}
|
|
1864
2316
|
function resolveAliasTarget(value, root) {
|
|
1865
|
-
if (
|
|
1866
|
-
if (value.startsWith("/")) return
|
|
1867
|
-
return
|
|
2317
|
+
if (path5.isAbsolute(value) && fs5.existsSync(value)) return value;
|
|
2318
|
+
if (value.startsWith("/")) return path5.join(root, value.slice(1));
|
|
2319
|
+
return path5.resolve(root, value);
|
|
1868
2320
|
}
|
|
1869
2321
|
function tryResolveDiskPath(target) {
|
|
1870
|
-
if (
|
|
2322
|
+
if (fs5.existsSync(target) && fs5.statSync(target).isFile()) return target;
|
|
1871
2323
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
1872
2324
|
const withExt = target + ext;
|
|
1873
|
-
if (
|
|
2325
|
+
if (fs5.existsSync(withExt) && fs5.statSync(withExt).isFile()) return withExt;
|
|
1874
2326
|
}
|
|
1875
|
-
if (
|
|
2327
|
+
if (fs5.existsSync(target) && fs5.statSync(target).isDirectory()) {
|
|
1876
2328
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
1877
|
-
const idx =
|
|
1878
|
-
if (
|
|
2329
|
+
const idx = path5.join(target, "index" + ext);
|
|
2330
|
+
if (fs5.existsSync(idx) && fs5.statSync(idx).isFile()) return idx;
|
|
1879
2331
|
}
|
|
1880
2332
|
}
|
|
1881
2333
|
return null;
|
|
1882
2334
|
}
|
|
1883
2335
|
function isUnderRoot(abs, root) {
|
|
1884
|
-
const rel =
|
|
1885
|
-
return !!rel && !rel.startsWith("..") && !
|
|
2336
|
+
const rel = path5.relative(root, abs);
|
|
2337
|
+
return !!rel && !rel.startsWith("..") && !path5.isAbsolute(rel);
|
|
2338
|
+
}
|
|
2339
|
+
function appendTimestampQuery(url, timestamp) {
|
|
2340
|
+
const hashIndex = url.indexOf("#");
|
|
2341
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
|
|
2342
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
2343
|
+
return `${withoutHash}${withoutHash.includes("?") ? "&" : "?"}t=${timestamp}${hash}`;
|
|
1886
2344
|
}
|
|
1887
2345
|
function externalSpecToModuleUrl(spec, baseDir, root) {
|
|
1888
2346
|
const resolved = resolveNodeModule(baseDir, spec);
|
|
@@ -1895,7 +2353,7 @@ function resolveNodeModule(baseDir, moduleName) {
|
|
|
1895
2353
|
const resolved = resolveNodeModuleEntry(baseDir, moduleName);
|
|
1896
2354
|
if (!resolved) return null;
|
|
1897
2355
|
try {
|
|
1898
|
-
return
|
|
2356
|
+
return fs5.realpathSync(resolved);
|
|
1899
2357
|
} catch {
|
|
1900
2358
|
return resolved;
|
|
1901
2359
|
}
|
|
@@ -1915,21 +2373,21 @@ function resolveNodeModuleEntry(root, moduleName) {
|
|
|
1915
2373
|
let pkgDir = null;
|
|
1916
2374
|
let dir = root;
|
|
1917
2375
|
for (; ; ) {
|
|
1918
|
-
const candidate =
|
|
1919
|
-
if (
|
|
2376
|
+
const candidate = path5.join(dir, "node_modules", pkgName);
|
|
2377
|
+
if (fs5.existsSync(candidate)) {
|
|
1920
2378
|
pkgDir = candidate;
|
|
1921
2379
|
break;
|
|
1922
2380
|
}
|
|
1923
|
-
const parent =
|
|
2381
|
+
const parent = path5.dirname(dir);
|
|
1924
2382
|
if (parent === dir) break;
|
|
1925
2383
|
dir = parent;
|
|
1926
2384
|
}
|
|
1927
2385
|
if (!pkgDir) return null;
|
|
1928
|
-
const pkgJsonPath =
|
|
1929
|
-
if (!
|
|
2386
|
+
const pkgJsonPath = path5.join(pkgDir, "package.json");
|
|
2387
|
+
if (!fs5.existsSync(pkgJsonPath)) return null;
|
|
1930
2388
|
let pkg;
|
|
1931
2389
|
try {
|
|
1932
|
-
pkg = JSON.parse(
|
|
2390
|
+
pkg = JSON.parse(fs5.readFileSync(pkgJsonPath, "utf-8"));
|
|
1933
2391
|
} catch {
|
|
1934
2392
|
return null;
|
|
1935
2393
|
}
|
|
@@ -1942,32 +2400,32 @@ function resolveNodeModuleEntry(root, moduleName) {
|
|
|
1942
2400
|
const subDirs = [""];
|
|
1943
2401
|
for (const field of ["module", "main"]) {
|
|
1944
2402
|
if (typeof pkg[field] === "string") {
|
|
1945
|
-
const dir2 =
|
|
2403
|
+
const dir2 = path5.dirname(pkg[field]);
|
|
1946
2404
|
if (dir2 && dir2 !== "." && !subDirs.includes(dir2)) subDirs.push(dir2);
|
|
1947
2405
|
}
|
|
1948
2406
|
}
|
|
1949
2407
|
for (const dir2 of subDirs) {
|
|
1950
|
-
const direct =
|
|
1951
|
-
if (
|
|
2408
|
+
const direct = path5.join(pkgDir, dir2, subpath);
|
|
2409
|
+
if (fs5.existsSync(direct) && fs5.statSync(direct).isFile()) return direct;
|
|
1952
2410
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
1953
|
-
if (
|
|
2411
|
+
if (fs5.existsSync(direct + ext)) return direct + ext;
|
|
1954
2412
|
}
|
|
1955
2413
|
}
|
|
1956
2414
|
return null;
|
|
1957
2415
|
}
|
|
1958
2416
|
for (const field of ["module", "jsnext:main", "jsnext", "main"]) {
|
|
1959
2417
|
if (typeof pkg[field] === "string") {
|
|
1960
|
-
const entry =
|
|
1961
|
-
if (
|
|
2418
|
+
const entry = path5.join(pkgDir, pkg[field]);
|
|
2419
|
+
if (fs5.existsSync(entry)) return entry;
|
|
1962
2420
|
}
|
|
1963
2421
|
}
|
|
1964
|
-
const indexFallback =
|
|
1965
|
-
if (
|
|
2422
|
+
const indexFallback = path5.join(pkgDir, "index.js");
|
|
2423
|
+
if (fs5.existsSync(indexFallback)) return indexFallback;
|
|
1966
2424
|
return null;
|
|
1967
2425
|
}
|
|
1968
2426
|
function resolvePackageExports(exports, key, pkgDir) {
|
|
1969
2427
|
if (typeof exports === "string") {
|
|
1970
|
-
return key === "." ?
|
|
2428
|
+
return key === "." ? path5.join(pkgDir, exports) : null;
|
|
1971
2429
|
}
|
|
1972
2430
|
const entry = exports[key];
|
|
1973
2431
|
if (entry === void 0) {
|
|
@@ -1979,7 +2437,7 @@ function resolvePackageExports(exports, key, pkgDir) {
|
|
|
1979
2437
|
return resolveExportValue(entry, pkgDir);
|
|
1980
2438
|
}
|
|
1981
2439
|
function resolveExportValue(value, pkgDir) {
|
|
1982
|
-
if (typeof value === "string") return
|
|
2440
|
+
if (typeof value === "string") return path5.join(pkgDir, value);
|
|
1983
2441
|
if (Array.isArray(value)) {
|
|
1984
2442
|
for (const item of value) {
|
|
1985
2443
|
const r = resolveExportValue(item, pkgDir);
|
|
@@ -2003,54 +2461,62 @@ function resolveUrlToFile(url, root) {
|
|
|
2003
2461
|
const moduleName = cleanUrl.slice("/@modules/".length);
|
|
2004
2462
|
return resolveNodeModule(root, moduleName);
|
|
2005
2463
|
}
|
|
2006
|
-
const filePath =
|
|
2007
|
-
if (
|
|
2464
|
+
const filePath = path5.resolve(root, cleanUrl.replace(/^\//, ""));
|
|
2465
|
+
if (fs5.existsSync(filePath) && fs5.statSync(filePath).isFile()) {
|
|
2008
2466
|
return filePath;
|
|
2009
2467
|
}
|
|
2010
2468
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
2011
2469
|
const withExt = filePath + ext;
|
|
2012
|
-
if (
|
|
2470
|
+
if (fs5.existsSync(withExt)) return withExt;
|
|
2013
2471
|
}
|
|
2014
2472
|
for (const ext of RESOLVE_EXTENSIONS) {
|
|
2015
|
-
const indexFile =
|
|
2016
|
-
if (
|
|
2473
|
+
const indexFile = path5.join(filePath, "index" + ext);
|
|
2474
|
+
if (fs5.existsSync(indexFile)) return indexFile;
|
|
2017
2475
|
}
|
|
2018
2476
|
return null;
|
|
2019
2477
|
}
|
|
2020
|
-
function isModuleRequest(url) {
|
|
2478
|
+
function isModuleRequest(url, destination) {
|
|
2021
2479
|
const cleanUrl = url.split("?")[0];
|
|
2022
2480
|
if (/\.(ts|tsx|jsx|js|mjs|vue|css|json)$/.test(cleanUrl)) return true;
|
|
2023
2481
|
if (cleanUrl.startsWith("/@modules/")) return true;
|
|
2024
|
-
if (
|
|
2482
|
+
if (isAssetFile(cleanUrl)) {
|
|
2483
|
+
const query = url.includes("?") ? url.slice(url.indexOf("?") + 1) : "";
|
|
2484
|
+
const isExplicitAssetModule = /(?:^|&)(?:url|raw)(?:&|$)/.test(query);
|
|
2485
|
+
return isExplicitAssetModule || destination === "script";
|
|
2486
|
+
}
|
|
2487
|
+
if (!path5.extname(cleanUrl)) return true;
|
|
2025
2488
|
return false;
|
|
2026
2489
|
}
|
|
2027
2490
|
function getHmrClientCode() {
|
|
2028
2491
|
return `
|
|
2029
2492
|
// Nasti HMR Client
|
|
2030
|
-
const
|
|
2493
|
+
const socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws';
|
|
2494
|
+
const socket = new WebSocket(socketProtocol + '://' + location.host, 'nasti-hmr');
|
|
2031
2495
|
const hotModulesMap = new Map();
|
|
2032
2496
|
const disposeMap = new Map();
|
|
2033
2497
|
const pruneMap = new Map();
|
|
2498
|
+
const dataMap = new Map();
|
|
2499
|
+
const customListenersMap = new Map();
|
|
2500
|
+
let updateQueue = [];
|
|
2501
|
+
let pendingUpdateQueue = false;
|
|
2034
2502
|
|
|
2035
2503
|
socket.addEventListener('message', async ({ data }) => {
|
|
2036
2504
|
const payload = JSON.parse(data);
|
|
2505
|
+
// \u9ED8\u8BA4\u6D4F\u89C8\u5668 client \u53EA\u6D88\u8D39\u81EA\u5DF1\u7684 HMR \u6D88\u606F\uFF1Bnative/worker \u73AF\u5883\u901A\u8FC7\u5404\u81EA\u7684
|
|
2506
|
+
// HotChannel \u6216 app-level HMR \u534F\u8C03\u5668\u5904\u7406\u540C\u4E00 transport \u4E0A\u7684\u547D\u540D\u6D88\u606F\u3002
|
|
2507
|
+
if (payload.environment && payload.environment !== 'client') return;
|
|
2037
2508
|
switch (payload.type) {
|
|
2038
2509
|
case 'connected':
|
|
2039
|
-
console.
|
|
2510
|
+
console.debug('[nasti] connected.');
|
|
2040
2511
|
clearErrorOverlay();
|
|
2041
2512
|
break;
|
|
2042
2513
|
case 'update':
|
|
2043
2514
|
try {
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
} else if (update.type === 'css-update') {
|
|
2048
|
-
return updateCss(update.path);
|
|
2049
|
-
}
|
|
2050
|
-
}));
|
|
2515
|
+
// CSS \u5728 unbundled \u6A21\u5F0F\u4E0B\u4E5F\u662F\u4F1A\u6CE8\u5165 <style> \u7684 JS \u6A21\u5757\uFF0C\u548C\u666E\u901A JS
|
|
2516
|
+
// \u4E00\u6837\u91CD\u65B0 import \u624D\u80FD\u6267\u884C dispose/accept \u5E76\u4FDD\u6301\u9875\u9762\u72B6\u6001\u3002
|
|
2517
|
+
await Promise.all(payload.updates.map(queueUpdate));
|
|
2051
2518
|
clearErrorOverlay();
|
|
2052
|
-
console.
|
|
2053
|
-
location.reload();
|
|
2519
|
+
console.debug('[nasti] HMR update complete.');
|
|
2054
2520
|
} catch (err) {
|
|
2055
2521
|
console.error('[nasti] HMR update failed:', err);
|
|
2056
2522
|
showErrorOverlay(err);
|
|
@@ -2061,11 +2527,34 @@ socket.addEventListener('message', async ({ data }) => {
|
|
|
2061
2527
|
location.reload();
|
|
2062
2528
|
break;
|
|
2063
2529
|
case 'prune':
|
|
2064
|
-
payload.paths.
|
|
2065
|
-
const
|
|
2066
|
-
|
|
2067
|
-
|
|
2530
|
+
await Promise.all(payload.paths.map(async (path) => {
|
|
2531
|
+
const data = dataMap.get(path);
|
|
2532
|
+
const dispose = disposeMap.get(path);
|
|
2533
|
+
const prune = pruneMap.get(path);
|
|
2534
|
+
if (dispose) await dispose(data);
|
|
2535
|
+
if (prune) await prune(data);
|
|
2536
|
+
hotModulesMap.delete(path);
|
|
2537
|
+
disposeMap.delete(path);
|
|
2538
|
+
pruneMap.delete(path);
|
|
2539
|
+
dataMap.delete(path);
|
|
2540
|
+
clearCustomListeners(path);
|
|
2541
|
+
}));
|
|
2542
|
+
break;
|
|
2543
|
+
case 'custom': {
|
|
2544
|
+
const listenersByOwner = customListenersMap.get(payload.event);
|
|
2545
|
+
if (!listenersByOwner) break;
|
|
2546
|
+
const results = await Promise.allSettled(
|
|
2547
|
+
[...listenersByOwner.values()]
|
|
2548
|
+
.flatMap((listeners) => [...listeners])
|
|
2549
|
+
.map((listener) => Promise.resolve().then(() => listener(payload.data)))
|
|
2550
|
+
);
|
|
2551
|
+
for (const result of results) {
|
|
2552
|
+
if (result.status === 'rejected') {
|
|
2553
|
+
console.error('[nasti] custom HMR event listener failed:', result.reason);
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2068
2556
|
break;
|
|
2557
|
+
}
|
|
2069
2558
|
case 'error':
|
|
2070
2559
|
console.error('[nasti] error:', payload.err.message);
|
|
2071
2560
|
showErrorOverlay(payload.err);
|
|
@@ -2073,33 +2562,64 @@ socket.addEventListener('message', async ({ data }) => {
|
|
|
2073
2562
|
}
|
|
2074
2563
|
});
|
|
2075
2564
|
|
|
2076
|
-
// \
|
|
2565
|
+
// \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
|
|
2077
2566
|
let reconnectTimer = 0;
|
|
2078
2567
|
socket.addEventListener('close', () => {
|
|
2079
2568
|
clearTimeout(reconnectTimer);
|
|
2080
2569
|
reconnectTimer = setTimeout(() => location.reload(), 1000);
|
|
2081
2570
|
});
|
|
2082
2571
|
|
|
2572
|
+
/**
|
|
2573
|
+
* \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
|
|
2574
|
+
* \u6539\u53D8\u6A21\u5757\u5E94\u7528\u987A\u5E8F\u3002\u8FD9\u4E0E Vite HMRClient \u7684 fetch/apply \u4E24\u9636\u6BB5\u4E00\u81F4\u3002
|
|
2575
|
+
*/
|
|
2576
|
+
async function queueUpdate(update) {
|
|
2577
|
+
updateQueue.push(fetchUpdate(update));
|
|
2578
|
+
if (pendingUpdateQueue) return;
|
|
2579
|
+
|
|
2580
|
+
pendingUpdateQueue = true;
|
|
2581
|
+
await Promise.resolve();
|
|
2582
|
+
pendingUpdateQueue = false;
|
|
2583
|
+
const loading = updateQueue;
|
|
2584
|
+
updateQueue = [];
|
|
2585
|
+
const applyUpdates = await Promise.all(loading);
|
|
2586
|
+
for (const apply of applyUpdates) {
|
|
2587
|
+
if (apply) apply();
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2083
2591
|
async function fetchUpdate(update) {
|
|
2084
2592
|
const mod = hotModulesMap.get(update.path);
|
|
2085
|
-
// \
|
|
2086
|
-
|
|
2087
|
-
if (dispose) dispose();
|
|
2593
|
+
// \u5C1A\u672A\u5728\u5F53\u524D\u9875\u9762\u52A0\u8F7D\u7684\u52A8\u6001\u6A21\u5757\u4E0D\u9700\u8981\u66F4\u65B0\u3002
|
|
2594
|
+
if (!mod) return;
|
|
2088
2595
|
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2596
|
+
// \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
|
|
2597
|
+
const qualifiedCallbacks = mod.callbacks.filter(({ deps }) =>
|
|
2598
|
+
deps.includes(update.acceptedPath)
|
|
2599
|
+
);
|
|
2600
|
+
const isSelfUpdate = update.path === update.acceptedPath;
|
|
2601
|
+
if (!isSelfUpdate && qualifiedCallbacks.length === 0) return;
|
|
2602
|
+
|
|
2603
|
+
const dispose = disposeMap.get(update.acceptedPath);
|
|
2604
|
+
if (dispose) await dispose(dataMap.get(update.acceptedPath));
|
|
2605
|
+
const newMod = await import(appendTimestampQuery(update.acceptedPath, update.timestamp));
|
|
2606
|
+
|
|
2607
|
+
return () => {
|
|
2608
|
+
for (const { deps, fn } of qualifiedCallbacks) {
|
|
2609
|
+
fn(deps.map((dep) => dep === update.acceptedPath ? newMod : undefined));
|
|
2610
|
+
}
|
|
2611
|
+
const detail = isSelfUpdate
|
|
2612
|
+
? update.path
|
|
2613
|
+
: update.acceptedPath + ' via ' + update.path;
|
|
2614
|
+
console.debug('[nasti] hot updated:', detail);
|
|
2615
|
+
};
|
|
2094
2616
|
}
|
|
2095
2617
|
|
|
2096
|
-
function
|
|
2097
|
-
const
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
.then(css => { el.textContent = css; });
|
|
2102
|
-
}
|
|
2618
|
+
function appendTimestampQuery(url, timestamp) {
|
|
2619
|
+
const hashIndex = url.indexOf('#');
|
|
2620
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : '';
|
|
2621
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
2622
|
+
return withoutHash + (withoutHash.includes('?') ? '&' : '?') + 't=' + timestamp + hash;
|
|
2103
2623
|
}
|
|
2104
2624
|
|
|
2105
2625
|
function clearErrorOverlay() {
|
|
@@ -2127,23 +2647,31 @@ function showErrorOverlay(err) {
|
|
|
2127
2647
|
document.body.appendChild(overlay);
|
|
2128
2648
|
}
|
|
2129
2649
|
|
|
2130
|
-
/**
|
|
2131
|
-
* \u751F\u6210 import.meta.hot \u7684 hot context\u3002
|
|
2132
|
-
* \u5173\u952E\u7EA6\u675F\uFF1A\u540C\u4E00 ownerPath \u7684 accept \u56DE\u8C03\u5FC5\u987B\u66FF\u6362\uFF08\u4E0D\u662F append\uFF09\u3002
|
|
2133
|
-
* \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
|
|
2134
|
-
* \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
|
|
2135
|
-
*/
|
|
2136
2650
|
export function createHotContext(ownerPath) {
|
|
2651
|
+
if (!dataMap.has(ownerPath)) dataMap.set(ownerPath, {});
|
|
2652
|
+
|
|
2653
|
+
// \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
|
|
2654
|
+
const existing = hotModulesMap.get(ownerPath);
|
|
2655
|
+
if (existing) existing.callbacks = [];
|
|
2656
|
+
clearCustomListeners(ownerPath);
|
|
2657
|
+
|
|
2658
|
+
const acceptDeps = (deps, callback = () => {}) => {
|
|
2659
|
+
const mod = hotModulesMap.get(ownerPath) || { id: ownerPath, callbacks: [] };
|
|
2660
|
+
mod.callbacks.push({ deps, fn: callback });
|
|
2661
|
+
hotModulesMap.set(ownerPath, mod);
|
|
2662
|
+
};
|
|
2663
|
+
|
|
2137
2664
|
return {
|
|
2138
2665
|
accept(deps, callback) {
|
|
2139
|
-
// \u81EA\u63A5\u53D7: hot.accept() \u6216 hot.accept(callback)
|
|
2140
2666
|
if (typeof deps === 'function' || deps === undefined) {
|
|
2141
|
-
|
|
2142
|
-
|
|
2667
|
+
acceptDeps([ownerPath], ([mod]) => deps?.(mod));
|
|
2668
|
+
} else if (typeof deps === 'string') {
|
|
2669
|
+
acceptDeps([deps], ([mod]) => callback?.(mod));
|
|
2670
|
+
} else if (Array.isArray(deps)) {
|
|
2671
|
+
acceptDeps(deps, callback);
|
|
2672
|
+
} else {
|
|
2673
|
+
throw new Error('invalid hot.accept() usage');
|
|
2143
2674
|
}
|
|
2144
|
-
// \u4F9D\u8D56\u63A5\u53D7: hot.accept(deps, callback)\uFF0C\u591A\u6B21\u8C03\u7528\u8FFD\u52A0
|
|
2145
|
-
const existing = hotModulesMap.get(ownerPath)?.callbacks ?? [];
|
|
2146
|
-
hotModulesMap.set(ownerPath, { callbacks: [...existing, callback] });
|
|
2147
2675
|
},
|
|
2148
2676
|
prune(callback) {
|
|
2149
2677
|
pruneMap.set(ownerPath, callback);
|
|
@@ -2151,24 +2679,116 @@ export function createHotContext(ownerPath) {
|
|
|
2151
2679
|
dispose(callback) {
|
|
2152
2680
|
disposeMap.set(ownerPath, callback);
|
|
2153
2681
|
},
|
|
2682
|
+
on(event, callback) {
|
|
2683
|
+
let listenersByOwner = customListenersMap.get(event);
|
|
2684
|
+
if (!listenersByOwner) {
|
|
2685
|
+
listenersByOwner = new Map();
|
|
2686
|
+
customListenersMap.set(event, listenersByOwner);
|
|
2687
|
+
}
|
|
2688
|
+
let listeners = listenersByOwner.get(ownerPath);
|
|
2689
|
+
if (!listeners) {
|
|
2690
|
+
listeners = new Set();
|
|
2691
|
+
listenersByOwner.set(ownerPath, listeners);
|
|
2692
|
+
}
|
|
2693
|
+
listeners.add(callback);
|
|
2694
|
+
},
|
|
2695
|
+
off(event, callback) {
|
|
2696
|
+
const listenersByOwner = customListenersMap.get(event);
|
|
2697
|
+
const listeners = listenersByOwner?.get(ownerPath);
|
|
2698
|
+
listeners?.delete(callback);
|
|
2699
|
+
if (listeners?.size === 0) listenersByOwner.delete(ownerPath);
|
|
2700
|
+
if (listenersByOwner?.size === 0) customListenersMap.delete(event);
|
|
2701
|
+
},
|
|
2154
2702
|
invalidate() {
|
|
2155
2703
|
location.reload();
|
|
2156
2704
|
},
|
|
2157
|
-
data:
|
|
2705
|
+
data: dataMap.get(ownerPath),
|
|
2158
2706
|
};
|
|
2159
2707
|
}
|
|
2708
|
+
|
|
2709
|
+
function clearCustomListeners(ownerPath) {
|
|
2710
|
+
for (const [event, listenersByOwner] of customListenersMap) {
|
|
2711
|
+
listenersByOwner.delete(ownerPath);
|
|
2712
|
+
if (listenersByOwner.size === 0) customListenersMap.delete(event);
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2160
2715
|
`;
|
|
2161
2716
|
}
|
|
2162
|
-
var __dirname_esm, __require2, __refreshRuntimeCache, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
|
|
2717
|
+
var __dirname_esm, __require2, __refreshRuntimeCache, REACT_REFRESH_BOUNDARY_HELPERS, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
|
|
2163
2718
|
var init_middleware = __esm({
|
|
2164
2719
|
"src/server/middleware.ts"() {
|
|
2165
2720
|
"use strict";
|
|
2166
2721
|
init_transformer();
|
|
2167
2722
|
init_html();
|
|
2168
2723
|
init_env();
|
|
2169
|
-
|
|
2724
|
+
init_url();
|
|
2725
|
+
init_assets();
|
|
2726
|
+
__dirname_esm = path5.dirname(fileURLToPath(import.meta.url));
|
|
2170
2727
|
__require2 = createRequire(import.meta.url);
|
|
2171
2728
|
__refreshRuntimeCache = null;
|
|
2729
|
+
REACT_REFRESH_BOUNDARY_HELPERS = `
|
|
2730
|
+
function __nastiIsPlainObject(obj) {
|
|
2731
|
+
return Object.prototype.toString.call(obj) === '[object Object]' &&
|
|
2732
|
+
(obj.constructor === Object || obj.constructor === undefined);
|
|
2733
|
+
}
|
|
2734
|
+
function __nastiIsCompoundComponent(type) {
|
|
2735
|
+
if (!__nastiIsPlainObject(type)) return false;
|
|
2736
|
+
for (const key in type) {
|
|
2737
|
+
if (!isLikelyComponentType(type[key])) return false;
|
|
2738
|
+
}
|
|
2739
|
+
return true;
|
|
2740
|
+
}
|
|
2741
|
+
export function registerExportsForReactRefresh(filename, moduleExports) {
|
|
2742
|
+
for (const key in moduleExports) {
|
|
2743
|
+
if (key === '__esModule') continue;
|
|
2744
|
+
const value = moduleExports[key];
|
|
2745
|
+
if (isLikelyComponentType(value)) {
|
|
2746
|
+
register(value, filename + ' export ' + key);
|
|
2747
|
+
} else if (__nastiIsCompoundComponent(value)) {
|
|
2748
|
+
for (const subKey in value) {
|
|
2749
|
+
register(value[subKey], filename + ' export ' + key + '-' + subKey);
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
let __nastiRefreshTimer;
|
|
2755
|
+
function __nastiEnqueueRefresh() {
|
|
2756
|
+
clearTimeout(__nastiRefreshTimer);
|
|
2757
|
+
__nastiRefreshTimer = setTimeout(() => performReactRefresh(), 16);
|
|
2758
|
+
}
|
|
2759
|
+
function __nastiCheckExports(ignored, exports, predicate) {
|
|
2760
|
+
for (const key in exports) {
|
|
2761
|
+
if (ignored.includes(key)) continue;
|
|
2762
|
+
if (!predicate(key, exports[key])) return key;
|
|
2763
|
+
}
|
|
2764
|
+
return true;
|
|
2765
|
+
}
|
|
2766
|
+
export function validateRefreshBoundaryAndEnqueueUpdate(id, prevExports, nextExports) {
|
|
2767
|
+
const ignored = window.__getReactRefreshIgnoredExports?.({ id }) ?? [];
|
|
2768
|
+
if (__nastiCheckExports(ignored, prevExports, (key) => key in nextExports) !== true) {
|
|
2769
|
+
return 'Could not Fast Refresh (export removed)';
|
|
2770
|
+
}
|
|
2771
|
+
if (__nastiCheckExports(ignored, nextExports, (key) => key in prevExports) !== true) {
|
|
2772
|
+
return 'Could not Fast Refresh (new export)';
|
|
2773
|
+
}
|
|
2774
|
+
let hasExports = false;
|
|
2775
|
+
const compatible = __nastiCheckExports(ignored, nextExports, (key, value) => {
|
|
2776
|
+
hasExports = true;
|
|
2777
|
+
return isLikelyComponentType(value) ||
|
|
2778
|
+
__nastiIsCompoundComponent(value) ||
|
|
2779
|
+
prevExports[key] === value;
|
|
2780
|
+
});
|
|
2781
|
+
if (!hasExports) {
|
|
2782
|
+
return 'Could not Fast Refresh (no exports)';
|
|
2783
|
+
}
|
|
2784
|
+
if (compatible === true) {
|
|
2785
|
+
__nastiEnqueueRefresh();
|
|
2786
|
+
return;
|
|
2787
|
+
}
|
|
2788
|
+
return 'Could not Fast Refresh ("' + compatible + '" export is incompatible)';
|
|
2789
|
+
}
|
|
2790
|
+
export const __hmr_import = (module) => import(module);
|
|
2791
|
+
`;
|
|
2172
2792
|
REACT_REFRESH_GLOBAL_PREAMBLE = `
|
|
2173
2793
|
import RefreshRuntime from "/@react-refresh";
|
|
2174
2794
|
RefreshRuntime.injectIntoGlobalHook(window);
|
|
@@ -2184,31 +2804,40 @@ window.__vite_plugin_react_preamble_installed__ = true;
|
|
|
2184
2804
|
});
|
|
2185
2805
|
|
|
2186
2806
|
// src/server/hmr.ts
|
|
2187
|
-
import
|
|
2188
|
-
import
|
|
2807
|
+
import path6 from "path";
|
|
2808
|
+
import fs6 from "fs";
|
|
2189
2809
|
import pc4 from "picocolors";
|
|
2190
|
-
async function handleFileChange(file, server) {
|
|
2191
|
-
const {
|
|
2810
|
+
async function handleFileChange(file, server, environmentName = "client", timestamp = Date.now()) {
|
|
2811
|
+
const { config } = server;
|
|
2812
|
+
const environment = server.environments[environmentName];
|
|
2813
|
+
if (!environment) {
|
|
2814
|
+
throw new Error(`[nasti] unknown dev environment "${environmentName}"`);
|
|
2815
|
+
}
|
|
2816
|
+
const moduleGraph = environment.moduleGraph;
|
|
2192
2817
|
const logger = config.logger;
|
|
2193
|
-
const relativePath = "/" +
|
|
2194
|
-
const shortFile =
|
|
2818
|
+
const relativePath = "/" + path6.relative(config.root, file);
|
|
2819
|
+
const shortFile = path6.relative(config.root, file);
|
|
2195
2820
|
const mods = moduleGraph.getModulesByFile(file);
|
|
2196
2821
|
if (!mods || mods.size === 0) {
|
|
2197
|
-
return;
|
|
2822
|
+
return null;
|
|
2198
2823
|
}
|
|
2199
2824
|
const updates = [];
|
|
2200
|
-
const
|
|
2825
|
+
const graph = moduleGraph;
|
|
2826
|
+
const invalidatedModules = /* @__PURE__ */ new Set();
|
|
2827
|
+
const affectedSet = /* @__PURE__ */ new Set();
|
|
2828
|
+
let fullReload = false;
|
|
2201
2829
|
for (const mod of mods) {
|
|
2202
|
-
|
|
2830
|
+
graph.invalidateModuleAndImporters(mod, timestamp, invalidatedModules);
|
|
2203
2831
|
const ctx = {
|
|
2204
2832
|
file,
|
|
2205
2833
|
timestamp,
|
|
2206
2834
|
modules: [mod],
|
|
2207
|
-
read: () =>
|
|
2208
|
-
server
|
|
2835
|
+
read: () => fs6.readFileSync(file, "utf-8"),
|
|
2836
|
+
server,
|
|
2837
|
+
environment
|
|
2209
2838
|
};
|
|
2210
2839
|
let affectedModules = [mod];
|
|
2211
|
-
for (const plugin of
|
|
2840
|
+
for (const plugin of environment.plugins) {
|
|
2212
2841
|
if (plugin.handleHotUpdate) {
|
|
2213
2842
|
const result = await plugin.handleHotUpdate(ctx);
|
|
2214
2843
|
if (result) {
|
|
@@ -2217,29 +2846,52 @@ async function handleFileChange(file, server) {
|
|
|
2217
2846
|
}
|
|
2218
2847
|
}
|
|
2219
2848
|
for (const affected of affectedModules) {
|
|
2220
|
-
|
|
2849
|
+
affectedSet.add(affected);
|
|
2850
|
+
graph.invalidateModuleAndImporters(affected, timestamp, invalidatedModules);
|
|
2851
|
+
const boundaries = graph.getHmrBoundaries(affected);
|
|
2221
2852
|
if (boundaries.length === 0) {
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
return;
|
|
2853
|
+
fullReload = true;
|
|
2854
|
+
continue;
|
|
2225
2855
|
}
|
|
2226
|
-
for (const { boundary } of boundaries) {
|
|
2227
|
-
|
|
2856
|
+
for (const { boundary, acceptedVia } of boundaries) {
|
|
2857
|
+
const update = {
|
|
2228
2858
|
type: boundary.type === "css" ? "css-update" : "js-update",
|
|
2229
2859
|
path: boundary.url,
|
|
2230
|
-
acceptedPath:
|
|
2860
|
+
acceptedPath: acceptedVia.url,
|
|
2231
2861
|
timestamp
|
|
2232
|
-
}
|
|
2862
|
+
};
|
|
2863
|
+
if (!updates.some(
|
|
2864
|
+
(existing) => existing.type === update.type && existing.path === update.path && existing.acceptedPath === update.acceptedPath
|
|
2865
|
+
)) {
|
|
2866
|
+
updates.push(update);
|
|
2867
|
+
}
|
|
2233
2868
|
}
|
|
2234
2869
|
}
|
|
2235
2870
|
}
|
|
2236
|
-
|
|
2871
|
+
const transformed = await Promise.all(
|
|
2872
|
+
[...affectedSet].map(async (module) => ({
|
|
2873
|
+
module,
|
|
2874
|
+
result: await environment.transformRequest(module.url)
|
|
2875
|
+
}))
|
|
2876
|
+
);
|
|
2877
|
+
const logPrefix = environmentName === "client" ? "" : `[${environmentName}] `;
|
|
2878
|
+
if (fullReload) {
|
|
2879
|
+
logger.info(pc4.green(`${logPrefix}reload `) + pc4.dim(shortFile), { timestamp: true });
|
|
2880
|
+
environment.hot.send({ type: "full-reload", path: relativePath });
|
|
2881
|
+
} else if (updates.length > 0) {
|
|
2237
2882
|
logger.info(
|
|
2238
|
-
updates.map((u) => pc4.green(
|
|
2883
|
+
updates.map((u) => pc4.green(`${logPrefix}hmr update `) + pc4.dim(u.path)).join("\n"),
|
|
2239
2884
|
{ timestamp: true }
|
|
2240
2885
|
);
|
|
2241
|
-
|
|
2886
|
+
environment.hot.send({ type: "update", updates });
|
|
2242
2887
|
}
|
|
2888
|
+
return {
|
|
2889
|
+
environment,
|
|
2890
|
+
modules: [...affectedSet],
|
|
2891
|
+
updates,
|
|
2892
|
+
transformed,
|
|
2893
|
+
fullReload
|
|
2894
|
+
};
|
|
2243
2895
|
}
|
|
2244
2896
|
var init_hmr = __esm({
|
|
2245
2897
|
"src/server/hmr.ts"() {
|
|
@@ -2248,12 +2900,12 @@ var init_hmr = __esm({
|
|
|
2248
2900
|
});
|
|
2249
2901
|
|
|
2250
2902
|
// src/plugins/resolve.ts
|
|
2251
|
-
import
|
|
2252
|
-
import
|
|
2903
|
+
import path7 from "path";
|
|
2904
|
+
import fs7 from "fs";
|
|
2253
2905
|
import { createRequire as createRequire2 } from "module";
|
|
2254
2906
|
function resolvePlugin(config) {
|
|
2255
2907
|
const { alias, extensions } = config.resolve;
|
|
2256
|
-
const require2 = createRequire2(
|
|
2908
|
+
const require2 = createRequire2(path7.resolve(config.root, "package.json"));
|
|
2257
2909
|
const aliasEntries = Object.entries(alias).sort(
|
|
2258
2910
|
([a], [b]) => b.length - a.length
|
|
2259
2911
|
);
|
|
@@ -2261,10 +2913,10 @@ function resolvePlugin(config) {
|
|
|
2261
2913
|
if (config.framework === "vue") {
|
|
2262
2914
|
try {
|
|
2263
2915
|
const vuePkgJson = require2.resolve("vue/package.json", { paths: [config.root] });
|
|
2264
|
-
const vueDir =
|
|
2265
|
-
const mod = JSON.parse(
|
|
2266
|
-
const entry =
|
|
2267
|
-
if (
|
|
2916
|
+
const vueDir = path7.dirname(vuePkgJson);
|
|
2917
|
+
const mod = JSON.parse(fs7.readFileSync(vuePkgJson, "utf-8")).module;
|
|
2918
|
+
const entry = path7.join(vueDir, mod ?? "dist/vue.runtime.esm-bundler.js");
|
|
2919
|
+
if (fs7.existsSync(entry)) vueRuntimeEntry = entry;
|
|
2268
2920
|
} catch {
|
|
2269
2921
|
}
|
|
2270
2922
|
}
|
|
@@ -2276,32 +2928,33 @@ function resolvePlugin(config) {
|
|
|
2276
2928
|
if (source === key || source.startsWith(key + "/")) {
|
|
2277
2929
|
const aliasBase = resolveAliasTarget2(value, config.root);
|
|
2278
2930
|
const sub = source.slice(key.length).replace(/^\//, "");
|
|
2279
|
-
const target = sub ?
|
|
2931
|
+
const target = sub ? path7.join(aliasBase, sub) : aliasBase;
|
|
2280
2932
|
const resolved = tryResolveFile(target, extensions);
|
|
2281
2933
|
if (resolved) return resolved;
|
|
2282
2934
|
break;
|
|
2283
2935
|
}
|
|
2284
2936
|
}
|
|
2285
2937
|
if (source.startsWith("/") && !source.startsWith("//")) {
|
|
2286
|
-
const rootRelative =
|
|
2938
|
+
const rootRelative = path7.join(config.root, source.slice(1));
|
|
2287
2939
|
const resolved = tryResolveFile(rootRelative, extensions);
|
|
2288
2940
|
if (resolved) return resolved;
|
|
2289
2941
|
}
|
|
2290
|
-
if (
|
|
2942
|
+
if (path7.isAbsolute(source) && fs7.existsSync(source)) {
|
|
2291
2943
|
const resolved = tryResolveFile(source, extensions);
|
|
2292
2944
|
if (resolved) return resolved;
|
|
2293
2945
|
}
|
|
2294
2946
|
if (source.startsWith(".")) {
|
|
2295
|
-
const dir = importer ?
|
|
2296
|
-
const absolute =
|
|
2947
|
+
const dir = importer ? path7.dirname(importer) : config.root;
|
|
2948
|
+
const absolute = path7.resolve(dir, source);
|
|
2297
2949
|
const resolved = tryResolveFile(absolute, extensions);
|
|
2298
2950
|
if (resolved) return resolved;
|
|
2299
2951
|
}
|
|
2300
2952
|
if (!source.startsWith("/") && !source.startsWith(".")) {
|
|
2301
2953
|
if (vueRuntimeEntry && source === "vue") return vueRuntimeEntry;
|
|
2954
|
+
if (config.command === "build") return null;
|
|
2302
2955
|
try {
|
|
2303
2956
|
const resolved = require2.resolve(source, {
|
|
2304
|
-
paths: [importer ?
|
|
2957
|
+
paths: [importer ? path7.dirname(importer) : config.root]
|
|
2305
2958
|
});
|
|
2306
2959
|
return resolved;
|
|
2307
2960
|
} catch {
|
|
@@ -2312,34 +2965,34 @@ function resolvePlugin(config) {
|
|
|
2312
2965
|
},
|
|
2313
2966
|
load(id) {
|
|
2314
2967
|
if (id.startsWith("\0")) return null;
|
|
2315
|
-
if (!
|
|
2968
|
+
if (!fs7.existsSync(id)) return null;
|
|
2316
2969
|
if (id.endsWith(".json")) {
|
|
2317
|
-
const content =
|
|
2970
|
+
const content = fs7.readFileSync(id, "utf-8");
|
|
2318
2971
|
return `export default ${content}`;
|
|
2319
2972
|
}
|
|
2320
|
-
return
|
|
2973
|
+
return null;
|
|
2321
2974
|
}
|
|
2322
2975
|
};
|
|
2323
2976
|
}
|
|
2324
2977
|
function resolveAliasTarget2(value, root) {
|
|
2325
|
-
if (
|
|
2326
|
-
if (value.startsWith("/")) return
|
|
2327
|
-
return
|
|
2978
|
+
if (path7.isAbsolute(value) && fs7.existsSync(value)) return value;
|
|
2979
|
+
if (value.startsWith("/")) return path7.join(root, value.slice(1));
|
|
2980
|
+
return path7.resolve(root, value);
|
|
2328
2981
|
}
|
|
2329
2982
|
function tryResolveFile(file, extensions) {
|
|
2330
|
-
if (
|
|
2983
|
+
if (fs7.existsSync(file) && fs7.statSync(file).isFile()) {
|
|
2331
2984
|
return file;
|
|
2332
2985
|
}
|
|
2333
2986
|
for (const ext of extensions) {
|
|
2334
2987
|
const withExt = file + ext;
|
|
2335
|
-
if (
|
|
2988
|
+
if (fs7.existsSync(withExt) && fs7.statSync(withExt).isFile()) {
|
|
2336
2989
|
return withExt;
|
|
2337
2990
|
}
|
|
2338
2991
|
}
|
|
2339
|
-
if (
|
|
2992
|
+
if (fs7.existsSync(file) && fs7.statSync(file).isDirectory()) {
|
|
2340
2993
|
for (const ext of extensions) {
|
|
2341
|
-
const indexFile =
|
|
2342
|
-
if (
|
|
2994
|
+
const indexFile = path7.join(file, "index" + ext);
|
|
2995
|
+
if (fs7.existsSync(indexFile)) {
|
|
2343
2996
|
return indexFile;
|
|
2344
2997
|
}
|
|
2345
2998
|
}
|
|
@@ -2387,27 +3040,27 @@ var require_process = __commonJS({
|
|
|
2387
3040
|
var require_filesystem = __commonJS({
|
|
2388
3041
|
"node_modules/detect-libc/lib/filesystem.js"(exports, module) {
|
|
2389
3042
|
"use strict";
|
|
2390
|
-
var
|
|
3043
|
+
var fs13 = __require("fs");
|
|
2391
3044
|
var LDD_PATH = "/usr/bin/ldd";
|
|
2392
3045
|
var SELF_PATH = "/proc/self/exe";
|
|
2393
3046
|
var MAX_LENGTH = 2048;
|
|
2394
|
-
var readFileSync = (
|
|
2395
|
-
const fd =
|
|
3047
|
+
var readFileSync = (path18) => {
|
|
3048
|
+
const fd = fs13.openSync(path18, "r");
|
|
2396
3049
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
2397
|
-
const bytesRead =
|
|
2398
|
-
|
|
3050
|
+
const bytesRead = fs13.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
3051
|
+
fs13.close(fd, () => {
|
|
2399
3052
|
});
|
|
2400
3053
|
return buffer.subarray(0, bytesRead);
|
|
2401
3054
|
};
|
|
2402
|
-
var readFile = (
|
|
2403
|
-
|
|
3055
|
+
var readFile = (path18) => new Promise((resolve, reject) => {
|
|
3056
|
+
fs13.open(path18, "r", (err, fd) => {
|
|
2404
3057
|
if (err) {
|
|
2405
3058
|
reject(err);
|
|
2406
3059
|
} else {
|
|
2407
3060
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
2408
|
-
|
|
3061
|
+
fs13.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
|
|
2409
3062
|
resolve(buffer.subarray(0, bytesRead));
|
|
2410
|
-
|
|
3063
|
+
fs13.close(fd, () => {
|
|
2411
3064
|
});
|
|
2412
3065
|
});
|
|
2413
3066
|
}
|
|
@@ -2519,11 +3172,11 @@ var require_detect_libc = __commonJS({
|
|
|
2519
3172
|
}
|
|
2520
3173
|
return null;
|
|
2521
3174
|
};
|
|
2522
|
-
var familyFromInterpreterPath = (
|
|
2523
|
-
if (
|
|
2524
|
-
if (
|
|
3175
|
+
var familyFromInterpreterPath = (path18) => {
|
|
3176
|
+
if (path18) {
|
|
3177
|
+
if (path18.includes("/ld-musl-")) {
|
|
2525
3178
|
return MUSL;
|
|
2526
|
-
} else if (
|
|
3179
|
+
} else if (path18.includes("/ld-linux-")) {
|
|
2527
3180
|
return GLIBC;
|
|
2528
3181
|
}
|
|
2529
3182
|
}
|
|
@@ -2570,8 +3223,8 @@ var require_detect_libc = __commonJS({
|
|
|
2570
3223
|
cachedFamilyInterpreter = null;
|
|
2571
3224
|
try {
|
|
2572
3225
|
const selfContent = await readFile(SELF_PATH);
|
|
2573
|
-
const
|
|
2574
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
3226
|
+
const path18 = interpreterPath(selfContent);
|
|
3227
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path18);
|
|
2575
3228
|
} catch (e) {
|
|
2576
3229
|
}
|
|
2577
3230
|
return cachedFamilyInterpreter;
|
|
@@ -2583,8 +3236,8 @@ var require_detect_libc = __commonJS({
|
|
|
2583
3236
|
cachedFamilyInterpreter = null;
|
|
2584
3237
|
try {
|
|
2585
3238
|
const selfContent = readFileSync(SELF_PATH);
|
|
2586
|
-
const
|
|
2587
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
3239
|
+
const path18 = interpreterPath(selfContent);
|
|
3240
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path18);
|
|
2588
3241
|
} catch (e) {
|
|
2589
3242
|
}
|
|
2590
3243
|
return cachedFamilyInterpreter;
|
|
@@ -3231,12 +3884,31 @@ var init_node = __esm({
|
|
|
3231
3884
|
function createCssEngine() {
|
|
3232
3885
|
return {
|
|
3233
3886
|
styles: /* @__PURE__ */ new Map(),
|
|
3887
|
+
modules: /* @__PURE__ */ new Map(),
|
|
3888
|
+
chunks: /* @__PURE__ */ new Map(),
|
|
3234
3889
|
entryCss: /* @__PURE__ */ new Map(),
|
|
3235
3890
|
allCss: [],
|
|
3236
3891
|
pendingSingle: [],
|
|
3237
3892
|
singleFileName: null
|
|
3238
3893
|
};
|
|
3239
3894
|
}
|
|
3895
|
+
function getCssMetadata(engine) {
|
|
3896
|
+
return {
|
|
3897
|
+
modules: Object.fromEntries(
|
|
3898
|
+
[...engine.modules].map(([id, module]) => [id, { ...module }])
|
|
3899
|
+
),
|
|
3900
|
+
chunks: Object.fromEntries(
|
|
3901
|
+
[...engine.chunks].map(([fileName, chunk]) => [
|
|
3902
|
+
fileName,
|
|
3903
|
+
{
|
|
3904
|
+
fileName,
|
|
3905
|
+
moduleIds: [...chunk.moduleIds],
|
|
3906
|
+
cssFileNames: [...chunk.cssFileNames]
|
|
3907
|
+
}
|
|
3908
|
+
])
|
|
3909
|
+
)
|
|
3910
|
+
};
|
|
3911
|
+
}
|
|
3240
3912
|
function normalizeCssModuleId(id) {
|
|
3241
3913
|
return id.startsWith("\0") ? id.slice(1) : id;
|
|
3242
3914
|
}
|
|
@@ -3284,7 +3956,7 @@ var init_css_engine = __esm({
|
|
|
3284
3956
|
});
|
|
3285
3957
|
|
|
3286
3958
|
// src/plugins/tailwind.ts
|
|
3287
|
-
import
|
|
3959
|
+
import path8 from "path";
|
|
3288
3960
|
import { createRequire as createRequire3 } from "module";
|
|
3289
3961
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
3290
3962
|
function hasTailwindDirectives(css) {
|
|
@@ -3294,7 +3966,7 @@ function hasTailwindDirectives(css) {
|
|
|
3294
3966
|
}
|
|
3295
3967
|
async function loadTailwind(projectRoot) {
|
|
3296
3968
|
if (cached && cachedRoot === projectRoot) return cached;
|
|
3297
|
-
const req = createRequire3(
|
|
3969
|
+
const req = createRequire3(path8.join(projectRoot, "package.json"));
|
|
3298
3970
|
let nodePath;
|
|
3299
3971
|
let oxidePath;
|
|
3300
3972
|
try {
|
|
@@ -3315,7 +3987,7 @@ async function compileTailwind(css, fromFile, projectRoot) {
|
|
|
3315
3987
|
const { node, oxide } = await loadTailwind(projectRoot);
|
|
3316
3988
|
const dependencies = [];
|
|
3317
3989
|
const compiler2 = await node.compile(css, {
|
|
3318
|
-
base:
|
|
3990
|
+
base: path8.dirname(fromFile),
|
|
3319
3991
|
from: fromFile,
|
|
3320
3992
|
onDependency: (p) => dependencies.push(p)
|
|
3321
3993
|
});
|
|
@@ -3337,7 +4009,8 @@ var init_tailwind = __esm({
|
|
|
3337
4009
|
});
|
|
3338
4010
|
|
|
3339
4011
|
// src/plugins/css.ts
|
|
3340
|
-
import
|
|
4012
|
+
import path9 from "path";
|
|
4013
|
+
import { SourceMapGenerator } from "source-map-js";
|
|
3341
4014
|
function cssPlugin(config, engine, consumer = "client") {
|
|
3342
4015
|
return {
|
|
3343
4016
|
name: "nasti:css",
|
|
@@ -3357,15 +4030,29 @@ function cssPlugin(config, engine, consumer = "client") {
|
|
|
3357
4030
|
}
|
|
3358
4031
|
const rewritten = rewriteCssUrls(cssSource, file, config.root);
|
|
3359
4032
|
const escaped = JSON.stringify(rewritten);
|
|
4033
|
+
const normalizedId = normalizeCssModuleId(id);
|
|
4034
|
+
const cssModule = { id: normalizedId, source: code, code: rewritten };
|
|
4035
|
+
const map = config.build.sourcemap ? createIdentitySourceMap(code, id) : void 0;
|
|
4036
|
+
engine?.modules.set(normalizedId, cssModule);
|
|
4037
|
+
this.environment?.setCssModule?.(cssModule);
|
|
3360
4038
|
if (query === "inline") {
|
|
3361
4039
|
return { code: `export default ${escaped};
|
|
3362
|
-
`, moduleType: "js" };
|
|
4040
|
+
`, map, moduleType: "js" };
|
|
3363
4041
|
}
|
|
3364
4042
|
if (consumer === "server") {
|
|
3365
4043
|
return { code: `export default ${escaped};
|
|
3366
|
-
`, moduleType: "js" };
|
|
4044
|
+
`, map, moduleType: "js" };
|
|
3367
4045
|
}
|
|
3368
4046
|
if (config.command === "serve") {
|
|
4047
|
+
if (config.build.css.inject === false) {
|
|
4048
|
+
return {
|
|
4049
|
+
code: `export default ${escaped};
|
|
4050
|
+
`,
|
|
4051
|
+
map,
|
|
4052
|
+
moduleType: "js",
|
|
4053
|
+
moduleSideEffects: "no-treeshake"
|
|
4054
|
+
};
|
|
4055
|
+
}
|
|
3369
4056
|
return {
|
|
3370
4057
|
code: `
|
|
3371
4058
|
const css = ${escaped};
|
|
@@ -3389,16 +4076,18 @@ if (import.meta.hot) {
|
|
|
3389
4076
|
|
|
3390
4077
|
export default css;
|
|
3391
4078
|
`,
|
|
4079
|
+
map,
|
|
3392
4080
|
// bundled dev(DevEngine)下该模块会进 Rolldown:不标 js 会按 .css
|
|
3393
4081
|
// 扩展名走 CSS 管线触发 #4271 报错;unbundled 中间件忽略此字段
|
|
3394
4082
|
moduleType: "js"
|
|
3395
4083
|
};
|
|
3396
4084
|
}
|
|
3397
4085
|
if (engine) {
|
|
3398
|
-
engine.styles.set(
|
|
4086
|
+
engine.styles.set(normalizedId, rewritten);
|
|
3399
4087
|
return {
|
|
3400
4088
|
code: `export default '';
|
|
3401
4089
|
`,
|
|
4090
|
+
map,
|
|
3402
4091
|
moduleType: "js",
|
|
3403
4092
|
// 防止空 stub 被 tree-shake 出 chunk.moduleIds(css-post 靠它定位)
|
|
3404
4093
|
moduleSideEffects: "no-treeshake"
|
|
@@ -3418,18 +4107,34 @@ document.head.appendChild(style);
|
|
|
3418
4107
|
|
|
3419
4108
|
export default css;
|
|
3420
4109
|
`,
|
|
4110
|
+
map,
|
|
3421
4111
|
moduleType: "js"
|
|
3422
4112
|
};
|
|
3423
4113
|
}
|
|
3424
4114
|
};
|
|
3425
4115
|
}
|
|
4116
|
+
function createIdentitySourceMap(code, id) {
|
|
4117
|
+
const map = new SourceMapGenerator({ file: id });
|
|
4118
|
+
const lines = code.split("\n");
|
|
4119
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
4120
|
+
for (let column = 0; column <= lines[lineIndex].length; column++) {
|
|
4121
|
+
map.addMapping({
|
|
4122
|
+
generated: { line: lineIndex + 1, column },
|
|
4123
|
+
original: { line: lineIndex + 1, column },
|
|
4124
|
+
source: id
|
|
4125
|
+
});
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
map.setSourceContent(id, code);
|
|
4129
|
+
return map.toJSON();
|
|
4130
|
+
}
|
|
3426
4131
|
function rewriteCssUrls(css, from, root) {
|
|
3427
4132
|
return css.replace(/url\(\s*['"]?([^'")\s]+)['"]?\s*\)/g, (match, url) => {
|
|
3428
4133
|
if (url.startsWith("/") || url.startsWith("data:") || url.startsWith("http")) {
|
|
3429
4134
|
return match;
|
|
3430
4135
|
}
|
|
3431
|
-
const resolved =
|
|
3432
|
-
const relative = "/" +
|
|
4136
|
+
const resolved = path9.resolve(path9.dirname(from), url);
|
|
4137
|
+
const relative = "/" + path9.relative(root, resolved).replace(/\\/g, "/");
|
|
3433
4138
|
return `url(${relative})`;
|
|
3434
4139
|
});
|
|
3435
4140
|
}
|
|
@@ -3445,19 +4150,27 @@ var init_css = __esm({
|
|
|
3445
4150
|
function collectChunkCss(chunk, engine) {
|
|
3446
4151
|
const ids = chunk.moduleIds ?? Object.keys(chunk.modules);
|
|
3447
4152
|
let css = "";
|
|
4153
|
+
const moduleIds = [];
|
|
3448
4154
|
for (const id of ids) {
|
|
3449
|
-
const
|
|
3450
|
-
|
|
4155
|
+
const normalizedId = normalizeCssModuleId(id);
|
|
4156
|
+
const styles = engine.styles.get(normalizedId);
|
|
4157
|
+
if (styles) {
|
|
4158
|
+
css += styles + "\n";
|
|
4159
|
+
moduleIds.push(normalizedId);
|
|
4160
|
+
}
|
|
3451
4161
|
}
|
|
3452
|
-
return css;
|
|
4162
|
+
return { css, moduleIds };
|
|
3453
4163
|
}
|
|
3454
4164
|
function cssPostPlugin(config, engine) {
|
|
3455
4165
|
return {
|
|
3456
4166
|
name: "nasti:css-post",
|
|
3457
4167
|
enforce: "post",
|
|
3458
4168
|
async renderChunk(code, chunk) {
|
|
3459
|
-
const css = collectChunkCss(chunk, engine);
|
|
4169
|
+
const { css, moduleIds } = collectChunkCss(chunk, engine);
|
|
3460
4170
|
if (!css) return null;
|
|
4171
|
+
const ownership = { moduleIds, cssFileNames: [] };
|
|
4172
|
+
engine.chunks.set(chunk.fileName, ownership);
|
|
4173
|
+
if (config.build.css.emit === false) return null;
|
|
3461
4174
|
if (!config.build.cssCodeSplit) {
|
|
3462
4175
|
engine.pendingSingle.push(css);
|
|
3463
4176
|
return null;
|
|
@@ -3470,6 +4183,7 @@ function cssPostPlugin(config, engine) {
|
|
|
3470
4183
|
});
|
|
3471
4184
|
const fileName = this.getFileName(ref);
|
|
3472
4185
|
engine.allCss.push(fileName);
|
|
4186
|
+
ownership.cssFileNames.push(fileName);
|
|
3473
4187
|
if (chunk.isEntry) {
|
|
3474
4188
|
const key = chunk.facadeModuleId ?? chunk.name;
|
|
3475
4189
|
const existing = engine.entryCss.get(key) ?? [];
|
|
@@ -3477,105 +4191,44 @@ function cssPostPlugin(config, engine) {
|
|
|
3477
4191
|
engine.entryCss.set(key, existing);
|
|
3478
4192
|
return null;
|
|
3479
4193
|
}
|
|
4194
|
+
if (config.build.css.inject === false) return null;
|
|
3480
4195
|
const href = JSON.stringify(config.base + fileName);
|
|
3481
4196
|
const snippet = `
|
|
3482
4197
|
;(function(){try{var d=document,h=${href};if(!d.querySelector('link[data-nasti-css="'+h+'"]')){var l=d.createElement('link');l.rel='stylesheet';l.href=h;l.setAttribute('data-nasti-css',h);d.head.appendChild(l);}}catch(e){}})();`;
|
|
3483
4198
|
return { code: code + snippet, map: null };
|
|
3484
4199
|
},
|
|
3485
4200
|
augmentChunkHash(chunk) {
|
|
3486
|
-
const css = collectChunkCss(chunk, engine);
|
|
4201
|
+
const { css } = collectChunkCss(chunk, engine);
|
|
3487
4202
|
return css || void 0;
|
|
3488
4203
|
},
|
|
3489
4204
|
async generateBundle() {
|
|
3490
4205
|
if (config.build.cssCodeSplit || engine.pendingSingle.length === 0) return;
|
|
3491
|
-
const merged = engine.pendingSingle.join("\n");
|
|
3492
|
-
const finalCss = config.build.cssMinify ? await minifyCss(merged, config) : merged;
|
|
3493
|
-
const ref = this.emitFile({ type: "asset", name: "style.css", source: finalCss });
|
|
3494
|
-
const fileName = this.getFileName(ref);
|
|
3495
|
-
engine.singleFileName = fileName;
|
|
3496
|
-
engine.allCss.push(fileName);
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
}
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
// src/plugins/assets.ts
|
|
3508
|
-
import path9 from "path";
|
|
3509
|
-
import fs7 from "fs";
|
|
3510
|
-
import crypto from "crypto";
|
|
3511
|
-
function assetsPlugin(config) {
|
|
3512
|
-
return {
|
|
3513
|
-
name: "nasti:assets",
|
|
3514
|
-
resolveId(source) {
|
|
3515
|
-
if (source.endsWith("?url") || source.endsWith("?raw")) {
|
|
3516
|
-
return source;
|
|
3517
|
-
}
|
|
3518
|
-
return null;
|
|
3519
|
-
},
|
|
3520
|
-
load(id) {
|
|
3521
|
-
const ext = path9.extname(id.replace(/\?.*$/, ""));
|
|
3522
|
-
if (id.endsWith("?raw")) {
|
|
3523
|
-
const file = id.slice(0, -4);
|
|
3524
|
-
if (fs7.existsSync(file)) {
|
|
3525
|
-
const content = fs7.readFileSync(file, "utf-8");
|
|
3526
|
-
return `export default ${JSON.stringify(content)}`;
|
|
3527
|
-
}
|
|
3528
|
-
}
|
|
3529
|
-
if (id.endsWith("?url") || ASSET_EXTENSIONS.has(ext)) {
|
|
3530
|
-
const file = id.replace(/\?.*$/, "");
|
|
3531
|
-
if (!fs7.existsSync(file)) return null;
|
|
3532
|
-
if (config.command === "serve") {
|
|
3533
|
-
const url = "/" + path9.relative(config.root, file);
|
|
3534
|
-
return `export default ${JSON.stringify(url)}`;
|
|
3535
|
-
}
|
|
3536
|
-
const content = fs7.readFileSync(file);
|
|
3537
|
-
const hash = crypto.createHash("sha256").update(content).digest("hex").slice(0, 8);
|
|
3538
|
-
const basename = path9.basename(file, ext);
|
|
3539
|
-
const hashedName = `${config.build.assetsDir}/${basename}.${hash}${ext}`;
|
|
3540
|
-
return `export default ${JSON.stringify(config.base + hashedName)}`;
|
|
3541
|
-
}
|
|
3542
|
-
return null;
|
|
3543
|
-
}
|
|
3544
|
-
};
|
|
3545
|
-
}
|
|
3546
|
-
var ASSET_EXTENSIONS;
|
|
3547
|
-
var init_assets = __esm({
|
|
3548
|
-
"src/plugins/assets.ts"() {
|
|
3549
|
-
"use strict";
|
|
3550
|
-
ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
3551
|
-
".png",
|
|
3552
|
-
".jpg",
|
|
3553
|
-
".jpeg",
|
|
3554
|
-
".gif",
|
|
3555
|
-
".svg",
|
|
3556
|
-
".ico",
|
|
3557
|
-
".webp",
|
|
3558
|
-
".avif",
|
|
3559
|
-
".mp4",
|
|
3560
|
-
".webm",
|
|
3561
|
-
".ogg",
|
|
3562
|
-
".mp3",
|
|
3563
|
-
".wav",
|
|
3564
|
-
".flac",
|
|
3565
|
-
".aac",
|
|
3566
|
-
".woff",
|
|
3567
|
-
".woff2",
|
|
3568
|
-
".eot",
|
|
3569
|
-
".ttf",
|
|
3570
|
-
".otf",
|
|
3571
|
-
".pdf",
|
|
3572
|
-
".txt"
|
|
3573
|
-
]);
|
|
4206
|
+
const merged = engine.pendingSingle.join("\n");
|
|
4207
|
+
const finalCss = config.build.cssMinify ? await minifyCss(merged, config) : merged;
|
|
4208
|
+
const ref = this.emitFile({ type: "asset", name: "style.css", source: finalCss });
|
|
4209
|
+
const fileName = this.getFileName(ref);
|
|
4210
|
+
engine.singleFileName = fileName;
|
|
4211
|
+
engine.allCss.push(fileName);
|
|
4212
|
+
for (const ownership of engine.chunks.values()) {
|
|
4213
|
+
if (ownership.moduleIds.length > 0) ownership.cssFileNames.push(fileName);
|
|
4214
|
+
}
|
|
4215
|
+
}
|
|
4216
|
+
};
|
|
4217
|
+
}
|
|
4218
|
+
var init_css_post = __esm({
|
|
4219
|
+
"src/plugins/css-post.ts"() {
|
|
4220
|
+
"use strict";
|
|
4221
|
+
init_css_engine();
|
|
3574
4222
|
}
|
|
3575
4223
|
});
|
|
3576
4224
|
|
|
3577
4225
|
// src/plugins/vue.ts
|
|
3578
4226
|
import crypto2 from "crypto";
|
|
4227
|
+
import {
|
|
4228
|
+
SourceMapConsumer,
|
|
4229
|
+
SourceMapGenerator as SourceMapGenerator2,
|
|
4230
|
+
SourceNode
|
|
4231
|
+
} from "source-map-js";
|
|
3579
4232
|
async function loadVueCompiler() {
|
|
3580
4233
|
if (compiler) return compiler;
|
|
3581
4234
|
try {
|
|
@@ -3585,9 +4238,10 @@ async function loadVueCompiler() {
|
|
|
3585
4238
|
return null;
|
|
3586
4239
|
}
|
|
3587
4240
|
}
|
|
3588
|
-
function vuePlugin(config) {
|
|
4241
|
+
function vuePlugin(config, environmentName = "client") {
|
|
3589
4242
|
const isDev = config.command === "serve";
|
|
3590
4243
|
const descriptorCache = /* @__PURE__ */ new Map();
|
|
4244
|
+
const vueOptions = config.environments[environmentName]?.vue ?? {};
|
|
3591
4245
|
return {
|
|
3592
4246
|
name: "nasti:vue",
|
|
3593
4247
|
enforce: "pre",
|
|
@@ -3607,32 +4261,63 @@ function vuePlugin(config) {
|
|
|
3607
4261
|
const sfc = await loadVueCompiler();
|
|
3608
4262
|
if (!sfc) return null;
|
|
3609
4263
|
const [, filePath, indexStr] = match;
|
|
3610
|
-
let
|
|
3611
|
-
if (!
|
|
4264
|
+
let cached2 = descriptorCache.get(filePath);
|
|
4265
|
+
if (!cached2) {
|
|
3612
4266
|
try {
|
|
3613
|
-
const
|
|
3614
|
-
const
|
|
3615
|
-
const
|
|
4267
|
+
const fs13 = await import("fs");
|
|
4268
|
+
const rawSource = fs13.readFileSync(filePath, "utf-8");
|
|
4269
|
+
const transformedSfc = await applySourceTransform(
|
|
4270
|
+
vueOptions.transformSfc,
|
|
4271
|
+
rawSource,
|
|
4272
|
+
{ filename: filePath, environmentName, type: "sfc" }
|
|
4273
|
+
);
|
|
4274
|
+
const parsed = sfc.parse(transformedSfc.code, {
|
|
4275
|
+
...vueOptions.parse,
|
|
4276
|
+
filename: filePath,
|
|
4277
|
+
sourceMap: true
|
|
4278
|
+
});
|
|
3616
4279
|
if (parsed.errors.length) return null;
|
|
3617
|
-
|
|
3618
|
-
|
|
4280
|
+
cached2 = {
|
|
4281
|
+
descriptor: parsed.descriptor,
|
|
4282
|
+
sourceMap: transformedSfc.map
|
|
4283
|
+
};
|
|
4284
|
+
descriptorCache.set(filePath, cached2);
|
|
3619
4285
|
} catch {
|
|
3620
4286
|
return null;
|
|
3621
4287
|
}
|
|
3622
4288
|
}
|
|
4289
|
+
const { descriptor, sourceMap: sfcSourceMap } = cached2;
|
|
3623
4290
|
const index2 = parseInt(indexStr ?? "0", 10);
|
|
3624
4291
|
const style = descriptor.styles[index2];
|
|
3625
4292
|
if (!style) return null;
|
|
3626
4293
|
const scopeId = hashId(filePath);
|
|
4294
|
+
const transformedStyle = await applySourceTransform(
|
|
4295
|
+
vueOptions.transformStyle,
|
|
4296
|
+
style.content,
|
|
4297
|
+
{ filename: filePath, environmentName, type: "style", index: index2 }
|
|
4298
|
+
);
|
|
4299
|
+
const wantsStyleSourceMap = !!config.build.sourcemap || transformedStyle.map != null || sfcSourceMap != null;
|
|
4300
|
+
const styleInputMap = wantsStyleSourceMap ? composeSourceMapChain(
|
|
4301
|
+
[transformedStyle.map, style.map, sfcSourceMap],
|
|
4302
|
+
{ filename: filePath, environmentName, type: "style", index: index2 }
|
|
4303
|
+
) : void 0;
|
|
3627
4304
|
const result = await sfc.compileStyleAsync({
|
|
3628
|
-
|
|
4305
|
+
...vueOptions.style,
|
|
4306
|
+
source: transformedStyle.code,
|
|
3629
4307
|
filename: filePath,
|
|
3630
4308
|
id: `data-v-${scopeId}`,
|
|
3631
4309
|
scoped: style.scoped ?? false,
|
|
4310
|
+
inMap: styleInputMap,
|
|
3632
4311
|
// <style lang="scss|less|stylus"> 需经对应预处理器(缺省 undefined = 纯 CSS)
|
|
3633
4312
|
preprocessLang: style.lang
|
|
3634
4313
|
});
|
|
3635
|
-
|
|
4314
|
+
if (transformedStyle.map != null && result.map == null) {
|
|
4315
|
+
warnUnchainableMap(
|
|
4316
|
+
{ filename: filePath, environmentName, type: "style", index: index2 },
|
|
4317
|
+
"compiler-sfc did not return a style map"
|
|
4318
|
+
);
|
|
4319
|
+
}
|
|
4320
|
+
return wantsStyleSourceMap ? { code: result.code, map: result.map } : result.code;
|
|
3636
4321
|
},
|
|
3637
4322
|
async transform(code, id) {
|
|
3638
4323
|
if (!VUE_FILE_RE.test(id) && !VUE_QUERY_RE.test(id)) return null;
|
|
@@ -3644,57 +4329,144 @@ function vuePlugin(config) {
|
|
|
3644
4329
|
if (VUE_QUERY_RE.test(id)) {
|
|
3645
4330
|
return null;
|
|
3646
4331
|
}
|
|
3647
|
-
const
|
|
4332
|
+
const transformedSfc = await applySourceTransform(
|
|
4333
|
+
vueOptions.transformSfc,
|
|
4334
|
+
code,
|
|
4335
|
+
{ filename: id, environmentName, type: "sfc" }
|
|
4336
|
+
);
|
|
4337
|
+
code = transformedSfc.code;
|
|
4338
|
+
const { descriptor, errors } = sfc.parse(code, {
|
|
4339
|
+
...vueOptions.parse,
|
|
4340
|
+
filename: id,
|
|
4341
|
+
sourceMap: true
|
|
4342
|
+
});
|
|
3648
4343
|
if (errors.length) {
|
|
3649
|
-
|
|
4344
|
+
const firstError = errors[0];
|
|
4345
|
+
console.error(
|
|
4346
|
+
`[nasti:vue] Parse error in ${id}:`,
|
|
4347
|
+
typeof firstError === "string" ? firstError : firstError.message
|
|
4348
|
+
);
|
|
3650
4349
|
return null;
|
|
3651
4350
|
}
|
|
3652
|
-
descriptorCache.set(id,
|
|
4351
|
+
descriptorCache.set(id, {
|
|
4352
|
+
descriptor,
|
|
4353
|
+
sourceMap: transformedSfc.map
|
|
4354
|
+
});
|
|
3653
4355
|
const scopeId = hashId(id);
|
|
4356
|
+
const wantsSourceMap = !!config.build.sourcemap || transformedSfc.map != null;
|
|
3654
4357
|
let scriptCode = "";
|
|
4358
|
+
let scriptMap;
|
|
3655
4359
|
if (descriptor.script || descriptor.scriptSetup) {
|
|
4360
|
+
const inlineTemplate = vueOptions.script?.inlineTemplate !== false;
|
|
3656
4361
|
const compiled = sfc.compileScript(descriptor, {
|
|
4362
|
+
...vueOptions.script,
|
|
3657
4363
|
id: scopeId,
|
|
3658
4364
|
isProd: !isDev,
|
|
3659
|
-
inlineTemplate
|
|
4365
|
+
inlineTemplate,
|
|
4366
|
+
sourceMap: wantsSourceMap,
|
|
3660
4367
|
// 让 compileScript 产出 `const __sfc__ = ...`(而非默认的 `export default {...}`)。
|
|
3661
4368
|
// 否则下方追加的 `__sfc__.render` / `__sfc__.__scopeId` / HMR 记录会引用一个
|
|
3662
4369
|
// 不存在的 `__sfc__`,并与 compileScript 自带的 `export default` 形成双重默认导出。
|
|
3663
4370
|
genDefaultAs: "__sfc__"
|
|
3664
4371
|
});
|
|
3665
4372
|
scriptCode = compiled.content;
|
|
4373
|
+
scriptMap = composeSourceMapChain(
|
|
4374
|
+
[compiled.map, transformedSfc.map],
|
|
4375
|
+
{ filename: id, environmentName, type: "sfc" }
|
|
4376
|
+
);
|
|
4377
|
+
if (transformedSfc.map != null && scriptMap == null) {
|
|
4378
|
+
warnUnchainableMap(
|
|
4379
|
+
{ filename: id, environmentName, type: "sfc" },
|
|
4380
|
+
"compiler-sfc did not return a script map"
|
|
4381
|
+
);
|
|
4382
|
+
}
|
|
3666
4383
|
}
|
|
3667
4384
|
let templateCode = "";
|
|
3668
|
-
|
|
4385
|
+
let templateMap;
|
|
4386
|
+
const scriptSetupIsInline = !!descriptor.scriptSetup && vueOptions.script?.inlineTemplate !== false;
|
|
4387
|
+
if (descriptor.template && !scriptSetupIsInline) {
|
|
4388
|
+
const transformedTemplate = await applySourceTransform(
|
|
4389
|
+
vueOptions.transformTemplate,
|
|
4390
|
+
descriptor.template.content,
|
|
4391
|
+
{ filename: id, environmentName, type: "template" }
|
|
4392
|
+
);
|
|
4393
|
+
const templateInputMap = composeSourceMapChain(
|
|
4394
|
+
[
|
|
4395
|
+
transformedTemplate.map,
|
|
4396
|
+
descriptor.template.map,
|
|
4397
|
+
transformedSfc.map
|
|
4398
|
+
],
|
|
4399
|
+
{ filename: id, environmentName, type: "template" }
|
|
4400
|
+
);
|
|
4401
|
+
const customCompilerOptions = vueOptions.template?.compilerOptions ?? {};
|
|
3669
4402
|
const compiled = sfc.compileTemplate({
|
|
3670
|
-
|
|
4403
|
+
...vueOptions.template,
|
|
4404
|
+
source: transformedTemplate.code,
|
|
3671
4405
|
filename: id,
|
|
3672
4406
|
id: scopeId,
|
|
3673
|
-
|
|
4407
|
+
inMap: templateInputMap,
|
|
4408
|
+
compilerOptions: {
|
|
4409
|
+
...customCompilerOptions,
|
|
4410
|
+
scopeId: `data-v-${scopeId}`
|
|
4411
|
+
}
|
|
3674
4412
|
});
|
|
3675
4413
|
templateCode = compiled.code;
|
|
4414
|
+
if (wantsSourceMap || transformedTemplate.map != null) {
|
|
4415
|
+
templateMap = compiled.map;
|
|
4416
|
+
}
|
|
4417
|
+
if (transformedTemplate.map != null && templateMap == null) {
|
|
4418
|
+
warnUnchainableMap(
|
|
4419
|
+
{ filename: id, environmentName, type: "template" },
|
|
4420
|
+
"compiler-sfc did not return a template map"
|
|
4421
|
+
);
|
|
4422
|
+
}
|
|
3676
4423
|
}
|
|
3677
|
-
|
|
4424
|
+
const outputNode = new SourceNode();
|
|
4425
|
+
let hasMappedOutput = false;
|
|
4426
|
+
const append = (fragment, map) => {
|
|
4427
|
+
const normalizedMap = normalizeSourceMap(
|
|
4428
|
+
map,
|
|
4429
|
+
{ filename: id, environmentName, type: "sfc" }
|
|
4430
|
+
);
|
|
4431
|
+
if (!normalizedMap) {
|
|
4432
|
+
outputNode.add(fragment);
|
|
4433
|
+
return;
|
|
4434
|
+
}
|
|
4435
|
+
try {
|
|
4436
|
+
outputNode.add(
|
|
4437
|
+
SourceNode.fromStringWithSourceMap(
|
|
4438
|
+
fragment,
|
|
4439
|
+
new SourceMapConsumer(normalizedMap)
|
|
4440
|
+
)
|
|
4441
|
+
);
|
|
4442
|
+
hasMappedOutput = true;
|
|
4443
|
+
} catch (error) {
|
|
4444
|
+
warnUnchainableMap(
|
|
4445
|
+
{ filename: id, environmentName, type: "sfc" },
|
|
4446
|
+
`source-map assembly failed: ${error instanceof Error ? error.message : String(error)}`
|
|
4447
|
+
);
|
|
4448
|
+
outputNode.add(fragment);
|
|
4449
|
+
}
|
|
4450
|
+
};
|
|
4451
|
+
append(scriptCode || "const __sfc__ = {}", scriptMap);
|
|
3678
4452
|
if (templateCode) {
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
__sfc__.render = render
|
|
3684
|
-
`;
|
|
4453
|
+
append("\n");
|
|
4454
|
+
append(templateCode, templateMap);
|
|
4455
|
+
append("\n");
|
|
4456
|
+
append("\n__sfc__.render = render\n");
|
|
3685
4457
|
}
|
|
3686
4458
|
if (descriptor.styles.length > 0) {
|
|
3687
4459
|
for (let i = 0; i < descriptor.styles.length; i++) {
|
|
3688
|
-
|
|
4460
|
+
append(`
|
|
3689
4461
|
import "${id}?vue&type=style&index=${i}&lang.css"
|
|
3690
|
-
|
|
4462
|
+
`);
|
|
3691
4463
|
}
|
|
3692
4464
|
}
|
|
3693
|
-
|
|
4465
|
+
append(`
|
|
3694
4466
|
__sfc__.__scopeId = "data-v-${scopeId}"
|
|
3695
|
-
|
|
4467
|
+
`);
|
|
3696
4468
|
if (isDev) {
|
|
3697
|
-
|
|
4469
|
+
append(`
|
|
3698
4470
|
__sfc__.__hmrId = ${JSON.stringify(scopeId)}
|
|
3699
4471
|
if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
|
|
3700
4472
|
__VUE_HMR_RUNTIME__.createRecord(__sfc__.__hmrId, __sfc__)
|
|
@@ -3708,17 +4480,34 @@ if (import.meta.hot) {
|
|
|
3708
4480
|
}
|
|
3709
4481
|
})
|
|
3710
4482
|
}
|
|
3711
|
-
|
|
4483
|
+
`);
|
|
4484
|
+
}
|
|
4485
|
+
append("\nexport default __sfc__\n");
|
|
4486
|
+
const renderedOutput = outputNode.toStringWithSourceMap({ file: id });
|
|
4487
|
+
const output = renderedOutput.code;
|
|
4488
|
+
const outputMap = hasMappedOutput ? renderedOutput.map.toJSON() : void 0;
|
|
4489
|
+
if (transformedSfc.map != null && outputMap == null) {
|
|
4490
|
+
warnUnchainableMap(
|
|
4491
|
+
{ filename: id, environmentName, type: "sfc" },
|
|
4492
|
+
"the compiled SFC output contained no chainable mappings"
|
|
4493
|
+
);
|
|
3712
4494
|
}
|
|
3713
|
-
output += `
|
|
3714
|
-
export default __sfc__
|
|
3715
|
-
`;
|
|
3716
4495
|
const lang = descriptor.scriptSetup?.lang ?? descriptor.script?.lang;
|
|
3717
4496
|
if (lang === "ts") {
|
|
3718
|
-
const transpiled = transformCode(`${id}.ts`, output, {
|
|
3719
|
-
|
|
4497
|
+
const transpiled = transformCode(`${id}.ts`, output, {
|
|
4498
|
+
sourcemap: wantsSourceMap,
|
|
4499
|
+
target: config.build.target
|
|
4500
|
+
});
|
|
4501
|
+
const transpiledMap = transpiled.map ? JSON.parse(transpiled.map) : void 0;
|
|
4502
|
+
return {
|
|
4503
|
+
code: transpiled.code,
|
|
4504
|
+
map: composeSourceMapChain(
|
|
4505
|
+
[transpiledMap, outputMap],
|
|
4506
|
+
{ filename: id, environmentName, type: "sfc" }
|
|
4507
|
+
)
|
|
4508
|
+
};
|
|
3720
4509
|
}
|
|
3721
|
-
return { code: output };
|
|
4510
|
+
return { code: output, map: outputMap };
|
|
3722
4511
|
},
|
|
3723
4512
|
handleHotUpdate(ctx) {
|
|
3724
4513
|
const { file, modules } = ctx;
|
|
@@ -3732,16 +4521,75 @@ export default __sfc__
|
|
|
3732
4521
|
}
|
|
3733
4522
|
};
|
|
3734
4523
|
}
|
|
4524
|
+
async function applySourceTransform(transform2, source, context) {
|
|
4525
|
+
if (!transform2) return { code: source };
|
|
4526
|
+
const result = await transform2(source, context);
|
|
4527
|
+
return typeof result === "string" ? { code: result } : result;
|
|
4528
|
+
}
|
|
4529
|
+
function normalizeSourceMap(map, context) {
|
|
4530
|
+
if (map == null) return void 0;
|
|
4531
|
+
try {
|
|
4532
|
+
const value = typeof map === "string" ? JSON.parse(map) : map;
|
|
4533
|
+
if (value && typeof value === "object" && Array.isArray(value.sources) && Array.isArray(value.names) && typeof value.mappings === "string") {
|
|
4534
|
+
return value;
|
|
4535
|
+
}
|
|
4536
|
+
} catch {
|
|
4537
|
+
}
|
|
4538
|
+
warnUnchainableMap(context, "the provided map is not a valid source map");
|
|
4539
|
+
return void 0;
|
|
4540
|
+
}
|
|
4541
|
+
function composeSourceMapChain(maps, context) {
|
|
4542
|
+
const pending = maps.filter((map) => map != null);
|
|
4543
|
+
if (pending.length === 0) return void 0;
|
|
4544
|
+
let composed = normalizeSourceMap(pending.shift(), context);
|
|
4545
|
+
for (const map of pending) {
|
|
4546
|
+
const input = normalizeSourceMap(map, context);
|
|
4547
|
+
if (!input) continue;
|
|
4548
|
+
if (!composed) {
|
|
4549
|
+
composed = input;
|
|
4550
|
+
continue;
|
|
4551
|
+
}
|
|
4552
|
+
try {
|
|
4553
|
+
const consumer = new SourceMapConsumer(composed);
|
|
4554
|
+
if (consumer.sources.length !== 1) {
|
|
4555
|
+
warnUnchainableMap(
|
|
4556
|
+
context,
|
|
4557
|
+
"a generated map has multiple sources and cannot be chained safely"
|
|
4558
|
+
);
|
|
4559
|
+
continue;
|
|
4560
|
+
}
|
|
4561
|
+
const generator = SourceMapGenerator2.fromSourceMap(consumer);
|
|
4562
|
+
generator.applySourceMap(
|
|
4563
|
+
new SourceMapConsumer(input),
|
|
4564
|
+
consumer.sources[0]
|
|
4565
|
+
);
|
|
4566
|
+
composed = generator.toJSON();
|
|
4567
|
+
} catch (error) {
|
|
4568
|
+
warnUnchainableMap(
|
|
4569
|
+
context,
|
|
4570
|
+
`source-map composition failed: ${error instanceof Error ? error.message : String(error)}`
|
|
4571
|
+
);
|
|
4572
|
+
}
|
|
4573
|
+
}
|
|
4574
|
+
return composed;
|
|
4575
|
+
}
|
|
4576
|
+
function warnUnchainableMap(context, reason) {
|
|
4577
|
+
debug3?.(
|
|
4578
|
+
`source map warning for ${context.filename} (${context.type}, ${context.environmentName}): ${reason}`
|
|
4579
|
+
);
|
|
4580
|
+
}
|
|
3735
4581
|
function hashId(filename) {
|
|
3736
4582
|
return crypto2.createHash("sha256").update(filename).digest("hex").slice(0, 8);
|
|
3737
4583
|
}
|
|
3738
|
-
var VUE_FILE_RE, VUE_QUERY_RE, compiler;
|
|
4584
|
+
var VUE_FILE_RE, VUE_QUERY_RE, debug3, compiler;
|
|
3739
4585
|
var init_vue = __esm({
|
|
3740
4586
|
"src/plugins/vue.ts"() {
|
|
3741
4587
|
"use strict";
|
|
3742
4588
|
init_transformer();
|
|
4589
|
+
init_debug();
|
|
3743
4590
|
VUE_FILE_RE = /\.vue$/;
|
|
3744
4591
|
VUE_QUERY_RE = /\.vue\?vue&type=(script|template|style)(&index=\d+)?(&lang[.=]\w+)?/;
|
|
4592
|
+
debug3 = createDebugger("nasti:vue");
|
|
3745
4593
|
compiler = null;
|
|
3746
4594
|
}
|
|
3747
4595
|
});
|
|
@@ -3749,16 +4597,27 @@ var init_vue = __esm({
|
|
|
3749
4597
|
// src/plugins/builtins.ts
|
|
3750
4598
|
function resolvePluginList(config, userPlugins, opts = {}) {
|
|
3751
4599
|
const isServe = config.command === "serve";
|
|
4600
|
+
let environmentOptions;
|
|
4601
|
+
if (opts.environmentName) {
|
|
4602
|
+
environmentOptions = config.environments[opts.environmentName];
|
|
4603
|
+
if (!environmentOptions) {
|
|
4604
|
+
throw new Error(
|
|
4605
|
+
`[nasti] unknown environment "${opts.environmentName}" \u2014 declare it in config.environments`
|
|
4606
|
+
);
|
|
4607
|
+
}
|
|
4608
|
+
}
|
|
4609
|
+
const pluginConfig = environmentOptions ? { ...config, resolve: environmentOptions.resolve, build: environmentOptions.build } : config;
|
|
4610
|
+
const consumer = opts.consumer ?? environmentOptions?.consumer;
|
|
3752
4611
|
return [
|
|
3753
4612
|
// vuePlugin 排最前(enforce: 'pre' 语义):.vue 先编译成 JS 再走后续管道
|
|
3754
|
-
...config.framework === "vue" ? [vuePlugin(
|
|
3755
|
-
resolvePlugin(
|
|
3756
|
-
cssPlugin(
|
|
3757
|
-
assetsPlugin(
|
|
3758
|
-
...isServe ? [htmlPlugin(
|
|
4613
|
+
...config.framework === "vue" ? [vuePlugin(pluginConfig, opts.environmentName ?? "client")] : [],
|
|
4614
|
+
resolvePlugin(pluginConfig),
|
|
4615
|
+
cssPlugin(pluginConfig, opts.cssEngine, consumer),
|
|
4616
|
+
assetsPlugin(pluginConfig),
|
|
4617
|
+
...isServe ? [htmlPlugin(pluginConfig)] : [],
|
|
3759
4618
|
...userPlugins,
|
|
3760
4619
|
// cssPostPlugin 最后(enforce: 'post' 语义):renderChunk 聚合抽取
|
|
3761
|
-
...!isServe && opts.cssEngine ? [cssPostPlugin(
|
|
4620
|
+
...!isServe && opts.cssEngine ? [cssPostPlugin(pluginConfig, opts.cssEngine)] : []
|
|
3762
4621
|
];
|
|
3763
4622
|
}
|
|
3764
4623
|
var init_builtins = __esm({
|
|
@@ -3791,14 +4650,14 @@ function createModuleRunner(environment) {
|
|
|
3791
4650
|
}
|
|
3792
4651
|
return new NastiModuleRunner(environment);
|
|
3793
4652
|
}
|
|
3794
|
-
var
|
|
4653
|
+
var debug4, NODE_BUILTINS, NastiModuleRunner, AsyncFunction;
|
|
3795
4654
|
var init_runnable_environment = __esm({
|
|
3796
4655
|
"src/server/runnable-environment.ts"() {
|
|
3797
4656
|
"use strict";
|
|
3798
4657
|
init_transformer();
|
|
3799
4658
|
init_env();
|
|
3800
4659
|
init_debug();
|
|
3801
|
-
|
|
4660
|
+
debug4 = createDebugger("nasti:ssr");
|
|
3802
4661
|
NODE_BUILTINS = /* @__PURE__ */ new Set([...builtinModules, ...builtinModules.map((m) => `node:${m}`)]);
|
|
3803
4662
|
NastiModuleRunner = class {
|
|
3804
4663
|
environment;
|
|
@@ -3876,6 +4735,7 @@ var init_runnable_environment = __esm({
|
|
|
3876
4735
|
if (shouldTransform(cleanId)) {
|
|
3877
4736
|
const result = transformCode(cleanId, code, {
|
|
3878
4737
|
sourcemap: false,
|
|
4738
|
+
target: this.environment.options.build.target,
|
|
3879
4739
|
jsxRuntime: "automatic",
|
|
3880
4740
|
jsxImportSource: this.config.framework === "vue" ? "vue" : "react"
|
|
3881
4741
|
});
|
|
@@ -3892,7 +4752,7 @@ var init_runnable_environment = __esm({
|
|
|
3892
4752
|
);
|
|
3893
4753
|
}
|
|
3894
4754
|
const runnerResult = await moduleRunnerTransform(resolvedId, code);
|
|
3895
|
-
|
|
4755
|
+
debug4?.(`fetchModule ${resolvedId} (${runnerResult.deps?.length ?? 0} deps)`);
|
|
3896
4756
|
return { id: resolvedId, code: runnerResult.code };
|
|
3897
4757
|
}
|
|
3898
4758
|
completeExtension(id) {
|
|
@@ -4014,7 +4874,7 @@ async function tryNativeReporterPlugin(config, logger) {
|
|
|
4014
4874
|
logInfo: (msg) => logger.info(msg)
|
|
4015
4875
|
});
|
|
4016
4876
|
} catch (err) {
|
|
4017
|
-
|
|
4877
|
+
debug5?.(`native viteReporterPlugin unavailable, falling back to JS table: ${err}`);
|
|
4018
4878
|
return null;
|
|
4019
4879
|
}
|
|
4020
4880
|
}
|
|
@@ -4069,12 +4929,12 @@ function warnLargeChunks(output, config, logger) {
|
|
|
4069
4929
|
)
|
|
4070
4930
|
);
|
|
4071
4931
|
}
|
|
4072
|
-
var
|
|
4932
|
+
var debug5, numberFormatter;
|
|
4073
4933
|
var init_reporter = __esm({
|
|
4074
4934
|
"src/build/reporter.ts"() {
|
|
4075
4935
|
"use strict";
|
|
4076
4936
|
init_debug();
|
|
4077
|
-
|
|
4937
|
+
debug5 = createDebugger("nasti:reporter");
|
|
4078
4938
|
numberFormatter = new Intl.NumberFormat("en", {
|
|
4079
4939
|
maximumFractionDigits: 2,
|
|
4080
4940
|
minimumFractionDigits: 2
|
|
@@ -4082,6 +4942,155 @@ var init_reporter = __esm({
|
|
|
4082
4942
|
}
|
|
4083
4943
|
});
|
|
4084
4944
|
|
|
4945
|
+
// src/core/build-app-context.ts
|
|
4946
|
+
import fs9 from "fs";
|
|
4947
|
+
import path12 from "path";
|
|
4948
|
+
function createBuildAppContext(config, results) {
|
|
4949
|
+
const output = [];
|
|
4950
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
4951
|
+
const outDir = path12.resolve(config.root, config.build.outDir);
|
|
4952
|
+
let environmentArtifacts;
|
|
4953
|
+
return {
|
|
4954
|
+
config,
|
|
4955
|
+
results,
|
|
4956
|
+
get output() {
|
|
4957
|
+
return Object.freeze([...output]);
|
|
4958
|
+
},
|
|
4959
|
+
getResult(environmentName) {
|
|
4960
|
+
return results[environmentName];
|
|
4961
|
+
},
|
|
4962
|
+
getArtifact(environmentName, fileName) {
|
|
4963
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
4964
|
+
return results[environmentName]?.output.find(
|
|
4965
|
+
(artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalized
|
|
4966
|
+
);
|
|
4967
|
+
},
|
|
4968
|
+
getEntry(environmentName, entryName) {
|
|
4969
|
+
const result = results[environmentName];
|
|
4970
|
+
const fileName = result?.entries?.[entryName];
|
|
4971
|
+
if (!fileName) return void 0;
|
|
4972
|
+
return result.output.find(
|
|
4973
|
+
(artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalizeEnvironmentFileName(fileName)
|
|
4974
|
+
);
|
|
4975
|
+
},
|
|
4976
|
+
getManifest(environmentName) {
|
|
4977
|
+
return results[environmentName]?.manifest;
|
|
4978
|
+
},
|
|
4979
|
+
getChunk(environmentName, fileName) {
|
|
4980
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
4981
|
+
return results[environmentName]?.chunks?.[normalized];
|
|
4982
|
+
},
|
|
4983
|
+
getCss(environmentName) {
|
|
4984
|
+
return results[environmentName]?.css;
|
|
4985
|
+
},
|
|
4986
|
+
getSourceMap(environmentName, fileName) {
|
|
4987
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
4988
|
+
return results[environmentName]?.sourceMaps?.[normalized];
|
|
4989
|
+
},
|
|
4990
|
+
resolvePublicPath(environmentName, fileName) {
|
|
4991
|
+
const result = results[environmentName];
|
|
4992
|
+
if (!result) return void 0;
|
|
4993
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
4994
|
+
const base = result.publicPath ?? config.base;
|
|
4995
|
+
return joinPublicPath(base, normalized);
|
|
4996
|
+
},
|
|
4997
|
+
emitFile(file) {
|
|
4998
|
+
const fileName = normalizeAppFileName(file.fileName);
|
|
4999
|
+
const collisionKey = artifactCollisionKey(fileName);
|
|
5000
|
+
if (emitted.has(collisionKey)) {
|
|
5001
|
+
throw new Error(`[nasti] app artifact already emitted: ${fileName}`);
|
|
5002
|
+
}
|
|
5003
|
+
environmentArtifacts ??= collectEnvironmentArtifacts(config, results, outDir);
|
|
5004
|
+
if (environmentArtifacts.has(collisionKey)) {
|
|
5005
|
+
throw new Error(`[nasti] app artifact conflicts with environment output: ${fileName}`);
|
|
5006
|
+
}
|
|
5007
|
+
const target = path12.resolve(outDir, ...fileName.split("/"));
|
|
5008
|
+
const relative = path12.relative(outDir, target);
|
|
5009
|
+
if (relative.startsWith("..") || path12.isAbsolute(relative)) {
|
|
5010
|
+
throw new Error(`[nasti] app artifact must stay inside build.outDir: ${file.fileName}`);
|
|
5011
|
+
}
|
|
5012
|
+
assertNoSymlinkComponents(outDir, fileName);
|
|
5013
|
+
fs9.mkdirSync(path12.dirname(target), { recursive: true });
|
|
5014
|
+
fs9.writeFileSync(target, file.source);
|
|
5015
|
+
const artifact = {
|
|
5016
|
+
...file,
|
|
5017
|
+
fileName,
|
|
5018
|
+
type: "asset"
|
|
5019
|
+
};
|
|
5020
|
+
emitted.add(collisionKey);
|
|
5021
|
+
output.push(artifact);
|
|
5022
|
+
return fileName;
|
|
5023
|
+
}
|
|
5024
|
+
};
|
|
5025
|
+
}
|
|
5026
|
+
function joinPublicPath(base, fileName) {
|
|
5027
|
+
return `${base.endsWith("/") ? base : `${base}/`}${fileName.replace(/^\//, "")}`;
|
|
5028
|
+
}
|
|
5029
|
+
function normalizeEnvironmentFileName(fileName) {
|
|
5030
|
+
return path12.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
|
|
5031
|
+
}
|
|
5032
|
+
function isInvalidEnvironmentFileName(fileName) {
|
|
5033
|
+
return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || path12.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
|
|
5034
|
+
}
|
|
5035
|
+
function normalizeAppFileName(fileName) {
|
|
5036
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
5037
|
+
if (isInvalidEnvironmentFileName(normalized)) {
|
|
5038
|
+
throw new Error(`[nasti] invalid app artifact fileName: ${fileName}`);
|
|
5039
|
+
}
|
|
5040
|
+
return normalized;
|
|
5041
|
+
}
|
|
5042
|
+
function artifactCollisionKey(fileName) {
|
|
5043
|
+
return normalizeEnvironmentFileName(fileName).toLowerCase();
|
|
5044
|
+
}
|
|
5045
|
+
function collectEnvironmentArtifacts(config, results, appOutDir) {
|
|
5046
|
+
const occupied = /* @__PURE__ */ new Set();
|
|
5047
|
+
for (const [environmentName, result] of Object.entries(results)) {
|
|
5048
|
+
const environment = config.environments[environmentName];
|
|
5049
|
+
if (!environment) continue;
|
|
5050
|
+
const environmentOutDir = path12.resolve(config.root, environment.build.outDir);
|
|
5051
|
+
for (const artifact of result.output) {
|
|
5052
|
+
const artifactPath = path12.resolve(
|
|
5053
|
+
environmentOutDir,
|
|
5054
|
+
...normalizeEnvironmentFileName(artifact.fileName).split("/")
|
|
5055
|
+
);
|
|
5056
|
+
const relative = path12.relative(appOutDir, artifactPath);
|
|
5057
|
+
if (!relative.startsWith("..") && !path12.isAbsolute(relative)) {
|
|
5058
|
+
occupied.add(artifactCollisionKey(relative));
|
|
5059
|
+
}
|
|
5060
|
+
}
|
|
5061
|
+
}
|
|
5062
|
+
return occupied;
|
|
5063
|
+
}
|
|
5064
|
+
function assertNoSymlinkComponents(outDir, fileName) {
|
|
5065
|
+
let current = outDir;
|
|
5066
|
+
for (const segment of fileName.split("/")) {
|
|
5067
|
+
current = path12.join(current, segment);
|
|
5068
|
+
let stats;
|
|
5069
|
+
try {
|
|
5070
|
+
stats = fs9.lstatSync(current);
|
|
5071
|
+
} catch (error) {
|
|
5072
|
+
if (error.code === "ENOENT") continue;
|
|
5073
|
+
throw error;
|
|
5074
|
+
}
|
|
5075
|
+
if (stats.isSymbolicLink()) {
|
|
5076
|
+
throw new Error(`[nasti] app artifact path cannot traverse a symlink: ${fileName}`);
|
|
5077
|
+
}
|
|
5078
|
+
}
|
|
5079
|
+
}
|
|
5080
|
+
function inferEnvironmentEntries(output) {
|
|
5081
|
+
const entries = {};
|
|
5082
|
+
for (const artifact of output) {
|
|
5083
|
+
if (artifact.type !== "chunk" || !artifact.isEntry || !artifact.name) continue;
|
|
5084
|
+
entries[artifact.name] = normalizeEnvironmentFileName(artifact.fileName);
|
|
5085
|
+
}
|
|
5086
|
+
return Object.keys(entries).length > 0 ? entries : void 0;
|
|
5087
|
+
}
|
|
5088
|
+
var init_build_app_context = __esm({
|
|
5089
|
+
"src/core/build-app-context.ts"() {
|
|
5090
|
+
"use strict";
|
|
5091
|
+
}
|
|
5092
|
+
});
|
|
5093
|
+
|
|
4085
5094
|
// src/build/index.ts
|
|
4086
5095
|
var build_exports = {};
|
|
4087
5096
|
__export(build_exports, {
|
|
@@ -4091,8 +5100,8 @@ __export(build_exports, {
|
|
|
4091
5100
|
resolveClientEntries: () => resolveClientEntries,
|
|
4092
5101
|
toRolldownPlugins: () => toRolldownPlugins
|
|
4093
5102
|
});
|
|
4094
|
-
import
|
|
4095
|
-
import
|
|
5103
|
+
import path13 from "path";
|
|
5104
|
+
import fs10 from "fs";
|
|
4096
5105
|
import { builtinModules as builtinModules2 } from "module";
|
|
4097
5106
|
import { rolldown } from "rolldown";
|
|
4098
5107
|
import pc6 from "picocolors";
|
|
@@ -4100,9 +5109,14 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
4100
5109
|
const config = environment.config;
|
|
4101
5110
|
const envOptions = environment.options;
|
|
4102
5111
|
const isServer = environment.consumer === "server";
|
|
4103
|
-
const outDir =
|
|
5112
|
+
const outDir = path13.resolve(config.root, envOptions.build.outDir);
|
|
4104
5113
|
const assetsDir = envOptions.build.assetsDir;
|
|
4105
|
-
const {
|
|
5114
|
+
const {
|
|
5115
|
+
output: userOutput,
|
|
5116
|
+
transform: userTransform,
|
|
5117
|
+
resolve: userResolve,
|
|
5118
|
+
...restInputOptions
|
|
5119
|
+
} = envOptions.build.rolldownOptions;
|
|
4106
5120
|
const vueDefine = config.framework === "vue" ? {
|
|
4107
5121
|
__VUE_OPTIONS_API__: "true",
|
|
4108
5122
|
__VUE_PROD_DEVTOOLS__: "false",
|
|
@@ -4114,27 +5128,34 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
4114
5128
|
const inputOptions = {
|
|
4115
5129
|
...restInputOptions,
|
|
4116
5130
|
input: entryPoints,
|
|
4117
|
-
transform: {
|
|
5131
|
+
transform: {
|
|
5132
|
+
...userTransform,
|
|
5133
|
+
target: userTransform?.target ?? envOptions.build.target,
|
|
5134
|
+
define: mergedDefine
|
|
5135
|
+
},
|
|
4118
5136
|
plugins: rolldownPlugins,
|
|
5137
|
+
// client/server consumer 都必须使用当前环境的 conditions/mainFields;Lynx
|
|
5138
|
+
// BG/MT 通常同为 client consumer,但仍可能声明不同的运行时条件。
|
|
5139
|
+
resolve: {
|
|
5140
|
+
...userResolve ?? {},
|
|
5141
|
+
// Environment API 是条件解析的唯一高层入口,优先于继承来的底层选项。
|
|
5142
|
+
conditionNames: envOptions.resolve.conditions,
|
|
5143
|
+
mainFields: envOptions.resolve.mainFields
|
|
5144
|
+
},
|
|
4119
5145
|
...isServer ? {
|
|
4120
5146
|
platform: restInputOptions.platform ?? "node",
|
|
4121
|
-
resolve: {
|
|
4122
|
-
conditionNames: envOptions.resolve.conditions,
|
|
4123
|
-
mainFields: envOptions.resolve.mainFields,
|
|
4124
|
-
...restInputOptions.resolve
|
|
4125
|
-
},
|
|
4126
5147
|
// server 产物:node 内建恒外部化;bare specifier 默认外部化
|
|
4127
5148
|
//(同 Vite ssr.external 默认 —— 依赖由 node_modules 运行时解析),
|
|
4128
5149
|
// 相对/绝对/虚拟模块照常打包。需要内联依赖时经 rolldownOptions.external 覆盖。
|
|
4129
5150
|
external: restInputOptions.external ?? ((id) => {
|
|
4130
5151
|
if (NODE_BUILTINS2.has(id)) return true;
|
|
4131
|
-
return !id.startsWith(".") && !
|
|
5152
|
+
return !id.startsWith(".") && !path13.isAbsolute(id) && !id.startsWith("\0");
|
|
4132
5153
|
})
|
|
4133
5154
|
} : {}
|
|
4134
5155
|
};
|
|
4135
5156
|
const outputOptions = isServer ? {
|
|
4136
5157
|
format: "esm",
|
|
4137
|
-
sourcemap:
|
|
5158
|
+
sourcemap: envOptions.build.sourcemap,
|
|
4138
5159
|
minify: !!envOptions.build.minify,
|
|
4139
5160
|
entryFileNames: "[name].js",
|
|
4140
5161
|
chunkFileNames: "chunks/[name]-[hash].js",
|
|
@@ -4143,7 +5164,7 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
4143
5164
|
dir: outDir
|
|
4144
5165
|
} : {
|
|
4145
5166
|
format: "esm",
|
|
4146
|
-
sourcemap:
|
|
5167
|
+
sourcemap: envOptions.build.sourcemap,
|
|
4147
5168
|
minify: !!envOptions.build.minify,
|
|
4148
5169
|
entryFileNames: `${assetsDir}/[name].[hash].js`,
|
|
4149
5170
|
chunkFileNames: `${assetsDir}/[name].[hash].js`,
|
|
@@ -4155,27 +5176,177 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
4155
5176
|
};
|
|
4156
5177
|
return { inputOptions, outputOptions, outDir };
|
|
4157
5178
|
}
|
|
4158
|
-
function toRolldownPlugins(plugins) {
|
|
5179
|
+
function toRolldownPlugins(plugins, environment) {
|
|
5180
|
+
const wrap = (hook) => {
|
|
5181
|
+
if (!hook) return hook;
|
|
5182
|
+
return function(...args) {
|
|
5183
|
+
return hook.apply(attachEnvironment(this, environment), args);
|
|
5184
|
+
};
|
|
5185
|
+
};
|
|
4159
5186
|
return plugins.map((p) => ({
|
|
4160
5187
|
name: p.name,
|
|
4161
|
-
resolveId: p.resolveId,
|
|
4162
|
-
load: p.load,
|
|
4163
|
-
transform: p.transform,
|
|
4164
|
-
buildStart: p.buildStart,
|
|
4165
|
-
buildEnd: p.buildEnd,
|
|
5188
|
+
resolveId: wrap(p.resolveId),
|
|
5189
|
+
load: wrap(p.load),
|
|
5190
|
+
transform: wrap(p.transform),
|
|
5191
|
+
buildStart: wrap(p.buildStart),
|
|
5192
|
+
buildEnd: wrap(p.buildEnd),
|
|
4166
5193
|
// closeBundle 在 bundle.close() 时触发 —— PWA manifest/SW 等终态产物依赖
|
|
4167
|
-
closeBundle: p.closeBundle,
|
|
4168
|
-
renderChunk: p.renderChunk,
|
|
4169
|
-
augmentChunkHash: p.augmentChunkHash,
|
|
4170
|
-
generateBundle: p.generateBundle
|
|
5194
|
+
closeBundle: wrap(p.closeBundle),
|
|
5195
|
+
renderChunk: wrap(p.renderChunk),
|
|
5196
|
+
augmentChunkHash: wrap(p.augmentChunkHash),
|
|
5197
|
+
generateBundle: wrap(p.generateBundle)
|
|
4171
5198
|
}));
|
|
4172
5199
|
}
|
|
5200
|
+
function attachEnvironment(context, environment) {
|
|
5201
|
+
if (context?.environment === environment) return context;
|
|
5202
|
+
try {
|
|
5203
|
+
Object.defineProperty(context, "environment", {
|
|
5204
|
+
configurable: true,
|
|
5205
|
+
enumerable: false,
|
|
5206
|
+
writable: false,
|
|
5207
|
+
value: environment
|
|
5208
|
+
});
|
|
5209
|
+
return context;
|
|
5210
|
+
} catch {
|
|
5211
|
+
return new Proxy(context, {
|
|
5212
|
+
get(target, property) {
|
|
5213
|
+
if (property === "environment") return environment;
|
|
5214
|
+
const value = Reflect.get(target, property, target);
|
|
5215
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
5216
|
+
},
|
|
5217
|
+
set(target, property, value) {
|
|
5218
|
+
return Reflect.set(target, property, value, target);
|
|
5219
|
+
}
|
|
5220
|
+
});
|
|
5221
|
+
}
|
|
5222
|
+
}
|
|
5223
|
+
function finalizeEnvironmentResult(environment, result) {
|
|
5224
|
+
const metadata = environment.getBuildMetadata();
|
|
5225
|
+
const inferredEntries = inferEnvironmentEntries(result.output);
|
|
5226
|
+
const entries = {
|
|
5227
|
+
...inferredEntries,
|
|
5228
|
+
...metadata.entries,
|
|
5229
|
+
...result.entries
|
|
5230
|
+
};
|
|
5231
|
+
const normalizedEntries = Object.fromEntries(
|
|
5232
|
+
Object.entries(entries).map(([name, fileName]) => {
|
|
5233
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
5234
|
+
if (isInvalidEnvironmentFileName(normalized)) {
|
|
5235
|
+
throw new Error(
|
|
5236
|
+
`[nasti] environment "${environment.name}" returned invalid entry "${name}": ${fileName}`
|
|
5237
|
+
);
|
|
5238
|
+
}
|
|
5239
|
+
return [name, normalized];
|
|
5240
|
+
})
|
|
5241
|
+
);
|
|
5242
|
+
const inferredMetadata = inferOutputMetadata(environment, result.output);
|
|
5243
|
+
return {
|
|
5244
|
+
publicPath: environment.config.base,
|
|
5245
|
+
...inferredMetadata,
|
|
5246
|
+
...metadata,
|
|
5247
|
+
...result,
|
|
5248
|
+
output: result.output,
|
|
5249
|
+
chunks: {
|
|
5250
|
+
...inferredMetadata.chunks,
|
|
5251
|
+
...metadata.chunks,
|
|
5252
|
+
...result.chunks
|
|
5253
|
+
},
|
|
5254
|
+
assets: {
|
|
5255
|
+
...inferredMetadata.assets,
|
|
5256
|
+
...metadata.assets,
|
|
5257
|
+
...result.assets
|
|
5258
|
+
},
|
|
5259
|
+
sourceMaps: {
|
|
5260
|
+
...inferredMetadata.sourceMaps,
|
|
5261
|
+
...metadata.sourceMaps,
|
|
5262
|
+
...result.sourceMaps
|
|
5263
|
+
},
|
|
5264
|
+
...Object.keys(normalizedEntries).length > 0 ? { entries: normalizedEntries } : {}
|
|
5265
|
+
};
|
|
5266
|
+
}
|
|
5267
|
+
function inferOutputMetadata(environment, output) {
|
|
5268
|
+
const chunks = {};
|
|
5269
|
+
const assets = {};
|
|
5270
|
+
const sourceMaps = {};
|
|
5271
|
+
const cssChunks = environment.getBuildMetadata().css?.chunks ?? {};
|
|
5272
|
+
const assetModules = environment.getAssetModules();
|
|
5273
|
+
const publicPath = environment.config.base;
|
|
5274
|
+
for (const artifact of output) {
|
|
5275
|
+
const fileName = normalizeEnvironmentFileName(artifact.fileName);
|
|
5276
|
+
if (artifact.map != null) sourceMaps[fileName] = artifact.map;
|
|
5277
|
+
if (artifact.type === "chunk") {
|
|
5278
|
+
const moduleIds = [...artifact.moduleIds ?? []];
|
|
5279
|
+
chunks[fileName] = {
|
|
5280
|
+
fileName,
|
|
5281
|
+
name: artifact.name ?? fileName,
|
|
5282
|
+
isEntry: !!artifact.isEntry,
|
|
5283
|
+
isDynamicEntry: !!artifact.isDynamicEntry,
|
|
5284
|
+
imports: [...artifact.imports ?? []],
|
|
5285
|
+
dynamicImports: [...artifact.dynamicImports ?? []],
|
|
5286
|
+
moduleIds,
|
|
5287
|
+
css: [...cssChunks[fileName]?.cssFileNames ?? []],
|
|
5288
|
+
assets: [
|
|
5289
|
+
...new Set(
|
|
5290
|
+
moduleIds.map((id) => assetModules[id]).filter((asset) => !!asset)
|
|
5291
|
+
)
|
|
5292
|
+
]
|
|
5293
|
+
};
|
|
5294
|
+
} else if (artifact.type === "asset") {
|
|
5295
|
+
assets[fileName] = {
|
|
5296
|
+
fileName,
|
|
5297
|
+
names: [...artifact.names ?? (artifact.name ? [artifact.name] : [])],
|
|
5298
|
+
publicPath: joinPublicPath(publicPath, fileName)
|
|
5299
|
+
};
|
|
5300
|
+
}
|
|
5301
|
+
}
|
|
5302
|
+
return { chunks, assets, sourceMaps };
|
|
5303
|
+
}
|
|
5304
|
+
function prepareBuildOutputDirectories(config, buildableNames) {
|
|
5305
|
+
const directories = /* @__PURE__ */ new Set();
|
|
5306
|
+
const protectedPaths = /* @__PURE__ */ new Set();
|
|
5307
|
+
const clientIsBuilt = buildableNames.includes("client");
|
|
5308
|
+
if (!clientIsBuilt && config.build.emptyOutDir) {
|
|
5309
|
+
directories.add(path13.resolve(config.root, config.build.outDir));
|
|
5310
|
+
}
|
|
5311
|
+
for (const name of buildableNames) {
|
|
5312
|
+
const environment = config.environments[name];
|
|
5313
|
+
const outDir = path13.resolve(config.root, environment.build.outDir);
|
|
5314
|
+
if (!environment.build.emptyOutDir) {
|
|
5315
|
+
protectedPaths.add(outDir);
|
|
5316
|
+
continue;
|
|
5317
|
+
}
|
|
5318
|
+
if (!environment.driver) directories.add(outDir);
|
|
5319
|
+
}
|
|
5320
|
+
const containsPath = (parent, child) => {
|
|
5321
|
+
const relative = path13.relative(parent, child);
|
|
5322
|
+
return relative === "" || !relative.startsWith("..") && !path13.isAbsolute(relative);
|
|
5323
|
+
};
|
|
5324
|
+
const roots = [...directories].filter(
|
|
5325
|
+
(directory) => ![...protectedPaths].some((protectedPath) => containsPath(directory, protectedPath))
|
|
5326
|
+
).sort((a, b) => a.length - b.length).filter(
|
|
5327
|
+
(directory, index2, all) => !all.slice(0, index2).some((parent) => containsPath(parent, directory))
|
|
5328
|
+
);
|
|
5329
|
+
for (const directory of roots) {
|
|
5330
|
+
if (fs10.existsSync(directory)) fs10.rmSync(directory, { recursive: true, force: true });
|
|
5331
|
+
}
|
|
5332
|
+
}
|
|
5333
|
+
function assertDriverBuildResult(environment, result) {
|
|
5334
|
+
const output = result != null && typeof result === "object" ? result.output : void 0;
|
|
5335
|
+
const hasValidOutput = Array.isArray(output) && output.every(
|
|
5336
|
+
(artifact) => artifact != null && typeof artifact === "object" && typeof artifact.fileName === "string" && typeof artifact.type === "string"
|
|
5337
|
+
);
|
|
5338
|
+
if (!hasValidOutput) {
|
|
5339
|
+
throw new Error(
|
|
5340
|
+
`[nasti] environment "${environment.name}" driver "${environment.driver?.name}" returned an invalid build result; expected { output: EnvironmentBuildOutput[] }`
|
|
5341
|
+
);
|
|
5342
|
+
}
|
|
5343
|
+
}
|
|
4173
5344
|
function resolveClientEntries(config, html) {
|
|
4174
5345
|
const configuredEntries = config.environments.client?.entry ?? [];
|
|
4175
5346
|
if (configuredEntries.length > 0) return configuredEntries;
|
|
4176
5347
|
const entryPoints = [];
|
|
4177
5348
|
const htmlFile = config.environments.client?.html;
|
|
4178
|
-
const htmlDir = htmlFile ?
|
|
5349
|
+
const htmlDir = htmlFile ? path13.dirname(htmlFile) : config.root;
|
|
4179
5350
|
if (html) {
|
|
4180
5351
|
const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
|
|
4181
5352
|
for (const match of scriptMatches) {
|
|
@@ -4183,7 +5354,7 @@ function resolveClientEntries(config, html) {
|
|
|
4183
5354
|
if (src && !src.startsWith("http")) {
|
|
4184
5355
|
const cleanSrc = src.split(/[?#]/, 1)[0];
|
|
4185
5356
|
entryPoints.push(
|
|
4186
|
-
cleanSrc.startsWith("/") ?
|
|
5357
|
+
cleanSrc.startsWith("/") ? path13.resolve(config.root, cleanSrc.replace(/^\//, "")) : path13.resolve(htmlDir, cleanSrc)
|
|
4187
5358
|
);
|
|
4188
5359
|
}
|
|
4189
5360
|
}
|
|
@@ -4191,8 +5362,8 @@ function resolveClientEntries(config, html) {
|
|
|
4191
5362
|
if (entryPoints.length === 0) {
|
|
4192
5363
|
const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
|
|
4193
5364
|
for (const entry of fallbackEntries) {
|
|
4194
|
-
const fullPath =
|
|
4195
|
-
if (
|
|
5365
|
+
const fullPath = path13.resolve(config.root, entry);
|
|
5366
|
+
if (fs10.existsSync(fullPath)) {
|
|
4196
5367
|
entryPoints.push(fullPath);
|
|
4197
5368
|
break;
|
|
4198
5369
|
}
|
|
@@ -4207,6 +5378,7 @@ function createOxcTransformPlugin(config, environment) {
|
|
|
4207
5378
|
if (!shouldTransform(id)) return null;
|
|
4208
5379
|
const result = transformCode(id, code, {
|
|
4209
5380
|
sourcemap: !!environment.options.build.sourcemap,
|
|
5381
|
+
target: environment.options.build.target,
|
|
4210
5382
|
jsxRuntime: "automatic",
|
|
4211
5383
|
jsxImportSource: config.framework === "vue" ? "vue" : "react"
|
|
4212
5384
|
});
|
|
@@ -4220,16 +5392,20 @@ async function build(inlineConfig = {}) {
|
|
|
4220
5392
|
const startTime = performance.now();
|
|
4221
5393
|
logger.info(
|
|
4222
5394
|
pc6.cyan(`
|
|
4223
|
-
nasti v${"2.
|
|
4224
|
-
);
|
|
4225
|
-
debug5?.(`root: ${config.root}`);
|
|
4226
|
-
const buildableNames = Object.keys(config.environments).filter(
|
|
4227
|
-
(name) => name === "client" || config.environments[name].entry.length > 0 || !!config.environments[name].driver
|
|
5395
|
+
nasti v${"2.4.1"} `) + pc6.green(`building for ${config.mode}...`)
|
|
4228
5396
|
);
|
|
5397
|
+
debug6?.(`root: ${config.root}`);
|
|
5398
|
+
const buildableNames = Object.keys(config.environments).filter((name) => {
|
|
5399
|
+
const environment = config.environments[name];
|
|
5400
|
+
if (!environment.buildEnabled) return false;
|
|
5401
|
+
return name === "client" || environment.entry.length > 0 || !!environment.driver;
|
|
5402
|
+
});
|
|
4229
5403
|
buildableNames.sort((a, b) => a === "client" ? -1 : b === "client" ? 1 : 0);
|
|
5404
|
+
prepareBuildOutputDirectories(config, buildableNames);
|
|
4230
5405
|
const environments = {};
|
|
4231
5406
|
const environmentResults = {};
|
|
4232
5407
|
const initializedEnvironments = [];
|
|
5408
|
+
const buildAppContext = createBuildAppContext(config, environmentResults);
|
|
4233
5409
|
let clientOutput = [];
|
|
4234
5410
|
let buildFailed = false;
|
|
4235
5411
|
try {
|
|
@@ -4240,12 +5416,12 @@ nasti v${"2.3.1"} `) + pc6.green(`building for ${config.mode}...`)
|
|
|
4240
5416
|
environmentResults[name] = built.result;
|
|
4241
5417
|
if (name === "client") clientOutput = built.result.output;
|
|
4242
5418
|
if (buildableNames.length > 1) {
|
|
4243
|
-
|
|
5419
|
+
debug6?.(`environment "${name}" built (${built.result.output.length} files)`);
|
|
4244
5420
|
}
|
|
4245
5421
|
}
|
|
4246
5422
|
const pluginApi = getPluginApi(config);
|
|
4247
5423
|
for (const plugin of config.plugins) {
|
|
4248
|
-
await plugin.afterBuildApp?.(environmentResults, pluginApi);
|
|
5424
|
+
await plugin.afterBuildApp?.(environmentResults, pluginApi, buildAppContext);
|
|
4249
5425
|
}
|
|
4250
5426
|
} catch (error) {
|
|
4251
5427
|
buildFailed = true;
|
|
@@ -4272,22 +5448,31 @@ nasti v${"2.3.1"} `) + pc6.green(`building for ${config.mode}...`)
|
|
|
4272
5448
|
}
|
|
4273
5449
|
}
|
|
4274
5450
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
4275
|
-
const
|
|
5451
|
+
const allOutput = [...Object.values(environments).flat(), ...buildAppContext.output];
|
|
5452
|
+
const totalSize = allOutput.reduce((sum, chunk) => {
|
|
4276
5453
|
const content = chunk.type === "chunk" ? chunk.code : chunk.source;
|
|
4277
5454
|
if (content == null) return sum;
|
|
4278
5455
|
return sum + (typeof content === "string" ? Buffer.byteLength(content) : content.byteLength);
|
|
4279
5456
|
}, 0);
|
|
4280
|
-
const fileCount =
|
|
5457
|
+
const fileCount = allOutput.length;
|
|
4281
5458
|
const envSuffix = buildableNames.length > 1 ? ` (${buildableNames.join(" + ")})` : "";
|
|
4282
5459
|
logger.info(pc6.green(`\u2713 built in ${elapsed}s`) + pc6.dim(envSuffix));
|
|
4283
5460
|
logger.info(pc6.dim(` ${fileCount} files, ${displaySize(totalSize)} total \u2192 ${config.build.outDir}/`));
|
|
4284
|
-
return {
|
|
5461
|
+
return {
|
|
5462
|
+
output: clientOutput,
|
|
5463
|
+
environments,
|
|
5464
|
+
environmentResults,
|
|
5465
|
+
appOutput: [...buildAppContext.output]
|
|
5466
|
+
};
|
|
4285
5467
|
}
|
|
4286
5468
|
async function buildClientEnvironment(config) {
|
|
4287
5469
|
const logger = config.logger;
|
|
4288
|
-
const outDir =
|
|
5470
|
+
const outDir = path13.resolve(config.root, config.build.outDir);
|
|
4289
5471
|
const cssEngine = createCssEngine();
|
|
4290
|
-
const pluginList = resolvePluginList(config, config.plugins, {
|
|
5472
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
5473
|
+
cssEngine,
|
|
5474
|
+
environmentName: "client"
|
|
5475
|
+
});
|
|
4291
5476
|
const clientEnv = new NastiEnvironment("client", config, {
|
|
4292
5477
|
mode: "build",
|
|
4293
5478
|
plugins: pluginList,
|
|
@@ -4302,13 +5487,11 @@ async function buildClientEnvironment(config) {
|
|
|
4302
5487
|
);
|
|
4303
5488
|
}
|
|
4304
5489
|
const result = await clientEnv.driver.build(clientEnv.getDriverContext());
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
if (config.build.emptyOutDir && fs9.existsSync(outDir)) {
|
|
4308
|
-
fs9.rmSync(outDir, { recursive: true, force: true });
|
|
5490
|
+
assertDriverBuildResult(clientEnv, result);
|
|
5491
|
+
return { environment: clientEnv, result: finalizeEnvironmentResult(clientEnv, result) };
|
|
4309
5492
|
}
|
|
4310
|
-
|
|
4311
|
-
const htmlFile = config.environments.client.html ??
|
|
5493
|
+
fs10.mkdirSync(outDir, { recursive: true });
|
|
5494
|
+
const htmlFile = config.environments.client.html ?? path13.resolve(config.root, "index.html");
|
|
4312
5495
|
const html = await readHtmlFile(config.root, htmlFile);
|
|
4313
5496
|
const entryPoints = resolveClientEntries(config, html);
|
|
4314
5497
|
if (entryPoints.length === 0) {
|
|
@@ -4318,7 +5501,7 @@ async function buildClientEnvironment(config) {
|
|
|
4318
5501
|
const nativeReporter = config.logLevel === "silent" ? null : await tryNativeReporterPlugin(config, logger);
|
|
4319
5502
|
const rolldownPlugins = [
|
|
4320
5503
|
createOxcTransformPlugin(config, clientEnv),
|
|
4321
|
-
...toRolldownPlugins(allPlugins),
|
|
5504
|
+
...toRolldownPlugins(allPlugins, clientEnv),
|
|
4322
5505
|
...nativeReporter ? [nativeReporter] : []
|
|
4323
5506
|
];
|
|
4324
5507
|
const { inputOptions, outputOptions } = getRolldownOptions(
|
|
@@ -4329,6 +5512,7 @@ async function buildClientEnvironment(config) {
|
|
|
4329
5512
|
const bundle2 = await rolldown(inputOptions);
|
|
4330
5513
|
const { output } = await bundle2.write(outputOptions);
|
|
4331
5514
|
await bundle2.close();
|
|
5515
|
+
clientEnv.setBuildMetadata({ css: getCssMetadata(cssEngine) });
|
|
4332
5516
|
if (html) {
|
|
4333
5517
|
let processedHtml = html;
|
|
4334
5518
|
const htmlPlugins = [...allPlugins.filter((p) => p.transformIndexHtml), htmlPlugin(config)];
|
|
@@ -4342,7 +5526,9 @@ async function buildClientEnvironment(config) {
|
|
|
4342
5526
|
processedHtml = processHtml(processedHtml, result);
|
|
4343
5527
|
}
|
|
4344
5528
|
}
|
|
4345
|
-
|
|
5529
|
+
if (clientEnv.options.build.css.inject !== false) {
|
|
5530
|
+
processedHtml = injectCssLinks(processedHtml, cssEngine, config);
|
|
5531
|
+
}
|
|
4346
5532
|
for (const chunk of output) {
|
|
4347
5533
|
if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) {
|
|
4348
5534
|
processedHtml = replaceEntryScript(
|
|
@@ -4355,13 +5541,16 @@ async function buildClientEnvironment(config) {
|
|
|
4355
5541
|
);
|
|
4356
5542
|
}
|
|
4357
5543
|
}
|
|
4358
|
-
|
|
5544
|
+
fs10.writeFileSync(path13.resolve(outDir, "index.html"), processedHtml);
|
|
4359
5545
|
}
|
|
4360
5546
|
if (!nativeReporter && config.logLevel !== "silent") {
|
|
4361
5547
|
reportBuildOutput(output, config, logger);
|
|
4362
5548
|
}
|
|
4363
5549
|
warnLargeChunks(output, config, logger);
|
|
4364
|
-
return {
|
|
5550
|
+
return {
|
|
5551
|
+
environment: clientEnv,
|
|
5552
|
+
result: finalizeEnvironmentResult(clientEnv, { output })
|
|
5553
|
+
};
|
|
4365
5554
|
} catch (error) {
|
|
4366
5555
|
try {
|
|
4367
5556
|
await clientEnv.close();
|
|
@@ -4377,7 +5566,12 @@ async function buildClientEnvironment(config) {
|
|
|
4377
5566
|
async function buildServerEnvironment(config, name) {
|
|
4378
5567
|
const envOptions = config.environments[name];
|
|
4379
5568
|
const logger = config.logger;
|
|
4380
|
-
const
|
|
5569
|
+
const cssEngine = envOptions.consumer === "client" ? createCssEngine() : void 0;
|
|
5570
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
5571
|
+
consumer: envOptions.consumer,
|
|
5572
|
+
environmentName: name,
|
|
5573
|
+
cssEngine
|
|
5574
|
+
});
|
|
4381
5575
|
const environment = new NastiEnvironment(name, config, {
|
|
4382
5576
|
mode: "build",
|
|
4383
5577
|
plugins: pluginList,
|
|
@@ -4393,38 +5587,40 @@ async function buildServerEnvironment(config, name) {
|
|
|
4393
5587
|
}
|
|
4394
5588
|
try {
|
|
4395
5589
|
const result = await environment.driver.build(environment.getDriverContext());
|
|
4396
|
-
|
|
5590
|
+
assertDriverBuildResult(environment, result);
|
|
5591
|
+
return { environment, result: finalizeEnvironmentResult(environment, result) };
|
|
4397
5592
|
} catch (error) {
|
|
4398
5593
|
await environment.close();
|
|
4399
5594
|
throw error;
|
|
4400
5595
|
}
|
|
4401
5596
|
}
|
|
4402
5597
|
for (const entry of envOptions.entry) {
|
|
4403
|
-
if (!
|
|
5598
|
+
if (!fs10.existsSync(entry)) {
|
|
4404
5599
|
await environment.close();
|
|
4405
5600
|
throw new Error(`[nasti] environment "${name}" entry not found: ${entry}`);
|
|
4406
5601
|
}
|
|
4407
5602
|
}
|
|
4408
5603
|
const rolldownPlugins = [
|
|
4409
5604
|
createOxcTransformPlugin(config, environment),
|
|
4410
|
-
...toRolldownPlugins(environment.plugins)
|
|
5605
|
+
...toRolldownPlugins(environment.plugins, environment)
|
|
4411
5606
|
];
|
|
4412
5607
|
const { inputOptions, outputOptions, outDir } = getRolldownOptions(
|
|
4413
5608
|
environment,
|
|
4414
5609
|
envOptions.entry,
|
|
4415
5610
|
rolldownPlugins
|
|
4416
5611
|
);
|
|
4417
|
-
|
|
4418
|
-
fs9.rmSync(outDir, { recursive: true, force: true });
|
|
4419
|
-
}
|
|
4420
|
-
fs9.mkdirSync(outDir, { recursive: true });
|
|
5612
|
+
fs10.mkdirSync(outDir, { recursive: true });
|
|
4421
5613
|
const bundle2 = await rolldown(inputOptions);
|
|
4422
5614
|
const { output } = await bundle2.write(outputOptions);
|
|
4423
5615
|
await bundle2.close();
|
|
5616
|
+
if (cssEngine) environment.setBuildMetadata({ css: getCssMetadata(cssEngine) });
|
|
4424
5617
|
logger.info(
|
|
4425
|
-
pc6.dim(` [${name}] `) + output.map((o) =>
|
|
5618
|
+
pc6.dim(` [${name}] `) + output.map((o) => path13.join(envOptions.build.outDir, o.fileName)).join(pc6.dim(", "))
|
|
4426
5619
|
);
|
|
4427
|
-
return {
|
|
5620
|
+
return {
|
|
5621
|
+
environment,
|
|
5622
|
+
result: finalizeEnvironmentResult(environment, { output })
|
|
5623
|
+
};
|
|
4428
5624
|
}
|
|
4429
5625
|
function injectCssLinks(html, cssEngine, config) {
|
|
4430
5626
|
const cssLinkTags = [];
|
|
@@ -4451,9 +5647,9 @@ function escapeRegExp(string) {
|
|
|
4451
5647
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4452
5648
|
}
|
|
4453
5649
|
function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, urlPrefix) {
|
|
4454
|
-
const rootRelative =
|
|
4455
|
-
const resolvedHtmlFile =
|
|
4456
|
-
const htmlRelative =
|
|
5650
|
+
const rootRelative = path13.relative(config.root, facadeModuleId).split(path13.sep).join("/");
|
|
5651
|
+
const resolvedHtmlFile = path13.resolve(config.root, htmlFile);
|
|
5652
|
+
const htmlRelative = path13.relative(path13.dirname(resolvedHtmlFile), facadeModuleId).split(path13.sep).join("/");
|
|
4457
5653
|
const candidates = /* @__PURE__ */ new Set([
|
|
4458
5654
|
rootRelative,
|
|
4459
5655
|
`/${rootRelative}`,
|
|
@@ -4469,7 +5665,7 @@ function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, ur
|
|
|
4469
5665
|
}
|
|
4470
5666
|
return processed;
|
|
4471
5667
|
}
|
|
4472
|
-
var
|
|
5668
|
+
var debug6, NODE_BUILTINS2;
|
|
4473
5669
|
var init_build = __esm({
|
|
4474
5670
|
"src/build/index.ts"() {
|
|
4475
5671
|
"use strict";
|
|
@@ -4483,7 +5679,8 @@ var init_build = __esm({
|
|
|
4483
5679
|
init_reporter();
|
|
4484
5680
|
init_debug();
|
|
4485
5681
|
init_plugin_api();
|
|
4486
|
-
|
|
5682
|
+
init_build_app_context();
|
|
5683
|
+
debug6 = createDebugger("nasti:build");
|
|
4487
5684
|
NODE_BUILTINS2 = /* @__PURE__ */ new Set([...builtinModules2, ...builtinModules2.map((m) => `node:${m}`)]);
|
|
4488
5685
|
}
|
|
4489
5686
|
});
|
|
@@ -4493,7 +5690,7 @@ var dev_engine_exports = {};
|
|
|
4493
5690
|
__export(dev_engine_exports, {
|
|
4494
5691
|
createBundledDevServer: () => createBundledDevServer
|
|
4495
5692
|
});
|
|
4496
|
-
import
|
|
5693
|
+
import path14 from "path";
|
|
4497
5694
|
import crypto3 from "crypto";
|
|
4498
5695
|
import { WebSocketServer as WsServer2 } from "ws";
|
|
4499
5696
|
import pc7 from "picocolors";
|
|
@@ -4511,7 +5708,7 @@ async function createBundledDevServer(opts) {
|
|
|
4511
5708
|
}
|
|
4512
5709
|
} catch (err) {
|
|
4513
5710
|
throw new Error(
|
|
4514
|
-
`[nasti] experimental.bundledDev requires rolldown's experimental dev() API (locked
|
|
5711
|
+
`[nasti] experimental.bundledDev requires rolldown's experimental dev() API (locked version is incompatible; got: ${err.message}). Remove --bundle / experimental.bundledDev to use the default unbundled dev server.`
|
|
4515
5712
|
);
|
|
4516
5713
|
}
|
|
4517
5714
|
const html = await readHtmlFile(config.root, config.environments.client?.html);
|
|
@@ -4529,7 +5726,7 @@ async function createBundledDevServer(opts) {
|
|
|
4529
5726
|
createReactRefreshRuntimePlugin(entryPoints),
|
|
4530
5727
|
createBundledOxcRefreshPlugin()
|
|
4531
5728
|
] : [],
|
|
4532
|
-
...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins)),
|
|
5729
|
+
...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins, clientEnv)),
|
|
4533
5730
|
...useReactRefresh ? [
|
|
4534
5731
|
refreshWrapperFn({
|
|
4535
5732
|
cwd: config.root,
|
|
@@ -4564,7 +5761,7 @@ async function createBundledDevServer(opts) {
|
|
|
4564
5761
|
for (const { clientId, update } of updates) {
|
|
4565
5762
|
if (update.type === "Noop") continue;
|
|
4566
5763
|
if (update.type === "FullReload") {
|
|
4567
|
-
|
|
5764
|
+
debug7?.(`full reload for ${clientId}: ${update.reason ?? ""}`);
|
|
4568
5765
|
needsLatestOutput = true;
|
|
4569
5766
|
continue;
|
|
4570
5767
|
}
|
|
@@ -4578,7 +5775,7 @@ async function createBundledDevServer(opts) {
|
|
|
4578
5775
|
}
|
|
4579
5776
|
const url = `/${patchPath}`;
|
|
4580
5777
|
logger.info(
|
|
4581
|
-
pc7.green("hmr update ") + pc7.dim(changedFiles.map((f) =>
|
|
5778
|
+
pc7.green("hmr update ") + pc7.dim(changedFiles.map((f) => path14.relative(config.root, f)).join(", ")),
|
|
4582
5779
|
{ timestamp: true }
|
|
4583
5780
|
);
|
|
4584
5781
|
sendTo(clientId, { type: "hmr:update", path: url, url });
|
|
@@ -4614,7 +5811,7 @@ async function createBundledDevServer(opts) {
|
|
|
4614
5811
|
},
|
|
4615
5812
|
{
|
|
4616
5813
|
watch: { skipWrite: true },
|
|
4617
|
-
rebuildStrategy: "
|
|
5814
|
+
rebuildStrategy: "never",
|
|
4618
5815
|
onOutput(result) {
|
|
4619
5816
|
if (result instanceof Error) {
|
|
4620
5817
|
logger.error(pc7.red(`[bundled] build error: ${result.message}`), { error: result });
|
|
@@ -4630,7 +5827,13 @@ async function createBundledDevServer(opts) {
|
|
|
4630
5827
|
memoryFiles.set(`${file.fileName}.map`, JSON.stringify(file.map));
|
|
4631
5828
|
}
|
|
4632
5829
|
}
|
|
4633
|
-
|
|
5830
|
+
debug7?.(`bundle output refreshed (${result.output.length} files)`);
|
|
5831
|
+
},
|
|
5832
|
+
onAdditionalAssets(result) {
|
|
5833
|
+
for (const file of result.output) {
|
|
5834
|
+
const content = file.type === "chunk" ? file.code : file.source;
|
|
5835
|
+
if (content != null) memoryFiles.set(file.fileName, content);
|
|
5836
|
+
}
|
|
4634
5837
|
},
|
|
4635
5838
|
async onHmrUpdates(result) {
|
|
4636
5839
|
if (result instanceof Error) {
|
|
@@ -4639,7 +5842,7 @@ async function createBundledDevServer(opts) {
|
|
|
4639
5842
|
return;
|
|
4640
5843
|
}
|
|
4641
5844
|
const { updates, changedFiles } = result;
|
|
4642
|
-
|
|
5845
|
+
debug7?.(
|
|
4643
5846
|
`onHmrUpdates(engine watcher): ${changedFiles.length} changed, ${updates.length} updates`
|
|
4644
5847
|
);
|
|
4645
5848
|
if (changedFiles.length === 0) return;
|
|
@@ -4658,24 +5861,29 @@ async function createBundledDevServer(opts) {
|
|
|
4658
5861
|
if (!clientId) return;
|
|
4659
5862
|
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
4660
5863
|
bundledClients.set(clientId, ws);
|
|
4661
|
-
|
|
4662
|
-
|
|
5864
|
+
debug7?.(`bundled client connected: ${clientId}`);
|
|
5865
|
+
void engine.registerClient(clientId).then(async () => {
|
|
5866
|
+
for (const fileName of entryFileNames.values()) {
|
|
5867
|
+
await engine.notifyPayloadDelivered(fileName);
|
|
5868
|
+
}
|
|
5869
|
+
ws.send(JSON.stringify({ type: "connected" }));
|
|
5870
|
+
}).catch((err) => {
|
|
5871
|
+
debug7?.(`registerClient failed for ${clientId}: ${err?.message ?? err}`);
|
|
5872
|
+
ws.close();
|
|
5873
|
+
});
|
|
4663
5874
|
ws.on("message", async (raw) => {
|
|
4664
5875
|
try {
|
|
4665
5876
|
const msg = JSON.parse(String(raw));
|
|
4666
|
-
if (msg.type === "hmr:
|
|
4667
|
-
await engine.registerModules(clientId, msg.modules);
|
|
4668
|
-
debug6?.(`registered ${msg.modules.length} modules for ${clientId}`);
|
|
4669
|
-
} else if (msg.type === "hmr:invalidate") {
|
|
5877
|
+
if (msg.type === "hmr:invalidate") {
|
|
4670
5878
|
scheduleFullReload();
|
|
4671
5879
|
}
|
|
4672
5880
|
} catch (err) {
|
|
4673
|
-
|
|
5881
|
+
debug7?.(`bundled ws message error: ${err.message}`);
|
|
4674
5882
|
}
|
|
4675
5883
|
});
|
|
4676
5884
|
ws.on("close", () => {
|
|
4677
5885
|
bundledClients.delete(clientId);
|
|
4678
|
-
engine.removeClient(clientId).catch((err) =>
|
|
5886
|
+
engine.removeClient(clientId).catch((err) => debug7?.(`removeClient failed for ${clientId}: ${err?.message ?? err}`));
|
|
4679
5887
|
});
|
|
4680
5888
|
});
|
|
4681
5889
|
});
|
|
@@ -4692,10 +5900,18 @@ async function createBundledDevServer(opts) {
|
|
|
4692
5900
|
res.end("// [nasti] lazy endpoint requires id & clientId");
|
|
4693
5901
|
return;
|
|
4694
5902
|
}
|
|
4695
|
-
const
|
|
5903
|
+
const output = await engine.compileEntry(id, clientId);
|
|
5904
|
+
if (output.sourcemap && output.sourcemapFilename) {
|
|
5905
|
+
memoryFiles.set(output.sourcemapFilename, output.sourcemap);
|
|
5906
|
+
}
|
|
5907
|
+
res.once("finish", () => {
|
|
5908
|
+
void engine.notifyPayloadDelivered(output.filename).catch(
|
|
5909
|
+
(err) => debug7?.(`notifyPayloadDelivered failed: ${err?.message ?? err}`)
|
|
5910
|
+
);
|
|
5911
|
+
});
|
|
4696
5912
|
res.setHeader("Content-Type", "application/javascript");
|
|
4697
5913
|
res.setHeader("Cache-Control", "no-store");
|
|
4698
|
-
res.end(code + "\n;export {}");
|
|
5914
|
+
res.end(output.code + "\n;export {}");
|
|
4699
5915
|
return;
|
|
4700
5916
|
}
|
|
4701
5917
|
const patchHit = patches.get(pathname.replace(/^\//, ""));
|
|
@@ -4714,8 +5930,13 @@ async function createBundledDevServer(opts) {
|
|
|
4714
5930
|
return;
|
|
4715
5931
|
}
|
|
4716
5932
|
res.setHeader("ETag", hit.etag);
|
|
4717
|
-
res.setHeader("Content-Type", MIME_TYPES[
|
|
5933
|
+
res.setHeader("Content-Type", MIME_TYPES[path14.extname(fileName)] ?? "application/octet-stream");
|
|
4718
5934
|
res.setHeader("Cache-Control", "no-cache");
|
|
5935
|
+
res.once("finish", () => {
|
|
5936
|
+
void engine.notifyPayloadDelivered(fileName).catch(
|
|
5937
|
+
(err) => debug7?.(`notifyPayloadDelivered failed: ${err?.message ?? err}`)
|
|
5938
|
+
);
|
|
5939
|
+
});
|
|
4719
5940
|
res.end(hit.content);
|
|
4720
5941
|
return;
|
|
4721
5942
|
}
|
|
@@ -4750,7 +5971,7 @@ function stripCatchAllLoad(plugins) {
|
|
|
4750
5971
|
);
|
|
4751
5972
|
}
|
|
4752
5973
|
function createReactRefreshRuntimePlugin(entryPoints) {
|
|
4753
|
-
const entryIds = new Set(entryPoints.map((p) =>
|
|
5974
|
+
const entryIds = new Set(entryPoints.map((p) => path14.resolve(p)));
|
|
4754
5975
|
return {
|
|
4755
5976
|
name: "nasti:bundled-react-refresh",
|
|
4756
5977
|
resolveId(source) {
|
|
@@ -4768,7 +5989,7 @@ function createReactRefreshRuntimePlugin(entryPoints) {
|
|
|
4768
5989
|
return null;
|
|
4769
5990
|
},
|
|
4770
5991
|
transform(code, id) {
|
|
4771
|
-
if (!entryIds.has(
|
|
5992
|
+
if (!entryIds.has(path14.resolve(id.split("?")[0]))) return null;
|
|
4772
5993
|
return { code: `import ${JSON.stringify(PREAMBLE_SPEC)};
|
|
4773
5994
|
${code}`, map: null };
|
|
4774
5995
|
}
|
|
@@ -4815,7 +6036,7 @@ async function renderBundledIndexHtml(html, config, entryFileNames) {
|
|
|
4815
6036
|
}
|
|
4816
6037
|
return processed;
|
|
4817
6038
|
}
|
|
4818
|
-
var
|
|
6039
|
+
var debug7, MIME_TYPES, MemoryFiles, PREAMBLE_SPEC, RESOLVED_PREAMBLE_ID, REFRESH_RUNTIME_URL, BUNDLED_PREAMBLE_CODE, WRAPPER_RUNTIME_HELPERS;
|
|
4819
6040
|
var init_dev_engine = __esm({
|
|
4820
6041
|
"src/server/bundled/dev-engine.ts"() {
|
|
4821
6042
|
"use strict";
|
|
@@ -4824,7 +6045,7 @@ var init_dev_engine = __esm({
|
|
|
4824
6045
|
init_transformer();
|
|
4825
6046
|
init_middleware();
|
|
4826
6047
|
init_debug();
|
|
4827
|
-
|
|
6048
|
+
debug7 = createDebugger("nasti:bundled");
|
|
4828
6049
|
MIME_TYPES = {
|
|
4829
6050
|
".js": "application/javascript",
|
|
4830
6051
|
".mjs": "application/javascript",
|
|
@@ -4939,7 +6160,7 @@ __export(server_exports, {
|
|
|
4939
6160
|
createServer: () => createServer
|
|
4940
6161
|
});
|
|
4941
6162
|
import http from "http";
|
|
4942
|
-
import
|
|
6163
|
+
import path15 from "path";
|
|
4943
6164
|
import os from "os";
|
|
4944
6165
|
import connect from "connect";
|
|
4945
6166
|
import sirv from "sirv";
|
|
@@ -4949,14 +6170,16 @@ async function createServer(inlineConfig = {}) {
|
|
|
4949
6170
|
const startTime = performance.now();
|
|
4950
6171
|
const config = await resolveConfig(inlineConfig, "serve");
|
|
4951
6172
|
const logger = config.logger;
|
|
4952
|
-
const allPlugins = resolvePluginList(config, config.plugins
|
|
6173
|
+
const allPlugins = resolvePluginList(config, config.plugins, {
|
|
6174
|
+
environmentName: "client"
|
|
6175
|
+
});
|
|
4953
6176
|
const configWithPlugins = { ...config, plugins: allPlugins };
|
|
4954
6177
|
const app = connect();
|
|
4955
6178
|
const httpServer = http.createServer(app);
|
|
4956
6179
|
const ws = createWebSocketServer(httpServer);
|
|
4957
6180
|
const pluginApi = getPluginApi(config);
|
|
4958
6181
|
const clientEnv = new NastiEnvironment("client", config, {
|
|
4959
|
-
hot: createWsHotChannel(ws),
|
|
6182
|
+
hot: createWsHotChannel(ws, "client"),
|
|
4960
6183
|
mode: "dev",
|
|
4961
6184
|
plugins: allPlugins,
|
|
4962
6185
|
pluginApi
|
|
@@ -4966,15 +6189,45 @@ async function createServer(inlineConfig = {}) {
|
|
|
4966
6189
|
for (const name of Object.keys(config.environments)) {
|
|
4967
6190
|
if (name === "client") continue;
|
|
4968
6191
|
const consumer = config.environments[name].consumer;
|
|
4969
|
-
const envPlugins = resolvePluginList(config, config.plugins, {
|
|
6192
|
+
const envPlugins = resolvePluginList(config, config.plugins, {
|
|
6193
|
+
consumer,
|
|
6194
|
+
environmentName: name
|
|
6195
|
+
});
|
|
4970
6196
|
environments[name] = new NastiEnvironment(name, config, {
|
|
6197
|
+
hot: consumer === "client" ? createWsHotChannel(ws, name) : void 0,
|
|
4971
6198
|
mode: "dev",
|
|
4972
6199
|
plugins: envPlugins,
|
|
4973
6200
|
pluginApi
|
|
4974
6201
|
});
|
|
4975
6202
|
}
|
|
4976
6203
|
for (const [name, environment] of Object.entries(environments)) {
|
|
4977
|
-
if (name
|
|
6204
|
+
if (name === "client" || environment.consumer === "client" || environment.options.driver) {
|
|
6205
|
+
await environment.init();
|
|
6206
|
+
}
|
|
6207
|
+
}
|
|
6208
|
+
const transformContexts = /* @__PURE__ */ new Map();
|
|
6209
|
+
for (const environment of Object.values(environments)) {
|
|
6210
|
+
if (environment.consumer !== "client" || environment.driver) continue;
|
|
6211
|
+
const environmentConfig = {
|
|
6212
|
+
...configWithPlugins,
|
|
6213
|
+
resolve: environment.options.resolve,
|
|
6214
|
+
build: environment.options.build,
|
|
6215
|
+
plugins: environment.plugins
|
|
6216
|
+
};
|
|
6217
|
+
const context = {
|
|
6218
|
+
config: environmentConfig,
|
|
6219
|
+
pluginContainer: environment.pluginContainer,
|
|
6220
|
+
moduleGraph: environment.moduleGraph,
|
|
6221
|
+
environment,
|
|
6222
|
+
envDefine: buildEnvDefine(
|
|
6223
|
+
loadEnv(environmentConfig.mode, environmentConfig.root, environmentConfig.envPrefix),
|
|
6224
|
+
environmentConfig.mode,
|
|
6225
|
+
ssrDefineOverrides(environment.consumer)
|
|
6226
|
+
),
|
|
6227
|
+
onPrune: (paths) => environment.hot.send({ type: "prune", paths })
|
|
6228
|
+
};
|
|
6229
|
+
transformContexts.set(environment.name, context);
|
|
6230
|
+
environment.configureDevPipeline((url) => transformRequest(url, context));
|
|
4978
6231
|
}
|
|
4979
6232
|
let ssrRunner = null;
|
|
4980
6233
|
async function getSsrRunner() {
|
|
@@ -4989,7 +6242,6 @@ async function createServer(inlineConfig = {}) {
|
|
|
4989
6242
|
return ssrRunner;
|
|
4990
6243
|
}
|
|
4991
6244
|
const moduleGraph = clientEnv.moduleGraph;
|
|
4992
|
-
const pluginContainer = clientEnv.pluginContainer;
|
|
4993
6245
|
let bundledServer = null;
|
|
4994
6246
|
if (config.experimental.bundledDev) {
|
|
4995
6247
|
const { createBundledDevServer: createBundledDevServer2 } = await Promise.resolve().then(() => (init_dev_engine(), dev_engine_exports));
|
|
@@ -5001,14 +6253,14 @@ async function createServer(inlineConfig = {}) {
|
|
|
5001
6253
|
app.use(bundledServer.middleware);
|
|
5002
6254
|
}
|
|
5003
6255
|
const ignoredSegments = /* @__PURE__ */ new Set(["node_modules", ".git", ".nasti"]);
|
|
5004
|
-
const outDirAbs =
|
|
6256
|
+
const outDirAbs = path15.resolve(config.root, config.build.outDir);
|
|
5005
6257
|
const watcher = watch(config.root, {
|
|
5006
6258
|
ignored: (filePath) => {
|
|
5007
6259
|
if (filePath === config.root) return false;
|
|
5008
|
-
if (filePath === outDirAbs || filePath.startsWith(outDirAbs +
|
|
5009
|
-
const rel =
|
|
5010
|
-
if (!rel || rel.startsWith("..") ||
|
|
5011
|
-
for (const seg of rel.split(
|
|
6260
|
+
if (filePath === outDirAbs || filePath.startsWith(outDirAbs + path15.sep)) return true;
|
|
6261
|
+
const rel = path15.relative(config.root, filePath);
|
|
6262
|
+
if (!rel || rel.startsWith("..") || path15.isAbsolute(rel)) return false;
|
|
6263
|
+
for (const seg of rel.split(path15.sep)) {
|
|
5012
6264
|
if (ignoredSegments.has(seg)) return true;
|
|
5013
6265
|
}
|
|
5014
6266
|
return false;
|
|
@@ -5018,6 +6270,15 @@ async function createServer(inlineConfig = {}) {
|
|
|
5018
6270
|
let server;
|
|
5019
6271
|
const environmentServices = {};
|
|
5020
6272
|
let environmentDriversStarted = false;
|
|
6273
|
+
let devPipelinesStarted = false;
|
|
6274
|
+
const startDevPipelines = async () => {
|
|
6275
|
+
if (devPipelinesStarted) return;
|
|
6276
|
+
devPipelinesStarted = true;
|
|
6277
|
+
for (const environment of Object.values(environments)) {
|
|
6278
|
+
if (!transformContexts.has(environment.name)) continue;
|
|
6279
|
+
await environment.pluginContainer.buildStart();
|
|
6280
|
+
}
|
|
6281
|
+
};
|
|
5021
6282
|
const logCloseError = (target, error) => {
|
|
5022
6283
|
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
5023
6284
|
logger.error(`[nasti] failed to close ${target}`, { error: normalized });
|
|
@@ -5069,14 +6330,61 @@ async function createServer(inlineConfig = {}) {
|
|
|
5069
6330
|
});
|
|
5070
6331
|
}
|
|
5071
6332
|
};
|
|
6333
|
+
const updateClientEnvironments = async (file) => {
|
|
6334
|
+
const timestamp = Date.now();
|
|
6335
|
+
const results = {};
|
|
6336
|
+
for (const environment of Object.values(environments)) {
|
|
6337
|
+
if (environment.consumer !== "client" || environment.driver) continue;
|
|
6338
|
+
try {
|
|
6339
|
+
const result = await handleFileChange(file, server, environment.name, timestamp);
|
|
6340
|
+
if (result) results[environment.name] = result;
|
|
6341
|
+
} catch (error) {
|
|
6342
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
6343
|
+
logger.error(
|
|
6344
|
+
`[nasti] HMR failed for environment "${environment.name}": ${normalized.message}`,
|
|
6345
|
+
{ error: normalized }
|
|
6346
|
+
);
|
|
6347
|
+
try {
|
|
6348
|
+
environment.hot.send({
|
|
6349
|
+
type: "error",
|
|
6350
|
+
err: { message: normalized.message, stack: normalized.stack }
|
|
6351
|
+
});
|
|
6352
|
+
} catch (channelError) {
|
|
6353
|
+
const channelFailure = channelError instanceof Error ? channelError : new Error(String(channelError));
|
|
6354
|
+
logger.error(
|
|
6355
|
+
`[nasti] failed to deliver HMR error to environment "${environment.name}"`,
|
|
6356
|
+
{ error: channelFailure }
|
|
6357
|
+
);
|
|
6358
|
+
}
|
|
6359
|
+
}
|
|
6360
|
+
}
|
|
6361
|
+
if (Object.keys(results).length === 0) return;
|
|
6362
|
+
const context = {
|
|
6363
|
+
file,
|
|
6364
|
+
timestamp,
|
|
6365
|
+
environments: Object.freeze({ ...results }),
|
|
6366
|
+
server
|
|
6367
|
+
};
|
|
6368
|
+
for (const plugin of config.plugins) {
|
|
6369
|
+
await plugin.handleHotUpdateApp?.(context);
|
|
6370
|
+
}
|
|
6371
|
+
};
|
|
6372
|
+
const queueClientEnvironmentUpdate = (file) => {
|
|
6373
|
+
void updateClientEnvironments(file).catch((error) => {
|
|
6374
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
6375
|
+
logger.error(`[nasti] multi-environment HMR failed: ${normalized.message}`, {
|
|
6376
|
+
error: normalized
|
|
6377
|
+
});
|
|
6378
|
+
});
|
|
6379
|
+
};
|
|
5072
6380
|
watcher.on("change", (file) => {
|
|
5073
6381
|
ssrRunner?.invalidateFile(file);
|
|
5074
|
-
|
|
6382
|
+
queueClientEnvironmentUpdate(file);
|
|
5075
6383
|
notifyEnvironmentDrivers(file, "change");
|
|
5076
6384
|
});
|
|
5077
6385
|
watcher.on("add", (file) => {
|
|
5078
6386
|
ssrRunner?.invalidateFile(file);
|
|
5079
|
-
|
|
6387
|
+
queueClientEnvironmentUpdate(file);
|
|
5080
6388
|
notifyEnvironmentDrivers(file, "add");
|
|
5081
6389
|
});
|
|
5082
6390
|
watcher.on("unlink", (file) => {
|
|
@@ -5094,7 +6402,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
5094
6402
|
async listen(port) {
|
|
5095
6403
|
const finalPort = port ?? config.server.port;
|
|
5096
6404
|
const host = config.server.host === true ? "0.0.0.0" : config.server.host;
|
|
5097
|
-
await
|
|
6405
|
+
await startDevPipelines();
|
|
5098
6406
|
await startEnvironmentDrivers();
|
|
5099
6407
|
return new Promise((resolve, reject) => {
|
|
5100
6408
|
let currentPort = finalPort;
|
|
@@ -5109,7 +6417,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
5109
6417
|
const readyIn = Math.ceil(performance.now() - startTime);
|
|
5110
6418
|
logger.info(
|
|
5111
6419
|
`
|
|
5112
|
-
${pc8.cyan(pc8.bold("NASTI"))} ${pc8.cyan(`v${"2.
|
|
6420
|
+
${pc8.cyan(pc8.bold("NASTI"))} ${pc8.cyan(`v${"2.4.1"}`)} ${pc8.dim("ready in")} ${pc8.bold(readyIn)} ${pc8.dim("ms")}
|
|
5113
6421
|
`
|
|
5114
6422
|
);
|
|
5115
6423
|
printServerUrls(
|
|
@@ -5136,15 +6444,26 @@ async function createServer(inlineConfig = {}) {
|
|
|
5136
6444
|
});
|
|
5137
6445
|
},
|
|
5138
6446
|
async transformRequest(url) {
|
|
5139
|
-
|
|
5140
|
-
|
|
6447
|
+
return clientEnv.transformRequest(url);
|
|
6448
|
+
},
|
|
6449
|
+
async transformEnvironmentRequest(environmentName, url) {
|
|
6450
|
+
const environment = environments[environmentName];
|
|
6451
|
+
if (!environment) {
|
|
6452
|
+
throw new Error(`[nasti] unknown dev environment "${environmentName}"`);
|
|
6453
|
+
}
|
|
6454
|
+
return environment.transformRequest(url);
|
|
5141
6455
|
},
|
|
5142
6456
|
async ssrLoadModule(url) {
|
|
5143
6457
|
const runner = await getSsrRunner();
|
|
5144
6458
|
return runner.import(url);
|
|
5145
6459
|
},
|
|
5146
6460
|
async close() {
|
|
5147
|
-
|
|
6461
|
+
if (devPipelinesStarted) {
|
|
6462
|
+
for (const environment of Object.values(environments).reverse()) {
|
|
6463
|
+
if (!transformContexts.has(environment.name)) continue;
|
|
6464
|
+
await environment.pluginContainer.buildEnd();
|
|
6465
|
+
}
|
|
6466
|
+
}
|
|
5148
6467
|
await bundledServer?.close();
|
|
5149
6468
|
let environmentCloseFailed = false;
|
|
5150
6469
|
let firstEnvironmentCloseError;
|
|
@@ -5194,12 +6513,8 @@ async function createServer(inlineConfig = {}) {
|
|
|
5194
6513
|
}
|
|
5195
6514
|
throw error;
|
|
5196
6515
|
}
|
|
5197
|
-
app.use(transformMiddleware(
|
|
5198
|
-
|
|
5199
|
-
pluginContainer,
|
|
5200
|
-
moduleGraph
|
|
5201
|
-
}));
|
|
5202
|
-
const publicDir = path14.resolve(config.root, "public");
|
|
6516
|
+
app.use(transformMiddleware(transformContexts.get("client")));
|
|
6517
|
+
const publicDir = path15.resolve(config.root, "public");
|
|
5203
6518
|
app.use(sirv(publicDir, { dev: true, etag: true }));
|
|
5204
6519
|
app.use(sirv(config.root, { dev: true, etag: true }));
|
|
5205
6520
|
const postMiddlewares = [];
|
|
@@ -5237,6 +6552,7 @@ var init_server = __esm({
|
|
|
5237
6552
|
init_hmr();
|
|
5238
6553
|
init_builtins();
|
|
5239
6554
|
init_plugin_api();
|
|
6555
|
+
init_env();
|
|
5240
6556
|
}
|
|
5241
6557
|
});
|
|
5242
6558
|
|
|
@@ -5287,24 +6603,24 @@ __export(electron_exports, {
|
|
|
5287
6603
|
detectInstalledElectron: () => detectInstalledElectron,
|
|
5288
6604
|
normalizePreload: () => normalizePreload
|
|
5289
6605
|
});
|
|
5290
|
-
import
|
|
5291
|
-
import
|
|
6606
|
+
import path16 from "path";
|
|
6607
|
+
import fs11 from "fs";
|
|
5292
6608
|
import { rolldown as rolldown2 } from "rolldown";
|
|
5293
6609
|
import pc9 from "picocolors";
|
|
5294
6610
|
async function buildElectron(inlineConfig = {}) {
|
|
5295
6611
|
const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
|
|
5296
6612
|
const startTime = performance.now();
|
|
5297
6613
|
assertElectronVersion(config);
|
|
5298
|
-
console.log(pc9.cyan("\n\u26A1 nasti build (electron)") + pc9.dim(` v${"2.
|
|
6614
|
+
console.log(pc9.cyan("\n\u26A1 nasti build (electron)") + pc9.dim(` v${"2.4.1"}`));
|
|
5299
6615
|
console.log(pc9.dim(` root: ${config.root}`));
|
|
5300
6616
|
console.log(pc9.dim(` mode: ${config.mode}`));
|
|
5301
6617
|
console.log(pc9.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
|
|
5302
|
-
const outDir =
|
|
5303
|
-
if (config.build.emptyOutDir &&
|
|
5304
|
-
|
|
6618
|
+
const outDir = path16.resolve(config.root, config.build.outDir);
|
|
6619
|
+
if (config.build.emptyOutDir && fs11.existsSync(outDir)) {
|
|
6620
|
+
fs11.rmSync(outDir, { recursive: true, force: true });
|
|
5305
6621
|
}
|
|
5306
|
-
|
|
5307
|
-
const rendererOutDir =
|
|
6622
|
+
fs11.mkdirSync(outDir, { recursive: true });
|
|
6623
|
+
const rendererOutDir = path16.join(outDir, "renderer");
|
|
5308
6624
|
const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
|
|
5309
6625
|
await build2(createElectronRendererConfig(config, inlineConfig, {
|
|
5310
6626
|
build: {
|
|
@@ -5313,8 +6629,8 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5313
6629
|
emptyOutDir: false
|
|
5314
6630
|
}
|
|
5315
6631
|
}));
|
|
5316
|
-
const mainEntry =
|
|
5317
|
-
if (!
|
|
6632
|
+
const mainEntry = path16.resolve(config.root, config.electron.main);
|
|
6633
|
+
if (!fs11.existsSync(mainEntry)) {
|
|
5318
6634
|
throw new Error(
|
|
5319
6635
|
`Electron main entry not found: ${config.electron.main}
|
|
5320
6636
|
\u5728 nasti.config.ts \u7684 electron.main \u6307\u5B9A\u4E3B\u8FDB\u7A0B\u5165\u53E3\u6587\u4EF6\u3002`
|
|
@@ -5328,11 +6644,11 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5328
6644
|
const preloadEntries = normalizePreload(config.electron.preload, config.root);
|
|
5329
6645
|
const preloadFiles = [];
|
|
5330
6646
|
for (const entry of preloadEntries) {
|
|
5331
|
-
if (!
|
|
6647
|
+
if (!fs11.existsSync(entry)) {
|
|
5332
6648
|
console.warn(pc9.yellow(` \u26A0 preload entry not found, skipped: ${entry}`));
|
|
5333
6649
|
continue;
|
|
5334
6650
|
}
|
|
5335
|
-
const base =
|
|
6651
|
+
const base = path16.basename(entry).replace(/\.[^.]+$/, "");
|
|
5336
6652
|
const out = outFileName(outDir, base, config.electron.preloadFormat);
|
|
5337
6653
|
await bundleNode(config, entry, {
|
|
5338
6654
|
outFile: out,
|
|
@@ -5344,10 +6660,10 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
5344
6660
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
5345
6661
|
console.log(pc9.green(`
|
|
5346
6662
|
\u2713 Electron build complete in ${elapsed}s`));
|
|
5347
|
-
console.log(pc9.dim(` renderer: ${
|
|
5348
|
-
console.log(pc9.dim(` main: ${
|
|
6663
|
+
console.log(pc9.dim(` renderer: ${path16.relative(config.root, rendererOutDir)}/`));
|
|
6664
|
+
console.log(pc9.dim(` main: ${path16.relative(config.root, mainFile)}`));
|
|
5349
6665
|
for (const pf of preloadFiles) {
|
|
5350
|
-
console.log(pc9.dim(` preload: ${
|
|
6666
|
+
console.log(pc9.dim(` preload: ${path16.relative(config.root, pf)}`));
|
|
5351
6667
|
}
|
|
5352
6668
|
console.log();
|
|
5353
6669
|
return { rendererOutDir, mainFile, preloadFiles };
|
|
@@ -5385,7 +6701,7 @@ async function bundleNode(config, entry, opts) {
|
|
|
5385
6701
|
},
|
|
5386
6702
|
plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
|
|
5387
6703
|
});
|
|
5388
|
-
|
|
6704
|
+
fs11.mkdirSync(path16.dirname(opts.outFile), { recursive: true });
|
|
5389
6705
|
await bundle2.write({
|
|
5390
6706
|
sourcemap: !!config.build.sourcemap,
|
|
5391
6707
|
minify: !!config.build.minify,
|
|
@@ -5396,7 +6712,7 @@ async function bundleNode(config, entry, opts) {
|
|
|
5396
6712
|
codeSplitting: false
|
|
5397
6713
|
});
|
|
5398
6714
|
await bundle2.close();
|
|
5399
|
-
console.log(pc9.dim(` \u2713 ${opts.label} \u2192 ${
|
|
6715
|
+
console.log(pc9.dim(` \u2713 ${opts.label} \u2192 ${path16.relative(config.root, opts.outFile)}`));
|
|
5400
6716
|
return opts.outFile;
|
|
5401
6717
|
}
|
|
5402
6718
|
function createElectronRendererConfig(config, inlineConfig = {}, overrides = {}) {
|
|
@@ -5420,11 +6736,11 @@ function createElectronRendererConfig(config, inlineConfig = {}, overrides = {})
|
|
|
5420
6736
|
}
|
|
5421
6737
|
function outFileName(outDir, base, format) {
|
|
5422
6738
|
const ext = format === "cjs" ? ".cjs" : ".mjs";
|
|
5423
|
-
return
|
|
6739
|
+
return path16.join(outDir, base + ext);
|
|
5424
6740
|
}
|
|
5425
6741
|
function normalizePreload(preload, root) {
|
|
5426
6742
|
const list = Array.isArray(preload) ? preload : preload ? [preload] : [];
|
|
5427
|
-
return list.map((p) =>
|
|
6743
|
+
return list.map((p) => path16.resolve(root, p));
|
|
5428
6744
|
}
|
|
5429
6745
|
function assertElectronVersion(config) {
|
|
5430
6746
|
const min = config.electron.minVersion;
|
|
@@ -5439,9 +6755,9 @@ function assertElectronVersion(config) {
|
|
|
5439
6755
|
}
|
|
5440
6756
|
function detectInstalledElectron(root) {
|
|
5441
6757
|
try {
|
|
5442
|
-
const pkgPath =
|
|
5443
|
-
if (!
|
|
5444
|
-
const pkg = JSON.parse(
|
|
6758
|
+
const pkgPath = path16.resolve(root, "node_modules/electron/package.json");
|
|
6759
|
+
if (!fs11.existsSync(pkgPath)) return null;
|
|
6760
|
+
const pkg = JSON.parse(fs11.readFileSync(pkgPath, "utf-8"));
|
|
5445
6761
|
const major = parseInt(String(pkg.version).split(".")[0], 10);
|
|
5446
6762
|
return Number.isFinite(major) ? major : null;
|
|
5447
6763
|
} catch {
|
|
@@ -5465,8 +6781,8 @@ __export(electron_dev_exports, {
|
|
|
5465
6781
|
electronRendererDevPath: () => electronRendererDevPath,
|
|
5466
6782
|
startElectronDev: () => startElectronDev
|
|
5467
6783
|
});
|
|
5468
|
-
import
|
|
5469
|
-
import
|
|
6784
|
+
import path17 from "path";
|
|
6785
|
+
import fs12 from "fs";
|
|
5470
6786
|
import { createRequire as createRequire5 } from "module";
|
|
5471
6787
|
import { spawn } from "child_process";
|
|
5472
6788
|
import chokidar from "chokidar";
|
|
@@ -5476,7 +6792,7 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5476
6792
|
const { noSpawn, ...rest } = inlineConfig;
|
|
5477
6793
|
const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
|
|
5478
6794
|
warnElectronVersion(config);
|
|
5479
|
-
console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.
|
|
6795
|
+
console.log(pc10.cyan("\n\u26A1 nasti electron dev") + pc10.dim(` v${"2.4.1"}`));
|
|
5480
6796
|
const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
5481
6797
|
const server = await createServer2({
|
|
5482
6798
|
...rest,
|
|
@@ -5486,11 +6802,11 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5486
6802
|
await server.listen();
|
|
5487
6803
|
const devUrl = `http://localhost:${server.config.server.port}` + electronRendererDevPath(config.electron.renderer);
|
|
5488
6804
|
console.log(pc10.dim(` renderer: ${devUrl}`));
|
|
5489
|
-
const stageDir =
|
|
5490
|
-
|
|
5491
|
-
const mainEntry =
|
|
6805
|
+
const stageDir = path17.resolve(config.root, ".nasti");
|
|
6806
|
+
fs12.mkdirSync(stageDir, { recursive: true });
|
|
6807
|
+
const mainEntry = path17.resolve(config.root, config.electron.main);
|
|
5492
6808
|
const preloadEntries = normalizePreload(config.electron.preload, config.root);
|
|
5493
|
-
const builtMainFile =
|
|
6809
|
+
const builtMainFile = path17.join(stageDir, "main" + extFor(config.electron.mainFormat));
|
|
5494
6810
|
const builtPreloadFiles = [];
|
|
5495
6811
|
const compileAll = async () => {
|
|
5496
6812
|
await compileNode(config, mainEntry, {
|
|
@@ -5500,9 +6816,9 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5500
6816
|
});
|
|
5501
6817
|
builtPreloadFiles.length = 0;
|
|
5502
6818
|
for (const entry of preloadEntries) {
|
|
5503
|
-
if (!
|
|
5504
|
-
const base =
|
|
5505
|
-
const out =
|
|
6819
|
+
if (!fs12.existsSync(entry)) continue;
|
|
6820
|
+
const base = path17.basename(entry).replace(/\.[^.]+$/, "");
|
|
6821
|
+
const out = path17.join(stageDir, base + extFor(config.electron.preloadFormat));
|
|
5506
6822
|
await compileNode(config, entry, {
|
|
5507
6823
|
outFile: out,
|
|
5508
6824
|
format: config.electron.preloadFormat,
|
|
@@ -5541,7 +6857,7 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5541
6857
|
};
|
|
5542
6858
|
spawnElectron();
|
|
5543
6859
|
if (config.electron.autoRestart) {
|
|
5544
|
-
const watchTargets = [mainEntry, ...preloadEntries].filter(
|
|
6860
|
+
const watchTargets = [mainEntry, ...preloadEntries].filter(fs12.existsSync);
|
|
5545
6861
|
const watcher = chokidar.watch(watchTargets, { ignoreInitial: true });
|
|
5546
6862
|
let restarting = null;
|
|
5547
6863
|
let pending = false;
|
|
@@ -5621,7 +6937,7 @@ async function compileNode(config, entry, opts) {
|
|
|
5621
6937
|
platform: "node",
|
|
5622
6938
|
plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
|
|
5623
6939
|
});
|
|
5624
|
-
|
|
6940
|
+
fs12.mkdirSync(path17.dirname(opts.outFile), { recursive: true });
|
|
5625
6941
|
await bundle2.write({
|
|
5626
6942
|
file: opts.outFile,
|
|
5627
6943
|
format: opts.format === "cjs" ? "cjs" : "esm",
|
|
@@ -5634,18 +6950,18 @@ async function compileNode(config, entry, opts) {
|
|
|
5634
6950
|
await bundle2.close();
|
|
5635
6951
|
}
|
|
5636
6952
|
function electronRendererDevPath(renderer) {
|
|
5637
|
-
const normalized = renderer.split(
|
|
6953
|
+
const normalized = renderer.split(path17.sep).join("/").replace(/^\.?\//, "");
|
|
5638
6954
|
return normalized === "index.html" ? "/" : `/${normalized}`;
|
|
5639
6955
|
}
|
|
5640
6956
|
function resolveElectronBinary(config) {
|
|
5641
|
-
if (config.electron.electronPath &&
|
|
6957
|
+
if (config.electron.electronPath && fs12.existsSync(config.electron.electronPath)) {
|
|
5642
6958
|
return config.electron.electronPath;
|
|
5643
6959
|
}
|
|
5644
6960
|
try {
|
|
5645
|
-
const require2 = createRequire5(
|
|
6961
|
+
const require2 = createRequire5(path17.resolve(config.root, "package.json"));
|
|
5646
6962
|
const pathFile = require2.resolve("electron");
|
|
5647
6963
|
const electronModule = require2(pathFile);
|
|
5648
|
-
if (typeof electronModule === "string" &&
|
|
6964
|
+
if (typeof electronModule === "string" && fs12.existsSync(electronModule)) {
|
|
5649
6965
|
return electronModule;
|
|
5650
6966
|
}
|
|
5651
6967
|
} catch {
|
|
@@ -5820,20 +7136,20 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
|
|
|
5820
7136
|
const logger = createCliLogger(options);
|
|
5821
7137
|
try {
|
|
5822
7138
|
const http2 = await import("http");
|
|
5823
|
-
const
|
|
7139
|
+
const path18 = await import("path");
|
|
5824
7140
|
const os2 = await import("os");
|
|
5825
7141
|
const sirv2 = (await import("sirv")).default;
|
|
5826
7142
|
const connect2 = (await import("connect")).default;
|
|
5827
7143
|
const { printServerUrls: printServerUrls2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
|
|
5828
|
-
const resolvedRoot =
|
|
5829
|
-
const outDir =
|
|
7144
|
+
const resolvedRoot = path18.resolve(root ?? ".");
|
|
7145
|
+
const outDir = path18.resolve(resolvedRoot, options.outDir);
|
|
5830
7146
|
const app = connect2();
|
|
5831
7147
|
app.use(sirv2(outDir, { single: true, etag: true, gzip: true, brotli: true }));
|
|
5832
7148
|
const port = options.port;
|
|
5833
7149
|
const host = options.host === true ? "0.0.0.0" : options.host ?? "localhost";
|
|
5834
7150
|
http2.createServer(app).listen(port, host, () => {
|
|
5835
7151
|
logger.info(`
|
|
5836
|
-
${pc11.cyan(pc11.bold("NASTI"))} ${pc11.cyan(`v${"2.
|
|
7152
|
+
${pc11.cyan(pc11.bold("NASTI"))} ${pc11.cyan(`v${"2.4.1"}`)} ${pc11.dim("preview")}
|
|
5837
7153
|
`);
|
|
5838
7154
|
printServerUrls2(
|
|
5839
7155
|
{
|
|
@@ -5850,6 +7166,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
|
|
|
5850
7166
|
}
|
|
5851
7167
|
});
|
|
5852
7168
|
cli.help();
|
|
5853
|
-
cli.version("2.
|
|
7169
|
+
cli.version("2.4.1");
|
|
5854
7170
|
cli.parse();
|
|
5855
7171
|
//# sourceMappingURL=cli.js.map
|