@nasti-toolchain/nasti 1.2.1 → 1.3.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/dist/cli.cjs +269 -100
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +260 -98
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +336 -166
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +333 -170
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
-
}) : x)(function(x) {
|
|
6
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
-
});
|
|
9
3
|
var __esm = (fn, res) => function __init() {
|
|
10
4
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
5
|
};
|
|
@@ -62,6 +56,27 @@ var init_defaults = __esm({
|
|
|
62
56
|
import { pathToFileURL } from "url";
|
|
63
57
|
import path from "path";
|
|
64
58
|
import fs from "fs";
|
|
59
|
+
function loadTsconfigPaths(root) {
|
|
60
|
+
const tsconfigPath = path.resolve(root, "tsconfig.json");
|
|
61
|
+
if (!fs.existsSync(tsconfigPath)) return {};
|
|
62
|
+
try {
|
|
63
|
+
const content = fs.readFileSync(tsconfigPath, "utf-8");
|
|
64
|
+
const stripped = content.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
65
|
+
const tsconfig = JSON.parse(stripped);
|
|
66
|
+
const paths = tsconfig?.compilerOptions?.paths ?? {};
|
|
67
|
+
const baseUrl = tsconfig?.compilerOptions?.baseUrl ?? ".";
|
|
68
|
+
const alias = {};
|
|
69
|
+
for (const [pattern, targets] of Object.entries(paths)) {
|
|
70
|
+
if (!targets.length) continue;
|
|
71
|
+
const cleanKey = pattern.replace(/\/\*$/, "");
|
|
72
|
+
const cleanTarget = targets[0].replace(/\/\*$/, "");
|
|
73
|
+
alias[cleanKey] = path.resolve(root, baseUrl, cleanTarget);
|
|
74
|
+
}
|
|
75
|
+
return alias;
|
|
76
|
+
} catch {
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
65
80
|
async function loadConfigFromFile(root) {
|
|
66
81
|
for (const file of CONFIG_FILES) {
|
|
67
82
|
const filePath = path.resolve(root, file);
|
|
@@ -104,11 +119,6 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
104
119
|
if (result) Object.assign(merged, result);
|
|
105
120
|
}
|
|
106
121
|
}
|
|
107
|
-
const filteredPlugins = rawPlugins.filter((p) => {
|
|
108
|
-
if (!p.apply) return true;
|
|
109
|
-
if (typeof p.apply === "function") return p.apply(resolved, env);
|
|
110
|
-
return p.apply === command;
|
|
111
|
-
});
|
|
112
122
|
const resolved = {
|
|
113
123
|
root,
|
|
114
124
|
base: merged.base ?? defaults.base,
|
|
@@ -116,17 +126,24 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
116
126
|
framework: merged.framework ?? defaults.framework,
|
|
117
127
|
command,
|
|
118
128
|
resolve: {
|
|
119
|
-
|
|
129
|
+
// tsconfig paths 优先级最低:tsconfig < defaults < user config
|
|
130
|
+
alias: { ...loadTsconfigPaths(root), ...defaults.resolve.alias, ...merged.resolve?.alias },
|
|
120
131
|
extensions: merged.resolve?.extensions ?? defaults.resolve.extensions,
|
|
121
132
|
conditions: merged.resolve?.conditions ?? defaults.resolve.conditions,
|
|
122
133
|
mainFields: merged.resolve?.mainFields ?? defaults.resolve.mainFields
|
|
123
134
|
},
|
|
124
|
-
plugins:
|
|
135
|
+
plugins: [],
|
|
125
136
|
server: { ...defaults.server, ...merged.server },
|
|
126
137
|
build: { ...defaults.build, ...merged.build },
|
|
127
138
|
envPrefix: Array.isArray(merged.envPrefix) ? merged.envPrefix : merged.envPrefix ? [merged.envPrefix] : [...defaults.envPrefix],
|
|
128
139
|
logLevel: merged.logLevel ?? defaults.logLevel
|
|
129
140
|
};
|
|
141
|
+
const filteredPlugins = rawPlugins.filter((p) => {
|
|
142
|
+
if (!p.apply) return true;
|
|
143
|
+
if (typeof p.apply === "function") return p.apply(resolved, env);
|
|
144
|
+
return p.apply === command;
|
|
145
|
+
});
|
|
146
|
+
resolved.plugins = filteredPlugins;
|
|
130
147
|
for (const plugin of resolved.plugins) {
|
|
131
148
|
if (plugin.configResolved) {
|
|
132
149
|
await plugin.configResolved(resolved);
|
|
@@ -183,6 +200,7 @@ var init_plugin_container = __esm({
|
|
|
183
200
|
plugins;
|
|
184
201
|
config;
|
|
185
202
|
ctx;
|
|
203
|
+
emittedFiles = /* @__PURE__ */ new Map();
|
|
186
204
|
constructor(config) {
|
|
187
205
|
this.config = config;
|
|
188
206
|
this.plugins = sortPlugins(config.plugins);
|
|
@@ -194,14 +212,24 @@ var init_plugin_container = __esm({
|
|
|
194
212
|
async resolve(source, importer) {
|
|
195
213
|
return container.resolveId(source, importer);
|
|
196
214
|
},
|
|
197
|
-
emitFile(
|
|
198
|
-
|
|
215
|
+
emitFile(file) {
|
|
216
|
+
const fileName = file.fileName ?? file.name ?? `asset-${container.emittedFiles.size}`;
|
|
217
|
+
const id = `emitted:${fileName}`;
|
|
218
|
+
container.emittedFiles.set(id, {
|
|
219
|
+
fileName,
|
|
220
|
+
source: file.source ?? ""
|
|
221
|
+
});
|
|
222
|
+
return id;
|
|
199
223
|
},
|
|
200
224
|
getModuleInfo(_id) {
|
|
201
225
|
return null;
|
|
202
226
|
}
|
|
203
227
|
};
|
|
204
228
|
}
|
|
229
|
+
/** 返回所有通过 emitFile() 输出的文件 */
|
|
230
|
+
getEmittedFiles() {
|
|
231
|
+
return Array.from(this.emittedFiles.values());
|
|
232
|
+
}
|
|
205
233
|
async buildStart() {
|
|
206
234
|
for (const plugin of this.plugins) {
|
|
207
235
|
if (plugin.buildStart) {
|
|
@@ -445,6 +473,11 @@ function transformCode(filename, code, options = {}) {
|
|
|
445
473
|
} : void 0,
|
|
446
474
|
sourcemap: options.sourcemap ?? true
|
|
447
475
|
});
|
|
476
|
+
if (result.errors && result.errors.length > 0) {
|
|
477
|
+
const msg = result.errors.map((e) => e.message ?? String(e)).join("\n");
|
|
478
|
+
throw new Error(`OXC transform failed for ${filename}:
|
|
479
|
+
${msg}`);
|
|
480
|
+
}
|
|
448
481
|
return {
|
|
449
482
|
code: result.code,
|
|
450
483
|
map: result.map ? JSON.stringify(result.map) : null
|
|
@@ -526,17 +559,94 @@ var init_html = __esm({
|
|
|
526
559
|
}
|
|
527
560
|
});
|
|
528
561
|
|
|
562
|
+
// src/core/env.ts
|
|
563
|
+
import path3 from "path";
|
|
564
|
+
import fs3 from "fs";
|
|
565
|
+
function loadEnv(mode, root, prefixes) {
|
|
566
|
+
const envFiles = [
|
|
567
|
+
".env",
|
|
568
|
+
`.env.${mode}`,
|
|
569
|
+
".env.local",
|
|
570
|
+
`.env.${mode}.local`
|
|
571
|
+
];
|
|
572
|
+
const raw = {};
|
|
573
|
+
for (const file of envFiles) {
|
|
574
|
+
const filePath = path3.resolve(root, file);
|
|
575
|
+
if (!fs3.existsSync(filePath)) continue;
|
|
576
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
577
|
+
for (const line of content.split("\n")) {
|
|
578
|
+
const trimmed = line.trim();
|
|
579
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
580
|
+
const eqIdx = trimmed.indexOf("=");
|
|
581
|
+
if (eqIdx === -1) continue;
|
|
582
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
583
|
+
let value = trimmed.slice(eqIdx + 1).trim();
|
|
584
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
585
|
+
value = value.slice(1, -1);
|
|
586
|
+
}
|
|
587
|
+
raw[key] = value;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
const filtered = {};
|
|
591
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
592
|
+
if (prefixes.some((prefix) => key.startsWith(prefix))) {
|
|
593
|
+
filtered[key] = value;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return filtered;
|
|
597
|
+
}
|
|
598
|
+
function buildEnvDefine(env, mode) {
|
|
599
|
+
const define = {};
|
|
600
|
+
for (const [key, value] of Object.entries(env)) {
|
|
601
|
+
define[`import.meta.env.${key}`] = JSON.stringify(value);
|
|
602
|
+
}
|
|
603
|
+
define["import.meta.env.MODE"] = JSON.stringify(mode);
|
|
604
|
+
define["import.meta.env.DEV"] = mode !== "production" ? "true" : "false";
|
|
605
|
+
define["import.meta.env.PROD"] = mode === "production" ? "true" : "false";
|
|
606
|
+
define["import.meta.env.SSR"] = "false";
|
|
607
|
+
return define;
|
|
608
|
+
}
|
|
609
|
+
function replaceEnvInCode(code, define) {
|
|
610
|
+
let result = code;
|
|
611
|
+
for (const [key, value] of Object.entries(define)) {
|
|
612
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
613
|
+
result = result.replace(new RegExp(escaped, "g"), value);
|
|
614
|
+
}
|
|
615
|
+
return result;
|
|
616
|
+
}
|
|
617
|
+
var init_env = __esm({
|
|
618
|
+
"src/core/env.ts"() {
|
|
619
|
+
"use strict";
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
|
|
529
623
|
// src/server/middleware.ts
|
|
530
624
|
var middleware_exports = {};
|
|
531
625
|
__export(middleware_exports, {
|
|
532
626
|
transformMiddleware: () => transformMiddleware,
|
|
533
627
|
transformRequest: () => transformRequest
|
|
534
628
|
});
|
|
535
|
-
import
|
|
536
|
-
import
|
|
629
|
+
import path4 from "path";
|
|
630
|
+
import fs4 from "fs";
|
|
631
|
+
import { createRequire } from "module";
|
|
537
632
|
function transformMiddleware(ctx) {
|
|
633
|
+
ctx.envDefine = buildEnvDefine(
|
|
634
|
+
loadEnv(ctx.config.mode, ctx.config.root, ctx.config.envPrefix),
|
|
635
|
+
ctx.config.mode
|
|
636
|
+
);
|
|
538
637
|
return async (req, res, next) => {
|
|
539
638
|
const url = req.url ?? "/";
|
|
639
|
+
if (ctx.config.server.cors) {
|
|
640
|
+
const origin = req.headers.origin ?? "*";
|
|
641
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
642
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
|
|
643
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
644
|
+
if (req.method === "OPTIONS") {
|
|
645
|
+
res.statusCode = 204;
|
|
646
|
+
res.end();
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
540
650
|
if (req.method !== "GET") return next();
|
|
541
651
|
if (url === "/@nasti/client") {
|
|
542
652
|
res.setHeader("Content-Type", "application/javascript");
|
|
@@ -559,10 +669,6 @@ function transformMiddleware(ctx) {
|
|
|
559
669
|
}
|
|
560
670
|
}
|
|
561
671
|
}
|
|
562
|
-
processedHtml = processedHtml.replace(
|
|
563
|
-
"<head>",
|
|
564
|
-
'<head>\n <script type="module" src="/@nasti/client"></script>'
|
|
565
|
-
);
|
|
566
672
|
res.setHeader("Content-Type", "text/html");
|
|
567
673
|
res.end(processedHtml);
|
|
568
674
|
return;
|
|
@@ -595,10 +701,10 @@ async function transformRequest(url, ctx) {
|
|
|
595
701
|
return cached.transformResult;
|
|
596
702
|
}
|
|
597
703
|
const filePath = resolveUrlToFile(url, config.root);
|
|
598
|
-
if (!filePath || !
|
|
704
|
+
if (!filePath || !fs4.existsSync(filePath)) return null;
|
|
599
705
|
const mod = await moduleGraph.ensureEntryFromUrl(url);
|
|
600
706
|
moduleGraph.registerModule(mod, filePath);
|
|
601
|
-
let code =
|
|
707
|
+
let code = fs4.readFileSync(filePath, "utf-8");
|
|
602
708
|
const pluginResult = await pluginContainer.transform(code, filePath);
|
|
603
709
|
if (pluginResult) {
|
|
604
710
|
code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
|
|
@@ -612,23 +718,33 @@ async function transformRequest(url, ctx) {
|
|
|
612
718
|
});
|
|
613
719
|
code = result.code;
|
|
614
720
|
}
|
|
721
|
+
const envDefine = ctx.envDefine ?? buildEnvDefine(
|
|
722
|
+
loadEnv(config.mode, config.root, config.envPrefix),
|
|
723
|
+
config.mode
|
|
724
|
+
);
|
|
725
|
+
code = replaceEnvInCode(code, envDefine);
|
|
615
726
|
code = rewriteImports(code, config);
|
|
616
727
|
const transformResult = { code };
|
|
617
728
|
mod.transformResult = transformResult;
|
|
618
729
|
return transformResult;
|
|
619
730
|
}
|
|
620
|
-
function rewriteImports(code,
|
|
731
|
+
function rewriteImports(code, _config) {
|
|
621
732
|
return code.replace(
|
|
622
|
-
|
|
623
|
-
(match, specifier) => {
|
|
624
|
-
|
|
625
|
-
|
|
733
|
+
/\bfrom\s+(['"])([^'"./][^'"]*)\1/g,
|
|
734
|
+
(match, quote, specifier) => {
|
|
735
|
+
return `from ${quote}/@modules/${specifier}${quote}`;
|
|
736
|
+
}
|
|
737
|
+
).replace(
|
|
738
|
+
// 处理纯副作用导入: import 'bare-specifier'
|
|
739
|
+
/\bimport\s+(['"])([^'"./][^'"]*)\1/g,
|
|
740
|
+
(match, quote, specifier) => {
|
|
741
|
+
return `import ${quote}/@modules/${specifier}${quote}`;
|
|
626
742
|
}
|
|
627
743
|
).replace(
|
|
628
|
-
|
|
629
|
-
(
|
|
630
|
-
|
|
631
|
-
return `import
|
|
744
|
+
// 处理动态导入: import('bare-specifier')
|
|
745
|
+
/\bimport\s*\(\s*(['"])([^'"./][^'"]*)\1\s*\)/g,
|
|
746
|
+
(match, quote, specifier) => {
|
|
747
|
+
return `import(${quote}/@modules/${specifier}${quote})`;
|
|
632
748
|
}
|
|
633
749
|
);
|
|
634
750
|
}
|
|
@@ -637,14 +753,13 @@ function resolveUrlToFile(url, root) {
|
|
|
637
753
|
if (cleanUrl.startsWith("/@modules/")) {
|
|
638
754
|
const moduleName = cleanUrl.slice("/@modules/".length);
|
|
639
755
|
try {
|
|
640
|
-
const
|
|
641
|
-
const req = createRequire2(path3.resolve(root, "package.json"));
|
|
756
|
+
const req = createRequire(path4.resolve(root, "package.json"));
|
|
642
757
|
return req.resolve(moduleName);
|
|
643
758
|
} catch {
|
|
644
759
|
return null;
|
|
645
760
|
}
|
|
646
761
|
}
|
|
647
|
-
return
|
|
762
|
+
return path4.resolve(root, cleanUrl.replace(/^\//, ""));
|
|
648
763
|
}
|
|
649
764
|
function isModuleRequest(url) {
|
|
650
765
|
const cleanUrl = url.split("?")[0];
|
|
@@ -706,7 +821,18 @@ function showErrorOverlay(err) {
|
|
|
706
821
|
const overlay = document.createElement('div');
|
|
707
822
|
overlay.id = 'nasti-error-overlay';
|
|
708
823
|
overlay.style.cssText = 'position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,0.85);color:#fff;font-family:monospace;padding:2rem;overflow:auto;';
|
|
709
|
-
|
|
824
|
+
const title = document.createElement('h2');
|
|
825
|
+
title.style.color = '#ff5555';
|
|
826
|
+
title.textContent = 'Build Error';
|
|
827
|
+
const pre = document.createElement('pre');
|
|
828
|
+
pre.textContent = err.message + '\\n' + (err.stack || '');
|
|
829
|
+
const btn = document.createElement('button');
|
|
830
|
+
btn.style.cssText = 'margin-top:1rem;padding:0.5rem 1rem;cursor:pointer';
|
|
831
|
+
btn.textContent = 'Close';
|
|
832
|
+
btn.onclick = () => overlay.remove();
|
|
833
|
+
overlay.appendChild(title);
|
|
834
|
+
overlay.appendChild(pre);
|
|
835
|
+
overlay.appendChild(btn);
|
|
710
836
|
document.body.appendChild(overlay);
|
|
711
837
|
}
|
|
712
838
|
|
|
@@ -742,15 +868,16 @@ var init_middleware = __esm({
|
|
|
742
868
|
"use strict";
|
|
743
869
|
init_transformer();
|
|
744
870
|
init_html();
|
|
871
|
+
init_env();
|
|
745
872
|
}
|
|
746
873
|
});
|
|
747
874
|
|
|
748
875
|
// src/server/hmr.ts
|
|
749
|
-
import
|
|
750
|
-
import
|
|
876
|
+
import path5 from "path";
|
|
877
|
+
import fs5 from "fs";
|
|
751
878
|
async function handleFileChange(file, server) {
|
|
752
879
|
const { moduleGraph, ws, config } = server;
|
|
753
|
-
const relativePath = "/" +
|
|
880
|
+
const relativePath = "/" + path5.relative(config.root, file);
|
|
754
881
|
const mods = moduleGraph.getModulesByFile(file);
|
|
755
882
|
if (!mods || mods.size === 0) {
|
|
756
883
|
return;
|
|
@@ -763,7 +890,7 @@ async function handleFileChange(file, server) {
|
|
|
763
890
|
file,
|
|
764
891
|
timestamp,
|
|
765
892
|
modules: [mod],
|
|
766
|
-
read: () =>
|
|
893
|
+
read: () => fs5.readFileSync(file, "utf-8"),
|
|
767
894
|
server
|
|
768
895
|
};
|
|
769
896
|
let affectedModules = [mod];
|
|
@@ -802,12 +929,12 @@ var init_hmr = __esm({
|
|
|
802
929
|
});
|
|
803
930
|
|
|
804
931
|
// src/plugins/resolve.ts
|
|
805
|
-
import
|
|
806
|
-
import
|
|
807
|
-
import { createRequire } from "module";
|
|
932
|
+
import path6 from "path";
|
|
933
|
+
import fs6 from "fs";
|
|
934
|
+
import { createRequire as createRequire2 } from "module";
|
|
808
935
|
function resolvePlugin(config) {
|
|
809
936
|
const { alias, extensions } = config.resolve;
|
|
810
|
-
const require2 =
|
|
937
|
+
const require2 = createRequire2(path6.resolve(config.root, "package.json"));
|
|
811
938
|
return {
|
|
812
939
|
name: "nasti:resolve",
|
|
813
940
|
enforce: "pre",
|
|
@@ -815,26 +942,26 @@ function resolvePlugin(config) {
|
|
|
815
942
|
for (const [key, value] of Object.entries(alias)) {
|
|
816
943
|
if (source === key || source.startsWith(key + "/")) {
|
|
817
944
|
source = source.replace(key, value);
|
|
818
|
-
if (!
|
|
819
|
-
source =
|
|
945
|
+
if (!path6.isAbsolute(source)) {
|
|
946
|
+
source = path6.resolve(config.root, source);
|
|
820
947
|
}
|
|
821
948
|
break;
|
|
822
949
|
}
|
|
823
950
|
}
|
|
824
|
-
if (
|
|
951
|
+
if (path6.isAbsolute(source)) {
|
|
825
952
|
const resolved = tryResolveFile(source, extensions);
|
|
826
953
|
if (resolved) return resolved;
|
|
827
954
|
}
|
|
828
955
|
if (source.startsWith(".")) {
|
|
829
|
-
const dir = importer ?
|
|
830
|
-
const absolute =
|
|
956
|
+
const dir = importer ? path6.dirname(importer) : config.root;
|
|
957
|
+
const absolute = path6.resolve(dir, source);
|
|
831
958
|
const resolved = tryResolveFile(absolute, extensions);
|
|
832
959
|
if (resolved) return resolved;
|
|
833
960
|
}
|
|
834
961
|
if (!source.startsWith("/") && !source.startsWith(".")) {
|
|
835
962
|
try {
|
|
836
963
|
const resolved = require2.resolve(source, {
|
|
837
|
-
paths: [importer ?
|
|
964
|
+
paths: [importer ? path6.dirname(importer) : config.root]
|
|
838
965
|
});
|
|
839
966
|
return resolved;
|
|
840
967
|
} catch {
|
|
@@ -844,27 +971,29 @@ function resolvePlugin(config) {
|
|
|
844
971
|
return null;
|
|
845
972
|
},
|
|
846
973
|
load(id) {
|
|
847
|
-
if (
|
|
848
|
-
|
|
974
|
+
if (!fs6.existsSync(id)) return null;
|
|
975
|
+
if (id.endsWith(".json")) {
|
|
976
|
+
const content = fs6.readFileSync(id, "utf-8");
|
|
977
|
+
return `export default ${content}`;
|
|
849
978
|
}
|
|
850
|
-
return
|
|
979
|
+
return fs6.readFileSync(id, "utf-8");
|
|
851
980
|
}
|
|
852
981
|
};
|
|
853
982
|
}
|
|
854
983
|
function tryResolveFile(file, extensions) {
|
|
855
|
-
if (
|
|
984
|
+
if (fs6.existsSync(file) && fs6.statSync(file).isFile()) {
|
|
856
985
|
return file;
|
|
857
986
|
}
|
|
858
987
|
for (const ext of extensions) {
|
|
859
988
|
const withExt = file + ext;
|
|
860
|
-
if (
|
|
989
|
+
if (fs6.existsSync(withExt) && fs6.statSync(withExt).isFile()) {
|
|
861
990
|
return withExt;
|
|
862
991
|
}
|
|
863
992
|
}
|
|
864
|
-
if (
|
|
993
|
+
if (fs6.existsSync(file) && fs6.statSync(file).isDirectory()) {
|
|
865
994
|
for (const ext of extensions) {
|
|
866
|
-
const indexFile =
|
|
867
|
-
if (
|
|
995
|
+
const indexFile = path6.join(file, "index" + ext);
|
|
996
|
+
if (fs6.existsSync(indexFile)) {
|
|
868
997
|
return indexFile;
|
|
869
998
|
}
|
|
870
999
|
}
|
|
@@ -878,7 +1007,7 @@ var init_resolve = __esm({
|
|
|
878
1007
|
});
|
|
879
1008
|
|
|
880
1009
|
// src/plugins/css.ts
|
|
881
|
-
import
|
|
1010
|
+
import path7 from "path";
|
|
882
1011
|
function cssPlugin(config) {
|
|
883
1012
|
return {
|
|
884
1013
|
name: "nasti:css",
|
|
@@ -888,13 +1017,17 @@ function cssPlugin(config) {
|
|
|
888
1017
|
},
|
|
889
1018
|
transform(code, id) {
|
|
890
1019
|
if (!id.endsWith(".css")) return null;
|
|
1020
|
+
const rewritten = rewriteCssUrls(code, id, config.root);
|
|
891
1021
|
if (config.command === "serve") {
|
|
892
|
-
const escaped = JSON.stringify(
|
|
1022
|
+
const escaped = JSON.stringify(rewritten);
|
|
893
1023
|
return {
|
|
894
1024
|
code: `
|
|
895
1025
|
const css = ${escaped};
|
|
1026
|
+
const __nasti_css_id__ = ${JSON.stringify(id)};
|
|
1027
|
+
const __nasti_existing__ = document.querySelector('style[data-nasti-css=' + JSON.stringify(__nasti_css_id__) + ']');
|
|
1028
|
+
if (__nasti_existing__) __nasti_existing__.remove();
|
|
896
1029
|
const style = document.createElement('style');
|
|
897
|
-
style.setAttribute('data-nasti-css',
|
|
1030
|
+
style.setAttribute('data-nasti-css', __nasti_css_id__);
|
|
898
1031
|
style.textContent = css;
|
|
899
1032
|
document.head.appendChild(style);
|
|
900
1033
|
|
|
@@ -910,10 +1043,20 @@ export default css;
|
|
|
910
1043
|
`
|
|
911
1044
|
};
|
|
912
1045
|
}
|
|
913
|
-
return null;
|
|
1046
|
+
return rewritten !== code ? { code: rewritten } : null;
|
|
914
1047
|
}
|
|
915
1048
|
};
|
|
916
1049
|
}
|
|
1050
|
+
function rewriteCssUrls(css, from, root) {
|
|
1051
|
+
return css.replace(/url\(\s*['"]?([^'")\s]+)['"]?\s*\)/g, (match, url) => {
|
|
1052
|
+
if (url.startsWith("/") || url.startsWith("data:") || url.startsWith("http")) {
|
|
1053
|
+
return match;
|
|
1054
|
+
}
|
|
1055
|
+
const resolved = path7.resolve(path7.dirname(from), url);
|
|
1056
|
+
const relative = "/" + path7.relative(root, resolved);
|
|
1057
|
+
return `url(${relative})`;
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
917
1060
|
var init_css = __esm({
|
|
918
1061
|
"src/plugins/css.ts"() {
|
|
919
1062
|
"use strict";
|
|
@@ -921,8 +1064,8 @@ var init_css = __esm({
|
|
|
921
1064
|
});
|
|
922
1065
|
|
|
923
1066
|
// src/plugins/assets.ts
|
|
924
|
-
import
|
|
925
|
-
import
|
|
1067
|
+
import path8 from "path";
|
|
1068
|
+
import fs7 from "fs";
|
|
926
1069
|
import crypto from "crypto";
|
|
927
1070
|
function assetsPlugin(config) {
|
|
928
1071
|
return {
|
|
@@ -934,24 +1077,24 @@ function assetsPlugin(config) {
|
|
|
934
1077
|
return null;
|
|
935
1078
|
},
|
|
936
1079
|
load(id) {
|
|
937
|
-
const ext =
|
|
1080
|
+
const ext = path8.extname(id.replace(/\?.*$/, ""));
|
|
938
1081
|
if (id.endsWith("?raw")) {
|
|
939
1082
|
const file = id.slice(0, -4);
|
|
940
|
-
if (
|
|
941
|
-
const content =
|
|
1083
|
+
if (fs7.existsSync(file)) {
|
|
1084
|
+
const content = fs7.readFileSync(file, "utf-8");
|
|
942
1085
|
return `export default ${JSON.stringify(content)}`;
|
|
943
1086
|
}
|
|
944
1087
|
}
|
|
945
1088
|
if (id.endsWith("?url") || ASSET_EXTENSIONS.has(ext)) {
|
|
946
1089
|
const file = id.replace(/\?.*$/, "");
|
|
947
|
-
if (!
|
|
1090
|
+
if (!fs7.existsSync(file)) return null;
|
|
948
1091
|
if (config.command === "serve") {
|
|
949
|
-
const url = "/" +
|
|
1092
|
+
const url = "/" + path8.relative(config.root, file);
|
|
950
1093
|
return `export default ${JSON.stringify(url)}`;
|
|
951
1094
|
}
|
|
952
|
-
const content =
|
|
1095
|
+
const content = fs7.readFileSync(file);
|
|
953
1096
|
const hash = crypto.createHash("sha256").update(content).digest("hex").slice(0, 8);
|
|
954
|
-
const basename =
|
|
1097
|
+
const basename = path8.basename(file, ext);
|
|
955
1098
|
const hashedName = `${config.build.assetsDir}/${basename}.${hash}${ext}`;
|
|
956
1099
|
return `export default ${JSON.stringify(config.base + hashedName)}`;
|
|
957
1100
|
}
|
|
@@ -996,7 +1139,8 @@ __export(server_exports, {
|
|
|
996
1139
|
createServer: () => createServer
|
|
997
1140
|
});
|
|
998
1141
|
import http from "http";
|
|
999
|
-
import
|
|
1142
|
+
import path9 from "path";
|
|
1143
|
+
import os from "os";
|
|
1000
1144
|
import connect from "connect";
|
|
1001
1145
|
import sirv from "sirv";
|
|
1002
1146
|
import { watch } from "chokidar";
|
|
@@ -1019,7 +1163,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
1019
1163
|
pluginContainer,
|
|
1020
1164
|
moduleGraph
|
|
1021
1165
|
}));
|
|
1022
|
-
const publicDir =
|
|
1166
|
+
const publicDir = path9.resolve(config.root, "public");
|
|
1023
1167
|
app.use(sirv(publicDir, { dev: true, etag: true }));
|
|
1024
1168
|
app.use(sirv(config.root, { dev: true, etag: true }));
|
|
1025
1169
|
const httpServer = http.createServer(app);
|
|
@@ -1059,11 +1203,13 @@ async function createServer(inlineConfig = {}) {
|
|
|
1059
1203
|
const host = config.server.host === true ? "0.0.0.0" : config.server.host;
|
|
1060
1204
|
await pluginContainer.buildStart();
|
|
1061
1205
|
return new Promise((resolve, reject) => {
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
const
|
|
1206
|
+
let currentPort = finalPort;
|
|
1207
|
+
const onListening = () => {
|
|
1208
|
+
const actualPort = httpServer.address()?.port ?? currentPort;
|
|
1209
|
+
const localUrl = `http://localhost:${actualPort}`;
|
|
1210
|
+
const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
|
|
1065
1211
|
console.log();
|
|
1066
|
-
console.log(pc.cyan(" nasti dev server") + pc.dim(`
|
|
1212
|
+
console.log(pc.cyan(" nasti dev server") + pc.dim(` v${"1.3.0"}`));
|
|
1067
1213
|
console.log();
|
|
1068
1214
|
console.log(` ${pc.green(">")} Local: ${pc.cyan(localUrl)}`);
|
|
1069
1215
|
if (networkUrl) {
|
|
@@ -1071,15 +1217,18 @@ async function createServer(inlineConfig = {}) {
|
|
|
1071
1217
|
}
|
|
1072
1218
|
console.log();
|
|
1073
1219
|
resolve(server);
|
|
1074
|
-
}
|
|
1220
|
+
};
|
|
1221
|
+
httpServer.on("listening", onListening);
|
|
1075
1222
|
httpServer.on("error", (err) => {
|
|
1076
1223
|
if (err.code === "EADDRINUSE") {
|
|
1077
|
-
|
|
1078
|
-
|
|
1224
|
+
currentPort++;
|
|
1225
|
+
console.log(pc.yellow(`Port ${currentPort - 1} is in use, trying ${currentPort}...`));
|
|
1226
|
+
httpServer.listen(currentPort, host);
|
|
1079
1227
|
} else {
|
|
1080
1228
|
reject(err);
|
|
1081
1229
|
}
|
|
1082
1230
|
});
|
|
1231
|
+
httpServer.listen(currentPort, host);
|
|
1083
1232
|
});
|
|
1084
1233
|
},
|
|
1085
1234
|
async transformRequest(url) {
|
|
@@ -1096,7 +1245,6 @@ async function createServer(inlineConfig = {}) {
|
|
|
1096
1245
|
return server;
|
|
1097
1246
|
}
|
|
1098
1247
|
function getNetworkAddress() {
|
|
1099
|
-
const os = __require("os");
|
|
1100
1248
|
const interfaces = os.networkInterfaces();
|
|
1101
1249
|
for (const name of Object.keys(interfaces)) {
|
|
1102
1250
|
for (const iface of interfaces[name] ?? []) {
|
|
@@ -1128,21 +1276,21 @@ var build_exports = {};
|
|
|
1128
1276
|
__export(build_exports, {
|
|
1129
1277
|
build: () => build
|
|
1130
1278
|
});
|
|
1131
|
-
import
|
|
1132
|
-
import
|
|
1279
|
+
import path10 from "path";
|
|
1280
|
+
import fs8 from "fs";
|
|
1133
1281
|
import { rolldown } from "rolldown";
|
|
1134
1282
|
import pc2 from "picocolors";
|
|
1135
1283
|
async function build(inlineConfig = {}) {
|
|
1136
1284
|
const config = await resolveConfig(inlineConfig, "build");
|
|
1137
1285
|
const startTime = performance.now();
|
|
1138
|
-
console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${
|
|
1286
|
+
console.log(pc2.cyan("\n\u{1F528} nasti build") + pc2.dim(` v${"1.3.0"}`));
|
|
1139
1287
|
console.log(pc2.dim(` root: ${config.root}`));
|
|
1140
1288
|
console.log(pc2.dim(` mode: ${config.mode}`));
|
|
1141
|
-
const outDir =
|
|
1142
|
-
if (config.build.emptyOutDir &&
|
|
1143
|
-
|
|
1289
|
+
const outDir = path10.resolve(config.root, config.build.outDir);
|
|
1290
|
+
if (config.build.emptyOutDir && fs8.existsSync(outDir)) {
|
|
1291
|
+
fs8.rmSync(outDir, { recursive: true, force: true });
|
|
1144
1292
|
}
|
|
1145
|
-
|
|
1293
|
+
fs8.mkdirSync(outDir, { recursive: true });
|
|
1146
1294
|
const html = await readHtmlFile(config.root);
|
|
1147
1295
|
let entryPoints = [];
|
|
1148
1296
|
if (html) {
|
|
@@ -1150,15 +1298,15 @@ async function build(inlineConfig = {}) {
|
|
|
1150
1298
|
for (const match of scriptMatches) {
|
|
1151
1299
|
const src = match[1];
|
|
1152
1300
|
if (src && !src.startsWith("http")) {
|
|
1153
|
-
entryPoints.push(
|
|
1301
|
+
entryPoints.push(path10.resolve(config.root, src.replace(/^\//, "")));
|
|
1154
1302
|
}
|
|
1155
1303
|
}
|
|
1156
1304
|
}
|
|
1157
1305
|
if (entryPoints.length === 0) {
|
|
1158
1306
|
const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
|
|
1159
1307
|
for (const entry of fallbackEntries) {
|
|
1160
|
-
const fullPath =
|
|
1161
|
-
if (
|
|
1308
|
+
const fullPath = path10.resolve(config.root, entry);
|
|
1309
|
+
if (fs8.existsSync(fullPath)) {
|
|
1162
1310
|
entryPoints.push(fullPath);
|
|
1163
1311
|
break;
|
|
1164
1312
|
}
|
|
@@ -1173,6 +1321,8 @@ async function build(inlineConfig = {}) {
|
|
|
1173
1321
|
assetsPlugin(config)
|
|
1174
1322
|
];
|
|
1175
1323
|
const allPlugins = [...builtinPlugins, ...config.plugins];
|
|
1324
|
+
const pluginContainer = new PluginContainer(config);
|
|
1325
|
+
await pluginContainer.buildStart();
|
|
1176
1326
|
const oxcTransformPlugin = {
|
|
1177
1327
|
name: "nasti:oxc-transform",
|
|
1178
1328
|
transform(code, id) {
|
|
@@ -1185,8 +1335,11 @@ async function build(inlineConfig = {}) {
|
|
|
1185
1335
|
return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
|
|
1186
1336
|
}
|
|
1187
1337
|
};
|
|
1338
|
+
const env = loadEnv(config.mode, config.root, config.envPrefix);
|
|
1339
|
+
const envDefine = buildEnvDefine(env, config.mode);
|
|
1188
1340
|
const bundle = await rolldown({
|
|
1189
1341
|
input: entryPoints,
|
|
1342
|
+
define: envDefine,
|
|
1190
1343
|
plugins: [
|
|
1191
1344
|
oxcTransformPlugin,
|
|
1192
1345
|
// 转换 Nasti 插件为 Rolldown 插件格式
|
|
@@ -1205,11 +1358,18 @@ async function build(inlineConfig = {}) {
|
|
|
1205
1358
|
dir: outDir,
|
|
1206
1359
|
format: "esm",
|
|
1207
1360
|
sourcemap: !!config.build.sourcemap,
|
|
1361
|
+
minify: !!config.build.minify,
|
|
1208
1362
|
entryFileNames: "assets/[name].[hash].js",
|
|
1209
1363
|
chunkFileNames: "assets/[name].[hash].js",
|
|
1210
1364
|
assetFileNames: "assets/[name].[hash][extname]"
|
|
1211
1365
|
});
|
|
1212
1366
|
await bundle.close();
|
|
1367
|
+
await pluginContainer.buildEnd();
|
|
1368
|
+
for (const ef of pluginContainer.getEmittedFiles()) {
|
|
1369
|
+
const dest = path10.resolve(outDir, ef.fileName);
|
|
1370
|
+
fs8.mkdirSync(path10.dirname(dest), { recursive: true });
|
|
1371
|
+
fs8.writeFileSync(dest, ef.source);
|
|
1372
|
+
}
|
|
1213
1373
|
if (html) {
|
|
1214
1374
|
let processedHtml = html;
|
|
1215
1375
|
const htmlPlugin_ = htmlPlugin(config);
|
|
@@ -1224,15 +1384,15 @@ async function build(inlineConfig = {}) {
|
|
|
1224
1384
|
}
|
|
1225
1385
|
}
|
|
1226
1386
|
for (const chunk of output) {
|
|
1227
|
-
if (chunk.type === "chunk" && chunk.isEntry) {
|
|
1228
|
-
const originalEntry =
|
|
1387
|
+
if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) {
|
|
1388
|
+
const originalEntry = path10.relative(config.root, chunk.facadeModuleId);
|
|
1229
1389
|
processedHtml = processedHtml.replace(
|
|
1230
1390
|
new RegExp(`(src=["'])/?(${escapeRegExp(originalEntry)})(["'])`, "g"),
|
|
1231
1391
|
`$1${config.base}${chunk.fileName}$3`
|
|
1232
1392
|
);
|
|
1233
1393
|
}
|
|
1234
1394
|
}
|
|
1235
|
-
|
|
1395
|
+
fs8.writeFileSync(path10.resolve(outDir, "index.html"), processedHtml);
|
|
1236
1396
|
}
|
|
1237
1397
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
1238
1398
|
const totalSize = output.reduce((sum, chunk) => {
|
|
@@ -1263,6 +1423,8 @@ var init_build = __esm({
|
|
|
1263
1423
|
init_assets();
|
|
1264
1424
|
init_html();
|
|
1265
1425
|
init_transformer();
|
|
1426
|
+
init_env();
|
|
1427
|
+
init_plugin_container();
|
|
1266
1428
|
}
|
|
1267
1429
|
});
|
|
1268
1430
|
|
|
@@ -1316,11 +1478,11 @@ cli.command("build [root]", "Build for production").option("--outDir <dir>", "Ou
|
|
|
1316
1478
|
cli.command("preview [root]", "Preview production build").option("--port <port>", "Port number", { default: 4173 }).option("--host [host]", "Hostname").option("--outDir <dir>", "Output directory to serve", { default: "dist" }).action(async (root, options) => {
|
|
1317
1479
|
try {
|
|
1318
1480
|
const http2 = await import("http");
|
|
1319
|
-
const
|
|
1481
|
+
const path11 = await import("path");
|
|
1320
1482
|
const sirv2 = (await import("sirv")).default;
|
|
1321
1483
|
const connect2 = (await import("connect")).default;
|
|
1322
|
-
const resolvedRoot =
|
|
1323
|
-
const outDir =
|
|
1484
|
+
const resolvedRoot = path11.resolve(root ?? ".");
|
|
1485
|
+
const outDir = path11.resolve(resolvedRoot, options.outDir);
|
|
1324
1486
|
const app = connect2();
|
|
1325
1487
|
app.use(sirv2(outDir, { single: true, etag: true, gzip: true, brotli: true }));
|
|
1326
1488
|
const port = options.port;
|
|
@@ -1341,6 +1503,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
|
|
|
1341
1503
|
}
|
|
1342
1504
|
});
|
|
1343
1505
|
cli.help();
|
|
1344
|
-
cli.version("
|
|
1506
|
+
cli.version("1.3.0");
|
|
1345
1507
|
cli.parse();
|
|
1346
1508
|
//# sourceMappingURL=cli.js.map
|