@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.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, {
|
|
@@ -550,8 +651,23 @@ __export(middleware_exports, {
|
|
|
550
651
|
transformRequest: () => transformRequest
|
|
551
652
|
});
|
|
552
653
|
function transformMiddleware(ctx) {
|
|
654
|
+
ctx.envDefine = buildEnvDefine(
|
|
655
|
+
loadEnv(ctx.config.mode, ctx.config.root, ctx.config.envPrefix),
|
|
656
|
+
ctx.config.mode
|
|
657
|
+
);
|
|
553
658
|
return async (req, res, next) => {
|
|
554
659
|
const url = req.url ?? "/";
|
|
660
|
+
if (ctx.config.server.cors) {
|
|
661
|
+
const origin = req.headers.origin ?? "*";
|
|
662
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
663
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
|
|
664
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
665
|
+
if (req.method === "OPTIONS") {
|
|
666
|
+
res.statusCode = 204;
|
|
667
|
+
res.end();
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
555
671
|
if (req.method !== "GET") return next();
|
|
556
672
|
if (url === "/@nasti/client") {
|
|
557
673
|
res.setHeader("Content-Type", "application/javascript");
|
|
@@ -574,10 +690,6 @@ function transformMiddleware(ctx) {
|
|
|
574
690
|
}
|
|
575
691
|
}
|
|
576
692
|
}
|
|
577
|
-
processedHtml = processedHtml.replace(
|
|
578
|
-
"<head>",
|
|
579
|
-
'<head>\n <script type="module" src="/@nasti/client"></script>'
|
|
580
|
-
);
|
|
581
693
|
res.setHeader("Content-Type", "text/html");
|
|
582
694
|
res.end(processedHtml);
|
|
583
695
|
return;
|
|
@@ -610,10 +722,10 @@ async function transformRequest(url, ctx) {
|
|
|
610
722
|
return cached.transformResult;
|
|
611
723
|
}
|
|
612
724
|
const filePath = resolveUrlToFile(url, config.root);
|
|
613
|
-
if (!filePath || !
|
|
725
|
+
if (!filePath || !import_node_fs4.default.existsSync(filePath)) return null;
|
|
614
726
|
const mod = await moduleGraph.ensureEntryFromUrl(url);
|
|
615
727
|
moduleGraph.registerModule(mod, filePath);
|
|
616
|
-
let code =
|
|
728
|
+
let code = import_node_fs4.default.readFileSync(filePath, "utf-8");
|
|
617
729
|
const pluginResult = await pluginContainer.transform(code, filePath);
|
|
618
730
|
if (pluginResult) {
|
|
619
731
|
code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
|
|
@@ -627,23 +739,33 @@ async function transformRequest(url, ctx) {
|
|
|
627
739
|
});
|
|
628
740
|
code = result.code;
|
|
629
741
|
}
|
|
742
|
+
const envDefine = ctx.envDefine ?? buildEnvDefine(
|
|
743
|
+
loadEnv(config.mode, config.root, config.envPrefix),
|
|
744
|
+
config.mode
|
|
745
|
+
);
|
|
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);
|
|
@@ -1074,11 +1224,13 @@ async function createServer(inlineConfig = {}) {
|
|
|
1074
1224
|
const host = config.server.host === true ? "0.0.0.0" : config.server.host;
|
|
1075
1225
|
await pluginContainer.buildStart();
|
|
1076
1226
|
return new Promise((resolve, reject) => {
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
const
|
|
1227
|
+
let currentPort = finalPort;
|
|
1228
|
+
const onListening = () => {
|
|
1229
|
+
const actualPort = httpServer.address()?.port ?? currentPort;
|
|
1230
|
+
const localUrl = `http://localhost:${actualPort}`;
|
|
1231
|
+
const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${actualPort}` : null;
|
|
1080
1232
|
console.log();
|
|
1081
|
-
console.log(import_picocolors.default.cyan(" nasti dev server") + import_picocolors.default.dim(`
|
|
1233
|
+
console.log(import_picocolors.default.cyan(" nasti dev server") + import_picocolors.default.dim(` v${"1.3.0"}`));
|
|
1082
1234
|
console.log();
|
|
1083
1235
|
console.log(` ${import_picocolors.default.green(">")} Local: ${import_picocolors.default.cyan(localUrl)}`);
|
|
1084
1236
|
if (networkUrl) {
|
|
@@ -1086,15 +1238,18 @@ async function createServer(inlineConfig = {}) {
|
|
|
1086
1238
|
}
|
|
1087
1239
|
console.log();
|
|
1088
1240
|
resolve(server);
|
|
1089
|
-
}
|
|
1241
|
+
};
|
|
1242
|
+
httpServer.on("listening", onListening);
|
|
1090
1243
|
httpServer.on("error", (err) => {
|
|
1091
1244
|
if (err.code === "EADDRINUSE") {
|
|
1092
|
-
|
|
1093
|
-
|
|
1245
|
+
currentPort++;
|
|
1246
|
+
console.log(import_picocolors.default.yellow(`Port ${currentPort - 1} is in use, trying ${currentPort}...`));
|
|
1247
|
+
httpServer.listen(currentPort, host);
|
|
1094
1248
|
} else {
|
|
1095
1249
|
reject(err);
|
|
1096
1250
|
}
|
|
1097
1251
|
});
|
|
1252
|
+
httpServer.listen(currentPort, host);
|
|
1098
1253
|
});
|
|
1099
1254
|
},
|
|
1100
1255
|
async transformRequest(url) {
|
|
@@ -1111,8 +1266,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
1111
1266
|
return server;
|
|
1112
1267
|
}
|
|
1113
1268
|
function getNetworkAddress() {
|
|
1114
|
-
const
|
|
1115
|
-
const interfaces = os.networkInterfaces();
|
|
1269
|
+
const interfaces = import_node_os.default.networkInterfaces();
|
|
1116
1270
|
for (const name of Object.keys(interfaces)) {
|
|
1117
1271
|
for (const iface of interfaces[name] ?? []) {
|
|
1118
1272
|
if (iface.family === "IPv4" && !iface.internal) {
|
|
@@ -1122,12 +1276,13 @@ function getNetworkAddress() {
|
|
|
1122
1276
|
}
|
|
1123
1277
|
return "localhost";
|
|
1124
1278
|
}
|
|
1125
|
-
var import_node_http,
|
|
1279
|
+
var import_node_http, import_node_path9, import_node_os, import_connect, import_sirv, import_chokidar, import_picocolors;
|
|
1126
1280
|
var init_server = __esm({
|
|
1127
1281
|
"src/server/index.ts"() {
|
|
1128
1282
|
"use strict";
|
|
1129
1283
|
import_node_http = __toESM(require("http"), 1);
|
|
1130
|
-
|
|
1284
|
+
import_node_path9 = __toESM(require("path"), 1);
|
|
1285
|
+
import_node_os = __toESM(require("os"), 1);
|
|
1131
1286
|
import_connect = __toESM(require("connect"), 1);
|
|
1132
1287
|
import_sirv = __toESM(require("sirv"), 1);
|
|
1133
1288
|
import_chokidar = require("chokidar");
|
|
@@ -1153,14 +1308,14 @@ __export(build_exports, {
|
|
|
1153
1308
|
async function build(inlineConfig = {}) {
|
|
1154
1309
|
const config = await resolveConfig(inlineConfig, "build");
|
|
1155
1310
|
const startTime = performance.now();
|
|
1156
|
-
console.log(import_picocolors2.default.cyan("\n\u{1F528} nasti build") + import_picocolors2.default.dim(` v${
|
|
1311
|
+
console.log(import_picocolors2.default.cyan("\n\u{1F528} nasti build") + import_picocolors2.default.dim(` v${"1.3.0"}`));
|
|
1157
1312
|
console.log(import_picocolors2.default.dim(` root: ${config.root}`));
|
|
1158
1313
|
console.log(import_picocolors2.default.dim(` mode: ${config.mode}`));
|
|
1159
|
-
const outDir =
|
|
1160
|
-
if (config.build.emptyOutDir &&
|
|
1161
|
-
|
|
1314
|
+
const outDir = import_node_path10.default.resolve(config.root, config.build.outDir);
|
|
1315
|
+
if (config.build.emptyOutDir && import_node_fs8.default.existsSync(outDir)) {
|
|
1316
|
+
import_node_fs8.default.rmSync(outDir, { recursive: true, force: true });
|
|
1162
1317
|
}
|
|
1163
|
-
|
|
1318
|
+
import_node_fs8.default.mkdirSync(outDir, { recursive: true });
|
|
1164
1319
|
const html = await readHtmlFile(config.root);
|
|
1165
1320
|
let entryPoints = [];
|
|
1166
1321
|
if (html) {
|
|
@@ -1168,15 +1323,15 @@ async function build(inlineConfig = {}) {
|
|
|
1168
1323
|
for (const match of scriptMatches) {
|
|
1169
1324
|
const src = match[1];
|
|
1170
1325
|
if (src && !src.startsWith("http")) {
|
|
1171
|
-
entryPoints.push(
|
|
1326
|
+
entryPoints.push(import_node_path10.default.resolve(config.root, src.replace(/^\//, "")));
|
|
1172
1327
|
}
|
|
1173
1328
|
}
|
|
1174
1329
|
}
|
|
1175
1330
|
if (entryPoints.length === 0) {
|
|
1176
1331
|
const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
|
|
1177
1332
|
for (const entry of fallbackEntries) {
|
|
1178
|
-
const fullPath =
|
|
1179
|
-
if (
|
|
1333
|
+
const fullPath = import_node_path10.default.resolve(config.root, entry);
|
|
1334
|
+
if (import_node_fs8.default.existsSync(fullPath)) {
|
|
1180
1335
|
entryPoints.push(fullPath);
|
|
1181
1336
|
break;
|
|
1182
1337
|
}
|
|
@@ -1191,6 +1346,8 @@ async function build(inlineConfig = {}) {
|
|
|
1191
1346
|
assetsPlugin(config)
|
|
1192
1347
|
];
|
|
1193
1348
|
const allPlugins = [...builtinPlugins, ...config.plugins];
|
|
1349
|
+
const pluginContainer = new PluginContainer(config);
|
|
1350
|
+
await pluginContainer.buildStart();
|
|
1194
1351
|
const oxcTransformPlugin = {
|
|
1195
1352
|
name: "nasti:oxc-transform",
|
|
1196
1353
|
transform(code, id) {
|
|
@@ -1203,8 +1360,11 @@ async function build(inlineConfig = {}) {
|
|
|
1203
1360
|
return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
|
|
1204
1361
|
}
|
|
1205
1362
|
};
|
|
1363
|
+
const env = loadEnv(config.mode, config.root, config.envPrefix);
|
|
1364
|
+
const envDefine = buildEnvDefine(env, config.mode);
|
|
1206
1365
|
const bundle = await (0, import_rolldown.rolldown)({
|
|
1207
1366
|
input: entryPoints,
|
|
1367
|
+
define: envDefine,
|
|
1208
1368
|
plugins: [
|
|
1209
1369
|
oxcTransformPlugin,
|
|
1210
1370
|
// 转换 Nasti 插件为 Rolldown 插件格式
|
|
@@ -1223,11 +1383,18 @@ async function build(inlineConfig = {}) {
|
|
|
1223
1383
|
dir: outDir,
|
|
1224
1384
|
format: "esm",
|
|
1225
1385
|
sourcemap: !!config.build.sourcemap,
|
|
1386
|
+
minify: !!config.build.minify,
|
|
1226
1387
|
entryFileNames: "assets/[name].[hash].js",
|
|
1227
1388
|
chunkFileNames: "assets/[name].[hash].js",
|
|
1228
1389
|
assetFileNames: "assets/[name].[hash][extname]"
|
|
1229
1390
|
});
|
|
1230
1391
|
await bundle.close();
|
|
1392
|
+
await pluginContainer.buildEnd();
|
|
1393
|
+
for (const ef of pluginContainer.getEmittedFiles()) {
|
|
1394
|
+
const dest = import_node_path10.default.resolve(outDir, ef.fileName);
|
|
1395
|
+
import_node_fs8.default.mkdirSync(import_node_path10.default.dirname(dest), { recursive: true });
|
|
1396
|
+
import_node_fs8.default.writeFileSync(dest, ef.source);
|
|
1397
|
+
}
|
|
1231
1398
|
if (html) {
|
|
1232
1399
|
let processedHtml = html;
|
|
1233
1400
|
const htmlPlugin_ = htmlPlugin(config);
|
|
@@ -1242,15 +1409,15 @@ async function build(inlineConfig = {}) {
|
|
|
1242
1409
|
}
|
|
1243
1410
|
}
|
|
1244
1411
|
for (const chunk of output) {
|
|
1245
|
-
if (chunk.type === "chunk" && chunk.isEntry) {
|
|
1246
|
-
const originalEntry =
|
|
1412
|
+
if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) {
|
|
1413
|
+
const originalEntry = import_node_path10.default.relative(config.root, chunk.facadeModuleId);
|
|
1247
1414
|
processedHtml = processedHtml.replace(
|
|
1248
1415
|
new RegExp(`(src=["'])/?(${escapeRegExp(originalEntry)})(["'])`, "g"),
|
|
1249
1416
|
`$1${config.base}${chunk.fileName}$3`
|
|
1250
1417
|
);
|
|
1251
1418
|
}
|
|
1252
1419
|
}
|
|
1253
|
-
|
|
1420
|
+
import_node_fs8.default.writeFileSync(import_node_path10.default.resolve(outDir, "index.html"), processedHtml);
|
|
1254
1421
|
}
|
|
1255
1422
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
1256
1423
|
const totalSize = output.reduce((sum, chunk) => {
|
|
@@ -1272,12 +1439,12 @@ function formatSize(bytes) {
|
|
|
1272
1439
|
function escapeRegExp(string) {
|
|
1273
1440
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1274
1441
|
}
|
|
1275
|
-
var
|
|
1442
|
+
var import_node_path10, import_node_fs8, import_rolldown, import_picocolors2;
|
|
1276
1443
|
var init_build = __esm({
|
|
1277
1444
|
"src/build/index.ts"() {
|
|
1278
1445
|
"use strict";
|
|
1279
|
-
|
|
1280
|
-
|
|
1446
|
+
import_node_path10 = __toESM(require("path"), 1);
|
|
1447
|
+
import_node_fs8 = __toESM(require("fs"), 1);
|
|
1281
1448
|
import_rolldown = require("rolldown");
|
|
1282
1449
|
init_config();
|
|
1283
1450
|
init_resolve();
|
|
@@ -1285,6 +1452,8 @@ var init_build = __esm({
|
|
|
1285
1452
|
init_assets();
|
|
1286
1453
|
init_html();
|
|
1287
1454
|
init_transformer();
|
|
1455
|
+
init_env();
|
|
1456
|
+
init_plugin_container();
|
|
1288
1457
|
import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
1289
1458
|
}
|
|
1290
1459
|
});
|
|
@@ -1339,11 +1508,11 @@ cli.command("build [root]", "Build for production").option("--outDir <dir>", "Ou
|
|
|
1339
1508
|
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
1509
|
try {
|
|
1341
1510
|
const http2 = await import("http");
|
|
1342
|
-
const
|
|
1511
|
+
const path11 = await import("path");
|
|
1343
1512
|
const sirv2 = (await import("sirv")).default;
|
|
1344
1513
|
const connect2 = (await import("connect")).default;
|
|
1345
|
-
const resolvedRoot =
|
|
1346
|
-
const outDir =
|
|
1514
|
+
const resolvedRoot = path11.resolve(root ?? ".");
|
|
1515
|
+
const outDir = path11.resolve(resolvedRoot, options.outDir);
|
|
1347
1516
|
const app = connect2();
|
|
1348
1517
|
app.use(sirv2(outDir, { single: true, etag: true, gzip: true, brotli: true }));
|
|
1349
1518
|
const port = options.port;
|
|
@@ -1364,6 +1533,6 @@ cli.command("preview [root]", "Preview production build").option("--port <port>"
|
|
|
1364
1533
|
}
|
|
1365
1534
|
});
|
|
1366
1535
|
cli.help();
|
|
1367
|
-
cli.version("
|
|
1536
|
+
cli.version("1.3.0");
|
|
1368
1537
|
cli.parse();
|
|
1369
1538
|
//# sourceMappingURL=cli.cjs.map
|