@nasti-toolchain/nasti 1.2.1 → 1.2.3
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 +255 -91
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +246 -89
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +323 -158
- 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 +320 -162
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -74,6 +74,27 @@ var init_defaults = __esm({
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
// src/config/index.ts
|
|
77
|
+
function loadTsconfigPaths(root) {
|
|
78
|
+
const tsconfigPath = import_node_path.default.resolve(root, "tsconfig.json");
|
|
79
|
+
if (!import_node_fs.default.existsSync(tsconfigPath)) return {};
|
|
80
|
+
try {
|
|
81
|
+
const content = import_node_fs.default.readFileSync(tsconfigPath, "utf-8");
|
|
82
|
+
const stripped = content.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
83
|
+
const tsconfig = JSON.parse(stripped);
|
|
84
|
+
const paths = tsconfig?.compilerOptions?.paths ?? {};
|
|
85
|
+
const baseUrl = tsconfig?.compilerOptions?.baseUrl ?? ".";
|
|
86
|
+
const alias = {};
|
|
87
|
+
for (const [pattern, targets] of Object.entries(paths)) {
|
|
88
|
+
if (!targets.length) continue;
|
|
89
|
+
const cleanKey = pattern.replace(/\/\*$/, "");
|
|
90
|
+
const cleanTarget = targets[0].replace(/\/\*$/, "");
|
|
91
|
+
alias[cleanKey] = import_node_path.default.resolve(root, baseUrl, cleanTarget);
|
|
92
|
+
}
|
|
93
|
+
return alias;
|
|
94
|
+
} catch {
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
77
98
|
async function loadConfigFromFile(root) {
|
|
78
99
|
for (const file of CONFIG_FILES) {
|
|
79
100
|
const filePath = import_node_path.default.resolve(root, file);
|
|
@@ -116,11 +137,6 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
116
137
|
if (result) Object.assign(merged, result);
|
|
117
138
|
}
|
|
118
139
|
}
|
|
119
|
-
const filteredPlugins = rawPlugins.filter((p) => {
|
|
120
|
-
if (!p.apply) return true;
|
|
121
|
-
if (typeof p.apply === "function") return p.apply(resolved, env);
|
|
122
|
-
return p.apply === command;
|
|
123
|
-
});
|
|
124
140
|
const resolved = {
|
|
125
141
|
root,
|
|
126
142
|
base: merged.base ?? defaults.base,
|
|
@@ -128,17 +144,24 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
128
144
|
framework: merged.framework ?? defaults.framework,
|
|
129
145
|
command,
|
|
130
146
|
resolve: {
|
|
131
|
-
|
|
147
|
+
// tsconfig paths 优先级最低:tsconfig < defaults < user config
|
|
148
|
+
alias: { ...loadTsconfigPaths(root), ...defaults.resolve.alias, ...merged.resolve?.alias },
|
|
132
149
|
extensions: merged.resolve?.extensions ?? defaults.resolve.extensions,
|
|
133
150
|
conditions: merged.resolve?.conditions ?? defaults.resolve.conditions,
|
|
134
151
|
mainFields: merged.resolve?.mainFields ?? defaults.resolve.mainFields
|
|
135
152
|
},
|
|
136
|
-
plugins:
|
|
153
|
+
plugins: [],
|
|
137
154
|
server: { ...defaults.server, ...merged.server },
|
|
138
155
|
build: { ...defaults.build, ...merged.build },
|
|
139
156
|
envPrefix: Array.isArray(merged.envPrefix) ? merged.envPrefix : merged.envPrefix ? [merged.envPrefix] : [...defaults.envPrefix],
|
|
140
157
|
logLevel: merged.logLevel ?? defaults.logLevel
|
|
141
158
|
};
|
|
159
|
+
const filteredPlugins = rawPlugins.filter((p) => {
|
|
160
|
+
if (!p.apply) return true;
|
|
161
|
+
if (typeof p.apply === "function") return p.apply(resolved, env);
|
|
162
|
+
return p.apply === command;
|
|
163
|
+
});
|
|
164
|
+
resolved.plugins = filteredPlugins;
|
|
142
165
|
for (const plugin of resolved.plugins) {
|
|
143
166
|
if (plugin.configResolved) {
|
|
144
167
|
await plugin.configResolved(resolved);
|
|
@@ -198,6 +221,7 @@ var init_plugin_container = __esm({
|
|
|
198
221
|
plugins;
|
|
199
222
|
config;
|
|
200
223
|
ctx;
|
|
224
|
+
emittedFiles = /* @__PURE__ */ new Map();
|
|
201
225
|
constructor(config) {
|
|
202
226
|
this.config = config;
|
|
203
227
|
this.plugins = sortPlugins(config.plugins);
|
|
@@ -209,14 +233,24 @@ var init_plugin_container = __esm({
|
|
|
209
233
|
async resolve(source, importer) {
|
|
210
234
|
return container.resolveId(source, importer);
|
|
211
235
|
},
|
|
212
|
-
emitFile(
|
|
213
|
-
|
|
236
|
+
emitFile(file) {
|
|
237
|
+
const fileName = file.fileName ?? file.name ?? `asset-${container.emittedFiles.size}`;
|
|
238
|
+
const id = `emitted:${fileName}`;
|
|
239
|
+
container.emittedFiles.set(id, {
|
|
240
|
+
fileName,
|
|
241
|
+
source: file.source ?? ""
|
|
242
|
+
});
|
|
243
|
+
return id;
|
|
214
244
|
},
|
|
215
245
|
getModuleInfo(_id) {
|
|
216
246
|
return null;
|
|
217
247
|
}
|
|
218
248
|
};
|
|
219
249
|
}
|
|
250
|
+
/** 返回所有通过 emitFile() 输出的文件 */
|
|
251
|
+
getEmittedFiles() {
|
|
252
|
+
return Array.from(this.emittedFiles.values());
|
|
253
|
+
}
|
|
220
254
|
async buildStart() {
|
|
221
255
|
for (const plugin of this.plugins) {
|
|
222
256
|
if (plugin.buildStart) {
|
|
@@ -460,6 +494,11 @@ function transformCode(filename, code, options = {}) {
|
|
|
460
494
|
} : void 0,
|
|
461
495
|
sourcemap: options.sourcemap ?? true
|
|
462
496
|
});
|
|
497
|
+
if (result.errors && result.errors.length > 0) {
|
|
498
|
+
const msg = result.errors.map((e) => e.message ?? String(e)).join("\n");
|
|
499
|
+
throw new Error(`OXC transform failed for ${filename}:
|
|
500
|
+
${msg}`);
|
|
501
|
+
}
|
|
463
502
|
return {
|
|
464
503
|
code: result.code,
|
|
465
504
|
map: result.map ? JSON.stringify(result.map) : null
|
|
@@ -543,6 +582,68 @@ var init_html = __esm({
|
|
|
543
582
|
}
|
|
544
583
|
});
|
|
545
584
|
|
|
585
|
+
// src/core/env.ts
|
|
586
|
+
function loadEnv(mode, root, prefixes) {
|
|
587
|
+
const envFiles = [
|
|
588
|
+
".env",
|
|
589
|
+
`.env.${mode}`,
|
|
590
|
+
".env.local",
|
|
591
|
+
`.env.${mode}.local`
|
|
592
|
+
];
|
|
593
|
+
const raw = {};
|
|
594
|
+
for (const file of envFiles) {
|
|
595
|
+
const filePath = import_node_path3.default.resolve(root, file);
|
|
596
|
+
if (!import_node_fs3.default.existsSync(filePath)) continue;
|
|
597
|
+
const content = import_node_fs3.default.readFileSync(filePath, "utf-8");
|
|
598
|
+
for (const line of content.split("\n")) {
|
|
599
|
+
const trimmed = line.trim();
|
|
600
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
601
|
+
const eqIdx = trimmed.indexOf("=");
|
|
602
|
+
if (eqIdx === -1) continue;
|
|
603
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
604
|
+
let value = trimmed.slice(eqIdx + 1).trim();
|
|
605
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
606
|
+
value = value.slice(1, -1);
|
|
607
|
+
}
|
|
608
|
+
raw[key] = value;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
const filtered = {};
|
|
612
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
613
|
+
if (prefixes.some((prefix) => key.startsWith(prefix))) {
|
|
614
|
+
filtered[key] = value;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
return filtered;
|
|
618
|
+
}
|
|
619
|
+
function buildEnvDefine(env, mode) {
|
|
620
|
+
const define = {};
|
|
621
|
+
for (const [key, value] of Object.entries(env)) {
|
|
622
|
+
define[`import.meta.env.${key}`] = JSON.stringify(value);
|
|
623
|
+
}
|
|
624
|
+
define["import.meta.env.MODE"] = JSON.stringify(mode);
|
|
625
|
+
define["import.meta.env.DEV"] = mode !== "production" ? "true" : "false";
|
|
626
|
+
define["import.meta.env.PROD"] = mode === "production" ? "true" : "false";
|
|
627
|
+
define["import.meta.env.SSR"] = "false";
|
|
628
|
+
return define;
|
|
629
|
+
}
|
|
630
|
+
function replaceEnvInCode(code, define) {
|
|
631
|
+
let result = code;
|
|
632
|
+
for (const [key, value] of Object.entries(define)) {
|
|
633
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
634
|
+
result = result.replace(new RegExp(escaped, "g"), value);
|
|
635
|
+
}
|
|
636
|
+
return result;
|
|
637
|
+
}
|
|
638
|
+
var import_node_path3, import_node_fs3;
|
|
639
|
+
var init_env = __esm({
|
|
640
|
+
"src/core/env.ts"() {
|
|
641
|
+
"use strict";
|
|
642
|
+
import_node_path3 = __toESM(require("path"), 1);
|
|
643
|
+
import_node_fs3 = __toESM(require("fs"), 1);
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
|
|
546
647
|
// src/server/middleware.ts
|
|
547
648
|
var middleware_exports = {};
|
|
548
649
|
__export(middleware_exports, {
|
|
@@ -552,6 +653,17 @@ __export(middleware_exports, {
|
|
|
552
653
|
function transformMiddleware(ctx) {
|
|
553
654
|
return async (req, res, next) => {
|
|
554
655
|
const url = req.url ?? "/";
|
|
656
|
+
if (ctx.config.server.cors) {
|
|
657
|
+
const origin = req.headers.origin ?? "*";
|
|
658
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
659
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
|
|
660
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
661
|
+
if (req.method === "OPTIONS") {
|
|
662
|
+
res.statusCode = 204;
|
|
663
|
+
res.end();
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
555
667
|
if (req.method !== "GET") return next();
|
|
556
668
|
if (url === "/@nasti/client") {
|
|
557
669
|
res.setHeader("Content-Type", "application/javascript");
|
|
@@ -574,10 +686,12 @@ function transformMiddleware(ctx) {
|
|
|
574
686
|
}
|
|
575
687
|
}
|
|
576
688
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
689
|
+
if (ctx.config.server.hmr !== false) {
|
|
690
|
+
processedHtml = processedHtml.replace(
|
|
691
|
+
"<head>",
|
|
692
|
+
'<head>\n <script type="module" src="/@nasti/client"></script>'
|
|
693
|
+
);
|
|
694
|
+
}
|
|
581
695
|
res.setHeader("Content-Type", "text/html");
|
|
582
696
|
res.end(processedHtml);
|
|
583
697
|
return;
|
|
@@ -610,10 +724,10 @@ async function transformRequest(url, ctx) {
|
|
|
610
724
|
return cached.transformResult;
|
|
611
725
|
}
|
|
612
726
|
const filePath = resolveUrlToFile(url, config.root);
|
|
613
|
-
if (!filePath || !
|
|
727
|
+
if (!filePath || !import_node_fs4.default.existsSync(filePath)) return null;
|
|
614
728
|
const mod = await moduleGraph.ensureEntryFromUrl(url);
|
|
615
729
|
moduleGraph.registerModule(mod, filePath);
|
|
616
|
-
let code =
|
|
730
|
+
let code = import_node_fs4.default.readFileSync(filePath, "utf-8");
|
|
617
731
|
const pluginResult = await pluginContainer.transform(code, filePath);
|
|
618
732
|
if (pluginResult) {
|
|
619
733
|
code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
|
|
@@ -627,23 +741,31 @@ async function transformRequest(url, ctx) {
|
|
|
627
741
|
});
|
|
628
742
|
code = result.code;
|
|
629
743
|
}
|
|
744
|
+
const env = loadEnv(config.mode, config.root, config.envPrefix);
|
|
745
|
+
const envDefine = buildEnvDefine(env, config.mode);
|
|
746
|
+
code = replaceEnvInCode(code, envDefine);
|
|
630
747
|
code = rewriteImports(code, config);
|
|
631
748
|
const transformResult = { code };
|
|
632
749
|
mod.transformResult = transformResult;
|
|
633
750
|
return transformResult;
|
|
634
751
|
}
|
|
635
|
-
function rewriteImports(code,
|
|
752
|
+
function rewriteImports(code, _config) {
|
|
636
753
|
return code.replace(
|
|
637
|
-
|
|
638
|
-
(match, specifier) => {
|
|
639
|
-
|
|
640
|
-
|
|
754
|
+
/\bfrom\s+(['"])([^'"./][^'"]*)\1/g,
|
|
755
|
+
(match, quote, specifier) => {
|
|
756
|
+
return `from ${quote}/@modules/${specifier}${quote}`;
|
|
757
|
+
}
|
|
758
|
+
).replace(
|
|
759
|
+
// 处理纯副作用导入: import 'bare-specifier'
|
|
760
|
+
/\bimport\s+(['"])([^'"./][^'"]*)\1/g,
|
|
761
|
+
(match, quote, specifier) => {
|
|
762
|
+
return `import ${quote}/@modules/${specifier}${quote}`;
|
|
641
763
|
}
|
|
642
764
|
).replace(
|
|
643
|
-
|
|
644
|
-
(
|
|
645
|
-
|
|
646
|
-
return `import
|
|
765
|
+
// 处理动态导入: import('bare-specifier')
|
|
766
|
+
/\bimport\s*\(\s*(['"])([^'"./][^'"]*)\1\s*\)/g,
|
|
767
|
+
(match, quote, specifier) => {
|
|
768
|
+
return `import(${quote}/@modules/${specifier}${quote})`;
|
|
647
769
|
}
|
|
648
770
|
);
|
|
649
771
|
}
|
|
@@ -652,14 +774,13 @@ function resolveUrlToFile(url, root) {
|
|
|
652
774
|
if (cleanUrl.startsWith("/@modules/")) {
|
|
653
775
|
const moduleName = cleanUrl.slice("/@modules/".length);
|
|
654
776
|
try {
|
|
655
|
-
const
|
|
656
|
-
const req = createRequire2(import_node_path3.default.resolve(root, "package.json"));
|
|
777
|
+
const req = (0, import_node_module.createRequire)(import_node_path4.default.resolve(root, "package.json"));
|
|
657
778
|
return req.resolve(moduleName);
|
|
658
779
|
} catch {
|
|
659
780
|
return null;
|
|
660
781
|
}
|
|
661
782
|
}
|
|
662
|
-
return
|
|
783
|
+
return import_node_path4.default.resolve(root, cleanUrl.replace(/^\//, ""));
|
|
663
784
|
}
|
|
664
785
|
function isModuleRequest(url) {
|
|
665
786
|
const cleanUrl = url.split("?")[0];
|
|
@@ -721,7 +842,18 @@ function showErrorOverlay(err) {
|
|
|
721
842
|
const overlay = document.createElement('div');
|
|
722
843
|
overlay.id = 'nasti-error-overlay';
|
|
723
844
|
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;';
|
|
724
|
-
|
|
845
|
+
const title = document.createElement('h2');
|
|
846
|
+
title.style.color = '#ff5555';
|
|
847
|
+
title.textContent = 'Build Error';
|
|
848
|
+
const pre = document.createElement('pre');
|
|
849
|
+
pre.textContent = err.message + '\\n' + (err.stack || '');
|
|
850
|
+
const btn = document.createElement('button');
|
|
851
|
+
btn.style.cssText = 'margin-top:1rem;padding:0.5rem 1rem;cursor:pointer';
|
|
852
|
+
btn.textContent = 'Close';
|
|
853
|
+
btn.onclick = () => overlay.remove();
|
|
854
|
+
overlay.appendChild(title);
|
|
855
|
+
overlay.appendChild(pre);
|
|
856
|
+
overlay.appendChild(btn);
|
|
725
857
|
document.body.appendChild(overlay);
|
|
726
858
|
}
|
|
727
859
|
|
|
@@ -752,21 +884,23 @@ if (!window.__nasti_hot_map) window.__nasti_hot_map = new Map();
|
|
|
752
884
|
window.__NASTI_HMR__ = { createHotContext };
|
|
753
885
|
`;
|
|
754
886
|
}
|
|
755
|
-
var
|
|
887
|
+
var import_node_path4, import_node_fs4, import_node_module;
|
|
756
888
|
var init_middleware = __esm({
|
|
757
889
|
"src/server/middleware.ts"() {
|
|
758
890
|
"use strict";
|
|
759
|
-
|
|
760
|
-
|
|
891
|
+
import_node_path4 = __toESM(require("path"), 1);
|
|
892
|
+
import_node_fs4 = __toESM(require("fs"), 1);
|
|
893
|
+
import_node_module = require("module");
|
|
761
894
|
init_transformer();
|
|
762
895
|
init_html();
|
|
896
|
+
init_env();
|
|
763
897
|
}
|
|
764
898
|
});
|
|
765
899
|
|
|
766
900
|
// src/server/hmr.ts
|
|
767
901
|
async function handleFileChange(file, server) {
|
|
768
902
|
const { moduleGraph, ws, config } = server;
|
|
769
|
-
const relativePath = "/" +
|
|
903
|
+
const relativePath = "/" + import_node_path5.default.relative(config.root, file);
|
|
770
904
|
const mods = moduleGraph.getModulesByFile(file);
|
|
771
905
|
if (!mods || mods.size === 0) {
|
|
772
906
|
return;
|
|
@@ -779,7 +913,7 @@ async function handleFileChange(file, server) {
|
|
|
779
913
|
file,
|
|
780
914
|
timestamp,
|
|
781
915
|
modules: [mod],
|
|
782
|
-
read: () =>
|
|
916
|
+
read: () => import_node_fs5.default.readFileSync(file, "utf-8"),
|
|
783
917
|
server
|
|
784
918
|
};
|
|
785
919
|
let affectedModules = [mod];
|
|
@@ -811,19 +945,19 @@ async function handleFileChange(file, server) {
|
|
|
811
945
|
ws.send({ type: "update", updates });
|
|
812
946
|
}
|
|
813
947
|
}
|
|
814
|
-
var
|
|
948
|
+
var import_node_path5, import_node_fs5;
|
|
815
949
|
var init_hmr = __esm({
|
|
816
950
|
"src/server/hmr.ts"() {
|
|
817
951
|
"use strict";
|
|
818
|
-
|
|
819
|
-
|
|
952
|
+
import_node_path5 = __toESM(require("path"), 1);
|
|
953
|
+
import_node_fs5 = __toESM(require("fs"), 1);
|
|
820
954
|
}
|
|
821
955
|
});
|
|
822
956
|
|
|
823
957
|
// src/plugins/resolve.ts
|
|
824
958
|
function resolvePlugin(config) {
|
|
825
959
|
const { alias, extensions } = config.resolve;
|
|
826
|
-
const require2 = (0,
|
|
960
|
+
const require2 = (0, import_node_module2.createRequire)(import_node_path6.default.resolve(config.root, "package.json"));
|
|
827
961
|
return {
|
|
828
962
|
name: "nasti:resolve",
|
|
829
963
|
enforce: "pre",
|
|
@@ -831,26 +965,26 @@ function resolvePlugin(config) {
|
|
|
831
965
|
for (const [key, value] of Object.entries(alias)) {
|
|
832
966
|
if (source === key || source.startsWith(key + "/")) {
|
|
833
967
|
source = source.replace(key, value);
|
|
834
|
-
if (!
|
|
835
|
-
source =
|
|
968
|
+
if (!import_node_path6.default.isAbsolute(source)) {
|
|
969
|
+
source = import_node_path6.default.resolve(config.root, source);
|
|
836
970
|
}
|
|
837
971
|
break;
|
|
838
972
|
}
|
|
839
973
|
}
|
|
840
|
-
if (
|
|
974
|
+
if (import_node_path6.default.isAbsolute(source)) {
|
|
841
975
|
const resolved = tryResolveFile(source, extensions);
|
|
842
976
|
if (resolved) return resolved;
|
|
843
977
|
}
|
|
844
978
|
if (source.startsWith(".")) {
|
|
845
|
-
const dir = importer ?
|
|
846
|
-
const absolute =
|
|
979
|
+
const dir = importer ? import_node_path6.default.dirname(importer) : config.root;
|
|
980
|
+
const absolute = import_node_path6.default.resolve(dir, source);
|
|
847
981
|
const resolved = tryResolveFile(absolute, extensions);
|
|
848
982
|
if (resolved) return resolved;
|
|
849
983
|
}
|
|
850
984
|
if (!source.startsWith("/") && !source.startsWith(".")) {
|
|
851
985
|
try {
|
|
852
986
|
const resolved = require2.resolve(source, {
|
|
853
|
-
paths: [importer ?
|
|
987
|
+
paths: [importer ? import_node_path6.default.dirname(importer) : config.root]
|
|
854
988
|
});
|
|
855
989
|
return resolved;
|
|
856
990
|
} catch {
|
|
@@ -860,40 +994,42 @@ function resolvePlugin(config) {
|
|
|
860
994
|
return null;
|
|
861
995
|
},
|
|
862
996
|
load(id) {
|
|
863
|
-
if (
|
|
864
|
-
|
|
997
|
+
if (!import_node_fs6.default.existsSync(id)) return null;
|
|
998
|
+
if (id.endsWith(".json")) {
|
|
999
|
+
const content = import_node_fs6.default.readFileSync(id, "utf-8");
|
|
1000
|
+
return `export default ${content}`;
|
|
865
1001
|
}
|
|
866
|
-
return
|
|
1002
|
+
return import_node_fs6.default.readFileSync(id, "utf-8");
|
|
867
1003
|
}
|
|
868
1004
|
};
|
|
869
1005
|
}
|
|
870
1006
|
function tryResolveFile(file, extensions) {
|
|
871
|
-
if (
|
|
1007
|
+
if (import_node_fs6.default.existsSync(file) && import_node_fs6.default.statSync(file).isFile()) {
|
|
872
1008
|
return file;
|
|
873
1009
|
}
|
|
874
1010
|
for (const ext of extensions) {
|
|
875
1011
|
const withExt = file + ext;
|
|
876
|
-
if (
|
|
1012
|
+
if (import_node_fs6.default.existsSync(withExt) && import_node_fs6.default.statSync(withExt).isFile()) {
|
|
877
1013
|
return withExt;
|
|
878
1014
|
}
|
|
879
1015
|
}
|
|
880
|
-
if (
|
|
1016
|
+
if (import_node_fs6.default.existsSync(file) && import_node_fs6.default.statSync(file).isDirectory()) {
|
|
881
1017
|
for (const ext of extensions) {
|
|
882
|
-
const indexFile =
|
|
883
|
-
if (
|
|
1018
|
+
const indexFile = import_node_path6.default.join(file, "index" + ext);
|
|
1019
|
+
if (import_node_fs6.default.existsSync(indexFile)) {
|
|
884
1020
|
return indexFile;
|
|
885
1021
|
}
|
|
886
1022
|
}
|
|
887
1023
|
}
|
|
888
1024
|
return null;
|
|
889
1025
|
}
|
|
890
|
-
var
|
|
1026
|
+
var import_node_path6, import_node_fs6, import_node_module2;
|
|
891
1027
|
var init_resolve = __esm({
|
|
892
1028
|
"src/plugins/resolve.ts"() {
|
|
893
1029
|
"use strict";
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
1030
|
+
import_node_path6 = __toESM(require("path"), 1);
|
|
1031
|
+
import_node_fs6 = __toESM(require("fs"), 1);
|
|
1032
|
+
import_node_module2 = require("module");
|
|
897
1033
|
}
|
|
898
1034
|
});
|
|
899
1035
|
|
|
@@ -907,13 +1043,17 @@ function cssPlugin(config) {
|
|
|
907
1043
|
},
|
|
908
1044
|
transform(code, id) {
|
|
909
1045
|
if (!id.endsWith(".css")) return null;
|
|
1046
|
+
const rewritten = rewriteCssUrls(code, id, config.root);
|
|
910
1047
|
if (config.command === "serve") {
|
|
911
|
-
const escaped = JSON.stringify(
|
|
1048
|
+
const escaped = JSON.stringify(rewritten);
|
|
912
1049
|
return {
|
|
913
1050
|
code: `
|
|
914
1051
|
const css = ${escaped};
|
|
1052
|
+
const __nasti_css_id__ = ${JSON.stringify(id)};
|
|
1053
|
+
const __nasti_existing__ = document.querySelector('style[data-nasti-css=' + JSON.stringify(__nasti_css_id__) + ']');
|
|
1054
|
+
if (__nasti_existing__) __nasti_existing__.remove();
|
|
915
1055
|
const style = document.createElement('style');
|
|
916
|
-
style.setAttribute('data-nasti-css',
|
|
1056
|
+
style.setAttribute('data-nasti-css', __nasti_css_id__);
|
|
917
1057
|
style.textContent = css;
|
|
918
1058
|
document.head.appendChild(style);
|
|
919
1059
|
|
|
@@ -929,15 +1069,25 @@ export default css;
|
|
|
929
1069
|
`
|
|
930
1070
|
};
|
|
931
1071
|
}
|
|
932
|
-
return null;
|
|
1072
|
+
return rewritten !== code ? { code: rewritten } : null;
|
|
933
1073
|
}
|
|
934
1074
|
};
|
|
935
1075
|
}
|
|
936
|
-
|
|
1076
|
+
function rewriteCssUrls(css, from, root) {
|
|
1077
|
+
return css.replace(/url\(\s*['"]?([^'")\s]+)['"]?\s*\)/g, (match, url) => {
|
|
1078
|
+
if (url.startsWith("/") || url.startsWith("data:") || url.startsWith("http")) {
|
|
1079
|
+
return match;
|
|
1080
|
+
}
|
|
1081
|
+
const resolved = import_node_path7.default.resolve(import_node_path7.default.dirname(from), url);
|
|
1082
|
+
const relative = "/" + import_node_path7.default.relative(root, resolved);
|
|
1083
|
+
return `url(${relative})`;
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
var import_node_path7;
|
|
937
1087
|
var init_css = __esm({
|
|
938
1088
|
"src/plugins/css.ts"() {
|
|
939
1089
|
"use strict";
|
|
940
|
-
|
|
1090
|
+
import_node_path7 = __toESM(require("path"), 1);
|
|
941
1091
|
}
|
|
942
1092
|
});
|
|
943
1093
|
|
|
@@ -952,24 +1102,24 @@ function assetsPlugin(config) {
|
|
|
952
1102
|
return null;
|
|
953
1103
|
},
|
|
954
1104
|
load(id) {
|
|
955
|
-
const ext =
|
|
1105
|
+
const ext = import_node_path8.default.extname(id.replace(/\?.*$/, ""));
|
|
956
1106
|
if (id.endsWith("?raw")) {
|
|
957
1107
|
const file = id.slice(0, -4);
|
|
958
|
-
if (
|
|
959
|
-
const content =
|
|
1108
|
+
if (import_node_fs7.default.existsSync(file)) {
|
|
1109
|
+
const content = import_node_fs7.default.readFileSync(file, "utf-8");
|
|
960
1110
|
return `export default ${JSON.stringify(content)}`;
|
|
961
1111
|
}
|
|
962
1112
|
}
|
|
963
1113
|
if (id.endsWith("?url") || ASSET_EXTENSIONS.has(ext)) {
|
|
964
1114
|
const file = id.replace(/\?.*$/, "");
|
|
965
|
-
if (!
|
|
1115
|
+
if (!import_node_fs7.default.existsSync(file)) return null;
|
|
966
1116
|
if (config.command === "serve") {
|
|
967
|
-
const url = "/" +
|
|
1117
|
+
const url = "/" + import_node_path8.default.relative(config.root, file);
|
|
968
1118
|
return `export default ${JSON.stringify(url)}`;
|
|
969
1119
|
}
|
|
970
|
-
const content =
|
|
1120
|
+
const content = import_node_fs7.default.readFileSync(file);
|
|
971
1121
|
const hash = import_node_crypto.default.createHash("sha256").update(content).digest("hex").slice(0, 8);
|
|
972
|
-
const basename =
|
|
1122
|
+
const basename = import_node_path8.default.basename(file, ext);
|
|
973
1123
|
const hashedName = `${config.build.assetsDir}/${basename}.${hash}${ext}`;
|
|
974
1124
|
return `export default ${JSON.stringify(config.base + hashedName)}`;
|
|
975
1125
|
}
|
|
@@ -977,12 +1127,12 @@ function assetsPlugin(config) {
|
|
|
977
1127
|
}
|
|
978
1128
|
};
|
|
979
1129
|
}
|
|
980
|
-
var
|
|
1130
|
+
var import_node_path8, import_node_fs7, import_node_crypto, ASSET_EXTENSIONS;
|
|
981
1131
|
var init_assets = __esm({
|
|
982
1132
|
"src/plugins/assets.ts"() {
|
|
983
1133
|
"use strict";
|
|
984
|
-
|
|
985
|
-
|
|
1134
|
+
import_node_path8 = __toESM(require("path"), 1);
|
|
1135
|
+
import_node_fs7 = __toESM(require("fs"), 1);
|
|
986
1136
|
import_node_crypto = __toESM(require("crypto"), 1);
|
|
987
1137
|
ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
988
1138
|
".png",
|
|
@@ -1034,7 +1184,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
1034
1184
|
pluginContainer,
|
|
1035
1185
|
moduleGraph
|
|
1036
1186
|
}));
|
|
1037
|
-
const publicDir =
|
|
1187
|
+
const publicDir = import_node_path9.default.resolve(config.root, "public");
|
|
1038
1188
|
app.use((0, import_sirv.default)(publicDir, { dev: true, etag: true }));
|
|
1039
1189
|
app.use((0, import_sirv.default)(config.root, { dev: true, etag: true }));
|
|
1040
1190
|
const httpServer = import_node_http.default.createServer(app);
|
|
@@ -1111,8 +1261,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
1111
1261
|
return server;
|
|
1112
1262
|
}
|
|
1113
1263
|
function getNetworkAddress() {
|
|
1114
|
-
const
|
|
1115
|
-
const interfaces = os.networkInterfaces();
|
|
1264
|
+
const interfaces = import_node_os.default.networkInterfaces();
|
|
1116
1265
|
for (const name of Object.keys(interfaces)) {
|
|
1117
1266
|
for (const iface of interfaces[name] ?? []) {
|
|
1118
1267
|
if (iface.family === "IPv4" && !iface.internal) {
|
|
@@ -1122,12 +1271,13 @@ function getNetworkAddress() {
|
|
|
1122
1271
|
}
|
|
1123
1272
|
return "localhost";
|
|
1124
1273
|
}
|
|
1125
|
-
var import_node_http,
|
|
1274
|
+
var import_node_http, import_node_path9, import_node_os, import_connect, import_sirv, import_chokidar, import_picocolors;
|
|
1126
1275
|
var init_server = __esm({
|
|
1127
1276
|
"src/server/index.ts"() {
|
|
1128
1277
|
"use strict";
|
|
1129
1278
|
import_node_http = __toESM(require("http"), 1);
|
|
1130
|
-
|
|
1279
|
+
import_node_path9 = __toESM(require("path"), 1);
|
|
1280
|
+
import_node_os = __toESM(require("os"), 1);
|
|
1131
1281
|
import_connect = __toESM(require("connect"), 1);
|
|
1132
1282
|
import_sirv = __toESM(require("sirv"), 1);
|
|
1133
1283
|
import_chokidar = require("chokidar");
|
|
@@ -1156,11 +1306,11 @@ async function build(inlineConfig = {}) {
|
|
|
1156
1306
|
console.log(import_picocolors2.default.cyan("\n\u{1F528} nasti build") + import_picocolors2.default.dim(` v${process.env.npm_package_version ?? "0.0.1"}`));
|
|
1157
1307
|
console.log(import_picocolors2.default.dim(` root: ${config.root}`));
|
|
1158
1308
|
console.log(import_picocolors2.default.dim(` mode: ${config.mode}`));
|
|
1159
|
-
const outDir =
|
|
1160
|
-
if (config.build.emptyOutDir &&
|
|
1161
|
-
|
|
1309
|
+
const outDir = import_node_path10.default.resolve(config.root, config.build.outDir);
|
|
1310
|
+
if (config.build.emptyOutDir && import_node_fs8.default.existsSync(outDir)) {
|
|
1311
|
+
import_node_fs8.default.rmSync(outDir, { recursive: true, force: true });
|
|
1162
1312
|
}
|
|
1163
|
-
|
|
1313
|
+
import_node_fs8.default.mkdirSync(outDir, { recursive: true });
|
|
1164
1314
|
const html = await readHtmlFile(config.root);
|
|
1165
1315
|
let entryPoints = [];
|
|
1166
1316
|
if (html) {
|
|
@@ -1168,15 +1318,15 @@ async function build(inlineConfig = {}) {
|
|
|
1168
1318
|
for (const match of scriptMatches) {
|
|
1169
1319
|
const src = match[1];
|
|
1170
1320
|
if (src && !src.startsWith("http")) {
|
|
1171
|
-
entryPoints.push(
|
|
1321
|
+
entryPoints.push(import_node_path10.default.resolve(config.root, src.replace(/^\//, "")));
|
|
1172
1322
|
}
|
|
1173
1323
|
}
|
|
1174
1324
|
}
|
|
1175
1325
|
if (entryPoints.length === 0) {
|
|
1176
1326
|
const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
|
|
1177
1327
|
for (const entry of fallbackEntries) {
|
|
1178
|
-
const fullPath =
|
|
1179
|
-
if (
|
|
1328
|
+
const fullPath = import_node_path10.default.resolve(config.root, entry);
|
|
1329
|
+
if (import_node_fs8.default.existsSync(fullPath)) {
|
|
1180
1330
|
entryPoints.push(fullPath);
|
|
1181
1331
|
break;
|
|
1182
1332
|
}
|
|
@@ -1191,6 +1341,8 @@ async function build(inlineConfig = {}) {
|
|
|
1191
1341
|
assetsPlugin(config)
|
|
1192
1342
|
];
|
|
1193
1343
|
const allPlugins = [...builtinPlugins, ...config.plugins];
|
|
1344
|
+
const pluginContainer = new PluginContainer(config);
|
|
1345
|
+
await pluginContainer.buildStart();
|
|
1194
1346
|
const oxcTransformPlugin = {
|
|
1195
1347
|
name: "nasti:oxc-transform",
|
|
1196
1348
|
transform(code, id) {
|
|
@@ -1203,8 +1355,11 @@ async function build(inlineConfig = {}) {
|
|
|
1203
1355
|
return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
|
|
1204
1356
|
}
|
|
1205
1357
|
};
|
|
1358
|
+
const env = loadEnv(config.mode, config.root, config.envPrefix);
|
|
1359
|
+
const envDefine = buildEnvDefine(env, config.mode);
|
|
1206
1360
|
const bundle = await (0, import_rolldown.rolldown)({
|
|
1207
1361
|
input: entryPoints,
|
|
1362
|
+
define: envDefine,
|
|
1208
1363
|
plugins: [
|
|
1209
1364
|
oxcTransformPlugin,
|
|
1210
1365
|
// 转换 Nasti 插件为 Rolldown 插件格式
|
|
@@ -1223,11 +1378,18 @@ async function build(inlineConfig = {}) {
|
|
|
1223
1378
|
dir: outDir,
|
|
1224
1379
|
format: "esm",
|
|
1225
1380
|
sourcemap: !!config.build.sourcemap,
|
|
1381
|
+
minify: !!config.build.minify,
|
|
1226
1382
|
entryFileNames: "assets/[name].[hash].js",
|
|
1227
1383
|
chunkFileNames: "assets/[name].[hash].js",
|
|
1228
1384
|
assetFileNames: "assets/[name].[hash][extname]"
|
|
1229
1385
|
});
|
|
1230
1386
|
await bundle.close();
|
|
1387
|
+
await pluginContainer.buildEnd();
|
|
1388
|
+
for (const ef of pluginContainer.getEmittedFiles()) {
|
|
1389
|
+
const dest = import_node_path10.default.resolve(outDir, ef.fileName);
|
|
1390
|
+
import_node_fs8.default.mkdirSync(import_node_path10.default.dirname(dest), { recursive: true });
|
|
1391
|
+
import_node_fs8.default.writeFileSync(dest, ef.source);
|
|
1392
|
+
}
|
|
1231
1393
|
if (html) {
|
|
1232
1394
|
let processedHtml = html;
|
|
1233
1395
|
const htmlPlugin_ = htmlPlugin(config);
|
|
@@ -1242,15 +1404,15 @@ async function build(inlineConfig = {}) {
|
|
|
1242
1404
|
}
|
|
1243
1405
|
}
|
|
1244
1406
|
for (const chunk of output) {
|
|
1245
|
-
if (chunk.type === "chunk" && chunk.isEntry) {
|
|
1246
|
-
const originalEntry =
|
|
1407
|
+
if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) {
|
|
1408
|
+
const originalEntry = import_node_path10.default.relative(config.root, chunk.facadeModuleId);
|
|
1247
1409
|
processedHtml = processedHtml.replace(
|
|
1248
1410
|
new RegExp(`(src=["'])/?(${escapeRegExp(originalEntry)})(["'])`, "g"),
|
|
1249
1411
|
`$1${config.base}${chunk.fileName}$3`
|
|
1250
1412
|
);
|
|
1251
1413
|
}
|
|
1252
1414
|
}
|
|
1253
|
-
|
|
1415
|
+
import_node_fs8.default.writeFileSync(import_node_path10.default.resolve(outDir, "index.html"), processedHtml);
|
|
1254
1416
|
}
|
|
1255
1417
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
1256
1418
|
const totalSize = output.reduce((sum, chunk) => {
|
|
@@ -1272,12 +1434,12 @@ function formatSize(bytes) {
|
|
|
1272
1434
|
function escapeRegExp(string) {
|
|
1273
1435
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1274
1436
|
}
|
|
1275
|
-
var
|
|
1437
|
+
var import_node_path10, import_node_fs8, import_rolldown, import_picocolors2;
|
|
1276
1438
|
var init_build = __esm({
|
|
1277
1439
|
"src/build/index.ts"() {
|
|
1278
1440
|
"use strict";
|
|
1279
|
-
|
|
1280
|
-
|
|
1441
|
+
import_node_path10 = __toESM(require("path"), 1);
|
|
1442
|
+
import_node_fs8 = __toESM(require("fs"), 1);
|
|
1281
1443
|
import_rolldown = require("rolldown");
|
|
1282
1444
|
init_config();
|
|
1283
1445
|
init_resolve();
|
|
@@ -1285,6 +1447,8 @@ var init_build = __esm({
|
|
|
1285
1447
|
init_assets();
|
|
1286
1448
|
init_html();
|
|
1287
1449
|
init_transformer();
|
|
1450
|
+
init_env();
|
|
1451
|
+
init_plugin_container();
|
|
1288
1452
|
import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
1289
1453
|
}
|
|
1290
1454
|
});
|
|
@@ -1339,11 +1503,11 @@ cli.command("build [root]", "Build for production").option("--outDir <dir>", "Ou
|
|
|
1339
1503
|
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) => {
|
|
1340
1504
|
try {
|
|
1341
1505
|
const http2 = await import("http");
|
|
1342
|
-
const
|
|
1506
|
+
const path11 = await import("path");
|
|
1343
1507
|
const sirv2 = (await import("sirv")).default;
|
|
1344
1508
|
const connect2 = (await import("connect")).default;
|
|
1345
|
-
const resolvedRoot =
|
|
1346
|
-
const outDir =
|
|
1509
|
+
const resolvedRoot = path11.resolve(root ?? ".");
|
|
1510
|
+
const outDir = path11.resolve(resolvedRoot, options.outDir);
|
|
1347
1511
|
const app = connect2();
|
|
1348
1512
|
app.use(sirv2(outDir, { single: true, etag: true, gzip: true, brotli: true }));
|
|
1349
1513
|
const port = options.port;
|