@nasti-toolchain/nasti 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -1
- package/bin/nasti.js +0 -0
- package/client/hmr.ts +4 -3
- package/dist/cli.cjs +1480 -363
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1474 -358
- 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 +1581 -460
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +167 -13
- package/dist/index.d.ts +167 -13
- package/dist/index.js +1572 -455
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/cli.cjs
CHANGED
|
@@ -5,10 +5,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __glob = (map) => (
|
|
9
|
-
var fn = map[
|
|
8
|
+
var __glob = (map) => (path18) => {
|
|
9
|
+
var fn = map[path18];
|
|
10
10
|
if (fn) return fn();
|
|
11
|
-
throw new Error("Module not found in bundle: " +
|
|
11
|
+
throw new Error("Module not found in bundle: " + path18);
|
|
12
12
|
};
|
|
13
13
|
var __esm = (fn, res) => function __init() {
|
|
14
14
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -226,6 +226,92 @@ var init_defaults = __esm({
|
|
|
226
226
|
}
|
|
227
227
|
});
|
|
228
228
|
|
|
229
|
+
// src/core/plugin-api.ts
|
|
230
|
+
function orderPlugins(plugins) {
|
|
231
|
+
const baseline = plugins.map((plugin, index2) => ({ plugin, index: index2 })).sort((a, b) => enforceRank(a.plugin) - enforceRank(b.plugin) || a.index - b.index).map(({ plugin }) => plugin);
|
|
232
|
+
const indexesByName = /* @__PURE__ */ new Map();
|
|
233
|
+
baseline.forEach((plugin, index2) => {
|
|
234
|
+
const indexes = indexesByName.get(plugin.name) ?? [];
|
|
235
|
+
indexes.push(index2);
|
|
236
|
+
indexesByName.set(plugin.name, indexes);
|
|
237
|
+
});
|
|
238
|
+
const edges = baseline.map(() => /* @__PURE__ */ new Set());
|
|
239
|
+
const indegree = baseline.map(() => 0);
|
|
240
|
+
const addEdge = (from, to) => {
|
|
241
|
+
if (from === to || edges[from].has(to)) return;
|
|
242
|
+
edges[from].add(to);
|
|
243
|
+
indegree[to]++;
|
|
244
|
+
};
|
|
245
|
+
baseline.forEach((plugin, current) => {
|
|
246
|
+
for (const dependency of plugin.pre ?? []) {
|
|
247
|
+
for (const before of indexesByName.get(dependency) ?? []) addEdge(before, current);
|
|
248
|
+
}
|
|
249
|
+
for (const dependency of plugin.post ?? []) {
|
|
250
|
+
for (const after of indexesByName.get(dependency) ?? []) addEdge(current, after);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
const ready = indegree.map((degree, index2) => ({ degree, index: index2 })).filter(({ degree }) => degree === 0).map(({ index: index2 }) => index2);
|
|
254
|
+
const ordered = [];
|
|
255
|
+
while (ready.length > 0) {
|
|
256
|
+
ready.sort((a, b) => a - b);
|
|
257
|
+
const current = ready.shift();
|
|
258
|
+
ordered.push(baseline[current]);
|
|
259
|
+
for (const next of edges[current]) {
|
|
260
|
+
indegree[next]--;
|
|
261
|
+
if (indegree[next] === 0) ready.push(next);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (ordered.length !== baseline.length) {
|
|
265
|
+
const cyclic = baseline.filter((_, index2) => indegree[index2] > 0).map((plugin) => plugin.name);
|
|
266
|
+
throw new Error(
|
|
267
|
+
`[nasti] circular plugin setup dependency: ${[...new Set(cyclic)].join(", ")}`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
return ordered;
|
|
271
|
+
}
|
|
272
|
+
async function setupPluginApi(config, plugins) {
|
|
273
|
+
const exposed = /* @__PURE__ */ new Map();
|
|
274
|
+
const api = {
|
|
275
|
+
config,
|
|
276
|
+
logger: config.logger,
|
|
277
|
+
expose(key, value) {
|
|
278
|
+
if (exposed.has(key) && exposed.get(key) !== value) {
|
|
279
|
+
throw new Error(`[nasti] plugin API key already exposed: ${String(key)}`);
|
|
280
|
+
}
|
|
281
|
+
exposed.set(key, value);
|
|
282
|
+
},
|
|
283
|
+
useExposed(key) {
|
|
284
|
+
return exposed.get(key);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
apiByConfig.set(config, api);
|
|
288
|
+
for (const plugin of plugins) {
|
|
289
|
+
await plugin.setup?.(api);
|
|
290
|
+
}
|
|
291
|
+
return api;
|
|
292
|
+
}
|
|
293
|
+
function getPluginApi(config) {
|
|
294
|
+
const api = apiByConfig.get(config);
|
|
295
|
+
if (!api) {
|
|
296
|
+
throw new Error(
|
|
297
|
+
"[nasti] internal: plugin API requested before setup; getPluginApi requires the original ResolvedConfig reference registered by setupPluginApi, not a shallow copy"
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
return api;
|
|
301
|
+
}
|
|
302
|
+
function enforceRank(plugin) {
|
|
303
|
+
if (plugin.enforce === "pre") return 0;
|
|
304
|
+
if (plugin.enforce === "post") return 2;
|
|
305
|
+
return 1;
|
|
306
|
+
}
|
|
307
|
+
var apiByConfig;
|
|
308
|
+
var init_plugin_api = __esm({
|
|
309
|
+
"src/core/plugin-api.ts"() {
|
|
310
|
+
"use strict";
|
|
311
|
+
apiByConfig = /* @__PURE__ */ new WeakMap();
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
229
315
|
// src/config/index.ts
|
|
230
316
|
function loadTsconfigPaths(root) {
|
|
231
317
|
const tsconfigPath = import_node_path.default.resolve(root, "tsconfig.json");
|
|
@@ -260,6 +346,43 @@ async function loadConfigFromFile(root) {
|
|
|
260
346
|
}
|
|
261
347
|
return {};
|
|
262
348
|
}
|
|
349
|
+
function detectFramework(root) {
|
|
350
|
+
const sourceRoot = import_node_path.default.resolve(root, "src");
|
|
351
|
+
if (containsVueFile(sourceRoot)) return "vue";
|
|
352
|
+
const packagePath = import_node_path.default.resolve(root, "package.json");
|
|
353
|
+
if (import_node_fs.default.existsSync(packagePath)) {
|
|
354
|
+
try {
|
|
355
|
+
const pkg = JSON.parse(import_node_fs.default.readFileSync(packagePath, "utf-8"));
|
|
356
|
+
const dependencies = {
|
|
357
|
+
...pkg.dependencies ?? {},
|
|
358
|
+
...pkg.devDependencies ?? {},
|
|
359
|
+
...pkg.peerDependencies ?? {},
|
|
360
|
+
...pkg.optionalDependencies ?? {}
|
|
361
|
+
};
|
|
362
|
+
const hasVue = "vue" in dependencies || "@vue/runtime-dom" in dependencies;
|
|
363
|
+
const hasReact = "react" in dependencies || "react-dom" in dependencies;
|
|
364
|
+
if (hasVue && !hasReact) return "vue";
|
|
365
|
+
if (hasReact) return "react";
|
|
366
|
+
if (hasVue) return "vue";
|
|
367
|
+
} catch {
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return "react";
|
|
371
|
+
}
|
|
372
|
+
function containsVueFile(dir, depth = 0) {
|
|
373
|
+
if (depth > 5 || !import_node_fs.default.existsSync(dir)) return false;
|
|
374
|
+
try {
|
|
375
|
+
for (const entry of import_node_fs.default.readdirSync(dir, { withFileTypes: true })) {
|
|
376
|
+
if (entry.isFile() && entry.name.endsWith(".vue")) return true;
|
|
377
|
+
if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== "dist" && containsVueFile(import_node_path.default.join(dir, entry.name), depth + 1)) {
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
} catch {
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
263
386
|
async function loadTsConfig(filePath) {
|
|
264
387
|
const { transformSync: transformSync2 } = await import("oxc-transform");
|
|
265
388
|
const code = import_node_fs.default.readFileSync(filePath, "utf-8");
|
|
@@ -306,7 +429,7 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
306
429
|
base: merged.base ?? defaults.base,
|
|
307
430
|
mode,
|
|
308
431
|
target: merged.target ?? defaults.target,
|
|
309
|
-
framework: merged.framework ?? defaults.framework,
|
|
432
|
+
framework: (merged.framework ?? defaults.framework) === "auto" ? detectFramework(root) : merged.framework,
|
|
310
433
|
command,
|
|
311
434
|
resolve: {
|
|
312
435
|
// tsconfig paths 优先级最低:tsconfig < defaults < user config
|
|
@@ -353,7 +476,13 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
353
476
|
if (envOptions.build) Object.assign(resolved.build, envOptions.build);
|
|
354
477
|
resolved.environments.client = {
|
|
355
478
|
consumer,
|
|
356
|
-
|
|
479
|
+
buildEnabled: envOptions.buildEnabled ?? true,
|
|
480
|
+
entry: normalizeEnvironmentEntries(envOptions.entry, root),
|
|
481
|
+
html: import_node_path.default.resolve(
|
|
482
|
+
root,
|
|
483
|
+
envOptions.html ?? (resolved.target === "electron" ? resolved.electron.renderer : "index.html")
|
|
484
|
+
),
|
|
485
|
+
driver: envOptions.driver,
|
|
357
486
|
// 同引用 —— 精确镜像(assertClientEnvironmentMirror 校验)
|
|
358
487
|
resolve: resolved.resolve,
|
|
359
488
|
build: resolved.build
|
|
@@ -362,7 +491,10 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
362
491
|
}
|
|
363
492
|
resolved.environments[name] = {
|
|
364
493
|
consumer,
|
|
365
|
-
|
|
494
|
+
buildEnabled: envOptions.buildEnabled ?? true,
|
|
495
|
+
entry: normalizeEnvironmentEntries(envOptions.entry, root),
|
|
496
|
+
html: envOptions.consumer === "client" && envOptions.html ? import_node_path.default.resolve(root, envOptions.html) : void 0,
|
|
497
|
+
driver: envOptions.driver,
|
|
366
498
|
resolve: {
|
|
367
499
|
alias: { ...resolved.resolve.alias, ...envOptions.resolve?.alias },
|
|
368
500
|
extensions: envOptions.resolve?.extensions ?? [...resolved.resolve.extensions],
|
|
@@ -381,12 +513,13 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
381
513
|
};
|
|
382
514
|
}
|
|
383
515
|
assertClientEnvironmentMirror(resolved);
|
|
384
|
-
const filteredPlugins = rawPlugins.filter((p) => {
|
|
516
|
+
const filteredPlugins = orderPlugins(rawPlugins.filter((p) => {
|
|
385
517
|
if (!p.apply) return true;
|
|
386
518
|
if (typeof p.apply === "function") return p.apply(resolved, env);
|
|
387
519
|
return p.apply === command;
|
|
388
|
-
});
|
|
520
|
+
}));
|
|
389
521
|
resolved.plugins = filteredPlugins;
|
|
522
|
+
await setupPluginApi(resolved, filteredPlugins);
|
|
390
523
|
if (resolved.target === "electron") {
|
|
391
524
|
const autoExternal = detectNativeDeps(root);
|
|
392
525
|
if (autoExternal.length > 0) {
|
|
@@ -402,6 +535,10 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
402
535
|
}
|
|
403
536
|
return resolved;
|
|
404
537
|
}
|
|
538
|
+
function normalizeEnvironmentEntries(entry, root) {
|
|
539
|
+
const entries = Array.isArray(entry) ? entry : entry ? [entry] : [];
|
|
540
|
+
return entries.map((item) => import_node_path.default.resolve(root, item));
|
|
541
|
+
}
|
|
405
542
|
function detectNativeDeps(root) {
|
|
406
543
|
const result = /* @__PURE__ */ new Set();
|
|
407
544
|
const pkgJsonPath = import_node_path.default.resolve(root, "package.json");
|
|
@@ -522,6 +659,7 @@ var init_config = __esm({
|
|
|
522
659
|
import_node_fs = __toESM(require("fs"), 1);
|
|
523
660
|
init_defaults();
|
|
524
661
|
init_logger();
|
|
662
|
+
init_plugin_api();
|
|
525
663
|
CONFIG_FILES = [
|
|
526
664
|
"nasti.config.ts",
|
|
527
665
|
"nasti.config.js",
|
|
@@ -532,21 +670,11 @@ var init_config = __esm({
|
|
|
532
670
|
});
|
|
533
671
|
|
|
534
672
|
// src/core/plugin-container.ts
|
|
535
|
-
function sortPlugins(plugins) {
|
|
536
|
-
const pre = [];
|
|
537
|
-
const normal = [];
|
|
538
|
-
const post = [];
|
|
539
|
-
for (const plugin of plugins) {
|
|
540
|
-
if (plugin.enforce === "pre") pre.push(plugin);
|
|
541
|
-
else if (plugin.enforce === "post") post.push(plugin);
|
|
542
|
-
else normal.push(plugin);
|
|
543
|
-
}
|
|
544
|
-
return [...pre, ...normal, ...post];
|
|
545
|
-
}
|
|
546
673
|
var PluginContainer;
|
|
547
674
|
var init_plugin_container = __esm({
|
|
548
675
|
"src/core/plugin-container.ts"() {
|
|
549
676
|
"use strict";
|
|
677
|
+
init_plugin_api();
|
|
550
678
|
PluginContainer = class {
|
|
551
679
|
plugins;
|
|
552
680
|
config;
|
|
@@ -557,7 +685,7 @@ var init_plugin_container = __esm({
|
|
|
557
685
|
constructor(config, environment) {
|
|
558
686
|
this.config = config;
|
|
559
687
|
this.environment = environment;
|
|
560
|
-
this.plugins =
|
|
688
|
+
this.plugins = orderPlugins(config.plugins);
|
|
561
689
|
this.ctx = this.createContext();
|
|
562
690
|
}
|
|
563
691
|
createContext() {
|
|
@@ -656,17 +784,35 @@ var init_plugin_container = __esm({
|
|
|
656
784
|
}
|
|
657
785
|
});
|
|
658
786
|
|
|
787
|
+
// src/core/url.ts
|
|
788
|
+
function removeTimestampQuery(url) {
|
|
789
|
+
const hashIndex = url.indexOf("#");
|
|
790
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
|
|
791
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
792
|
+
const queryIndex = withoutHash.indexOf("?");
|
|
793
|
+
if (queryIndex < 0) return url;
|
|
794
|
+
const pathname = withoutHash.slice(0, queryIndex);
|
|
795
|
+
const query = withoutHash.slice(queryIndex + 1).split("&").filter((part) => !/^t=\d+$/.test(part)).join("&");
|
|
796
|
+
return pathname + (query ? `?${query}` : "") + hash;
|
|
797
|
+
}
|
|
798
|
+
var init_url = __esm({
|
|
799
|
+
"src/core/url.ts"() {
|
|
800
|
+
"use strict";
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
|
|
659
804
|
// src/core/module-graph.ts
|
|
660
805
|
var ModuleGraph;
|
|
661
806
|
var init_module_graph = __esm({
|
|
662
807
|
"src/core/module-graph.ts"() {
|
|
663
808
|
"use strict";
|
|
809
|
+
init_url();
|
|
664
810
|
ModuleGraph = class {
|
|
665
811
|
urlToModuleMap = /* @__PURE__ */ new Map();
|
|
666
812
|
idToModuleMap = /* @__PURE__ */ new Map();
|
|
667
813
|
fileToModulesMap = /* @__PURE__ */ new Map();
|
|
668
814
|
getModuleByUrl(url) {
|
|
669
|
-
return this.urlToModuleMap.get(url);
|
|
815
|
+
return this.urlToModuleMap.get(removeTimestampQuery(url));
|
|
670
816
|
}
|
|
671
817
|
getModuleById(id) {
|
|
672
818
|
return this.idToModuleMap.get(id);
|
|
@@ -675,10 +821,11 @@ var init_module_graph = __esm({
|
|
|
675
821
|
return this.fileToModulesMap.get(file);
|
|
676
822
|
}
|
|
677
823
|
async ensureEntryFromUrl(url) {
|
|
678
|
-
|
|
824
|
+
const normalizedUrl = removeTimestampQuery(url);
|
|
825
|
+
let mod = this.urlToModuleMap.get(normalizedUrl);
|
|
679
826
|
if (mod) return mod;
|
|
680
|
-
mod = this.createModule(
|
|
681
|
-
this.urlToModuleMap.set(
|
|
827
|
+
mod = this.createModule(normalizedUrl);
|
|
828
|
+
this.urlToModuleMap.set(normalizedUrl, mod);
|
|
682
829
|
return mod;
|
|
683
830
|
}
|
|
684
831
|
createModule(url, id) {
|
|
@@ -692,6 +839,7 @@ var init_module_graph = __esm({
|
|
|
692
839
|
acceptedHmrDeps: /* @__PURE__ */ new Set(),
|
|
693
840
|
transformResult: null,
|
|
694
841
|
lastHMRTimestamp: 0,
|
|
842
|
+
invalidationVersion: 0,
|
|
695
843
|
isSelfAccepting: false
|
|
696
844
|
};
|
|
697
845
|
this.idToModuleMap.set(mod.id, mod);
|
|
@@ -734,10 +882,64 @@ var init_module_graph = __esm({
|
|
|
734
882
|
}
|
|
735
883
|
}
|
|
736
884
|
}
|
|
885
|
+
/**
|
|
886
|
+
* 用一次转换得到的信息原子更新 import 与 HMR accept 关系。
|
|
887
|
+
* 依赖节点会在真正被浏览器请求前预先创建,这样入口模块先转换时也能建立完整图。
|
|
888
|
+
*/
|
|
889
|
+
async updateModuleInfo(mod, importedUrls, acceptedUrls, isSelfAccepting, expectedInvalidationVersion) {
|
|
890
|
+
const importedModules = await Promise.all(
|
|
891
|
+
[...importedUrls].map((url) => this.ensureEntryFromUrl(url))
|
|
892
|
+
);
|
|
893
|
+
const acceptedModules = await Promise.all(
|
|
894
|
+
[...acceptedUrls].map((url) => this.ensureEntryFromUrl(url))
|
|
895
|
+
);
|
|
896
|
+
if (expectedInvalidationVersion !== void 0 && mod.invalidationVersion !== expectedInvalidationVersion) {
|
|
897
|
+
return null;
|
|
898
|
+
}
|
|
899
|
+
const previousImports = new Set(mod.importedModules);
|
|
900
|
+
for (const imported of previousImports) {
|
|
901
|
+
imported.importers.delete(mod);
|
|
902
|
+
}
|
|
903
|
+
mod.importedModules.clear();
|
|
904
|
+
mod.acceptedHmrDeps.clear();
|
|
905
|
+
for (const imported of importedModules) {
|
|
906
|
+
mod.importedModules.add(imported);
|
|
907
|
+
imported.importers.add(mod);
|
|
908
|
+
}
|
|
909
|
+
for (const accepted of acceptedModules) {
|
|
910
|
+
mod.acceptedHmrDeps.add(accepted);
|
|
911
|
+
}
|
|
912
|
+
mod.isSelfAccepting = isSelfAccepting;
|
|
913
|
+
const pruned = /* @__PURE__ */ new Set();
|
|
914
|
+
for (const imported of previousImports) {
|
|
915
|
+
if (!mod.importedModules.has(imported) && imported.importers.size === 0) {
|
|
916
|
+
pruned.add(imported);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
return pruned;
|
|
920
|
+
}
|
|
737
921
|
/** 使模块的转换缓存失效 */
|
|
738
|
-
invalidateModule(mod) {
|
|
922
|
+
invalidateModule(mod, timestamp = Date.now()) {
|
|
739
923
|
mod.transformResult = null;
|
|
740
|
-
mod.lastHMRTimestamp =
|
|
924
|
+
mod.lastHMRTimestamp = timestamp;
|
|
925
|
+
mod.invalidationVersion++;
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* 仅失效到 HMR 边界:显式接受依赖的模块本身不会重执行;自接受模块需要失效,
|
|
929
|
+
* 但不再继续影响其 importer。这样既能传播依赖时间戳,也不会隐式重复副作用。
|
|
930
|
+
*/
|
|
931
|
+
invalidateModuleAndImporters(mod, timestamp = Date.now(), seen = /* @__PURE__ */ new Set()) {
|
|
932
|
+
if (seen.has(mod)) return;
|
|
933
|
+
seen.add(mod);
|
|
934
|
+
this.invalidateModule(mod, timestamp);
|
|
935
|
+
for (const importer of mod.importers) {
|
|
936
|
+
if (importer.acceptedHmrDeps.has(mod)) continue;
|
|
937
|
+
if (importer.isSelfAccepting) {
|
|
938
|
+
this.invalidateModule(importer, timestamp);
|
|
939
|
+
continue;
|
|
940
|
+
}
|
|
941
|
+
this.invalidateModuleAndImporters(importer, timestamp, seen);
|
|
942
|
+
}
|
|
741
943
|
}
|
|
742
944
|
/** 使所有模块缓存失效 */
|
|
743
945
|
invalidateAll() {
|
|
@@ -748,34 +950,32 @@ var init_module_graph = __esm({
|
|
|
748
950
|
/** 获取 HMR 传播边界 - 从变更模块向上遍历找到接受更新的边界 */
|
|
749
951
|
getHmrBoundaries(mod) {
|
|
750
952
|
const boundaries = [];
|
|
751
|
-
const
|
|
752
|
-
const
|
|
753
|
-
if (
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
boundaries.push({ boundary
|
|
757
|
-
return true;
|
|
953
|
+
const traversed = /* @__PURE__ */ new Set();
|
|
954
|
+
const addBoundary = (boundary, acceptedVia) => {
|
|
955
|
+
if (!boundaries.some(
|
|
956
|
+
(item) => item.boundary === boundary && item.acceptedVia === acceptedVia
|
|
957
|
+
)) {
|
|
958
|
+
boundaries.push({ boundary, acceptedVia });
|
|
758
959
|
}
|
|
759
|
-
|
|
760
|
-
|
|
960
|
+
};
|
|
961
|
+
const propagate = (node) => {
|
|
962
|
+
if (traversed.has(node)) return true;
|
|
963
|
+
traversed.add(node);
|
|
964
|
+
if (node.isSelfAccepting) {
|
|
965
|
+
addBoundary(node, node);
|
|
761
966
|
return true;
|
|
762
967
|
}
|
|
763
968
|
if (node.importers.size === 0) return false;
|
|
764
969
|
for (const importer of node.importers) {
|
|
765
|
-
if (
|
|
970
|
+
if (importer.acceptedHmrDeps.has(node)) {
|
|
971
|
+
addBoundary(importer, node);
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
974
|
+
if (!propagate(importer)) return false;
|
|
766
975
|
}
|
|
767
976
|
return true;
|
|
768
977
|
};
|
|
769
|
-
|
|
770
|
-
boundaries.push({ boundary: mod, acceptedVia: mod });
|
|
771
|
-
return boundaries;
|
|
772
|
-
}
|
|
773
|
-
for (const importer of mod.importers) {
|
|
774
|
-
if (!propagate(importer, mod)) {
|
|
775
|
-
return [];
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
return boundaries;
|
|
978
|
+
return propagate(mod) ? boundaries : [];
|
|
779
979
|
}
|
|
780
980
|
};
|
|
781
981
|
}
|
|
@@ -896,6 +1096,7 @@ var init_environment = __esm({
|
|
|
896
1096
|
init_module_graph();
|
|
897
1097
|
init_hot_channel();
|
|
898
1098
|
init_debug();
|
|
1099
|
+
init_plugin_api();
|
|
899
1100
|
debug = createDebugger("nasti:environment");
|
|
900
1101
|
NastiEnvironment = class {
|
|
901
1102
|
name;
|
|
@@ -904,6 +1105,7 @@ var init_environment = __esm({
|
|
|
904
1105
|
config;
|
|
905
1106
|
options;
|
|
906
1107
|
hot;
|
|
1108
|
+
driver;
|
|
907
1109
|
/** applyToEnvironment 过滤后的插件(init() 后可用) */
|
|
908
1110
|
plugins = [];
|
|
909
1111
|
/** per-env 插件容器(init() 后可用;dev 管线使用) */
|
|
@@ -911,6 +1113,8 @@ var init_environment = __esm({
|
|
|
911
1113
|
/** per-env 模块图(dev 管线使用) */
|
|
912
1114
|
moduleGraph;
|
|
913
1115
|
candidatePlugins;
|
|
1116
|
+
pluginApi;
|
|
1117
|
+
buildMetadata = {};
|
|
914
1118
|
initialized = false;
|
|
915
1119
|
constructor(name, config, init = {}) {
|
|
916
1120
|
const options = config.environments[name];
|
|
@@ -927,6 +1131,7 @@ var init_environment = __esm({
|
|
|
927
1131
|
this.hot = init.hot ?? createNoopHotChannel();
|
|
928
1132
|
this.moduleGraph = new ModuleGraph();
|
|
929
1133
|
this.candidatePlugins = init.plugins ?? config.plugins;
|
|
1134
|
+
this.pluginApi = init.pluginApi ?? getPluginApi(config);
|
|
930
1135
|
}
|
|
931
1136
|
/** 过滤插件并建 per-env PluginContainer */
|
|
932
1137
|
async init() {
|
|
@@ -937,10 +1142,57 @@ var init_environment = __esm({
|
|
|
937
1142
|
{ ...this.config, plugins: this.plugins },
|
|
938
1143
|
this
|
|
939
1144
|
);
|
|
1145
|
+
if (this.options.driver) {
|
|
1146
|
+
const claimed = [];
|
|
1147
|
+
for (const plugin of this.plugins) {
|
|
1148
|
+
const driver = await plugin.createEnvironmentDriver?.(this, this.pluginApi);
|
|
1149
|
+
if (driver) claimed.push({ plugin, driver });
|
|
1150
|
+
}
|
|
1151
|
+
if (claimed.length === 0) {
|
|
1152
|
+
throw new Error(
|
|
1153
|
+
`[nasti] environment "${this.name}" requested driver "${this.options.driver}", but no plugin provided it`
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1156
|
+
if (claimed.length > 1) {
|
|
1157
|
+
throw new Error(
|
|
1158
|
+
`[nasti] environment "${this.name}" was claimed by multiple drivers: ` + claimed.map(({ plugin, driver }) => `${plugin.name} (${driver.name})`).join(", ")
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1161
|
+
this.driver = claimed[0].driver;
|
|
1162
|
+
debug?.(`env "${this.name}" uses driver "${this.driver.name}"`);
|
|
1163
|
+
}
|
|
940
1164
|
debug?.(`env "${this.name}" initialized (${this.plugins.length} plugins)`);
|
|
941
1165
|
}
|
|
1166
|
+
getDriverContext() {
|
|
1167
|
+
return {
|
|
1168
|
+
environment: this,
|
|
1169
|
+
config: this.config,
|
|
1170
|
+
api: this.pluginApi,
|
|
1171
|
+
logger: this.config.logger
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
setBuildMetadata(metadata) {
|
|
1175
|
+
const { entries: currentEntries, ...currentMetadata } = this.buildMetadata;
|
|
1176
|
+
const { entries, ...nextMetadata } = metadata;
|
|
1177
|
+
this.buildMetadata = {
|
|
1178
|
+
...currentMetadata,
|
|
1179
|
+
...nextMetadata,
|
|
1180
|
+
...currentEntries || entries ? { entries: { ...currentEntries, ...entries } } : {}
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
getBuildMetadata() {
|
|
1184
|
+
const { entries, ...metadata } = this.buildMetadata;
|
|
1185
|
+
return {
|
|
1186
|
+
...metadata,
|
|
1187
|
+
...entries ? { entries: { ...entries } } : {}
|
|
1188
|
+
};
|
|
1189
|
+
}
|
|
942
1190
|
async close() {
|
|
943
|
-
|
|
1191
|
+
try {
|
|
1192
|
+
await this.driver?.close?.(this.getDriverContext());
|
|
1193
|
+
} finally {
|
|
1194
|
+
await this.hot.close?.();
|
|
1195
|
+
}
|
|
944
1196
|
}
|
|
945
1197
|
};
|
|
946
1198
|
}
|
|
@@ -1005,7 +1257,8 @@ function transformCode(filename, code, options = {}) {
|
|
|
1005
1257
|
importSource: options.jsxImportSource ?? "react",
|
|
1006
1258
|
refresh: options.reactRefresh ?? false
|
|
1007
1259
|
} : void 0,
|
|
1008
|
-
sourcemap: options.sourcemap ?? true
|
|
1260
|
+
sourcemap: options.sourcemap ?? true,
|
|
1261
|
+
target: options.target
|
|
1009
1262
|
});
|
|
1010
1263
|
if (result.errors && result.errors.length > 0) {
|
|
1011
1264
|
const msg = result.errors.map((e) => e.message ?? String(e)).join("\n");
|
|
@@ -1036,7 +1289,7 @@ function htmlPlugin(config) {
|
|
|
1036
1289
|
transformIndexHtml(html) {
|
|
1037
1290
|
const tags = [];
|
|
1038
1291
|
if (config.command === "serve") {
|
|
1039
|
-
const isReactLike = config.framework === "react"
|
|
1292
|
+
const isReactLike = config.framework === "react";
|
|
1040
1293
|
if (isReactLike) {
|
|
1041
1294
|
tags.push({
|
|
1042
1295
|
tag: "script",
|
|
@@ -1090,8 +1343,8 @@ function serializeTag(tag) {
|
|
|
1090
1343
|
}
|
|
1091
1344
|
return ` <${tag.tag}${attrs}>${children}</${tag.tag}>`;
|
|
1092
1345
|
}
|
|
1093
|
-
async function readHtmlFile(root) {
|
|
1094
|
-
const htmlPath = import_node_path2.default.resolve(root,
|
|
1346
|
+
async function readHtmlFile(root, htmlFile = "index.html") {
|
|
1347
|
+
const htmlPath = import_node_path2.default.isAbsolute(htmlFile) ? htmlFile : import_node_path2.default.resolve(root, htmlFile);
|
|
1095
1348
|
if (!import_node_fs2.default.existsSync(htmlPath)) return null;
|
|
1096
1349
|
return import_node_fs2.default.readFileSync(htmlPath, "utf-8");
|
|
1097
1350
|
}
|
|
@@ -1184,8 +1437,10 @@ __export(middleware_exports, {
|
|
|
1184
1437
|
transformMiddleware: () => transformMiddleware,
|
|
1185
1438
|
transformRequest: () => transformRequest
|
|
1186
1439
|
});
|
|
1187
|
-
function getReactRefreshRuntimeEsm() {
|
|
1188
|
-
if (__refreshRuntimeCache)
|
|
1440
|
+
function getReactRefreshRuntimeEsm(includeBoundaryHelpers = false) {
|
|
1441
|
+
if (__refreshRuntimeCache) {
|
|
1442
|
+
return includeBoundaryHelpers ? __refreshRuntimeCache + REACT_REFRESH_BOUNDARY_HELPERS : __refreshRuntimeCache;
|
|
1443
|
+
}
|
|
1189
1444
|
let cjsPath;
|
|
1190
1445
|
try {
|
|
1191
1446
|
const pkgPath = __require.resolve("react-refresh/package.json");
|
|
@@ -1220,7 +1475,7 @@ export const findAffectedHostInstances = __rt.findAffectedHostInstances;
|
|
|
1220
1475
|
export const collectCustomHooksForSignature = __rt.collectCustomHooksForSignature;
|
|
1221
1476
|
export default __rt;
|
|
1222
1477
|
`;
|
|
1223
|
-
return __refreshRuntimeCache;
|
|
1478
|
+
return includeBoundaryHelpers ? __refreshRuntimeCache + REACT_REFRESH_BOUNDARY_HELPERS : __refreshRuntimeCache;
|
|
1224
1479
|
}
|
|
1225
1480
|
function buildReactRefreshWrapper(moduleUrl, transformedCode) {
|
|
1226
1481
|
const urlLit = JSON.stringify(moduleUrl);
|
|
@@ -1246,22 +1501,40 @@ window.$RefreshReg$ = prevRefreshReg;
|
|
|
1246
1501
|
window.$RefreshSig$ = prevRefreshSig;
|
|
1247
1502
|
|
|
1248
1503
|
if (__nasti_hot__) {
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1504
|
+
let __nasti_current_exports__;
|
|
1505
|
+
__nasti_hot__.accept((nextExports) => {
|
|
1506
|
+
if (!nextExports) return;
|
|
1507
|
+
if (!__nasti_current_exports__) {
|
|
1508
|
+
__nasti_hot__.invalidate('Could not Fast Refresh (previous exports unavailable)');
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(
|
|
1512
|
+
${urlLit},
|
|
1513
|
+
__nasti_current_exports__,
|
|
1514
|
+
nextExports,
|
|
1515
|
+
);
|
|
1516
|
+
if (invalidateMessage) __nasti_hot__.invalidate(invalidateMessage);
|
|
1517
|
+
});
|
|
1518
|
+
RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
|
|
1519
|
+
__nasti_current_exports__ = currentExports;
|
|
1520
|
+
RefreshRuntime.registerExportsForReactRefresh(${urlLit}, currentExports);
|
|
1254
1521
|
});
|
|
1255
1522
|
}
|
|
1256
1523
|
`;
|
|
1257
1524
|
}
|
|
1258
1525
|
function injectImportMetaHot(code, moduleUrl) {
|
|
1259
|
-
|
|
1526
|
+
const hotRE = /\bimport\.meta\.hot\b/g;
|
|
1527
|
+
const matches = [...maskStringsAndComments(code).matchAll(hotRE)];
|
|
1528
|
+
if (matches.length === 0) return code;
|
|
1529
|
+
for (const match of matches.reverse()) {
|
|
1530
|
+
const start = match.index;
|
|
1531
|
+
code = code.slice(0, start) + "__nasti_hot__" + code.slice(start + match[0].length);
|
|
1532
|
+
}
|
|
1260
1533
|
const urlLit = JSON.stringify(moduleUrl);
|
|
1261
1534
|
const header = `import { createHotContext as __nasti_createHotContext__ } from "/@nasti/client";
|
|
1262
1535
|
const __nasti_hot__ = __nasti_createHotContext__(${urlLit});
|
|
1263
1536
|
`;
|
|
1264
|
-
return header + code
|
|
1537
|
+
return header + code;
|
|
1265
1538
|
}
|
|
1266
1539
|
function transformMiddleware(ctx) {
|
|
1267
1540
|
ctx.envDefine = buildEnvDefine(
|
|
@@ -1288,7 +1561,10 @@ function transformMiddleware(ctx) {
|
|
|
1288
1561
|
return;
|
|
1289
1562
|
}
|
|
1290
1563
|
if (url === "/" || url.endsWith(".html")) {
|
|
1291
|
-
const html = await readHtmlFile(
|
|
1564
|
+
const html = await readHtmlFile(
|
|
1565
|
+
ctx.config.root,
|
|
1566
|
+
ctx.config.environments.client?.html
|
|
1567
|
+
);
|
|
1292
1568
|
if (html) {
|
|
1293
1569
|
let processedHtml = html;
|
|
1294
1570
|
for (const plugin of ctx.config.plugins) {
|
|
@@ -1334,13 +1610,14 @@ function transformMiddleware(ctx) {
|
|
|
1334
1610
|
}
|
|
1335
1611
|
async function transformRequest(url, ctx) {
|
|
1336
1612
|
const { config, pluginContainer, moduleGraph } = ctx;
|
|
1613
|
+
url = removeTimestampQuery(url);
|
|
1337
1614
|
const cleanReqUrl = url.split("?")[0];
|
|
1338
1615
|
const cached2 = moduleGraph.getModuleByUrl(url);
|
|
1339
1616
|
if (cached2?.transformResult) {
|
|
1340
1617
|
return cached2.transformResult;
|
|
1341
1618
|
}
|
|
1342
1619
|
if (cleanReqUrl === "/@react-refresh") {
|
|
1343
|
-
return { code: getReactRefreshRuntimeEsm() };
|
|
1620
|
+
return { code: getReactRefreshRuntimeEsm(true) };
|
|
1344
1621
|
}
|
|
1345
1622
|
if (cleanReqUrl.startsWith("/@modules/") && url.includes("?")) {
|
|
1346
1623
|
const idParam = new URLSearchParams(url.slice(url.indexOf("?") + 1)).get("id");
|
|
@@ -1376,6 +1653,8 @@ async function transformRequest(url, ctx) {
|
|
|
1376
1653
|
}
|
|
1377
1654
|
const rawQuery = url.includes("?") ? url.slice(url.indexOf("?") + 1) : "";
|
|
1378
1655
|
if (rawQuery && !/^t=\d+$/.test(rawQuery)) {
|
|
1656
|
+
const mod2 = await moduleGraph.ensureEntryFromUrl(url);
|
|
1657
|
+
const transformVersion2 = mod2.invalidationVersion;
|
|
1379
1658
|
const loaded = await pluginContainer.load(url);
|
|
1380
1659
|
if (loaded != null) {
|
|
1381
1660
|
let code2 = typeof loaded === "string" ? loaded : loaded.code;
|
|
@@ -1383,16 +1662,28 @@ async function transformRequest(url, ctx) {
|
|
|
1383
1662
|
if (transformed != null) {
|
|
1384
1663
|
code2 = typeof transformed === "string" ? transformed : transformed.code;
|
|
1385
1664
|
}
|
|
1386
|
-
const
|
|
1387
|
-
moduleGraph.registerModule(mod2,
|
|
1388
|
-
|
|
1665
|
+
const parentFile = resolveUrlToFile(cleanReqUrl, config.root) ?? cleanReqUrl;
|
|
1666
|
+
moduleGraph.registerModule(mod2, parentFile);
|
|
1667
|
+
const hotInfo2 = rewriteHotAcceptDeps(code2, config, parentFile);
|
|
1668
|
+
code2 = injectImportMetaHot(hotInfo2.code, url);
|
|
1389
1669
|
code2 = replaceEnvInCode(code2, ctx.envDefine ?? buildEnvDefine(
|
|
1390
1670
|
loadEnv(config.mode, config.root, config.envPrefix),
|
|
1391
1671
|
config.mode
|
|
1392
1672
|
));
|
|
1393
|
-
|
|
1673
|
+
const importedUrls2 = /* @__PURE__ */ new Set();
|
|
1674
|
+
code2 = rewriteImports(code2, config, parentFile, importedUrls2, moduleGraph);
|
|
1675
|
+
const pruned2 = await moduleGraph.updateModuleInfo(
|
|
1676
|
+
mod2,
|
|
1677
|
+
importedUrls2,
|
|
1678
|
+
hotInfo2.acceptedUrls,
|
|
1679
|
+
hotInfo2.isSelfAccepting,
|
|
1680
|
+
transformVersion2
|
|
1681
|
+
);
|
|
1394
1682
|
const transformResult2 = { code: code2 };
|
|
1395
|
-
|
|
1683
|
+
if (pruned2) {
|
|
1684
|
+
if (pruned2.size > 0) ctx.onPrune?.([...pruned2].map((item) => item.url));
|
|
1685
|
+
mod2.transformResult = transformResult2;
|
|
1686
|
+
}
|
|
1396
1687
|
return transformResult2;
|
|
1397
1688
|
}
|
|
1398
1689
|
}
|
|
@@ -1400,6 +1691,7 @@ async function transformRequest(url, ctx) {
|
|
|
1400
1691
|
if (!filePath || !import_node_fs4.default.existsSync(filePath)) return null;
|
|
1401
1692
|
const mod = await moduleGraph.ensureEntryFromUrl(url);
|
|
1402
1693
|
moduleGraph.registerModule(mod, filePath);
|
|
1694
|
+
const transformVersion = mod.invalidationVersion;
|
|
1403
1695
|
if (cleanReqUrl.startsWith("/@modules/")) {
|
|
1404
1696
|
const code2 = await bundlePackageAsEsm(filePath, config.root);
|
|
1405
1697
|
const transformResult2 = { code: code2 };
|
|
@@ -1426,9 +1718,10 @@ async function transformRequest(url, ctx) {
|
|
|
1426
1718
|
if (useRefresh) {
|
|
1427
1719
|
code = buildReactRefreshWrapper(stableUrl, code);
|
|
1428
1720
|
wrappedWithRefresh = true;
|
|
1429
|
-
mod.isSelfAccepting = true;
|
|
1430
1721
|
}
|
|
1431
1722
|
}
|
|
1723
|
+
const hotInfo = rewriteHotAcceptDeps(code, config, filePath);
|
|
1724
|
+
code = hotInfo.code;
|
|
1432
1725
|
if (!wrappedWithRefresh) {
|
|
1433
1726
|
code = injectImportMetaHot(code, stableUrl);
|
|
1434
1727
|
}
|
|
@@ -1437,9 +1730,20 @@ async function transformRequest(url, ctx) {
|
|
|
1437
1730
|
config.mode
|
|
1438
1731
|
);
|
|
1439
1732
|
code = replaceEnvInCode(code, envDefine);
|
|
1440
|
-
|
|
1733
|
+
const importedUrls = /* @__PURE__ */ new Set();
|
|
1734
|
+
code = rewriteImports(code, config, filePath, importedUrls, moduleGraph);
|
|
1735
|
+
const pruned = await moduleGraph.updateModuleInfo(
|
|
1736
|
+
mod,
|
|
1737
|
+
importedUrls,
|
|
1738
|
+
hotInfo.acceptedUrls,
|
|
1739
|
+
wrappedWithRefresh || hotInfo.isSelfAccepting,
|
|
1740
|
+
transformVersion
|
|
1741
|
+
);
|
|
1441
1742
|
const transformResult = { code };
|
|
1442
|
-
|
|
1743
|
+
if (pruned) {
|
|
1744
|
+
if (pruned.size > 0) ctx.onPrune?.([...pruned].map((item) => item.url));
|
|
1745
|
+
mod.transformResult = transformResult;
|
|
1746
|
+
}
|
|
1443
1747
|
return transformResult;
|
|
1444
1748
|
}
|
|
1445
1749
|
async function loadVirtualModule(spec, ctx) {
|
|
@@ -1644,49 +1948,202 @@ async function injectCjsNamedExports(code, entryFile) {
|
|
|
1644
1948
|
return code;
|
|
1645
1949
|
}
|
|
1646
1950
|
}
|
|
1647
|
-
function rewriteImports(code, config, filePath) {
|
|
1951
|
+
function rewriteImports(code, config, filePath, importedUrls, moduleGraph) {
|
|
1952
|
+
const resolveSpec = createModuleSpecifierResolver(config, filePath);
|
|
1953
|
+
const transformSpec = (spec) => {
|
|
1954
|
+
const resolved = removeTimestampQuery(resolveSpec(spec));
|
|
1955
|
+
importedUrls?.add(resolved);
|
|
1956
|
+
const timestamp = moduleGraph?.getModuleByUrl(resolved)?.lastHMRTimestamp ?? 0;
|
|
1957
|
+
return timestamp > 0 ? appendTimestampQuery(resolved, timestamp) : resolved;
|
|
1958
|
+
};
|
|
1959
|
+
return code.replace(
|
|
1960
|
+
/\bfrom\s+(['"])([^'"]+)\1/g,
|
|
1961
|
+
(_m, q, s) => `from ${q}${transformSpec(s)}${q}`
|
|
1962
|
+
).replace(
|
|
1963
|
+
/\bimport\s+(['"])([^'"]+)\1/g,
|
|
1964
|
+
(_m, q, s) => `import ${q}${transformSpec(s)}${q}`
|
|
1965
|
+
).replace(
|
|
1966
|
+
/\bimport\s*\(\s*(['"])([^'"]+)\1\s*\)/g,
|
|
1967
|
+
(_m, q, s) => `import(${q}${transformSpec(s)}${q})`
|
|
1968
|
+
);
|
|
1969
|
+
}
|
|
1970
|
+
function createModuleSpecifierResolver(config, filePath) {
|
|
1648
1971
|
const root = config.root;
|
|
1649
1972
|
const fileDir = import_node_path4.default.dirname(filePath);
|
|
1650
1973
|
const aliasEntries = Object.entries(config.resolve.alias).sort(
|
|
1651
1974
|
([a], [b]) => b.length - a.length
|
|
1652
1975
|
);
|
|
1653
1976
|
const toRootUrl = (abs) => "/" + import_node_path4.default.relative(root, abs).replace(/\\/g, "/");
|
|
1654
|
-
|
|
1655
|
-
const suffixMatch =
|
|
1977
|
+
return (specifier) => {
|
|
1978
|
+
const suffixMatch = specifier.match(/[?#].*$/);
|
|
1656
1979
|
const suffix = suffixMatch ? suffixMatch[0] : "";
|
|
1657
|
-
const baseSpec = suffix ?
|
|
1980
|
+
const baseSpec = suffix ? specifier.slice(0, -suffix.length) : specifier;
|
|
1658
1981
|
for (const [key, value] of aliasEntries) {
|
|
1659
1982
|
if (baseSpec === key || baseSpec.startsWith(key + "/")) {
|
|
1660
1983
|
const aliasBase = resolveAliasTarget(value, root);
|
|
1661
1984
|
const sub = baseSpec.slice(key.length).replace(/^\//, "");
|
|
1662
1985
|
const target = sub ? import_node_path4.default.join(aliasBase, sub) : aliasBase;
|
|
1663
1986
|
const resolved = tryResolveDiskPath(target);
|
|
1664
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix :
|
|
1987
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
1665
1988
|
}
|
|
1666
1989
|
}
|
|
1667
1990
|
if (baseSpec.startsWith("./") || baseSpec.startsWith("../")) {
|
|
1668
|
-
const
|
|
1669
|
-
|
|
1670
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
|
|
1991
|
+
const resolved = tryResolveDiskPath(import_node_path4.default.resolve(fileDir, baseSpec));
|
|
1992
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
1671
1993
|
}
|
|
1672
1994
|
if (baseSpec.startsWith("/") && !baseSpec.startsWith("/@")) {
|
|
1673
|
-
const
|
|
1674
|
-
|
|
1675
|
-
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : spec;
|
|
1995
|
+
const resolved = tryResolveDiskPath(import_node_path4.default.join(root, baseSpec.replace(/^\//, "")));
|
|
1996
|
+
return resolved && isUnderRoot(resolved, root) ? toRootUrl(resolved) + suffix : specifier;
|
|
1676
1997
|
}
|
|
1677
|
-
if (baseSpec.startsWith("/")) return
|
|
1678
|
-
return `/@modules/${
|
|
1998
|
+
if (baseSpec.startsWith("/")) return specifier;
|
|
1999
|
+
return `/@modules/${specifier}`;
|
|
1679
2000
|
};
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
)
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
)
|
|
2001
|
+
}
|
|
2002
|
+
function rewriteHotAcceptDeps(code, config, filePath) {
|
|
2003
|
+
const acceptedUrls = /* @__PURE__ */ new Set();
|
|
2004
|
+
const edits = [];
|
|
2005
|
+
const resolveSpec = createModuleSpecifierResolver(config, filePath);
|
|
2006
|
+
const acceptRE = /(?:\bimport\.meta\.hot|\b__nasti_hot__)(?:(?:\?\.)|\.)accept\s*\(/g;
|
|
2007
|
+
const searchableCode = maskStringsAndComments(code);
|
|
2008
|
+
let isSelfAccepting = false;
|
|
2009
|
+
let match;
|
|
2010
|
+
while (match = acceptRE.exec(searchableCode)) {
|
|
2011
|
+
let cursor = match.index + match[0].length;
|
|
2012
|
+
const skipTrivia = () => {
|
|
2013
|
+
while (cursor < code.length) {
|
|
2014
|
+
if (/\s/.test(code[cursor])) {
|
|
2015
|
+
cursor++;
|
|
2016
|
+
continue;
|
|
2017
|
+
}
|
|
2018
|
+
if (code[cursor] === "/" && code[cursor + 1] === "/") {
|
|
2019
|
+
cursor += 2;
|
|
2020
|
+
while (cursor < code.length && code[cursor] !== "\n") cursor++;
|
|
2021
|
+
continue;
|
|
2022
|
+
}
|
|
2023
|
+
if (code[cursor] === "/" && code[cursor + 1] === "*") {
|
|
2024
|
+
cursor += 2;
|
|
2025
|
+
while (cursor < code.length && !(code[cursor] === "*" && code[cursor + 1] === "/")) cursor++;
|
|
2026
|
+
cursor += 2;
|
|
2027
|
+
continue;
|
|
2028
|
+
}
|
|
2029
|
+
break;
|
|
2030
|
+
}
|
|
2031
|
+
};
|
|
2032
|
+
skipTrivia();
|
|
2033
|
+
const first = code[cursor];
|
|
2034
|
+
if (!first || first === ")" || first !== "[" && first !== "'" && first !== '"' && first !== "`") {
|
|
2035
|
+
isSelfAccepting = true;
|
|
2036
|
+
continue;
|
|
2037
|
+
}
|
|
2038
|
+
const readLiteral = () => {
|
|
2039
|
+
const quote = code[cursor];
|
|
2040
|
+
if (quote !== "'" && quote !== '"' && quote !== "`") return;
|
|
2041
|
+
const start = cursor;
|
|
2042
|
+
cursor++;
|
|
2043
|
+
let raw = "";
|
|
2044
|
+
while (cursor < code.length) {
|
|
2045
|
+
const char = code[cursor];
|
|
2046
|
+
if (char === "\\") {
|
|
2047
|
+
raw += code[cursor + 1] ?? "";
|
|
2048
|
+
cursor += 2;
|
|
2049
|
+
continue;
|
|
2050
|
+
}
|
|
2051
|
+
if (char === quote) {
|
|
2052
|
+
cursor++;
|
|
2053
|
+
const resolved = removeTimestampQuery(resolveSpec(raw));
|
|
2054
|
+
acceptedUrls.add(resolved);
|
|
2055
|
+
edits.push({ start, end: cursor, value: JSON.stringify(resolved) });
|
|
2056
|
+
return;
|
|
2057
|
+
}
|
|
2058
|
+
if (quote === "`" && char === "$" && code[cursor + 1] === "{") return;
|
|
2059
|
+
raw += char;
|
|
2060
|
+
cursor++;
|
|
2061
|
+
}
|
|
2062
|
+
};
|
|
2063
|
+
if (first === "[") {
|
|
2064
|
+
cursor++;
|
|
2065
|
+
while (cursor < code.length) {
|
|
2066
|
+
skipTrivia();
|
|
2067
|
+
if (code[cursor] === ",") {
|
|
2068
|
+
cursor++;
|
|
2069
|
+
skipTrivia();
|
|
2070
|
+
}
|
|
2071
|
+
if (code[cursor] === "]") break;
|
|
2072
|
+
const before = cursor;
|
|
2073
|
+
readLiteral();
|
|
2074
|
+
if (cursor === before) break;
|
|
2075
|
+
}
|
|
2076
|
+
} else {
|
|
2077
|
+
readLiteral();
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
for (const edit of edits.sort((a, b) => b.start - a.start)) {
|
|
2081
|
+
code = code.slice(0, edit.start) + edit.value + code.slice(edit.end);
|
|
2082
|
+
}
|
|
2083
|
+
return { code, acceptedUrls, isSelfAccepting };
|
|
2084
|
+
}
|
|
2085
|
+
function maskStringsAndComments(code) {
|
|
2086
|
+
const masked = code.split("");
|
|
2087
|
+
let state = "code";
|
|
2088
|
+
const isRegexStart = (index2) => {
|
|
2089
|
+
let previous = index2 - 1;
|
|
2090
|
+
while (previous >= 0 && /\s/.test(code[previous])) previous--;
|
|
2091
|
+
return previous < 0 || "=(:,!&|?{};[]+-*%^~<>".includes(code[previous]);
|
|
2092
|
+
};
|
|
2093
|
+
for (let i = 0; i < code.length; i++) {
|
|
2094
|
+
const char = code[i];
|
|
2095
|
+
const next = code[i + 1];
|
|
2096
|
+
if (state === "code") {
|
|
2097
|
+
if (char === "'") state = "single";
|
|
2098
|
+
else if (char === '"') state = "double";
|
|
2099
|
+
else if (char === "`") state = "template";
|
|
2100
|
+
else if (char === "/" && next === "/") state = "line-comment";
|
|
2101
|
+
else if (char === "/" && next === "*") state = "block-comment";
|
|
2102
|
+
else if (char === "/" && isRegexStart(i)) state = "regex";
|
|
2103
|
+
else continue;
|
|
2104
|
+
masked[i] = " ";
|
|
2105
|
+
continue;
|
|
2106
|
+
}
|
|
2107
|
+
if (state === "line-comment") {
|
|
2108
|
+
if (char === "\n") {
|
|
2109
|
+
state = "code";
|
|
2110
|
+
} else {
|
|
2111
|
+
masked[i] = " ";
|
|
2112
|
+
}
|
|
2113
|
+
continue;
|
|
2114
|
+
}
|
|
2115
|
+
if (state === "block-comment") {
|
|
2116
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
2117
|
+
if (char === "*" && next === "/") {
|
|
2118
|
+
masked[i + 1] = " ";
|
|
2119
|
+
i++;
|
|
2120
|
+
state = "code";
|
|
2121
|
+
}
|
|
2122
|
+
continue;
|
|
2123
|
+
}
|
|
2124
|
+
if (state === "regex" || state === "regex-class") {
|
|
2125
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
2126
|
+
if (char === "\\") {
|
|
2127
|
+
if (i + 1 < code.length) masked[++i] = " ";
|
|
2128
|
+
} else if (state === "regex" && char === "[") {
|
|
2129
|
+
state = "regex-class";
|
|
2130
|
+
} else if (state === "regex-class" && char === "]") {
|
|
2131
|
+
state = "regex";
|
|
2132
|
+
} else if (state === "regex" && char === "/") {
|
|
2133
|
+
state = "code";
|
|
2134
|
+
}
|
|
2135
|
+
continue;
|
|
2136
|
+
}
|
|
2137
|
+
masked[i] = char === "\n" ? "\n" : " ";
|
|
2138
|
+
if (char === "\\") {
|
|
2139
|
+
if (i + 1 < code.length) masked[++i] = " ";
|
|
2140
|
+
continue;
|
|
2141
|
+
}
|
|
2142
|
+
if (state === "single" && char === "'" || state === "double" && char === '"' || state === "template" && char === "`") {
|
|
2143
|
+
state = "code";
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
return masked.join("");
|
|
1690
2147
|
}
|
|
1691
2148
|
function resolveAliasTarget(value, root) {
|
|
1692
2149
|
if (import_node_path4.default.isAbsolute(value) && import_node_fs4.default.existsSync(value)) return value;
|
|
@@ -1711,6 +2168,12 @@ function isUnderRoot(abs, root) {
|
|
|
1711
2168
|
const rel = import_node_path4.default.relative(root, abs);
|
|
1712
2169
|
return !!rel && !rel.startsWith("..") && !import_node_path4.default.isAbsolute(rel);
|
|
1713
2170
|
}
|
|
2171
|
+
function appendTimestampQuery(url, timestamp) {
|
|
2172
|
+
const hashIndex = url.indexOf("#");
|
|
2173
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
|
|
2174
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
2175
|
+
return `${withoutHash}${withoutHash.includes("?") ? "&" : "?"}t=${timestamp}${hash}`;
|
|
2176
|
+
}
|
|
1714
2177
|
function externalSpecToModuleUrl(spec, baseDir, root) {
|
|
1715
2178
|
const resolved = resolveNodeModule(baseDir, spec);
|
|
1716
2179
|
if (!resolved) return `/@modules/${spec}`;
|
|
@@ -1854,30 +2317,29 @@ function isModuleRequest(url) {
|
|
|
1854
2317
|
function getHmrClientCode() {
|
|
1855
2318
|
return `
|
|
1856
2319
|
// Nasti HMR Client
|
|
1857
|
-
const
|
|
2320
|
+
const socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws';
|
|
2321
|
+
const socket = new WebSocket(socketProtocol + '://' + location.host, 'nasti-hmr');
|
|
1858
2322
|
const hotModulesMap = new Map();
|
|
1859
2323
|
const disposeMap = new Map();
|
|
1860
2324
|
const pruneMap = new Map();
|
|
2325
|
+
const dataMap = new Map();
|
|
2326
|
+
let updateQueue = [];
|
|
2327
|
+
let pendingUpdateQueue = false;
|
|
1861
2328
|
|
|
1862
2329
|
socket.addEventListener('message', async ({ data }) => {
|
|
1863
2330
|
const payload = JSON.parse(data);
|
|
1864
2331
|
switch (payload.type) {
|
|
1865
2332
|
case 'connected':
|
|
1866
|
-
console.
|
|
2333
|
+
console.debug('[nasti] connected.');
|
|
1867
2334
|
clearErrorOverlay();
|
|
1868
2335
|
break;
|
|
1869
2336
|
case 'update':
|
|
1870
2337
|
try {
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
} else if (update.type === 'css-update') {
|
|
1875
|
-
return updateCss(update.path);
|
|
1876
|
-
}
|
|
1877
|
-
}));
|
|
2338
|
+
// CSS \u5728 unbundled \u6A21\u5F0F\u4E0B\u4E5F\u662F\u4F1A\u6CE8\u5165 <style> \u7684 JS \u6A21\u5757\uFF0C\u548C\u666E\u901A JS
|
|
2339
|
+
// \u4E00\u6837\u91CD\u65B0 import \u624D\u80FD\u6267\u884C dispose/accept \u5E76\u4FDD\u6301\u9875\u9762\u72B6\u6001\u3002
|
|
2340
|
+
await Promise.all(payload.updates.map(queueUpdate));
|
|
1878
2341
|
clearErrorOverlay();
|
|
1879
|
-
console.
|
|
1880
|
-
location.reload();
|
|
2342
|
+
console.debug('[nasti] HMR update complete.');
|
|
1881
2343
|
} catch (err) {
|
|
1882
2344
|
console.error('[nasti] HMR update failed:', err);
|
|
1883
2345
|
showErrorOverlay(err);
|
|
@@ -1888,10 +2350,17 @@ socket.addEventListener('message', async ({ data }) => {
|
|
|
1888
2350
|
location.reload();
|
|
1889
2351
|
break;
|
|
1890
2352
|
case 'prune':
|
|
1891
|
-
payload.paths.
|
|
1892
|
-
const
|
|
1893
|
-
|
|
1894
|
-
|
|
2353
|
+
await Promise.all(payload.paths.map(async (path) => {
|
|
2354
|
+
const data = dataMap.get(path);
|
|
2355
|
+
const dispose = disposeMap.get(path);
|
|
2356
|
+
const prune = pruneMap.get(path);
|
|
2357
|
+
if (dispose) await dispose(data);
|
|
2358
|
+
if (prune) await prune(data);
|
|
2359
|
+
hotModulesMap.delete(path);
|
|
2360
|
+
disposeMap.delete(path);
|
|
2361
|
+
pruneMap.delete(path);
|
|
2362
|
+
dataMap.delete(path);
|
|
2363
|
+
}));
|
|
1895
2364
|
break;
|
|
1896
2365
|
case 'error':
|
|
1897
2366
|
console.error('[nasti] error:', payload.err.message);
|
|
@@ -1900,33 +2369,64 @@ socket.addEventListener('message', async ({ data }) => {
|
|
|
1900
2369
|
}
|
|
1901
2370
|
});
|
|
1902
2371
|
|
|
1903
|
-
// \
|
|
2372
|
+
// \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
|
|
1904
2373
|
let reconnectTimer = 0;
|
|
1905
2374
|
socket.addEventListener('close', () => {
|
|
1906
2375
|
clearTimeout(reconnectTimer);
|
|
1907
2376
|
reconnectTimer = setTimeout(() => location.reload(), 1000);
|
|
1908
2377
|
});
|
|
1909
2378
|
|
|
2379
|
+
/**
|
|
2380
|
+
* \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
|
|
2381
|
+
* \u6539\u53D8\u6A21\u5757\u5E94\u7528\u987A\u5E8F\u3002\u8FD9\u4E0E Vite HMRClient \u7684 fetch/apply \u4E24\u9636\u6BB5\u4E00\u81F4\u3002
|
|
2382
|
+
*/
|
|
2383
|
+
async function queueUpdate(update) {
|
|
2384
|
+
updateQueue.push(fetchUpdate(update));
|
|
2385
|
+
if (pendingUpdateQueue) return;
|
|
2386
|
+
|
|
2387
|
+
pendingUpdateQueue = true;
|
|
2388
|
+
await Promise.resolve();
|
|
2389
|
+
pendingUpdateQueue = false;
|
|
2390
|
+
const loading = updateQueue;
|
|
2391
|
+
updateQueue = [];
|
|
2392
|
+
const applyUpdates = await Promise.all(loading);
|
|
2393
|
+
for (const apply of applyUpdates) {
|
|
2394
|
+
if (apply) apply();
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
|
|
1910
2398
|
async function fetchUpdate(update) {
|
|
1911
2399
|
const mod = hotModulesMap.get(update.path);
|
|
1912
|
-
// \
|
|
1913
|
-
|
|
1914
|
-
if (dispose) dispose();
|
|
2400
|
+
// \u5C1A\u672A\u5728\u5F53\u524D\u9875\u9762\u52A0\u8F7D\u7684\u52A8\u6001\u6A21\u5757\u4E0D\u9700\u8981\u66F4\u65B0\u3002
|
|
2401
|
+
if (!mod) return;
|
|
1915
2402
|
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
2403
|
+
// \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
|
|
2404
|
+
const qualifiedCallbacks = mod.callbacks.filter(({ deps }) =>
|
|
2405
|
+
deps.includes(update.acceptedPath)
|
|
2406
|
+
);
|
|
2407
|
+
const isSelfUpdate = update.path === update.acceptedPath;
|
|
2408
|
+
if (!isSelfUpdate && qualifiedCallbacks.length === 0) return;
|
|
2409
|
+
|
|
2410
|
+
const dispose = disposeMap.get(update.acceptedPath);
|
|
2411
|
+
if (dispose) await dispose(dataMap.get(update.acceptedPath));
|
|
2412
|
+
const newMod = await import(appendTimestampQuery(update.acceptedPath, update.timestamp));
|
|
2413
|
+
|
|
2414
|
+
return () => {
|
|
2415
|
+
for (const { deps, fn } of qualifiedCallbacks) {
|
|
2416
|
+
fn(deps.map((dep) => dep === update.acceptedPath ? newMod : undefined));
|
|
2417
|
+
}
|
|
2418
|
+
const detail = isSelfUpdate
|
|
2419
|
+
? update.path
|
|
2420
|
+
: update.acceptedPath + ' via ' + update.path;
|
|
2421
|
+
console.debug('[nasti] hot updated:', detail);
|
|
2422
|
+
};
|
|
1921
2423
|
}
|
|
1922
2424
|
|
|
1923
|
-
function
|
|
1924
|
-
const
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
.then(css => { el.textContent = css; });
|
|
1929
|
-
}
|
|
2425
|
+
function appendTimestampQuery(url, timestamp) {
|
|
2426
|
+
const hashIndex = url.indexOf('#');
|
|
2427
|
+
const hash = hashIndex >= 0 ? url.slice(hashIndex) : '';
|
|
2428
|
+
const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
|
|
2429
|
+
return withoutHash + (withoutHash.includes('?') ? '&' : '?') + 't=' + timestamp + hash;
|
|
1930
2430
|
}
|
|
1931
2431
|
|
|
1932
2432
|
function clearErrorOverlay() {
|
|
@@ -1954,23 +2454,30 @@ function showErrorOverlay(err) {
|
|
|
1954
2454
|
document.body.appendChild(overlay);
|
|
1955
2455
|
}
|
|
1956
2456
|
|
|
1957
|
-
/**
|
|
1958
|
-
* \u751F\u6210 import.meta.hot \u7684 hot context\u3002
|
|
1959
|
-
* \u5173\u952E\u7EA6\u675F\uFF1A\u540C\u4E00 ownerPath \u7684 accept \u56DE\u8C03\u5FC5\u987B\u66FF\u6362\uFF08\u4E0D\u662F append\uFF09\u3002
|
|
1960
|
-
* \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
|
|
1961
|
-
* \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
|
|
1962
|
-
*/
|
|
1963
2457
|
export function createHotContext(ownerPath) {
|
|
2458
|
+
if (!dataMap.has(ownerPath)) dataMap.set(ownerPath, {});
|
|
2459
|
+
|
|
2460
|
+
// \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
|
|
2461
|
+
const existing = hotModulesMap.get(ownerPath);
|
|
2462
|
+
if (existing) existing.callbacks = [];
|
|
2463
|
+
|
|
2464
|
+
const acceptDeps = (deps, callback = () => {}) => {
|
|
2465
|
+
const mod = hotModulesMap.get(ownerPath) || { id: ownerPath, callbacks: [] };
|
|
2466
|
+
mod.callbacks.push({ deps, fn: callback });
|
|
2467
|
+
hotModulesMap.set(ownerPath, mod);
|
|
2468
|
+
};
|
|
2469
|
+
|
|
1964
2470
|
return {
|
|
1965
2471
|
accept(deps, callback) {
|
|
1966
|
-
// \u81EA\u63A5\u53D7: hot.accept() \u6216 hot.accept(callback)
|
|
1967
2472
|
if (typeof deps === 'function' || deps === undefined) {
|
|
1968
|
-
|
|
1969
|
-
|
|
2473
|
+
acceptDeps([ownerPath], ([mod]) => deps?.(mod));
|
|
2474
|
+
} else if (typeof deps === 'string') {
|
|
2475
|
+
acceptDeps([deps], ([mod]) => callback?.(mod));
|
|
2476
|
+
} else if (Array.isArray(deps)) {
|
|
2477
|
+
acceptDeps(deps, callback);
|
|
2478
|
+
} else {
|
|
2479
|
+
throw new Error('invalid hot.accept() usage');
|
|
1970
2480
|
}
|
|
1971
|
-
// \u4F9D\u8D56\u63A5\u53D7: hot.accept(deps, callback)\uFF0C\u591A\u6B21\u8C03\u7528\u8FFD\u52A0
|
|
1972
|
-
const existing = hotModulesMap.get(ownerPath)?.callbacks ?? [];
|
|
1973
|
-
hotModulesMap.set(ownerPath, { callbacks: [...existing, callback] });
|
|
1974
2481
|
},
|
|
1975
2482
|
prune(callback) {
|
|
1976
2483
|
pruneMap.set(ownerPath, callback);
|
|
@@ -1981,12 +2488,12 @@ export function createHotContext(ownerPath) {
|
|
|
1981
2488
|
invalidate() {
|
|
1982
2489
|
location.reload();
|
|
1983
2490
|
},
|
|
1984
|
-
data:
|
|
2491
|
+
data: dataMap.get(ownerPath),
|
|
1985
2492
|
};
|
|
1986
2493
|
}
|
|
1987
2494
|
`;
|
|
1988
2495
|
}
|
|
1989
|
-
var import_node_path4, import_node_fs4, import_node_module, import_node_url2, import_picocolors3, import_meta, __dirname_esm, __require, __refreshRuntimeCache, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
|
|
2496
|
+
var import_node_path4, import_node_fs4, import_node_module, import_node_url2, import_picocolors3, import_meta, __dirname_esm, __require, __refreshRuntimeCache, REACT_REFRESH_BOUNDARY_HELPERS, REACT_REFRESH_GLOBAL_PREAMBLE, esmBundleCache, VALID_IDENT, RESOLVE_EXTENSIONS, ESM_CONDITIONS;
|
|
1990
2497
|
var init_middleware = __esm({
|
|
1991
2498
|
"src/server/middleware.ts"() {
|
|
1992
2499
|
"use strict";
|
|
@@ -1998,10 +2505,74 @@ var init_middleware = __esm({
|
|
|
1998
2505
|
init_transformer();
|
|
1999
2506
|
init_html();
|
|
2000
2507
|
init_env();
|
|
2508
|
+
init_url();
|
|
2001
2509
|
import_meta = {};
|
|
2002
2510
|
__dirname_esm = import_node_path4.default.dirname((0, import_node_url2.fileURLToPath)(import_meta.url));
|
|
2003
2511
|
__require = (0, import_node_module.createRequire)(import_meta.url);
|
|
2004
2512
|
__refreshRuntimeCache = null;
|
|
2513
|
+
REACT_REFRESH_BOUNDARY_HELPERS = `
|
|
2514
|
+
function __nastiIsPlainObject(obj) {
|
|
2515
|
+
return Object.prototype.toString.call(obj) === '[object Object]' &&
|
|
2516
|
+
(obj.constructor === Object || obj.constructor === undefined);
|
|
2517
|
+
}
|
|
2518
|
+
function __nastiIsCompoundComponent(type) {
|
|
2519
|
+
if (!__nastiIsPlainObject(type)) return false;
|
|
2520
|
+
for (const key in type) {
|
|
2521
|
+
if (!isLikelyComponentType(type[key])) return false;
|
|
2522
|
+
}
|
|
2523
|
+
return true;
|
|
2524
|
+
}
|
|
2525
|
+
export function registerExportsForReactRefresh(filename, moduleExports) {
|
|
2526
|
+
for (const key in moduleExports) {
|
|
2527
|
+
if (key === '__esModule') continue;
|
|
2528
|
+
const value = moduleExports[key];
|
|
2529
|
+
if (isLikelyComponentType(value)) {
|
|
2530
|
+
register(value, filename + ' export ' + key);
|
|
2531
|
+
} else if (__nastiIsCompoundComponent(value)) {
|
|
2532
|
+
for (const subKey in value) {
|
|
2533
|
+
register(value[subKey], filename + ' export ' + key + '-' + subKey);
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
let __nastiRefreshTimer;
|
|
2539
|
+
function __nastiEnqueueRefresh() {
|
|
2540
|
+
clearTimeout(__nastiRefreshTimer);
|
|
2541
|
+
__nastiRefreshTimer = setTimeout(() => performReactRefresh(), 16);
|
|
2542
|
+
}
|
|
2543
|
+
function __nastiCheckExports(ignored, exports, predicate) {
|
|
2544
|
+
for (const key in exports) {
|
|
2545
|
+
if (ignored.includes(key)) continue;
|
|
2546
|
+
if (!predicate(key, exports[key])) return key;
|
|
2547
|
+
}
|
|
2548
|
+
return true;
|
|
2549
|
+
}
|
|
2550
|
+
export function validateRefreshBoundaryAndEnqueueUpdate(id, prevExports, nextExports) {
|
|
2551
|
+
const ignored = window.__getReactRefreshIgnoredExports?.({ id }) ?? [];
|
|
2552
|
+
if (__nastiCheckExports(ignored, prevExports, (key) => key in nextExports) !== true) {
|
|
2553
|
+
return 'Could not Fast Refresh (export removed)';
|
|
2554
|
+
}
|
|
2555
|
+
if (__nastiCheckExports(ignored, nextExports, (key) => key in prevExports) !== true) {
|
|
2556
|
+
return 'Could not Fast Refresh (new export)';
|
|
2557
|
+
}
|
|
2558
|
+
let hasExports = false;
|
|
2559
|
+
const compatible = __nastiCheckExports(ignored, nextExports, (key, value) => {
|
|
2560
|
+
hasExports = true;
|
|
2561
|
+
return isLikelyComponentType(value) ||
|
|
2562
|
+
__nastiIsCompoundComponent(value) ||
|
|
2563
|
+
prevExports[key] === value;
|
|
2564
|
+
});
|
|
2565
|
+
if (!hasExports) {
|
|
2566
|
+
return 'Could not Fast Refresh (no exports)';
|
|
2567
|
+
}
|
|
2568
|
+
if (compatible === true) {
|
|
2569
|
+
__nastiEnqueueRefresh();
|
|
2570
|
+
return;
|
|
2571
|
+
}
|
|
2572
|
+
return 'Could not Fast Refresh ("' + compatible + '" export is incompatible)';
|
|
2573
|
+
}
|
|
2574
|
+
export const __hmr_import = (module) => import(module);
|
|
2575
|
+
`;
|
|
2005
2576
|
REACT_REFRESH_GLOBAL_PREAMBLE = `
|
|
2006
2577
|
import RefreshRuntime from "/@react-refresh";
|
|
2007
2578
|
RefreshRuntime.injectIntoGlobalHook(window);
|
|
@@ -2028,8 +2599,10 @@ async function handleFileChange(file, server) {
|
|
|
2028
2599
|
}
|
|
2029
2600
|
const updates = [];
|
|
2030
2601
|
const timestamp = Date.now();
|
|
2602
|
+
const graph = moduleGraph;
|
|
2603
|
+
const invalidatedModules = /* @__PURE__ */ new Set();
|
|
2031
2604
|
for (const mod of mods) {
|
|
2032
|
-
|
|
2605
|
+
graph.invalidateModuleAndImporters(mod, timestamp, invalidatedModules);
|
|
2033
2606
|
const ctx = {
|
|
2034
2607
|
file,
|
|
2035
2608
|
timestamp,
|
|
@@ -2047,19 +2620,25 @@ async function handleFileChange(file, server) {
|
|
|
2047
2620
|
}
|
|
2048
2621
|
}
|
|
2049
2622
|
for (const affected of affectedModules) {
|
|
2050
|
-
|
|
2623
|
+
graph.invalidateModuleAndImporters(affected, timestamp, invalidatedModules);
|
|
2624
|
+
const boundaries = graph.getHmrBoundaries(affected);
|
|
2051
2625
|
if (boundaries.length === 0) {
|
|
2052
2626
|
logger.info(import_picocolors4.default.green("page reload ") + import_picocolors4.default.dim(shortFile), { timestamp: true });
|
|
2053
2627
|
ws.send({ type: "full-reload", path: relativePath });
|
|
2054
2628
|
return;
|
|
2055
2629
|
}
|
|
2056
|
-
for (const { boundary } of boundaries) {
|
|
2057
|
-
|
|
2630
|
+
for (const { boundary, acceptedVia } of boundaries) {
|
|
2631
|
+
const update = {
|
|
2058
2632
|
type: boundary.type === "css" ? "css-update" : "js-update",
|
|
2059
2633
|
path: boundary.url,
|
|
2060
|
-
acceptedPath:
|
|
2634
|
+
acceptedPath: acceptedVia.url,
|
|
2061
2635
|
timestamp
|
|
2062
|
-
}
|
|
2636
|
+
};
|
|
2637
|
+
if (!updates.some(
|
|
2638
|
+
(existing) => existing.type === update.type && existing.path === update.path && existing.acceptedPath === update.acceptedPath
|
|
2639
|
+
)) {
|
|
2640
|
+
updates.push(update);
|
|
2641
|
+
}
|
|
2063
2642
|
}
|
|
2064
2643
|
}
|
|
2065
2644
|
}
|
|
@@ -2130,6 +2709,7 @@ function resolvePlugin(config) {
|
|
|
2130
2709
|
}
|
|
2131
2710
|
if (!source.startsWith("/") && !source.startsWith(".")) {
|
|
2132
2711
|
if (vueRuntimeEntry && source === "vue") return vueRuntimeEntry;
|
|
2712
|
+
if (config.command === "build") return null;
|
|
2133
2713
|
try {
|
|
2134
2714
|
const resolved = require2.resolve(source, {
|
|
2135
2715
|
paths: [importer ? import_node_path6.default.dirname(importer) : config.root]
|
|
@@ -2222,27 +2802,27 @@ var require_process = __commonJS({
|
|
|
2222
2802
|
var require_filesystem = __commonJS({
|
|
2223
2803
|
"node_modules/detect-libc/lib/filesystem.js"(exports2, module2) {
|
|
2224
2804
|
"use strict";
|
|
2225
|
-
var
|
|
2805
|
+
var fs13 = require("fs");
|
|
2226
2806
|
var LDD_PATH = "/usr/bin/ldd";
|
|
2227
2807
|
var SELF_PATH = "/proc/self/exe";
|
|
2228
2808
|
var MAX_LENGTH = 2048;
|
|
2229
|
-
var readFileSync = (
|
|
2230
|
-
const fd =
|
|
2809
|
+
var readFileSync = (path18) => {
|
|
2810
|
+
const fd = fs13.openSync(path18, "r");
|
|
2231
2811
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
2232
|
-
const bytesRead =
|
|
2233
|
-
|
|
2812
|
+
const bytesRead = fs13.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
2813
|
+
fs13.close(fd, () => {
|
|
2234
2814
|
});
|
|
2235
2815
|
return buffer.subarray(0, bytesRead);
|
|
2236
2816
|
};
|
|
2237
|
-
var readFile = (
|
|
2238
|
-
|
|
2817
|
+
var readFile = (path18) => new Promise((resolve, reject) => {
|
|
2818
|
+
fs13.open(path18, "r", (err, fd) => {
|
|
2239
2819
|
if (err) {
|
|
2240
2820
|
reject(err);
|
|
2241
2821
|
} else {
|
|
2242
2822
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
2243
|
-
|
|
2823
|
+
fs13.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
|
|
2244
2824
|
resolve(buffer.subarray(0, bytesRead));
|
|
2245
|
-
|
|
2825
|
+
fs13.close(fd, () => {
|
|
2246
2826
|
});
|
|
2247
2827
|
});
|
|
2248
2828
|
}
|
|
@@ -2354,11 +2934,11 @@ var require_detect_libc = __commonJS({
|
|
|
2354
2934
|
}
|
|
2355
2935
|
return null;
|
|
2356
2936
|
};
|
|
2357
|
-
var familyFromInterpreterPath = (
|
|
2358
|
-
if (
|
|
2359
|
-
if (
|
|
2937
|
+
var familyFromInterpreterPath = (path18) => {
|
|
2938
|
+
if (path18) {
|
|
2939
|
+
if (path18.includes("/ld-musl-")) {
|
|
2360
2940
|
return MUSL;
|
|
2361
|
-
} else if (
|
|
2941
|
+
} else if (path18.includes("/ld-linux-")) {
|
|
2362
2942
|
return GLIBC;
|
|
2363
2943
|
}
|
|
2364
2944
|
}
|
|
@@ -2405,8 +2985,8 @@ var require_detect_libc = __commonJS({
|
|
|
2405
2985
|
cachedFamilyInterpreter = null;
|
|
2406
2986
|
try {
|
|
2407
2987
|
const selfContent = await readFile(SELF_PATH);
|
|
2408
|
-
const
|
|
2409
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
2988
|
+
const path18 = interpreterPath(selfContent);
|
|
2989
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path18);
|
|
2410
2990
|
} catch (e) {
|
|
2411
2991
|
}
|
|
2412
2992
|
return cachedFamilyInterpreter;
|
|
@@ -2418,8 +2998,8 @@ var require_detect_libc = __commonJS({
|
|
|
2418
2998
|
cachedFamilyInterpreter = null;
|
|
2419
2999
|
try {
|
|
2420
3000
|
const selfContent = readFileSync(SELF_PATH);
|
|
2421
|
-
const
|
|
2422
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
3001
|
+
const path18 = interpreterPath(selfContent);
|
|
3002
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path18);
|
|
2423
3003
|
} catch (e) {
|
|
2424
3004
|
}
|
|
2425
3005
|
return cachedFamilyInterpreter;
|
|
@@ -3445,8 +4025,8 @@ function vuePlugin(config) {
|
|
|
3445
4025
|
let descriptor = descriptorCache.get(filePath);
|
|
3446
4026
|
if (!descriptor) {
|
|
3447
4027
|
try {
|
|
3448
|
-
const
|
|
3449
|
-
const source =
|
|
4028
|
+
const fs13 = await import("fs");
|
|
4029
|
+
const source = fs13.readFileSync(filePath, "utf-8");
|
|
3450
4030
|
const parsed = sfc.parse(source, { filename: filePath });
|
|
3451
4031
|
if (parsed.errors.length) return null;
|
|
3452
4032
|
descriptor = parsed.descriptor;
|
|
@@ -3585,16 +4165,27 @@ var init_vue = __esm({
|
|
|
3585
4165
|
// src/plugins/builtins.ts
|
|
3586
4166
|
function resolvePluginList(config, userPlugins, opts = {}) {
|
|
3587
4167
|
const isServe = config.command === "serve";
|
|
4168
|
+
let environmentOptions;
|
|
4169
|
+
if (opts.environmentName) {
|
|
4170
|
+
environmentOptions = config.environments[opts.environmentName];
|
|
4171
|
+
if (!environmentOptions) {
|
|
4172
|
+
throw new Error(
|
|
4173
|
+
`[nasti] unknown environment "${opts.environmentName}" \u2014 declare it in config.environments`
|
|
4174
|
+
);
|
|
4175
|
+
}
|
|
4176
|
+
}
|
|
4177
|
+
const pluginConfig = environmentOptions ? { ...config, resolve: environmentOptions.resolve, build: environmentOptions.build } : config;
|
|
4178
|
+
const consumer = opts.consumer ?? environmentOptions?.consumer;
|
|
3588
4179
|
return [
|
|
3589
4180
|
// vuePlugin 排最前(enforce: 'pre' 语义):.vue 先编译成 JS 再走后续管道
|
|
3590
|
-
...config.framework === "vue" ? [vuePlugin(
|
|
3591
|
-
resolvePlugin(
|
|
3592
|
-
cssPlugin(
|
|
3593
|
-
assetsPlugin(
|
|
3594
|
-
...isServe ? [htmlPlugin(
|
|
4181
|
+
...config.framework === "vue" ? [vuePlugin(pluginConfig)] : [],
|
|
4182
|
+
resolvePlugin(pluginConfig),
|
|
4183
|
+
cssPlugin(pluginConfig, opts.cssEngine, consumer),
|
|
4184
|
+
assetsPlugin(pluginConfig),
|
|
4185
|
+
...isServe ? [htmlPlugin(pluginConfig)] : [],
|
|
3595
4186
|
...userPlugins,
|
|
3596
4187
|
// cssPostPlugin 最后(enforce: 'post' 语义):renderChunk 聚合抽取
|
|
3597
|
-
...!isServe && opts.cssEngine ? [cssPostPlugin(
|
|
4188
|
+
...!isServe && opts.cssEngine ? [cssPostPlugin(pluginConfig, opts.cssEngine)] : []
|
|
3598
4189
|
];
|
|
3599
4190
|
}
|
|
3600
4191
|
var init_builtins = __esm({
|
|
@@ -3918,11 +4509,141 @@ var init_reporter = __esm({
|
|
|
3918
4509
|
}
|
|
3919
4510
|
});
|
|
3920
4511
|
|
|
4512
|
+
// src/core/build-app-context.ts
|
|
4513
|
+
function createBuildAppContext(config, results) {
|
|
4514
|
+
const output = [];
|
|
4515
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
4516
|
+
const outDir = import_node_path12.default.resolve(config.root, config.build.outDir);
|
|
4517
|
+
let environmentArtifacts;
|
|
4518
|
+
return {
|
|
4519
|
+
config,
|
|
4520
|
+
results,
|
|
4521
|
+
get output() {
|
|
4522
|
+
return Object.freeze([...output]);
|
|
4523
|
+
},
|
|
4524
|
+
getResult(environmentName) {
|
|
4525
|
+
return results[environmentName];
|
|
4526
|
+
},
|
|
4527
|
+
getArtifact(environmentName, fileName) {
|
|
4528
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
4529
|
+
return results[environmentName]?.output.find(
|
|
4530
|
+
(artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalized
|
|
4531
|
+
);
|
|
4532
|
+
},
|
|
4533
|
+
getEntry(environmentName, entryName) {
|
|
4534
|
+
const result = results[environmentName];
|
|
4535
|
+
const fileName = result?.entries?.[entryName];
|
|
4536
|
+
if (!fileName) return void 0;
|
|
4537
|
+
return result.output.find(
|
|
4538
|
+
(artifact) => normalizeEnvironmentFileName(artifact.fileName) === normalizeEnvironmentFileName(fileName)
|
|
4539
|
+
);
|
|
4540
|
+
},
|
|
4541
|
+
getManifest(environmentName) {
|
|
4542
|
+
return results[environmentName]?.manifest;
|
|
4543
|
+
},
|
|
4544
|
+
emitFile(file) {
|
|
4545
|
+
const fileName = normalizeAppFileName(file.fileName);
|
|
4546
|
+
const collisionKey = artifactCollisionKey(fileName);
|
|
4547
|
+
if (emitted.has(collisionKey)) {
|
|
4548
|
+
throw new Error(`[nasti] app artifact already emitted: ${fileName}`);
|
|
4549
|
+
}
|
|
4550
|
+
environmentArtifacts ??= collectEnvironmentArtifacts(config, results, outDir);
|
|
4551
|
+
if (environmentArtifacts.has(collisionKey)) {
|
|
4552
|
+
throw new Error(`[nasti] app artifact conflicts with environment output: ${fileName}`);
|
|
4553
|
+
}
|
|
4554
|
+
const target = import_node_path12.default.resolve(outDir, ...fileName.split("/"));
|
|
4555
|
+
const relative = import_node_path12.default.relative(outDir, target);
|
|
4556
|
+
if (relative.startsWith("..") || import_node_path12.default.isAbsolute(relative)) {
|
|
4557
|
+
throw new Error(`[nasti] app artifact must stay inside build.outDir: ${file.fileName}`);
|
|
4558
|
+
}
|
|
4559
|
+
assertNoSymlinkComponents(outDir, fileName);
|
|
4560
|
+
import_node_fs9.default.mkdirSync(import_node_path12.default.dirname(target), { recursive: true });
|
|
4561
|
+
import_node_fs9.default.writeFileSync(target, file.source);
|
|
4562
|
+
const artifact = {
|
|
4563
|
+
...file,
|
|
4564
|
+
fileName,
|
|
4565
|
+
type: "asset"
|
|
4566
|
+
};
|
|
4567
|
+
emitted.add(collisionKey);
|
|
4568
|
+
output.push(artifact);
|
|
4569
|
+
return fileName;
|
|
4570
|
+
}
|
|
4571
|
+
};
|
|
4572
|
+
}
|
|
4573
|
+
function normalizeEnvironmentFileName(fileName) {
|
|
4574
|
+
return import_node_path12.default.posix.normalize(fileName.replace(/\\/g, "/").replace(/^\.\//, ""));
|
|
4575
|
+
}
|
|
4576
|
+
function isInvalidEnvironmentFileName(fileName) {
|
|
4577
|
+
return !fileName || fileName === "." || fileName === ".." || fileName.startsWith("../") || import_node_path12.default.posix.isAbsolute(fileName) || /^[A-Za-z]:\//.test(fileName);
|
|
4578
|
+
}
|
|
4579
|
+
function normalizeAppFileName(fileName) {
|
|
4580
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
4581
|
+
if (isInvalidEnvironmentFileName(normalized)) {
|
|
4582
|
+
throw new Error(`[nasti] invalid app artifact fileName: ${fileName}`);
|
|
4583
|
+
}
|
|
4584
|
+
return normalized;
|
|
4585
|
+
}
|
|
4586
|
+
function artifactCollisionKey(fileName) {
|
|
4587
|
+
return normalizeEnvironmentFileName(fileName).toLowerCase();
|
|
4588
|
+
}
|
|
4589
|
+
function collectEnvironmentArtifacts(config, results, appOutDir) {
|
|
4590
|
+
const occupied = /* @__PURE__ */ new Set();
|
|
4591
|
+
for (const [environmentName, result] of Object.entries(results)) {
|
|
4592
|
+
const environment = config.environments[environmentName];
|
|
4593
|
+
if (!environment) continue;
|
|
4594
|
+
const environmentOutDir = import_node_path12.default.resolve(config.root, environment.build.outDir);
|
|
4595
|
+
for (const artifact of result.output) {
|
|
4596
|
+
const artifactPath = import_node_path12.default.resolve(
|
|
4597
|
+
environmentOutDir,
|
|
4598
|
+
...normalizeEnvironmentFileName(artifact.fileName).split("/")
|
|
4599
|
+
);
|
|
4600
|
+
const relative = import_node_path12.default.relative(appOutDir, artifactPath);
|
|
4601
|
+
if (!relative.startsWith("..") && !import_node_path12.default.isAbsolute(relative)) {
|
|
4602
|
+
occupied.add(artifactCollisionKey(relative));
|
|
4603
|
+
}
|
|
4604
|
+
}
|
|
4605
|
+
}
|
|
4606
|
+
return occupied;
|
|
4607
|
+
}
|
|
4608
|
+
function assertNoSymlinkComponents(outDir, fileName) {
|
|
4609
|
+
let current = outDir;
|
|
4610
|
+
for (const segment of fileName.split("/")) {
|
|
4611
|
+
current = import_node_path12.default.join(current, segment);
|
|
4612
|
+
let stats;
|
|
4613
|
+
try {
|
|
4614
|
+
stats = import_node_fs9.default.lstatSync(current);
|
|
4615
|
+
} catch (error) {
|
|
4616
|
+
if (error.code === "ENOENT") continue;
|
|
4617
|
+
throw error;
|
|
4618
|
+
}
|
|
4619
|
+
if (stats.isSymbolicLink()) {
|
|
4620
|
+
throw new Error(`[nasti] app artifact path cannot traverse a symlink: ${fileName}`);
|
|
4621
|
+
}
|
|
4622
|
+
}
|
|
4623
|
+
}
|
|
4624
|
+
function inferEnvironmentEntries(output) {
|
|
4625
|
+
const entries = {};
|
|
4626
|
+
for (const artifact of output) {
|
|
4627
|
+
if (artifact.type !== "chunk" || !artifact.isEntry || !artifact.name) continue;
|
|
4628
|
+
entries[artifact.name] = normalizeEnvironmentFileName(artifact.fileName);
|
|
4629
|
+
}
|
|
4630
|
+
return Object.keys(entries).length > 0 ? entries : void 0;
|
|
4631
|
+
}
|
|
4632
|
+
var import_node_fs9, import_node_path12;
|
|
4633
|
+
var init_build_app_context = __esm({
|
|
4634
|
+
"src/core/build-app-context.ts"() {
|
|
4635
|
+
"use strict";
|
|
4636
|
+
import_node_fs9 = __toESM(require("fs"), 1);
|
|
4637
|
+
import_node_path12 = __toESM(require("path"), 1);
|
|
4638
|
+
}
|
|
4639
|
+
});
|
|
4640
|
+
|
|
3921
4641
|
// src/build/index.ts
|
|
3922
4642
|
var build_exports = {};
|
|
3923
4643
|
__export(build_exports, {
|
|
3924
4644
|
build: () => build,
|
|
3925
4645
|
getRolldownOptions: () => getRolldownOptions,
|
|
4646
|
+
replaceEntryScript: () => replaceEntryScript,
|
|
3926
4647
|
resolveClientEntries: () => resolveClientEntries,
|
|
3927
4648
|
toRolldownPlugins: () => toRolldownPlugins
|
|
3928
4649
|
});
|
|
@@ -3930,9 +4651,14 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
3930
4651
|
const config = environment.config;
|
|
3931
4652
|
const envOptions = environment.options;
|
|
3932
4653
|
const isServer = environment.consumer === "server";
|
|
3933
|
-
const outDir =
|
|
4654
|
+
const outDir = import_node_path13.default.resolve(config.root, envOptions.build.outDir);
|
|
3934
4655
|
const assetsDir = envOptions.build.assetsDir;
|
|
3935
|
-
const {
|
|
4656
|
+
const {
|
|
4657
|
+
output: userOutput,
|
|
4658
|
+
transform: userTransform,
|
|
4659
|
+
resolve: userResolve,
|
|
4660
|
+
...restInputOptions
|
|
4661
|
+
} = envOptions.build.rolldownOptions;
|
|
3936
4662
|
const vueDefine = config.framework === "vue" ? {
|
|
3937
4663
|
__VUE_OPTIONS_API__: "true",
|
|
3938
4664
|
__VUE_PROD_DEVTOOLS__: "false",
|
|
@@ -3946,19 +4672,22 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
3946
4672
|
input: entryPoints,
|
|
3947
4673
|
transform: { ...userTransform, define: mergedDefine },
|
|
3948
4674
|
plugins: rolldownPlugins,
|
|
4675
|
+
// client/server consumer 都必须使用当前环境的 conditions/mainFields;Lynx
|
|
4676
|
+
// BG/MT 通常同为 client consumer,但仍可能声明不同的运行时条件。
|
|
4677
|
+
resolve: {
|
|
4678
|
+
...userResolve ?? {},
|
|
4679
|
+
// Environment API 是条件解析的唯一高层入口,优先于继承来的底层选项。
|
|
4680
|
+
conditionNames: envOptions.resolve.conditions,
|
|
4681
|
+
mainFields: envOptions.resolve.mainFields
|
|
4682
|
+
},
|
|
3949
4683
|
...isServer ? {
|
|
3950
4684
|
platform: restInputOptions.platform ?? "node",
|
|
3951
|
-
resolve: {
|
|
3952
|
-
conditionNames: envOptions.resolve.conditions,
|
|
3953
|
-
mainFields: envOptions.resolve.mainFields,
|
|
3954
|
-
...restInputOptions.resolve
|
|
3955
|
-
},
|
|
3956
4685
|
// server 产物:node 内建恒外部化;bare specifier 默认外部化
|
|
3957
4686
|
//(同 Vite ssr.external 默认 —— 依赖由 node_modules 运行时解析),
|
|
3958
4687
|
// 相对/绝对/虚拟模块照常打包。需要内联依赖时经 rolldownOptions.external 覆盖。
|
|
3959
4688
|
external: restInputOptions.external ?? ((id) => {
|
|
3960
4689
|
if (NODE_BUILTINS2.has(id)) return true;
|
|
3961
|
-
return !id.startsWith(".") && !
|
|
4690
|
+
return !id.startsWith(".") && !import_node_path13.default.isAbsolute(id) && !id.startsWith("\0");
|
|
3962
4691
|
})
|
|
3963
4692
|
} : {}
|
|
3964
4693
|
};
|
|
@@ -3985,37 +4714,139 @@ function getRolldownOptions(environment, entryPoints, rolldownPlugins) {
|
|
|
3985
4714
|
};
|
|
3986
4715
|
return { inputOptions, outputOptions, outDir };
|
|
3987
4716
|
}
|
|
3988
|
-
function toRolldownPlugins(plugins) {
|
|
4717
|
+
function toRolldownPlugins(plugins, environment) {
|
|
4718
|
+
const wrap = (hook) => {
|
|
4719
|
+
if (!hook) return hook;
|
|
4720
|
+
return function(...args) {
|
|
4721
|
+
return hook.apply(attachEnvironment(this, environment), args);
|
|
4722
|
+
};
|
|
4723
|
+
};
|
|
3989
4724
|
return plugins.map((p) => ({
|
|
3990
4725
|
name: p.name,
|
|
3991
|
-
resolveId: p.resolveId,
|
|
3992
|
-
load: p.load,
|
|
3993
|
-
transform: p.transform,
|
|
3994
|
-
buildStart: p.buildStart,
|
|
3995
|
-
buildEnd: p.buildEnd,
|
|
4726
|
+
resolveId: wrap(p.resolveId),
|
|
4727
|
+
load: wrap(p.load),
|
|
4728
|
+
transform: wrap(p.transform),
|
|
4729
|
+
buildStart: wrap(p.buildStart),
|
|
4730
|
+
buildEnd: wrap(p.buildEnd),
|
|
3996
4731
|
// closeBundle 在 bundle.close() 时触发 —— PWA manifest/SW 等终态产物依赖
|
|
3997
|
-
closeBundle: p.closeBundle,
|
|
3998
|
-
renderChunk: p.renderChunk,
|
|
3999
|
-
augmentChunkHash: p.augmentChunkHash,
|
|
4000
|
-
generateBundle: p.generateBundle
|
|
4732
|
+
closeBundle: wrap(p.closeBundle),
|
|
4733
|
+
renderChunk: wrap(p.renderChunk),
|
|
4734
|
+
augmentChunkHash: wrap(p.augmentChunkHash),
|
|
4735
|
+
generateBundle: wrap(p.generateBundle)
|
|
4001
4736
|
}));
|
|
4002
4737
|
}
|
|
4738
|
+
function attachEnvironment(context, environment) {
|
|
4739
|
+
if (context?.environment === environment) return context;
|
|
4740
|
+
try {
|
|
4741
|
+
Object.defineProperty(context, "environment", {
|
|
4742
|
+
configurable: true,
|
|
4743
|
+
enumerable: false,
|
|
4744
|
+
writable: false,
|
|
4745
|
+
value: environment
|
|
4746
|
+
});
|
|
4747
|
+
return context;
|
|
4748
|
+
} catch {
|
|
4749
|
+
return new Proxy(context, {
|
|
4750
|
+
get(target, property) {
|
|
4751
|
+
if (property === "environment") return environment;
|
|
4752
|
+
const value = Reflect.get(target, property, target);
|
|
4753
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
4754
|
+
},
|
|
4755
|
+
set(target, property, value) {
|
|
4756
|
+
return Reflect.set(target, property, value, target);
|
|
4757
|
+
}
|
|
4758
|
+
});
|
|
4759
|
+
}
|
|
4760
|
+
}
|
|
4761
|
+
function finalizeEnvironmentResult(environment, result) {
|
|
4762
|
+
const metadata = environment.getBuildMetadata();
|
|
4763
|
+
const inferredEntries = inferEnvironmentEntries(result.output);
|
|
4764
|
+
const entries = {
|
|
4765
|
+
...inferredEntries,
|
|
4766
|
+
...metadata.entries,
|
|
4767
|
+
...result.entries
|
|
4768
|
+
};
|
|
4769
|
+
const normalizedEntries = Object.fromEntries(
|
|
4770
|
+
Object.entries(entries).map(([name, fileName]) => {
|
|
4771
|
+
const normalized = normalizeEnvironmentFileName(fileName);
|
|
4772
|
+
if (isInvalidEnvironmentFileName(normalized)) {
|
|
4773
|
+
throw new Error(
|
|
4774
|
+
`[nasti] environment "${environment.name}" returned invalid entry "${name}": ${fileName}`
|
|
4775
|
+
);
|
|
4776
|
+
}
|
|
4777
|
+
return [name, normalized];
|
|
4778
|
+
})
|
|
4779
|
+
);
|
|
4780
|
+
return {
|
|
4781
|
+
...metadata,
|
|
4782
|
+
...result,
|
|
4783
|
+
output: result.output,
|
|
4784
|
+
...Object.keys(normalizedEntries).length > 0 ? { entries: normalizedEntries } : {}
|
|
4785
|
+
};
|
|
4786
|
+
}
|
|
4787
|
+
function prepareBuildOutputDirectories(config, buildableNames) {
|
|
4788
|
+
const directories = /* @__PURE__ */ new Set();
|
|
4789
|
+
const protectedPaths = /* @__PURE__ */ new Set();
|
|
4790
|
+
const clientIsBuilt = buildableNames.includes("client");
|
|
4791
|
+
if (!clientIsBuilt && config.build.emptyOutDir) {
|
|
4792
|
+
directories.add(import_node_path13.default.resolve(config.root, config.build.outDir));
|
|
4793
|
+
}
|
|
4794
|
+
for (const name of buildableNames) {
|
|
4795
|
+
const environment = config.environments[name];
|
|
4796
|
+
const outDir = import_node_path13.default.resolve(config.root, environment.build.outDir);
|
|
4797
|
+
if (!environment.build.emptyOutDir) {
|
|
4798
|
+
protectedPaths.add(outDir);
|
|
4799
|
+
continue;
|
|
4800
|
+
}
|
|
4801
|
+
if (!environment.driver) directories.add(outDir);
|
|
4802
|
+
}
|
|
4803
|
+
const containsPath = (parent, child) => {
|
|
4804
|
+
const relative = import_node_path13.default.relative(parent, child);
|
|
4805
|
+
return relative === "" || !relative.startsWith("..") && !import_node_path13.default.isAbsolute(relative);
|
|
4806
|
+
};
|
|
4807
|
+
const roots = [...directories].filter(
|
|
4808
|
+
(directory) => ![...protectedPaths].some((protectedPath) => containsPath(directory, protectedPath))
|
|
4809
|
+
).sort((a, b) => a.length - b.length).filter(
|
|
4810
|
+
(directory, index2, all) => !all.slice(0, index2).some((parent) => containsPath(parent, directory))
|
|
4811
|
+
);
|
|
4812
|
+
for (const directory of roots) {
|
|
4813
|
+
if (import_node_fs10.default.existsSync(directory)) import_node_fs10.default.rmSync(directory, { recursive: true, force: true });
|
|
4814
|
+
}
|
|
4815
|
+
}
|
|
4816
|
+
function assertDriverBuildResult(environment, result) {
|
|
4817
|
+
const output = result != null && typeof result === "object" ? result.output : void 0;
|
|
4818
|
+
const hasValidOutput = Array.isArray(output) && output.every(
|
|
4819
|
+
(artifact) => artifact != null && typeof artifact === "object" && typeof artifact.fileName === "string" && typeof artifact.type === "string"
|
|
4820
|
+
);
|
|
4821
|
+
if (!hasValidOutput) {
|
|
4822
|
+
throw new Error(
|
|
4823
|
+
`[nasti] environment "${environment.name}" driver "${environment.driver?.name}" returned an invalid build result; expected { output: EnvironmentBuildOutput[] }`
|
|
4824
|
+
);
|
|
4825
|
+
}
|
|
4826
|
+
}
|
|
4003
4827
|
function resolveClientEntries(config, html) {
|
|
4828
|
+
const configuredEntries = config.environments.client?.entry ?? [];
|
|
4829
|
+
if (configuredEntries.length > 0) return configuredEntries;
|
|
4004
4830
|
const entryPoints = [];
|
|
4831
|
+
const htmlFile = config.environments.client?.html;
|
|
4832
|
+
const htmlDir = htmlFile ? import_node_path13.default.dirname(htmlFile) : config.root;
|
|
4005
4833
|
if (html) {
|
|
4006
4834
|
const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
|
|
4007
4835
|
for (const match of scriptMatches) {
|
|
4008
4836
|
const src = match[1];
|
|
4009
4837
|
if (src && !src.startsWith("http")) {
|
|
4010
|
-
|
|
4838
|
+
const cleanSrc = src.split(/[?#]/, 1)[0];
|
|
4839
|
+
entryPoints.push(
|
|
4840
|
+
cleanSrc.startsWith("/") ? import_node_path13.default.resolve(config.root, cleanSrc.replace(/^\//, "")) : import_node_path13.default.resolve(htmlDir, cleanSrc)
|
|
4841
|
+
);
|
|
4011
4842
|
}
|
|
4012
4843
|
}
|
|
4013
4844
|
}
|
|
4014
4845
|
if (entryPoints.length === 0) {
|
|
4015
4846
|
const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
|
|
4016
4847
|
for (const entry of fallbackEntries) {
|
|
4017
|
-
const fullPath =
|
|
4018
|
-
if (
|
|
4848
|
+
const fullPath = import_node_path13.default.resolve(config.root, entry);
|
|
4849
|
+
if (import_node_fs10.default.existsSync(fullPath)) {
|
|
4019
4850
|
entryPoints.push(fullPath);
|
|
4020
4851
|
break;
|
|
4021
4852
|
}
|
|
@@ -4043,130 +4874,229 @@ async function build(inlineConfig = {}) {
|
|
|
4043
4874
|
const startTime = performance.now();
|
|
4044
4875
|
logger.info(
|
|
4045
4876
|
import_picocolors6.default.cyan(`
|
|
4046
|
-
nasti v${"2.
|
|
4877
|
+
nasti v${"2.4.0"} `) + import_picocolors6.default.green(`building for ${config.mode}...`)
|
|
4047
4878
|
);
|
|
4048
4879
|
debug5?.(`root: ${config.root}`);
|
|
4049
|
-
const buildableNames = Object.keys(config.environments).filter(
|
|
4050
|
-
|
|
4051
|
-
|
|
4880
|
+
const buildableNames = Object.keys(config.environments).filter((name) => {
|
|
4881
|
+
const environment = config.environments[name];
|
|
4882
|
+
if (!environment.buildEnabled) return false;
|
|
4883
|
+
return name === "client" || environment.entry.length > 0 || !!environment.driver;
|
|
4884
|
+
});
|
|
4052
4885
|
buildableNames.sort((a, b) => a === "client" ? -1 : b === "client" ? 1 : 0);
|
|
4886
|
+
prepareBuildOutputDirectories(config, buildableNames);
|
|
4053
4887
|
const environments = {};
|
|
4888
|
+
const environmentResults = {};
|
|
4889
|
+
const initializedEnvironments = [];
|
|
4890
|
+
const buildAppContext = createBuildAppContext(config, environmentResults);
|
|
4054
4891
|
let clientOutput = [];
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4892
|
+
let buildFailed = false;
|
|
4893
|
+
try {
|
|
4894
|
+
for (const name of buildableNames) {
|
|
4895
|
+
const built = name === "client" ? await buildClientEnvironment(config) : await buildServerEnvironment(config, name);
|
|
4896
|
+
initializedEnvironments.push(built.environment);
|
|
4897
|
+
environments[name] = built.result.output;
|
|
4898
|
+
environmentResults[name] = built.result;
|
|
4899
|
+
if (name === "client") clientOutput = built.result.output;
|
|
4900
|
+
if (buildableNames.length > 1) {
|
|
4901
|
+
debug5?.(`environment "${name}" built (${built.result.output.length} files)`);
|
|
4902
|
+
}
|
|
4903
|
+
}
|
|
4904
|
+
const pluginApi = getPluginApi(config);
|
|
4905
|
+
for (const plugin of config.plugins) {
|
|
4906
|
+
await plugin.afterBuildApp?.(environmentResults, pluginApi, buildAppContext);
|
|
4907
|
+
}
|
|
4908
|
+
} catch (error) {
|
|
4909
|
+
buildFailed = true;
|
|
4910
|
+
throw error;
|
|
4911
|
+
} finally {
|
|
4912
|
+
let closeFailed = false;
|
|
4913
|
+
let firstCloseError;
|
|
4914
|
+
for (const environment of [...initializedEnvironments].reverse()) {
|
|
4915
|
+
try {
|
|
4916
|
+
await environment.close();
|
|
4917
|
+
} catch (error) {
|
|
4918
|
+
if (!closeFailed) {
|
|
4919
|
+
closeFailed = true;
|
|
4920
|
+
firstCloseError = error;
|
|
4921
|
+
}
|
|
4922
|
+
const closeError = error instanceof Error ? error : new Error(String(error));
|
|
4923
|
+
logger.error(`[nasti] failed to close environment "${environment.name}"`, {
|
|
4924
|
+
error: closeError
|
|
4925
|
+
});
|
|
4926
|
+
}
|
|
4927
|
+
}
|
|
4928
|
+
if (closeFailed && !buildFailed) {
|
|
4929
|
+
throw firstCloseError;
|
|
4061
4930
|
}
|
|
4062
4931
|
}
|
|
4063
4932
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
4064
|
-
const
|
|
4933
|
+
const allOutput = [...Object.values(environments).flat(), ...buildAppContext.output];
|
|
4934
|
+
const totalSize = allOutput.reduce((sum, chunk) => {
|
|
4065
4935
|
const content = chunk.type === "chunk" ? chunk.code : chunk.source;
|
|
4066
4936
|
if (content == null) return sum;
|
|
4067
4937
|
return sum + (typeof content === "string" ? Buffer.byteLength(content) : content.byteLength);
|
|
4068
4938
|
}, 0);
|
|
4069
|
-
const fileCount =
|
|
4939
|
+
const fileCount = allOutput.length;
|
|
4070
4940
|
const envSuffix = buildableNames.length > 1 ? ` (${buildableNames.join(" + ")})` : "";
|
|
4071
4941
|
logger.info(import_picocolors6.default.green(`\u2713 built in ${elapsed}s`) + import_picocolors6.default.dim(envSuffix));
|
|
4072
4942
|
logger.info(import_picocolors6.default.dim(` ${fileCount} files, ${displaySize(totalSize)} total \u2192 ${config.build.outDir}/`));
|
|
4073
|
-
return {
|
|
4943
|
+
return {
|
|
4944
|
+
output: clientOutput,
|
|
4945
|
+
environments,
|
|
4946
|
+
environmentResults,
|
|
4947
|
+
appOutput: [...buildAppContext.output]
|
|
4948
|
+
};
|
|
4074
4949
|
}
|
|
4075
4950
|
async function buildClientEnvironment(config) {
|
|
4076
4951
|
const logger = config.logger;
|
|
4077
|
-
const outDir =
|
|
4078
|
-
if (config.build.emptyOutDir && import_node_fs9.default.existsSync(outDir)) {
|
|
4079
|
-
import_node_fs9.default.rmSync(outDir, { recursive: true, force: true });
|
|
4080
|
-
}
|
|
4081
|
-
import_node_fs9.default.mkdirSync(outDir, { recursive: true });
|
|
4082
|
-
const html = await readHtmlFile(config.root);
|
|
4083
|
-
const entryPoints = resolveClientEntries(config, html);
|
|
4084
|
-
if (entryPoints.length === 0) {
|
|
4085
|
-
throw new Error("No entry point found. Add a <script> tag to index.html or create src/main.ts");
|
|
4086
|
-
}
|
|
4952
|
+
const outDir = import_node_path13.default.resolve(config.root, config.build.outDir);
|
|
4087
4953
|
const cssEngine = createCssEngine();
|
|
4088
|
-
const pluginList = resolvePluginList(config, config.plugins, {
|
|
4089
|
-
|
|
4954
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
4955
|
+
cssEngine,
|
|
4956
|
+
environmentName: "client"
|
|
4957
|
+
});
|
|
4958
|
+
const clientEnv = new NastiEnvironment("client", config, {
|
|
4090
4959
|
mode: "build",
|
|
4091
|
-
plugins: pluginList
|
|
4960
|
+
plugins: pluginList,
|
|
4961
|
+
pluginApi: getPluginApi(config)
|
|
4092
4962
|
});
|
|
4093
4963
|
await clientEnv.init();
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
...nativeReporter ? [nativeReporter] : []
|
|
4100
|
-
];
|
|
4101
|
-
const { inputOptions, outputOptions } = getRolldownOptions(clientEnv, entryPoints, rolldownPlugins);
|
|
4102
|
-
const bundle2 = await (0, import_rolldown.rolldown)(inputOptions);
|
|
4103
|
-
const { output } = await bundle2.write(outputOptions);
|
|
4104
|
-
await bundle2.close();
|
|
4105
|
-
if (html) {
|
|
4106
|
-
let processedHtml = html;
|
|
4107
|
-
const htmlPlugins = [...allPlugins.filter((p) => p.transformIndexHtml), htmlPlugin(config)];
|
|
4108
|
-
for (const p of htmlPlugins) {
|
|
4109
|
-
const result = await p.transformIndexHtml(processedHtml);
|
|
4110
|
-
if (typeof result === "string") {
|
|
4111
|
-
processedHtml = result;
|
|
4112
|
-
} else if (result && "html" in result) {
|
|
4113
|
-
processedHtml = processHtml(result.html, result.tags);
|
|
4114
|
-
} else if (Array.isArray(result)) {
|
|
4115
|
-
processedHtml = processHtml(processedHtml, result);
|
|
4116
|
-
}
|
|
4117
|
-
}
|
|
4118
|
-
processedHtml = injectCssLinks(processedHtml, cssEngine, config);
|
|
4119
|
-
for (const chunk of output) {
|
|
4120
|
-
if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) {
|
|
4121
|
-
const originalEntry = import_node_path12.default.relative(config.root, chunk.facadeModuleId);
|
|
4122
|
-
processedHtml = processedHtml.replace(
|
|
4123
|
-
new RegExp(`(src=["'])/?(${escapeRegExp(originalEntry)})(["'])`, "g"),
|
|
4124
|
-
`$1${config.base}${chunk.fileName}$3`
|
|
4964
|
+
try {
|
|
4965
|
+
if (clientEnv.driver) {
|
|
4966
|
+
if (!clientEnv.driver.build) {
|
|
4967
|
+
throw new Error(
|
|
4968
|
+
`[nasti] environment "client" driver "${clientEnv.driver.name}" does not implement build()`
|
|
4125
4969
|
);
|
|
4126
4970
|
}
|
|
4971
|
+
const result = await clientEnv.driver.build(clientEnv.getDriverContext());
|
|
4972
|
+
assertDriverBuildResult(clientEnv, result);
|
|
4973
|
+
return { environment: clientEnv, result: finalizeEnvironmentResult(clientEnv, result) };
|
|
4127
4974
|
}
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4975
|
+
import_node_fs10.default.mkdirSync(outDir, { recursive: true });
|
|
4976
|
+
const htmlFile = config.environments.client.html ?? import_node_path13.default.resolve(config.root, "index.html");
|
|
4977
|
+
const html = await readHtmlFile(config.root, htmlFile);
|
|
4978
|
+
const entryPoints = resolveClientEntries(config, html);
|
|
4979
|
+
if (entryPoints.length === 0) {
|
|
4980
|
+
throw new Error("No entry point found. Add a <script> tag to index.html or create src/main.ts");
|
|
4981
|
+
}
|
|
4982
|
+
const allPlugins = clientEnv.plugins;
|
|
4983
|
+
const nativeReporter = config.logLevel === "silent" ? null : await tryNativeReporterPlugin(config, logger);
|
|
4984
|
+
const rolldownPlugins = [
|
|
4985
|
+
createOxcTransformPlugin(config, clientEnv),
|
|
4986
|
+
...toRolldownPlugins(allPlugins, clientEnv),
|
|
4987
|
+
...nativeReporter ? [nativeReporter] : []
|
|
4988
|
+
];
|
|
4989
|
+
const { inputOptions, outputOptions } = getRolldownOptions(
|
|
4990
|
+
clientEnv,
|
|
4991
|
+
entryPoints,
|
|
4992
|
+
rolldownPlugins
|
|
4993
|
+
);
|
|
4994
|
+
const bundle2 = await (0, import_rolldown.rolldown)(inputOptions);
|
|
4995
|
+
const { output } = await bundle2.write(outputOptions);
|
|
4996
|
+
await bundle2.close();
|
|
4997
|
+
if (html) {
|
|
4998
|
+
let processedHtml = html;
|
|
4999
|
+
const htmlPlugins = [...allPlugins.filter((p) => p.transformIndexHtml), htmlPlugin(config)];
|
|
5000
|
+
for (const p of htmlPlugins) {
|
|
5001
|
+
const result = await p.transformIndexHtml(processedHtml);
|
|
5002
|
+
if (typeof result === "string") {
|
|
5003
|
+
processedHtml = result;
|
|
5004
|
+
} else if (result && "html" in result) {
|
|
5005
|
+
processedHtml = processHtml(result.html, result.tags);
|
|
5006
|
+
} else if (Array.isArray(result)) {
|
|
5007
|
+
processedHtml = processHtml(processedHtml, result);
|
|
5008
|
+
}
|
|
5009
|
+
}
|
|
5010
|
+
processedHtml = injectCssLinks(processedHtml, cssEngine, config);
|
|
5011
|
+
for (const chunk of output) {
|
|
5012
|
+
if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) {
|
|
5013
|
+
processedHtml = replaceEntryScript(
|
|
5014
|
+
processedHtml,
|
|
5015
|
+
chunk.facadeModuleId,
|
|
5016
|
+
chunk.fileName,
|
|
5017
|
+
config,
|
|
5018
|
+
htmlFile,
|
|
5019
|
+
config.base
|
|
5020
|
+
);
|
|
5021
|
+
}
|
|
5022
|
+
}
|
|
5023
|
+
import_node_fs10.default.writeFileSync(import_node_path13.default.resolve(outDir, "index.html"), processedHtml);
|
|
5024
|
+
}
|
|
5025
|
+
if (!nativeReporter && config.logLevel !== "silent") {
|
|
5026
|
+
reportBuildOutput(output, config, logger);
|
|
5027
|
+
}
|
|
5028
|
+
warnLargeChunks(output, config, logger);
|
|
5029
|
+
return {
|
|
5030
|
+
environment: clientEnv,
|
|
5031
|
+
result: finalizeEnvironmentResult(clientEnv, { output })
|
|
5032
|
+
};
|
|
5033
|
+
} catch (error) {
|
|
5034
|
+
try {
|
|
5035
|
+
await clientEnv.close();
|
|
5036
|
+
} catch (closeError) {
|
|
5037
|
+
const normalized = closeError instanceof Error ? closeError : new Error(String(closeError));
|
|
5038
|
+
logger.error("[nasti] failed to close client environment after build failure", {
|
|
5039
|
+
error: normalized
|
|
5040
|
+
});
|
|
5041
|
+
}
|
|
5042
|
+
throw error;
|
|
4132
5043
|
}
|
|
4133
|
-
warnLargeChunks(output, config, logger);
|
|
4134
|
-
return output;
|
|
4135
5044
|
}
|
|
4136
5045
|
async function buildServerEnvironment(config, name) {
|
|
4137
5046
|
const envOptions = config.environments[name];
|
|
4138
5047
|
const logger = config.logger;
|
|
5048
|
+
const pluginList = resolvePluginList(config, config.plugins, {
|
|
5049
|
+
consumer: envOptions.consumer,
|
|
5050
|
+
environmentName: name
|
|
5051
|
+
});
|
|
5052
|
+
const environment = new NastiEnvironment(name, config, {
|
|
5053
|
+
mode: "build",
|
|
5054
|
+
plugins: pluginList,
|
|
5055
|
+
pluginApi: getPluginApi(config)
|
|
5056
|
+
});
|
|
5057
|
+
await environment.init();
|
|
5058
|
+
if (environment.driver) {
|
|
5059
|
+
if (!environment.driver.build) {
|
|
5060
|
+
await environment.close();
|
|
5061
|
+
throw new Error(
|
|
5062
|
+
`[nasti] environment "${name}" driver "${environment.driver.name}" does not implement build()`
|
|
5063
|
+
);
|
|
5064
|
+
}
|
|
5065
|
+
try {
|
|
5066
|
+
const result = await environment.driver.build(environment.getDriverContext());
|
|
5067
|
+
assertDriverBuildResult(environment, result);
|
|
5068
|
+
return { environment, result: finalizeEnvironmentResult(environment, result) };
|
|
5069
|
+
} catch (error) {
|
|
5070
|
+
await environment.close();
|
|
5071
|
+
throw error;
|
|
5072
|
+
}
|
|
5073
|
+
}
|
|
4139
5074
|
for (const entry of envOptions.entry) {
|
|
4140
|
-
if (!
|
|
5075
|
+
if (!import_node_fs10.default.existsSync(entry)) {
|
|
5076
|
+
await environment.close();
|
|
4141
5077
|
throw new Error(`[nasti] environment "${name}" entry not found: ${entry}`);
|
|
4142
5078
|
}
|
|
4143
5079
|
}
|
|
4144
|
-
const pluginList = resolvePluginList(config, config.plugins, { consumer: envOptions.consumer });
|
|
4145
|
-
const environment = new NastiEnvironment(name, { ...config, plugins: pluginList }, {
|
|
4146
|
-
mode: "build",
|
|
4147
|
-
plugins: pluginList
|
|
4148
|
-
});
|
|
4149
|
-
await environment.init();
|
|
4150
5080
|
const rolldownPlugins = [
|
|
4151
5081
|
createOxcTransformPlugin(config, environment),
|
|
4152
|
-
...toRolldownPlugins(environment.plugins)
|
|
5082
|
+
...toRolldownPlugins(environment.plugins, environment)
|
|
4153
5083
|
];
|
|
4154
5084
|
const { inputOptions, outputOptions, outDir } = getRolldownOptions(
|
|
4155
5085
|
environment,
|
|
4156
5086
|
envOptions.entry,
|
|
4157
5087
|
rolldownPlugins
|
|
4158
5088
|
);
|
|
4159
|
-
|
|
4160
|
-
import_node_fs9.default.rmSync(outDir, { recursive: true, force: true });
|
|
4161
|
-
}
|
|
4162
|
-
import_node_fs9.default.mkdirSync(outDir, { recursive: true });
|
|
5089
|
+
import_node_fs10.default.mkdirSync(outDir, { recursive: true });
|
|
4163
5090
|
const bundle2 = await (0, import_rolldown.rolldown)(inputOptions);
|
|
4164
5091
|
const { output } = await bundle2.write(outputOptions);
|
|
4165
5092
|
await bundle2.close();
|
|
4166
5093
|
logger.info(
|
|
4167
|
-
import_picocolors6.default.dim(` [${name}] `) + output.map((o) =>
|
|
5094
|
+
import_picocolors6.default.dim(` [${name}] `) + output.map((o) => import_node_path13.default.join(envOptions.build.outDir, o.fileName)).join(import_picocolors6.default.dim(", "))
|
|
4168
5095
|
);
|
|
4169
|
-
return
|
|
5096
|
+
return {
|
|
5097
|
+
environment,
|
|
5098
|
+
result: finalizeEnvironmentResult(environment, { output })
|
|
5099
|
+
};
|
|
4170
5100
|
}
|
|
4171
5101
|
function injectCssLinks(html, cssEngine, config) {
|
|
4172
5102
|
const cssLinkTags = [];
|
|
@@ -4192,12 +5122,31 @@ function injectCssLinks(html, cssEngine, config) {
|
|
|
4192
5122
|
function escapeRegExp(string) {
|
|
4193
5123
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4194
5124
|
}
|
|
4195
|
-
|
|
5125
|
+
function replaceEntryScript(html, facadeModuleId, fileName, config, htmlFile, urlPrefix) {
|
|
5126
|
+
const rootRelative = import_node_path13.default.relative(config.root, facadeModuleId).split(import_node_path13.default.sep).join("/");
|
|
5127
|
+
const resolvedHtmlFile = import_node_path13.default.resolve(config.root, htmlFile);
|
|
5128
|
+
const htmlRelative = import_node_path13.default.relative(import_node_path13.default.dirname(resolvedHtmlFile), facadeModuleId).split(import_node_path13.default.sep).join("/");
|
|
5129
|
+
const candidates = /* @__PURE__ */ new Set([
|
|
5130
|
+
rootRelative,
|
|
5131
|
+
`/${rootRelative}`,
|
|
5132
|
+
htmlRelative,
|
|
5133
|
+
`./${htmlRelative}`
|
|
5134
|
+
]);
|
|
5135
|
+
let processed = html;
|
|
5136
|
+
for (const candidate of candidates) {
|
|
5137
|
+
processed = processed.replace(
|
|
5138
|
+
new RegExp(`(src=["'])${escapeRegExp(candidate)}([?#][^"']*)?(["'])`, "g"),
|
|
5139
|
+
`$1${urlPrefix}${fileName}$3`
|
|
5140
|
+
);
|
|
5141
|
+
}
|
|
5142
|
+
return processed;
|
|
5143
|
+
}
|
|
5144
|
+
var import_node_path13, import_node_fs10, import_node_module5, import_rolldown, import_picocolors6, debug5, NODE_BUILTINS2;
|
|
4196
5145
|
var init_build = __esm({
|
|
4197
5146
|
"src/build/index.ts"() {
|
|
4198
5147
|
"use strict";
|
|
4199
|
-
|
|
4200
|
-
|
|
5148
|
+
import_node_path13 = __toESM(require("path"), 1);
|
|
5149
|
+
import_node_fs10 = __toESM(require("fs"), 1);
|
|
4201
5150
|
import_node_module5 = require("module");
|
|
4202
5151
|
import_rolldown = require("rolldown");
|
|
4203
5152
|
init_config();
|
|
@@ -4209,6 +5158,8 @@ var init_build = __esm({
|
|
|
4209
5158
|
init_env();
|
|
4210
5159
|
init_reporter();
|
|
4211
5160
|
init_debug();
|
|
5161
|
+
init_plugin_api();
|
|
5162
|
+
init_build_app_context();
|
|
4212
5163
|
import_picocolors6 = __toESM(require("picocolors"), 1);
|
|
4213
5164
|
debug5 = createDebugger("nasti:build");
|
|
4214
5165
|
NODE_BUILTINS2 = /* @__PURE__ */ new Set([...import_node_module5.builtinModules, ...import_node_module5.builtinModules.map((m) => `node:${m}`)]);
|
|
@@ -4237,7 +5188,7 @@ async function createBundledDevServer(opts) {
|
|
|
4237
5188
|
`[nasti] experimental.bundledDev requires rolldown's experimental dev() API (locked to the installed rc; got: ${err.message}). Remove --bundle / experimental.bundledDev to use the default unbundled dev server.`
|
|
4238
5189
|
);
|
|
4239
5190
|
}
|
|
4240
|
-
const html = await readHtmlFile(config.root);
|
|
5191
|
+
const html = await readHtmlFile(config.root, config.environments.client?.html);
|
|
4241
5192
|
const entryPoints = resolveClientEntries(config, html);
|
|
4242
5193
|
if (entryPoints.length === 0) {
|
|
4243
5194
|
throw new Error("No entry point found. Add a <script> tag to index.html or create src/main.ts");
|
|
@@ -4252,7 +5203,7 @@ async function createBundledDevServer(opts) {
|
|
|
4252
5203
|
createReactRefreshRuntimePlugin(entryPoints),
|
|
4253
5204
|
createBundledOxcRefreshPlugin()
|
|
4254
5205
|
] : [],
|
|
4255
|
-
...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins)),
|
|
5206
|
+
...stripCatchAllLoad(toRolldownPlugins(clientEnv.plugins, clientEnv)),
|
|
4256
5207
|
...useReactRefresh ? [
|
|
4257
5208
|
refreshWrapperFn({
|
|
4258
5209
|
cwd: config.root,
|
|
@@ -4301,7 +5252,7 @@ async function createBundledDevServer(opts) {
|
|
|
4301
5252
|
}
|
|
4302
5253
|
const url = `/${patchPath}`;
|
|
4303
5254
|
logger.info(
|
|
4304
|
-
import_picocolors7.default.green("hmr update ") + import_picocolors7.default.dim(changedFiles.map((f) =>
|
|
5255
|
+
import_picocolors7.default.green("hmr update ") + import_picocolors7.default.dim(changedFiles.map((f) => import_node_path14.default.relative(config.root, f)).join(", ")),
|
|
4305
5256
|
{ timestamp: true }
|
|
4306
5257
|
);
|
|
4307
5258
|
sendTo(clientId, { type: "hmr:update", path: url, url });
|
|
@@ -4437,13 +5388,13 @@ async function createBundledDevServer(opts) {
|
|
|
4437
5388
|
return;
|
|
4438
5389
|
}
|
|
4439
5390
|
res.setHeader("ETag", hit.etag);
|
|
4440
|
-
res.setHeader("Content-Type", MIME_TYPES[
|
|
5391
|
+
res.setHeader("Content-Type", MIME_TYPES[import_node_path14.default.extname(fileName)] ?? "application/octet-stream");
|
|
4441
5392
|
res.setHeader("Cache-Control", "no-cache");
|
|
4442
5393
|
res.end(hit.content);
|
|
4443
5394
|
return;
|
|
4444
5395
|
}
|
|
4445
5396
|
if (pathname === "/" || pathname.endsWith(".html")) {
|
|
4446
|
-
const rawHtml = await readHtmlFile(config.root);
|
|
5397
|
+
const rawHtml = await readHtmlFile(config.root, config.environments.client?.html);
|
|
4447
5398
|
if (rawHtml) {
|
|
4448
5399
|
res.setHeader("Content-Type", "text/html");
|
|
4449
5400
|
res.setHeader("Cache-Control", "no-store");
|
|
@@ -4473,7 +5424,7 @@ function stripCatchAllLoad(plugins) {
|
|
|
4473
5424
|
);
|
|
4474
5425
|
}
|
|
4475
5426
|
function createReactRefreshRuntimePlugin(entryPoints) {
|
|
4476
|
-
const entryIds = new Set(entryPoints.map((p) =>
|
|
5427
|
+
const entryIds = new Set(entryPoints.map((p) => import_node_path14.default.resolve(p)));
|
|
4477
5428
|
return {
|
|
4478
5429
|
name: "nasti:bundled-react-refresh",
|
|
4479
5430
|
resolveId(source) {
|
|
@@ -4491,7 +5442,7 @@ function createReactRefreshRuntimePlugin(entryPoints) {
|
|
|
4491
5442
|
return null;
|
|
4492
5443
|
},
|
|
4493
5444
|
transform(code, id) {
|
|
4494
|
-
if (!entryIds.has(
|
|
5445
|
+
if (!entryIds.has(import_node_path14.default.resolve(id.split("?")[0]))) return null;
|
|
4495
5446
|
return { code: `import ${JSON.stringify(PREAMBLE_SPEC)};
|
|
4496
5447
|
${code}`, map: null };
|
|
4497
5448
|
}
|
|
@@ -4527,19 +5478,22 @@ async function renderBundledIndexHtml(html, config, entryFileNames) {
|
|
|
4527
5478
|
}
|
|
4528
5479
|
}
|
|
4529
5480
|
for (const [facadeModuleId, fileName] of entryFileNames) {
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
5481
|
+
processed = replaceEntryScript(
|
|
5482
|
+
processed,
|
|
5483
|
+
facadeModuleId,
|
|
5484
|
+
fileName,
|
|
5485
|
+
config,
|
|
5486
|
+
config.environments.client?.html ?? "index.html",
|
|
5487
|
+
"/"
|
|
4534
5488
|
);
|
|
4535
5489
|
}
|
|
4536
5490
|
return processed;
|
|
4537
5491
|
}
|
|
4538
|
-
var
|
|
5492
|
+
var import_node_path14, import_node_crypto3, import_ws2, import_picocolors7, debug6, MIME_TYPES, MemoryFiles, PREAMBLE_SPEC, RESOLVED_PREAMBLE_ID, REFRESH_RUNTIME_URL, BUNDLED_PREAMBLE_CODE, WRAPPER_RUNTIME_HELPERS;
|
|
4539
5493
|
var init_dev_engine = __esm({
|
|
4540
5494
|
"src/server/bundled/dev-engine.ts"() {
|
|
4541
5495
|
"use strict";
|
|
4542
|
-
|
|
5496
|
+
import_node_path14 = __toESM(require("path"), 1);
|
|
4543
5497
|
import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
4544
5498
|
import_ws2 = require("ws");
|
|
4545
5499
|
import_picocolors7 = __toESM(require("picocolors"), 1);
|
|
@@ -4666,27 +5620,38 @@ async function createServer(inlineConfig = {}) {
|
|
|
4666
5620
|
const startTime = performance.now();
|
|
4667
5621
|
const config = await resolveConfig(inlineConfig, "serve");
|
|
4668
5622
|
const logger = config.logger;
|
|
4669
|
-
const allPlugins = resolvePluginList(config, config.plugins
|
|
5623
|
+
const allPlugins = resolvePluginList(config, config.plugins, {
|
|
5624
|
+
environmentName: "client"
|
|
5625
|
+
});
|
|
4670
5626
|
const configWithPlugins = { ...config, plugins: allPlugins };
|
|
4671
5627
|
const app = (0, import_connect.default)();
|
|
4672
5628
|
const httpServer = import_node_http.default.createServer(app);
|
|
4673
5629
|
const ws = createWebSocketServer(httpServer);
|
|
4674
|
-
const
|
|
5630
|
+
const pluginApi = getPluginApi(config);
|
|
5631
|
+
const clientEnv = new NastiEnvironment("client", config, {
|
|
4675
5632
|
hot: createWsHotChannel(ws),
|
|
4676
5633
|
mode: "dev",
|
|
4677
|
-
plugins: allPlugins
|
|
5634
|
+
plugins: allPlugins,
|
|
5635
|
+
pluginApi
|
|
4678
5636
|
});
|
|
4679
5637
|
await clientEnv.init();
|
|
4680
5638
|
const environments = { client: clientEnv };
|
|
4681
5639
|
for (const name of Object.keys(config.environments)) {
|
|
4682
5640
|
if (name === "client") continue;
|
|
4683
5641
|
const consumer = config.environments[name].consumer;
|
|
4684
|
-
const envPlugins = resolvePluginList(config, config.plugins, {
|
|
4685
|
-
|
|
5642
|
+
const envPlugins = resolvePluginList(config, config.plugins, {
|
|
5643
|
+
consumer,
|
|
5644
|
+
environmentName: name
|
|
5645
|
+
});
|
|
5646
|
+
environments[name] = new NastiEnvironment(name, config, {
|
|
4686
5647
|
mode: "dev",
|
|
4687
|
-
plugins: envPlugins
|
|
5648
|
+
plugins: envPlugins,
|
|
5649
|
+
pluginApi
|
|
4688
5650
|
});
|
|
4689
5651
|
}
|
|
5652
|
+
for (const [name, environment] of Object.entries(environments)) {
|
|
5653
|
+
if (name !== "client" && environment.options.driver) await environment.init();
|
|
5654
|
+
}
|
|
4690
5655
|
let ssrRunner = null;
|
|
4691
5656
|
async function getSsrRunner() {
|
|
4692
5657
|
if (ssrRunner) return ssrRunner;
|
|
@@ -4711,23 +5676,15 @@ async function createServer(inlineConfig = {}) {
|
|
|
4711
5676
|
});
|
|
4712
5677
|
app.use(bundledServer.middleware);
|
|
4713
5678
|
}
|
|
4714
|
-
app.use(transformMiddleware({
|
|
4715
|
-
config: configWithPlugins,
|
|
4716
|
-
pluginContainer,
|
|
4717
|
-
moduleGraph
|
|
4718
|
-
}));
|
|
4719
|
-
const publicDir = import_node_path14.default.resolve(config.root, "public");
|
|
4720
|
-
app.use((0, import_sirv.default)(publicDir, { dev: true, etag: true }));
|
|
4721
|
-
app.use((0, import_sirv.default)(config.root, { dev: true, etag: true }));
|
|
4722
5679
|
const ignoredSegments = /* @__PURE__ */ new Set(["node_modules", ".git", ".nasti"]);
|
|
4723
|
-
const outDirAbs =
|
|
5680
|
+
const outDirAbs = import_node_path15.default.resolve(config.root, config.build.outDir);
|
|
4724
5681
|
const watcher = (0, import_chokidar.watch)(config.root, {
|
|
4725
5682
|
ignored: (filePath) => {
|
|
4726
5683
|
if (filePath === config.root) return false;
|
|
4727
|
-
if (filePath === outDirAbs || filePath.startsWith(outDirAbs +
|
|
4728
|
-
const rel =
|
|
4729
|
-
if (!rel || rel.startsWith("..") ||
|
|
4730
|
-
for (const seg of rel.split(
|
|
5684
|
+
if (filePath === outDirAbs || filePath.startsWith(outDirAbs + import_node_path15.default.sep)) return true;
|
|
5685
|
+
const rel = import_node_path15.default.relative(config.root, filePath);
|
|
5686
|
+
if (!rel || rel.startsWith("..") || import_node_path15.default.isAbsolute(rel)) return false;
|
|
5687
|
+
for (const seg of rel.split(import_node_path15.default.sep)) {
|
|
4731
5688
|
if (ignoredSegments.has(seg)) return true;
|
|
4732
5689
|
}
|
|
4733
5690
|
return false;
|
|
@@ -4735,13 +5692,72 @@ async function createServer(inlineConfig = {}) {
|
|
|
4735
5692
|
ignoreInitial: true
|
|
4736
5693
|
});
|
|
4737
5694
|
let server;
|
|
5695
|
+
const environmentServices = {};
|
|
5696
|
+
let environmentDriversStarted = false;
|
|
5697
|
+
const logCloseError = (target, error) => {
|
|
5698
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
5699
|
+
logger.error(`[nasti] failed to close ${target}`, { error: normalized });
|
|
5700
|
+
};
|
|
5701
|
+
const startEnvironmentDrivers = async () => {
|
|
5702
|
+
if (environmentDriversStarted) return;
|
|
5703
|
+
environmentDriversStarted = true;
|
|
5704
|
+
const started = [];
|
|
5705
|
+
const attempted = [];
|
|
5706
|
+
try {
|
|
5707
|
+
for (const [name, environment] of Object.entries(environments)) {
|
|
5708
|
+
if (!environment.driver?.serve) continue;
|
|
5709
|
+
attempted.push(environment);
|
|
5710
|
+
const result = await environment.driver.serve({
|
|
5711
|
+
...environment.getDriverContext(),
|
|
5712
|
+
server
|
|
5713
|
+
});
|
|
5714
|
+
started.push({ name, environment, service: result ?? {} });
|
|
5715
|
+
}
|
|
5716
|
+
for (const { name, service } of started) {
|
|
5717
|
+
environmentServices[name] = service;
|
|
5718
|
+
if (service.middleware) app.use(service.middleware);
|
|
5719
|
+
}
|
|
5720
|
+
} catch (error) {
|
|
5721
|
+
environmentDriversStarted = false;
|
|
5722
|
+
for (const { name } of started) {
|
|
5723
|
+
delete environmentServices[name];
|
|
5724
|
+
}
|
|
5725
|
+
for (const environment of attempted.reverse()) {
|
|
5726
|
+
try {
|
|
5727
|
+
await environment.driver?.close?.(environment.getDriverContext());
|
|
5728
|
+
} catch (closeError) {
|
|
5729
|
+
logCloseError(`environment driver "${environment.driver.name}"`, closeError);
|
|
5730
|
+
}
|
|
5731
|
+
}
|
|
5732
|
+
throw error;
|
|
5733
|
+
}
|
|
5734
|
+
};
|
|
5735
|
+
const notifyEnvironmentDrivers = (file, event) => {
|
|
5736
|
+
for (const environment of Object.values(environments)) {
|
|
5737
|
+
if (!environment.driver?.watchChange) continue;
|
|
5738
|
+
void Promise.resolve(
|
|
5739
|
+
environment.driver.watchChange(file, event, environment.getDriverContext())
|
|
5740
|
+
).catch((error) => {
|
|
5741
|
+
logger.error(
|
|
5742
|
+
`[nasti] environment driver "${environment.driver.name}" watchChange failed`,
|
|
5743
|
+
{ error }
|
|
5744
|
+
);
|
|
5745
|
+
});
|
|
5746
|
+
}
|
|
5747
|
+
};
|
|
4738
5748
|
watcher.on("change", (file) => {
|
|
4739
5749
|
ssrRunner?.invalidateFile(file);
|
|
4740
5750
|
handleFileChange(file, server);
|
|
5751
|
+
notifyEnvironmentDrivers(file, "change");
|
|
4741
5752
|
});
|
|
4742
5753
|
watcher.on("add", (file) => {
|
|
4743
5754
|
ssrRunner?.invalidateFile(file);
|
|
4744
5755
|
handleFileChange(file, server);
|
|
5756
|
+
notifyEnvironmentDrivers(file, "add");
|
|
5757
|
+
});
|
|
5758
|
+
watcher.on("unlink", (file) => {
|
|
5759
|
+
ssrRunner?.invalidateFile(file);
|
|
5760
|
+
notifyEnvironmentDrivers(file, "unlink");
|
|
4745
5761
|
});
|
|
4746
5762
|
server = {
|
|
4747
5763
|
config: configWithPlugins,
|
|
@@ -4750,10 +5766,12 @@ async function createServer(inlineConfig = {}) {
|
|
|
4750
5766
|
watcher,
|
|
4751
5767
|
ws,
|
|
4752
5768
|
environments,
|
|
5769
|
+
environmentServices,
|
|
4753
5770
|
async listen(port) {
|
|
4754
5771
|
const finalPort = port ?? config.server.port;
|
|
4755
5772
|
const host = config.server.host === true ? "0.0.0.0" : config.server.host;
|
|
4756
5773
|
await pluginContainer.buildStart();
|
|
5774
|
+
await startEnvironmentDrivers();
|
|
4757
5775
|
return new Promise((resolve, reject) => {
|
|
4758
5776
|
let currentPort = finalPort;
|
|
4759
5777
|
const onListening = () => {
|
|
@@ -4761,15 +5779,20 @@ async function createServer(inlineConfig = {}) {
|
|
|
4761
5779
|
config.server.port = actualPort;
|
|
4762
5780
|
const localUrl = `http://localhost:${actualPort}/`;
|
|
4763
5781
|
const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}/` : null;
|
|
5782
|
+
const driverLocalUrls = Object.values(environmentServices).flatMap((service) => service.localUrls ?? []);
|
|
5783
|
+
const driverNetworkUrls = Object.values(environmentServices).flatMap((service) => service.networkUrls ?? []);
|
|
4764
5784
|
logger.clearScreen("info");
|
|
4765
5785
|
const readyIn = Math.ceil(performance.now() - startTime);
|
|
4766
5786
|
logger.info(
|
|
4767
5787
|
`
|
|
4768
|
-
${import_picocolors8.default.cyan(import_picocolors8.default.bold("NASTI"))} ${import_picocolors8.default.cyan(`v${"2.
|
|
5788
|
+
${import_picocolors8.default.cyan(import_picocolors8.default.bold("NASTI"))} ${import_picocolors8.default.cyan(`v${"2.4.0"}`)} ${import_picocolors8.default.dim("ready in")} ${import_picocolors8.default.bold(readyIn)} ${import_picocolors8.default.dim("ms")}
|
|
4769
5789
|
`
|
|
4770
5790
|
);
|
|
4771
5791
|
printServerUrls(
|
|
4772
|
-
{
|
|
5792
|
+
{
|
|
5793
|
+
local: [localUrl, ...driverLocalUrls],
|
|
5794
|
+
network: [...networkUrl ? [networkUrl] : [], ...driverNetworkUrls]
|
|
5795
|
+
},
|
|
4773
5796
|
logger.info
|
|
4774
5797
|
);
|
|
4775
5798
|
logger.info("");
|
|
@@ -4790,7 +5813,12 @@ async function createServer(inlineConfig = {}) {
|
|
|
4790
5813
|
},
|
|
4791
5814
|
async transformRequest(url) {
|
|
4792
5815
|
const { transformRequest: transformRequest2 } = await Promise.resolve().then(() => (init_middleware(), middleware_exports));
|
|
4793
|
-
return transformRequest2(url, {
|
|
5816
|
+
return transformRequest2(url, {
|
|
5817
|
+
config: configWithPlugins,
|
|
5818
|
+
pluginContainer,
|
|
5819
|
+
moduleGraph,
|
|
5820
|
+
onPrune: (paths) => ws.send({ type: "prune", paths })
|
|
5821
|
+
});
|
|
4794
5822
|
},
|
|
4795
5823
|
async ssrLoadModule(url) {
|
|
4796
5824
|
const runner = await getSsrRunner();
|
|
@@ -4799,11 +5827,63 @@ async function createServer(inlineConfig = {}) {
|
|
|
4799
5827
|
async close() {
|
|
4800
5828
|
await pluginContainer.buildEnd();
|
|
4801
5829
|
await bundledServer?.close();
|
|
4802
|
-
|
|
5830
|
+
let environmentCloseFailed = false;
|
|
5831
|
+
let firstEnvironmentCloseError;
|
|
5832
|
+
for (const environment of Object.values(environments).reverse()) {
|
|
5833
|
+
try {
|
|
5834
|
+
await environment.close();
|
|
5835
|
+
} catch (error) {
|
|
5836
|
+
if (!environmentCloseFailed) {
|
|
5837
|
+
environmentCloseFailed = true;
|
|
5838
|
+
firstEnvironmentCloseError = error;
|
|
5839
|
+
}
|
|
5840
|
+
logCloseError(`environment "${environment.name}"`, error);
|
|
5841
|
+
}
|
|
5842
|
+
}
|
|
5843
|
+
await watcher.close();
|
|
4803
5844
|
ws.close();
|
|
4804
5845
|
httpServer.close();
|
|
5846
|
+
if (environmentCloseFailed) {
|
|
5847
|
+
throw firstEnvironmentCloseError;
|
|
5848
|
+
}
|
|
4805
5849
|
}
|
|
4806
5850
|
};
|
|
5851
|
+
try {
|
|
5852
|
+
await startEnvironmentDrivers();
|
|
5853
|
+
} catch (error) {
|
|
5854
|
+
if (bundledServer) {
|
|
5855
|
+
try {
|
|
5856
|
+
await bundledServer.close();
|
|
5857
|
+
} catch (closeError) {
|
|
5858
|
+
logCloseError("bundled dev server after driver startup failure", closeError);
|
|
5859
|
+
}
|
|
5860
|
+
}
|
|
5861
|
+
try {
|
|
5862
|
+
await watcher.close();
|
|
5863
|
+
} catch (closeError) {
|
|
5864
|
+
logCloseError("file watcher after driver startup failure", closeError);
|
|
5865
|
+
}
|
|
5866
|
+
try {
|
|
5867
|
+
ws.close();
|
|
5868
|
+
} catch (closeError) {
|
|
5869
|
+
logCloseError("WebSocket server after driver startup failure", closeError);
|
|
5870
|
+
}
|
|
5871
|
+
try {
|
|
5872
|
+
httpServer.close();
|
|
5873
|
+
} catch (closeError) {
|
|
5874
|
+
logCloseError("HTTP server after driver startup failure", closeError);
|
|
5875
|
+
}
|
|
5876
|
+
throw error;
|
|
5877
|
+
}
|
|
5878
|
+
app.use(transformMiddleware({
|
|
5879
|
+
config: configWithPlugins,
|
|
5880
|
+
pluginContainer,
|
|
5881
|
+
moduleGraph,
|
|
5882
|
+
onPrune: (paths) => ws.send({ type: "prune", paths })
|
|
5883
|
+
}));
|
|
5884
|
+
const publicDir = import_node_path15.default.resolve(config.root, "public");
|
|
5885
|
+
app.use((0, import_sirv.default)(publicDir, { dev: true, etag: true }));
|
|
5886
|
+
app.use((0, import_sirv.default)(config.root, { dev: true, etag: true }));
|
|
4807
5887
|
const postMiddlewares = [];
|
|
4808
5888
|
for (const plugin of allPlugins) {
|
|
4809
5889
|
if (plugin.configureServer) {
|
|
@@ -4827,12 +5907,12 @@ function getNetworkAddress() {
|
|
|
4827
5907
|
}
|
|
4828
5908
|
return "localhost";
|
|
4829
5909
|
}
|
|
4830
|
-
var import_node_http,
|
|
5910
|
+
var import_node_http, import_node_path15, import_node_os, import_connect, import_sirv, import_chokidar, import_picocolors8;
|
|
4831
5911
|
var init_server = __esm({
|
|
4832
5912
|
"src/server/index.ts"() {
|
|
4833
5913
|
"use strict";
|
|
4834
5914
|
import_node_http = __toESM(require("http"), 1);
|
|
4835
|
-
|
|
5915
|
+
import_node_path15 = __toESM(require("path"), 1);
|
|
4836
5916
|
import_node_os = __toESM(require("os"), 1);
|
|
4837
5917
|
import_connect = __toESM(require("connect"), 1);
|
|
4838
5918
|
import_sirv = __toESM(require("sirv"), 1);
|
|
@@ -4846,6 +5926,7 @@ var init_server = __esm({
|
|
|
4846
5926
|
init_middleware();
|
|
4847
5927
|
init_hmr();
|
|
4848
5928
|
init_builtins();
|
|
5929
|
+
init_plugin_api();
|
|
4849
5930
|
}
|
|
4850
5931
|
});
|
|
4851
5932
|
|
|
@@ -4892,6 +5973,7 @@ var init_electron = __esm({
|
|
|
4892
5973
|
var electron_exports = {};
|
|
4893
5974
|
__export(electron_exports, {
|
|
4894
5975
|
buildElectron: () => buildElectron,
|
|
5976
|
+
createElectronRendererConfig: () => createElectronRendererConfig,
|
|
4895
5977
|
detectInstalledElectron: () => detectInstalledElectron,
|
|
4896
5978
|
normalizePreload: () => normalizePreload
|
|
4897
5979
|
});
|
|
@@ -4899,28 +5981,26 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
4899
5981
|
const config = await resolveConfig({ ...inlineConfig, target: "electron" }, "build");
|
|
4900
5982
|
const startTime = performance.now();
|
|
4901
5983
|
assertElectronVersion(config);
|
|
4902
|
-
console.log(import_picocolors9.default.cyan("\n\u26A1 nasti build (electron)") + import_picocolors9.default.dim(` v${"2.
|
|
5984
|
+
console.log(import_picocolors9.default.cyan("\n\u26A1 nasti build (electron)") + import_picocolors9.default.dim(` v${"2.4.0"}`));
|
|
4903
5985
|
console.log(import_picocolors9.default.dim(` root: ${config.root}`));
|
|
4904
5986
|
console.log(import_picocolors9.default.dim(` mode: ${config.mode}`));
|
|
4905
5987
|
console.log(import_picocolors9.default.dim(` target: electron (\u2265 ${config.electron.minVersion})`));
|
|
4906
|
-
const outDir =
|
|
4907
|
-
if (config.build.emptyOutDir &&
|
|
4908
|
-
|
|
5988
|
+
const outDir = import_node_path16.default.resolve(config.root, config.build.outDir);
|
|
5989
|
+
if (config.build.emptyOutDir && import_node_fs11.default.existsSync(outDir)) {
|
|
5990
|
+
import_node_fs11.default.rmSync(outDir, { recursive: true, force: true });
|
|
4909
5991
|
}
|
|
4910
|
-
|
|
4911
|
-
const rendererOutDir =
|
|
5992
|
+
import_node_fs11.default.mkdirSync(outDir, { recursive: true });
|
|
5993
|
+
const rendererOutDir = import_node_path16.default.join(outDir, "renderer");
|
|
4912
5994
|
const { build: build2 } = await Promise.resolve().then(() => (init_build(), build_exports));
|
|
4913
|
-
await build2({
|
|
4914
|
-
...inlineConfig,
|
|
4915
|
-
target: "web",
|
|
5995
|
+
await build2(createElectronRendererConfig(config, inlineConfig, {
|
|
4916
5996
|
build: {
|
|
4917
5997
|
...inlineConfig.build,
|
|
4918
5998
|
outDir: rendererOutDir,
|
|
4919
5999
|
emptyOutDir: false
|
|
4920
6000
|
}
|
|
4921
|
-
});
|
|
4922
|
-
const mainEntry =
|
|
4923
|
-
if (!
|
|
6001
|
+
}));
|
|
6002
|
+
const mainEntry = import_node_path16.default.resolve(config.root, config.electron.main);
|
|
6003
|
+
if (!import_node_fs11.default.existsSync(mainEntry)) {
|
|
4924
6004
|
throw new Error(
|
|
4925
6005
|
`Electron main entry not found: ${config.electron.main}
|
|
4926
6006
|
\u5728 nasti.config.ts \u7684 electron.main \u6307\u5B9A\u4E3B\u8FDB\u7A0B\u5165\u53E3\u6587\u4EF6\u3002`
|
|
@@ -4934,11 +6014,11 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
4934
6014
|
const preloadEntries = normalizePreload(config.electron.preload, config.root);
|
|
4935
6015
|
const preloadFiles = [];
|
|
4936
6016
|
for (const entry of preloadEntries) {
|
|
4937
|
-
if (!
|
|
6017
|
+
if (!import_node_fs11.default.existsSync(entry)) {
|
|
4938
6018
|
console.warn(import_picocolors9.default.yellow(` \u26A0 preload entry not found, skipped: ${entry}`));
|
|
4939
6019
|
continue;
|
|
4940
6020
|
}
|
|
4941
|
-
const base =
|
|
6021
|
+
const base = import_node_path16.default.basename(entry).replace(/\.[^.]+$/, "");
|
|
4942
6022
|
const out = outFileName(outDir, base, config.electron.preloadFormat);
|
|
4943
6023
|
await bundleNode(config, entry, {
|
|
4944
6024
|
outFile: out,
|
|
@@ -4950,10 +6030,10 @@ async function buildElectron(inlineConfig = {}) {
|
|
|
4950
6030
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
4951
6031
|
console.log(import_picocolors9.default.green(`
|
|
4952
6032
|
\u2713 Electron build complete in ${elapsed}s`));
|
|
4953
|
-
console.log(import_picocolors9.default.dim(` renderer: ${
|
|
4954
|
-
console.log(import_picocolors9.default.dim(` main: ${
|
|
6033
|
+
console.log(import_picocolors9.default.dim(` renderer: ${import_node_path16.default.relative(config.root, rendererOutDir)}/`));
|
|
6034
|
+
console.log(import_picocolors9.default.dim(` main: ${import_node_path16.default.relative(config.root, mainFile)}`));
|
|
4955
6035
|
for (const pf of preloadFiles) {
|
|
4956
|
-
console.log(import_picocolors9.default.dim(` preload: ${
|
|
6036
|
+
console.log(import_picocolors9.default.dim(` preload: ${import_node_path16.default.relative(config.root, pf)}`));
|
|
4957
6037
|
}
|
|
4958
6038
|
console.log();
|
|
4959
6039
|
return { rendererOutDir, mainFile, preloadFiles };
|
|
@@ -4972,7 +6052,8 @@ async function bundleNode(config, entry, opts) {
|
|
|
4972
6052
|
const result = transformCode(id, code, {
|
|
4973
6053
|
sourcemap: !!config.build.sourcemap,
|
|
4974
6054
|
jsxRuntime: "automatic",
|
|
4975
|
-
jsxImportSource: config.framework === "vue" ? "vue" : "react"
|
|
6055
|
+
jsxImportSource: config.framework === "vue" ? "vue" : "react",
|
|
6056
|
+
target: config.electron.nodeTarget
|
|
4976
6057
|
});
|
|
4977
6058
|
return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
|
|
4978
6059
|
}
|
|
@@ -4983,10 +6064,14 @@ async function bundleNode(config, entry, opts) {
|
|
|
4983
6064
|
...restInputOptions,
|
|
4984
6065
|
input: entry,
|
|
4985
6066
|
platform: "node",
|
|
4986
|
-
transform: {
|
|
6067
|
+
transform: {
|
|
6068
|
+
...userTransform,
|
|
6069
|
+
target: config.electron.nodeTarget,
|
|
6070
|
+
define: mergedDefine
|
|
6071
|
+
},
|
|
4987
6072
|
plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
|
|
4988
6073
|
});
|
|
4989
|
-
|
|
6074
|
+
import_node_fs11.default.mkdirSync(import_node_path16.default.dirname(opts.outFile), { recursive: true });
|
|
4990
6075
|
await bundle2.write({
|
|
4991
6076
|
sourcemap: !!config.build.sourcemap,
|
|
4992
6077
|
minify: !!config.build.minify,
|
|
@@ -4997,16 +6082,35 @@ async function bundleNode(config, entry, opts) {
|
|
|
4997
6082
|
codeSplitting: false
|
|
4998
6083
|
});
|
|
4999
6084
|
await bundle2.close();
|
|
5000
|
-
console.log(import_picocolors9.default.dim(` \u2713 ${opts.label} \u2192 ${
|
|
6085
|
+
console.log(import_picocolors9.default.dim(` \u2713 ${opts.label} \u2192 ${import_node_path16.default.relative(config.root, opts.outFile)}`));
|
|
5001
6086
|
return opts.outFile;
|
|
5002
6087
|
}
|
|
6088
|
+
function createElectronRendererConfig(config, inlineConfig = {}, overrides = {}) {
|
|
6089
|
+
const inlineClient = inlineConfig.environments?.client ?? {};
|
|
6090
|
+
return {
|
|
6091
|
+
...inlineConfig,
|
|
6092
|
+
...overrides,
|
|
6093
|
+
root: config.root,
|
|
6094
|
+
mode: config.mode,
|
|
6095
|
+
target: "web",
|
|
6096
|
+
framework: config.framework,
|
|
6097
|
+
base: config.base === "/" ? "./" : config.base,
|
|
6098
|
+
environments: {
|
|
6099
|
+
...inlineConfig.environments ?? {},
|
|
6100
|
+
client: {
|
|
6101
|
+
...inlineClient,
|
|
6102
|
+
html: config.electron.renderer
|
|
6103
|
+
}
|
|
6104
|
+
}
|
|
6105
|
+
};
|
|
6106
|
+
}
|
|
5003
6107
|
function outFileName(outDir, base, format) {
|
|
5004
6108
|
const ext = format === "cjs" ? ".cjs" : ".mjs";
|
|
5005
|
-
return
|
|
6109
|
+
return import_node_path16.default.join(outDir, base + ext);
|
|
5006
6110
|
}
|
|
5007
6111
|
function normalizePreload(preload, root) {
|
|
5008
6112
|
const list = Array.isArray(preload) ? preload : preload ? [preload] : [];
|
|
5009
|
-
return list.map((p) =>
|
|
6113
|
+
return list.map((p) => import_node_path16.default.resolve(root, p));
|
|
5010
6114
|
}
|
|
5011
6115
|
function assertElectronVersion(config) {
|
|
5012
6116
|
const min = config.electron.minVersion;
|
|
@@ -5021,21 +6125,21 @@ function assertElectronVersion(config) {
|
|
|
5021
6125
|
}
|
|
5022
6126
|
function detectInstalledElectron(root) {
|
|
5023
6127
|
try {
|
|
5024
|
-
const pkgPath =
|
|
5025
|
-
if (!
|
|
5026
|
-
const pkg = JSON.parse(
|
|
6128
|
+
const pkgPath = import_node_path16.default.resolve(root, "node_modules/electron/package.json");
|
|
6129
|
+
if (!import_node_fs11.default.existsSync(pkgPath)) return null;
|
|
6130
|
+
const pkg = JSON.parse(import_node_fs11.default.readFileSync(pkgPath, "utf-8"));
|
|
5027
6131
|
const major = parseInt(String(pkg.version).split(".")[0], 10);
|
|
5028
6132
|
return Number.isFinite(major) ? major : null;
|
|
5029
6133
|
} catch {
|
|
5030
6134
|
return null;
|
|
5031
6135
|
}
|
|
5032
6136
|
}
|
|
5033
|
-
var
|
|
6137
|
+
var import_node_path16, import_node_fs11, import_rolldown2, import_picocolors9;
|
|
5034
6138
|
var init_electron2 = __esm({
|
|
5035
6139
|
"src/build/electron.ts"() {
|
|
5036
6140
|
"use strict";
|
|
5037
|
-
|
|
5038
|
-
|
|
6141
|
+
import_node_path16 = __toESM(require("path"), 1);
|
|
6142
|
+
import_node_fs11 = __toESM(require("fs"), 1);
|
|
5039
6143
|
import_rolldown2 = require("rolldown");
|
|
5040
6144
|
import_picocolors9 = __toESM(require("picocolors"), 1);
|
|
5041
6145
|
init_config();
|
|
@@ -5049,23 +6153,28 @@ var init_electron2 = __esm({
|
|
|
5049
6153
|
// src/server/electron-dev.ts
|
|
5050
6154
|
var electron_dev_exports = {};
|
|
5051
6155
|
__export(electron_dev_exports, {
|
|
6156
|
+
electronRendererDevPath: () => electronRendererDevPath,
|
|
5052
6157
|
startElectronDev: () => startElectronDev
|
|
5053
6158
|
});
|
|
5054
6159
|
async function startElectronDev(inlineConfig = {}) {
|
|
5055
6160
|
const { noSpawn, ...rest } = inlineConfig;
|
|
5056
6161
|
const config = await resolveConfig({ ...rest, target: "electron" }, "serve");
|
|
5057
6162
|
warnElectronVersion(config);
|
|
5058
|
-
console.log(import_picocolors10.default.cyan("\n\u26A1 nasti electron dev") + import_picocolors10.default.dim(` v${"2.
|
|
6163
|
+
console.log(import_picocolors10.default.cyan("\n\u26A1 nasti electron dev") + import_picocolors10.default.dim(` v${"2.4.0"}`));
|
|
5059
6164
|
const { createServer: createServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
5060
|
-
const server = await createServer2({
|
|
6165
|
+
const server = await createServer2({
|
|
6166
|
+
...rest,
|
|
6167
|
+
target: "electron",
|
|
6168
|
+
framework: config.framework
|
|
6169
|
+
});
|
|
5061
6170
|
await server.listen();
|
|
5062
|
-
const devUrl = `http://localhost:${server.config.server.port}
|
|
6171
|
+
const devUrl = `http://localhost:${server.config.server.port}` + electronRendererDevPath(config.electron.renderer);
|
|
5063
6172
|
console.log(import_picocolors10.default.dim(` renderer: ${devUrl}`));
|
|
5064
|
-
const stageDir =
|
|
5065
|
-
|
|
5066
|
-
const mainEntry =
|
|
6173
|
+
const stageDir = import_node_path17.default.resolve(config.root, ".nasti");
|
|
6174
|
+
import_node_fs12.default.mkdirSync(stageDir, { recursive: true });
|
|
6175
|
+
const mainEntry = import_node_path17.default.resolve(config.root, config.electron.main);
|
|
5067
6176
|
const preloadEntries = normalizePreload(config.electron.preload, config.root);
|
|
5068
|
-
const builtMainFile =
|
|
6177
|
+
const builtMainFile = import_node_path17.default.join(stageDir, "main" + extFor(config.electron.mainFormat));
|
|
5069
6178
|
const builtPreloadFiles = [];
|
|
5070
6179
|
const compileAll = async () => {
|
|
5071
6180
|
await compileNode(config, mainEntry, {
|
|
@@ -5075,9 +6184,9 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5075
6184
|
});
|
|
5076
6185
|
builtPreloadFiles.length = 0;
|
|
5077
6186
|
for (const entry of preloadEntries) {
|
|
5078
|
-
if (!
|
|
5079
|
-
const base =
|
|
5080
|
-
const out =
|
|
6187
|
+
if (!import_node_fs12.default.existsSync(entry)) continue;
|
|
6188
|
+
const base = import_node_path17.default.basename(entry).replace(/\.[^.]+$/, "");
|
|
6189
|
+
const out = import_node_path17.default.join(stageDir, base + extFor(config.electron.preloadFormat));
|
|
5081
6190
|
await compileNode(config, entry, {
|
|
5082
6191
|
outFile: out,
|
|
5083
6192
|
format: config.electron.preloadFormat,
|
|
@@ -5116,7 +6225,7 @@ async function startElectronDev(inlineConfig = {}) {
|
|
|
5116
6225
|
};
|
|
5117
6226
|
spawnElectron();
|
|
5118
6227
|
if (config.electron.autoRestart) {
|
|
5119
|
-
const watchTargets = [mainEntry, ...preloadEntries].filter(
|
|
6228
|
+
const watchTargets = [mainEntry, ...preloadEntries].filter(import_node_fs12.default.existsSync);
|
|
5120
6229
|
const watcher = import_chokidar2.default.watch(watchTargets, { ignoreInitial: true });
|
|
5121
6230
|
let restarting = null;
|
|
5122
6231
|
let pending = false;
|
|
@@ -5181,18 +6290,22 @@ async function compileNode(config, entry, opts) {
|
|
|
5181
6290
|
const result = transformCode(id, code, {
|
|
5182
6291
|
sourcemap: true,
|
|
5183
6292
|
jsxRuntime: "automatic",
|
|
5184
|
-
jsxImportSource: config.framework === "vue" ? "vue" : "react"
|
|
6293
|
+
jsxImportSource: config.framework === "vue" ? "vue" : "react",
|
|
6294
|
+
target: config.electron.nodeTarget
|
|
5185
6295
|
});
|
|
5186
6296
|
return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
|
|
5187
6297
|
}
|
|
5188
6298
|
};
|
|
5189
6299
|
const bundle2 = await (0, import_rolldown3.rolldown)({
|
|
5190
6300
|
input: entry,
|
|
5191
|
-
transform: {
|
|
6301
|
+
transform: {
|
|
6302
|
+
target: config.electron.nodeTarget,
|
|
6303
|
+
define: envDefine
|
|
6304
|
+
},
|
|
5192
6305
|
platform: "node",
|
|
5193
6306
|
plugins: [oxcTransformPlugin, electronPlugin(config), resolvePlugin(config)]
|
|
5194
6307
|
});
|
|
5195
|
-
|
|
6308
|
+
import_node_fs12.default.mkdirSync(import_node_path17.default.dirname(opts.outFile), { recursive: true });
|
|
5196
6309
|
await bundle2.write({
|
|
5197
6310
|
file: opts.outFile,
|
|
5198
6311
|
format: opts.format === "cjs" ? "cjs" : "esm",
|
|
@@ -5204,15 +6317,19 @@ async function compileNode(config, entry, opts) {
|
|
|
5204
6317
|
});
|
|
5205
6318
|
await bundle2.close();
|
|
5206
6319
|
}
|
|
6320
|
+
function electronRendererDevPath(renderer) {
|
|
6321
|
+
const normalized = renderer.split(import_node_path17.default.sep).join("/").replace(/^\.?\//, "");
|
|
6322
|
+
return normalized === "index.html" ? "/" : `/${normalized}`;
|
|
6323
|
+
}
|
|
5207
6324
|
function resolveElectronBinary(config) {
|
|
5208
|
-
if (config.electron.electronPath &&
|
|
6325
|
+
if (config.electron.electronPath && import_node_fs12.default.existsSync(config.electron.electronPath)) {
|
|
5209
6326
|
return config.electron.electronPath;
|
|
5210
6327
|
}
|
|
5211
6328
|
try {
|
|
5212
|
-
const require2 = (0, import_node_module7.createRequire)(
|
|
6329
|
+
const require2 = (0, import_node_module7.createRequire)(import_node_path17.default.resolve(config.root, "package.json"));
|
|
5213
6330
|
const pathFile = require2.resolve("electron");
|
|
5214
6331
|
const electronModule = require2(pathFile);
|
|
5215
|
-
if (typeof electronModule === "string" &&
|
|
6332
|
+
if (typeof electronModule === "string" && import_node_fs12.default.existsSync(electronModule)) {
|
|
5216
6333
|
return electronModule;
|
|
5217
6334
|
}
|
|
5218
6335
|
} catch {
|
|
@@ -5237,12 +6354,12 @@ function warnElectronVersion(config) {
|
|
|
5237
6354
|
);
|
|
5238
6355
|
}
|
|
5239
6356
|
}
|
|
5240
|
-
var
|
|
6357
|
+
var import_node_path17, import_node_fs12, import_node_module7, import_node_child_process, import_chokidar2, import_picocolors10, import_rolldown3;
|
|
5241
6358
|
var init_electron_dev = __esm({
|
|
5242
6359
|
"src/server/electron-dev.ts"() {
|
|
5243
6360
|
"use strict";
|
|
5244
|
-
|
|
5245
|
-
|
|
6361
|
+
import_node_path17 = __toESM(require("path"), 1);
|
|
6362
|
+
import_node_fs12 = __toESM(require("fs"), 1);
|
|
5246
6363
|
import_node_module7 = require("module");
|
|
5247
6364
|
import_node_child_process = require("child_process");
|
|
5248
6365
|
import_chokidar2 = __toESM(require("chokidar"), 1);
|
|
@@ -5395,20 +6512,20 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
|
|
|
5395
6512
|
const logger = createCliLogger(options);
|
|
5396
6513
|
try {
|
|
5397
6514
|
const http2 = await import("http");
|
|
5398
|
-
const
|
|
6515
|
+
const path18 = await import("path");
|
|
5399
6516
|
const os2 = await import("os");
|
|
5400
6517
|
const sirv2 = (await import("sirv")).default;
|
|
5401
6518
|
const connect2 = (await import("connect")).default;
|
|
5402
6519
|
const { printServerUrls: printServerUrls2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
|
|
5403
|
-
const resolvedRoot =
|
|
5404
|
-
const outDir =
|
|
6520
|
+
const resolvedRoot = path18.resolve(root ?? ".");
|
|
6521
|
+
const outDir = path18.resolve(resolvedRoot, options.outDir);
|
|
5405
6522
|
const app = connect2();
|
|
5406
6523
|
app.use(sirv2(outDir, { single: true, etag: true, gzip: true, brotli: true }));
|
|
5407
6524
|
const port = options.port;
|
|
5408
6525
|
const host = options.host === true ? "0.0.0.0" : options.host ?? "localhost";
|
|
5409
6526
|
http2.createServer(app).listen(port, host, () => {
|
|
5410
6527
|
logger.info(`
|
|
5411
|
-
${import_picocolors11.default.cyan(import_picocolors11.default.bold("NASTI"))} ${import_picocolors11.default.cyan(`v${"2.
|
|
6528
|
+
${import_picocolors11.default.cyan(import_picocolors11.default.bold("NASTI"))} ${import_picocolors11.default.cyan(`v${"2.4.0"}`)} ${import_picocolors11.default.dim("preview")}
|
|
5412
6529
|
`);
|
|
5413
6530
|
printServerUrls2(
|
|
5414
6531
|
{
|
|
@@ -5425,6 +6542,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
|
|
|
5425
6542
|
}
|
|
5426
6543
|
});
|
|
5427
6544
|
cli.help();
|
|
5428
|
-
cli.version("2.
|
|
6545
|
+
cli.version("2.4.0");
|
|
5429
6546
|
cli.parse();
|
|
5430
6547
|
//# sourceMappingURL=cli.cjs.map
|