@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/index.cjs
CHANGED
|
@@ -113,6 +113,11 @@ function transformCode(filename, code, options = {}) {
|
|
|
113
113
|
} : void 0,
|
|
114
114
|
sourcemap: options.sourcemap ?? true
|
|
115
115
|
});
|
|
116
|
+
if (result.errors && result.errors.length > 0) {
|
|
117
|
+
const msg = result.errors.map((e) => e.message ?? String(e)).join("\n");
|
|
118
|
+
throw new Error(`OXC transform failed for ${filename}:
|
|
119
|
+
${msg}`);
|
|
120
|
+
}
|
|
116
121
|
return {
|
|
117
122
|
code: result.code,
|
|
118
123
|
map: result.map ? JSON.stringify(result.map) : null
|
|
@@ -129,6 +134,68 @@ var init_transformer = __esm({
|
|
|
129
134
|
}
|
|
130
135
|
});
|
|
131
136
|
|
|
137
|
+
// src/core/env.ts
|
|
138
|
+
function loadEnv(mode, root, prefixes) {
|
|
139
|
+
const envFiles = [
|
|
140
|
+
".env",
|
|
141
|
+
`.env.${mode}`,
|
|
142
|
+
".env.local",
|
|
143
|
+
`.env.${mode}.local`
|
|
144
|
+
];
|
|
145
|
+
const raw = {};
|
|
146
|
+
for (const file of envFiles) {
|
|
147
|
+
const filePath = import_node_path6.default.resolve(root, file);
|
|
148
|
+
if (!import_node_fs5.default.existsSync(filePath)) continue;
|
|
149
|
+
const content = import_node_fs5.default.readFileSync(filePath, "utf-8");
|
|
150
|
+
for (const line of content.split("\n")) {
|
|
151
|
+
const trimmed = line.trim();
|
|
152
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
153
|
+
const eqIdx = trimmed.indexOf("=");
|
|
154
|
+
if (eqIdx === -1) continue;
|
|
155
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
156
|
+
let value = trimmed.slice(eqIdx + 1).trim();
|
|
157
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
158
|
+
value = value.slice(1, -1);
|
|
159
|
+
}
|
|
160
|
+
raw[key] = value;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const filtered = {};
|
|
164
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
165
|
+
if (prefixes.some((prefix) => key.startsWith(prefix))) {
|
|
166
|
+
filtered[key] = value;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return filtered;
|
|
170
|
+
}
|
|
171
|
+
function buildEnvDefine(env, mode) {
|
|
172
|
+
const define = {};
|
|
173
|
+
for (const [key, value] of Object.entries(env)) {
|
|
174
|
+
define[`import.meta.env.${key}`] = JSON.stringify(value);
|
|
175
|
+
}
|
|
176
|
+
define["import.meta.env.MODE"] = JSON.stringify(mode);
|
|
177
|
+
define["import.meta.env.DEV"] = mode !== "production" ? "true" : "false";
|
|
178
|
+
define["import.meta.env.PROD"] = mode === "production" ? "true" : "false";
|
|
179
|
+
define["import.meta.env.SSR"] = "false";
|
|
180
|
+
return define;
|
|
181
|
+
}
|
|
182
|
+
function replaceEnvInCode(code, define) {
|
|
183
|
+
let result = code;
|
|
184
|
+
for (const [key, value] of Object.entries(define)) {
|
|
185
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
186
|
+
result = result.replace(new RegExp(escaped, "g"), value);
|
|
187
|
+
}
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
var import_node_path6, import_node_fs5;
|
|
191
|
+
var init_env = __esm({
|
|
192
|
+
"src/core/env.ts"() {
|
|
193
|
+
"use strict";
|
|
194
|
+
import_node_path6 = __toESM(require("path"), 1);
|
|
195
|
+
import_node_fs5 = __toESM(require("fs"), 1);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
132
199
|
// src/server/middleware.ts
|
|
133
200
|
var middleware_exports = {};
|
|
134
201
|
__export(middleware_exports, {
|
|
@@ -138,6 +205,17 @@ __export(middleware_exports, {
|
|
|
138
205
|
function transformMiddleware(ctx) {
|
|
139
206
|
return async (req, res, next) => {
|
|
140
207
|
const url = req.url ?? "/";
|
|
208
|
+
if (ctx.config.server.cors) {
|
|
209
|
+
const origin = req.headers.origin ?? "*";
|
|
210
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
211
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS");
|
|
212
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
213
|
+
if (req.method === "OPTIONS") {
|
|
214
|
+
res.statusCode = 204;
|
|
215
|
+
res.end();
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
141
219
|
if (req.method !== "GET") return next();
|
|
142
220
|
if (url === "/@nasti/client") {
|
|
143
221
|
res.setHeader("Content-Type", "application/javascript");
|
|
@@ -160,10 +238,12 @@ function transformMiddleware(ctx) {
|
|
|
160
238
|
}
|
|
161
239
|
}
|
|
162
240
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
241
|
+
if (ctx.config.server.hmr !== false) {
|
|
242
|
+
processedHtml = processedHtml.replace(
|
|
243
|
+
"<head>",
|
|
244
|
+
'<head>\n <script type="module" src="/@nasti/client"></script>'
|
|
245
|
+
);
|
|
246
|
+
}
|
|
167
247
|
res.setHeader("Content-Type", "text/html");
|
|
168
248
|
res.end(processedHtml);
|
|
169
249
|
return;
|
|
@@ -196,10 +276,10 @@ async function transformRequest(url, ctx) {
|
|
|
196
276
|
return cached.transformResult;
|
|
197
277
|
}
|
|
198
278
|
const filePath = resolveUrlToFile(url, config.root);
|
|
199
|
-
if (!filePath || !
|
|
279
|
+
if (!filePath || !import_node_fs7.default.existsSync(filePath)) return null;
|
|
200
280
|
const mod = await moduleGraph.ensureEntryFromUrl(url);
|
|
201
281
|
moduleGraph.registerModule(mod, filePath);
|
|
202
|
-
let code =
|
|
282
|
+
let code = import_node_fs7.default.readFileSync(filePath, "utf-8");
|
|
203
283
|
const pluginResult = await pluginContainer.transform(code, filePath);
|
|
204
284
|
if (pluginResult) {
|
|
205
285
|
code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
|
|
@@ -213,23 +293,31 @@ async function transformRequest(url, ctx) {
|
|
|
213
293
|
});
|
|
214
294
|
code = result.code;
|
|
215
295
|
}
|
|
296
|
+
const env = loadEnv(config.mode, config.root, config.envPrefix);
|
|
297
|
+
const envDefine = buildEnvDefine(env, config.mode);
|
|
298
|
+
code = replaceEnvInCode(code, envDefine);
|
|
216
299
|
code = rewriteImports(code, config);
|
|
217
300
|
const transformResult = { code };
|
|
218
301
|
mod.transformResult = transformResult;
|
|
219
302
|
return transformResult;
|
|
220
303
|
}
|
|
221
|
-
function rewriteImports(code,
|
|
304
|
+
function rewriteImports(code, _config) {
|
|
222
305
|
return code.replace(
|
|
223
|
-
|
|
224
|
-
(match, specifier) => {
|
|
225
|
-
|
|
226
|
-
|
|
306
|
+
/\bfrom\s+(['"])([^'"./][^'"]*)\1/g,
|
|
307
|
+
(match, quote, specifier) => {
|
|
308
|
+
return `from ${quote}/@modules/${specifier}${quote}`;
|
|
309
|
+
}
|
|
310
|
+
).replace(
|
|
311
|
+
// 处理纯副作用导入: import 'bare-specifier'
|
|
312
|
+
/\bimport\s+(['"])([^'"./][^'"]*)\1/g,
|
|
313
|
+
(match, quote, specifier) => {
|
|
314
|
+
return `import ${quote}/@modules/${specifier}${quote}`;
|
|
227
315
|
}
|
|
228
316
|
).replace(
|
|
229
|
-
|
|
230
|
-
(
|
|
231
|
-
|
|
232
|
-
return `import
|
|
317
|
+
// 处理动态导入: import('bare-specifier')
|
|
318
|
+
/\bimport\s*\(\s*(['"])([^'"./][^'"]*)\1\s*\)/g,
|
|
319
|
+
(match, quote, specifier) => {
|
|
320
|
+
return `import(${quote}/@modules/${specifier}${quote})`;
|
|
233
321
|
}
|
|
234
322
|
);
|
|
235
323
|
}
|
|
@@ -238,14 +326,13 @@ function resolveUrlToFile(url, root) {
|
|
|
238
326
|
if (cleanUrl.startsWith("/@modules/")) {
|
|
239
327
|
const moduleName = cleanUrl.slice("/@modules/".length);
|
|
240
328
|
try {
|
|
241
|
-
const
|
|
242
|
-
const req = createRequire2(import_node_path7.default.resolve(root, "package.json"));
|
|
329
|
+
const req = (0, import_node_module2.createRequire)(import_node_path8.default.resolve(root, "package.json"));
|
|
243
330
|
return req.resolve(moduleName);
|
|
244
331
|
} catch {
|
|
245
332
|
return null;
|
|
246
333
|
}
|
|
247
334
|
}
|
|
248
|
-
return
|
|
335
|
+
return import_node_path8.default.resolve(root, cleanUrl.replace(/^\//, ""));
|
|
249
336
|
}
|
|
250
337
|
function isModuleRequest(url) {
|
|
251
338
|
const cleanUrl = url.split("?")[0];
|
|
@@ -307,7 +394,18 @@ function showErrorOverlay(err) {
|
|
|
307
394
|
const overlay = document.createElement('div');
|
|
308
395
|
overlay.id = 'nasti-error-overlay';
|
|
309
396
|
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;';
|
|
310
|
-
|
|
397
|
+
const title = document.createElement('h2');
|
|
398
|
+
title.style.color = '#ff5555';
|
|
399
|
+
title.textContent = 'Build Error';
|
|
400
|
+
const pre = document.createElement('pre');
|
|
401
|
+
pre.textContent = err.message + '\\n' + (err.stack || '');
|
|
402
|
+
const btn = document.createElement('button');
|
|
403
|
+
btn.style.cssText = 'margin-top:1rem;padding:0.5rem 1rem;cursor:pointer';
|
|
404
|
+
btn.textContent = 'Close';
|
|
405
|
+
btn.onclick = () => overlay.remove();
|
|
406
|
+
overlay.appendChild(title);
|
|
407
|
+
overlay.appendChild(pre);
|
|
408
|
+
overlay.appendChild(btn);
|
|
311
409
|
document.body.appendChild(overlay);
|
|
312
410
|
}
|
|
313
411
|
|
|
@@ -338,14 +436,16 @@ if (!window.__nasti_hot_map) window.__nasti_hot_map = new Map();
|
|
|
338
436
|
window.__NASTI_HMR__ = { createHotContext };
|
|
339
437
|
`;
|
|
340
438
|
}
|
|
341
|
-
var
|
|
439
|
+
var import_node_path8, import_node_fs7, import_node_module2;
|
|
342
440
|
var init_middleware = __esm({
|
|
343
441
|
"src/server/middleware.ts"() {
|
|
344
442
|
"use strict";
|
|
345
|
-
|
|
346
|
-
|
|
443
|
+
import_node_path8 = __toESM(require("path"), 1);
|
|
444
|
+
import_node_fs7 = __toESM(require("fs"), 1);
|
|
445
|
+
import_node_module2 = require("module");
|
|
347
446
|
init_transformer();
|
|
348
447
|
init_html();
|
|
448
|
+
init_env();
|
|
349
449
|
}
|
|
350
450
|
});
|
|
351
451
|
|
|
@@ -403,6 +503,27 @@ var defaults = {
|
|
|
403
503
|
};
|
|
404
504
|
|
|
405
505
|
// src/config/index.ts
|
|
506
|
+
function loadTsconfigPaths(root) {
|
|
507
|
+
const tsconfigPath = import_node_path.default.resolve(root, "tsconfig.json");
|
|
508
|
+
if (!import_node_fs.default.existsSync(tsconfigPath)) return {};
|
|
509
|
+
try {
|
|
510
|
+
const content = import_node_fs.default.readFileSync(tsconfigPath, "utf-8");
|
|
511
|
+
const stripped = content.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
512
|
+
const tsconfig = JSON.parse(stripped);
|
|
513
|
+
const paths = tsconfig?.compilerOptions?.paths ?? {};
|
|
514
|
+
const baseUrl = tsconfig?.compilerOptions?.baseUrl ?? ".";
|
|
515
|
+
const alias = {};
|
|
516
|
+
for (const [pattern, targets] of Object.entries(paths)) {
|
|
517
|
+
if (!targets.length) continue;
|
|
518
|
+
const cleanKey = pattern.replace(/\/\*$/, "");
|
|
519
|
+
const cleanTarget = targets[0].replace(/\/\*$/, "");
|
|
520
|
+
alias[cleanKey] = import_node_path.default.resolve(root, baseUrl, cleanTarget);
|
|
521
|
+
}
|
|
522
|
+
return alias;
|
|
523
|
+
} catch {
|
|
524
|
+
return {};
|
|
525
|
+
}
|
|
526
|
+
}
|
|
406
527
|
function defineConfig(config) {
|
|
407
528
|
return config;
|
|
408
529
|
}
|
|
@@ -454,11 +575,6 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
454
575
|
if (result) Object.assign(merged, result);
|
|
455
576
|
}
|
|
456
577
|
}
|
|
457
|
-
const filteredPlugins = rawPlugins.filter((p) => {
|
|
458
|
-
if (!p.apply) return true;
|
|
459
|
-
if (typeof p.apply === "function") return p.apply(resolved, env);
|
|
460
|
-
return p.apply === command;
|
|
461
|
-
});
|
|
462
578
|
const resolved = {
|
|
463
579
|
root,
|
|
464
580
|
base: merged.base ?? defaults.base,
|
|
@@ -466,17 +582,24 @@ async function resolveConfig(inlineConfig = {}, command) {
|
|
|
466
582
|
framework: merged.framework ?? defaults.framework,
|
|
467
583
|
command,
|
|
468
584
|
resolve: {
|
|
469
|
-
|
|
585
|
+
// tsconfig paths 优先级最低:tsconfig < defaults < user config
|
|
586
|
+
alias: { ...loadTsconfigPaths(root), ...defaults.resolve.alias, ...merged.resolve?.alias },
|
|
470
587
|
extensions: merged.resolve?.extensions ?? defaults.resolve.extensions,
|
|
471
588
|
conditions: merged.resolve?.conditions ?? defaults.resolve.conditions,
|
|
472
589
|
mainFields: merged.resolve?.mainFields ?? defaults.resolve.mainFields
|
|
473
590
|
},
|
|
474
|
-
plugins:
|
|
591
|
+
plugins: [],
|
|
475
592
|
server: { ...defaults.server, ...merged.server },
|
|
476
593
|
build: { ...defaults.build, ...merged.build },
|
|
477
594
|
envPrefix: Array.isArray(merged.envPrefix) ? merged.envPrefix : merged.envPrefix ? [merged.envPrefix] : [...defaults.envPrefix],
|
|
478
595
|
logLevel: merged.logLevel ?? defaults.logLevel
|
|
479
596
|
};
|
|
597
|
+
const filteredPlugins = rawPlugins.filter((p) => {
|
|
598
|
+
if (!p.apply) return true;
|
|
599
|
+
if (typeof p.apply === "function") return p.apply(resolved, env);
|
|
600
|
+
return p.apply === command;
|
|
601
|
+
});
|
|
602
|
+
resolved.plugins = filteredPlugins;
|
|
480
603
|
for (const plugin of resolved.plugins) {
|
|
481
604
|
if (plugin.configResolved) {
|
|
482
605
|
await plugin.configResolved(resolved);
|
|
@@ -501,8 +624,8 @@ function deepMerge(target, source) {
|
|
|
501
624
|
}
|
|
502
625
|
|
|
503
626
|
// src/build/index.ts
|
|
504
|
-
var
|
|
505
|
-
var
|
|
627
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
628
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
506
629
|
var import_rolldown = require("rolldown");
|
|
507
630
|
|
|
508
631
|
// src/plugins/resolve.ts
|
|
@@ -548,10 +671,12 @@ function resolvePlugin(config) {
|
|
|
548
671
|
return null;
|
|
549
672
|
},
|
|
550
673
|
load(id) {
|
|
551
|
-
if (import_node_fs2.default.existsSync(id))
|
|
552
|
-
|
|
674
|
+
if (!import_node_fs2.default.existsSync(id)) return null;
|
|
675
|
+
if (id.endsWith(".json")) {
|
|
676
|
+
const content = import_node_fs2.default.readFileSync(id, "utf-8");
|
|
677
|
+
return `export default ${content}`;
|
|
553
678
|
}
|
|
554
|
-
return
|
|
679
|
+
return import_node_fs2.default.readFileSync(id, "utf-8");
|
|
555
680
|
}
|
|
556
681
|
};
|
|
557
682
|
}
|
|
@@ -587,13 +712,17 @@ function cssPlugin(config) {
|
|
|
587
712
|
},
|
|
588
713
|
transform(code, id) {
|
|
589
714
|
if (!id.endsWith(".css")) return null;
|
|
715
|
+
const rewritten = rewriteCssUrls(code, id, config.root);
|
|
590
716
|
if (config.command === "serve") {
|
|
591
|
-
const escaped = JSON.stringify(
|
|
717
|
+
const escaped = JSON.stringify(rewritten);
|
|
592
718
|
return {
|
|
593
719
|
code: `
|
|
594
720
|
const css = ${escaped};
|
|
721
|
+
const __nasti_css_id__ = ${JSON.stringify(id)};
|
|
722
|
+
const __nasti_existing__ = document.querySelector('style[data-nasti-css=' + JSON.stringify(__nasti_css_id__) + ']');
|
|
723
|
+
if (__nasti_existing__) __nasti_existing__.remove();
|
|
595
724
|
const style = document.createElement('style');
|
|
596
|
-
style.setAttribute('data-nasti-css',
|
|
725
|
+
style.setAttribute('data-nasti-css', __nasti_css_id__);
|
|
597
726
|
style.textContent = css;
|
|
598
727
|
document.head.appendChild(style);
|
|
599
728
|
|
|
@@ -609,10 +738,20 @@ export default css;
|
|
|
609
738
|
`
|
|
610
739
|
};
|
|
611
740
|
}
|
|
612
|
-
return null;
|
|
741
|
+
return rewritten !== code ? { code: rewritten } : null;
|
|
613
742
|
}
|
|
614
743
|
};
|
|
615
744
|
}
|
|
745
|
+
function rewriteCssUrls(css, from, root) {
|
|
746
|
+
return css.replace(/url\(\s*['"]?([^'")\s]+)['"]?\s*\)/g, (match, url) => {
|
|
747
|
+
if (url.startsWith("/") || url.startsWith("data:") || url.startsWith("http")) {
|
|
748
|
+
return match;
|
|
749
|
+
}
|
|
750
|
+
const resolved = import_node_path3.default.resolve(import_node_path3.default.dirname(from), url);
|
|
751
|
+
const relative = "/" + import_node_path3.default.relative(root, resolved);
|
|
752
|
+
return `url(${relative})`;
|
|
753
|
+
});
|
|
754
|
+
}
|
|
616
755
|
|
|
617
756
|
// src/plugins/assets.ts
|
|
618
757
|
var import_node_path4 = __toESM(require("path"), 1);
|
|
@@ -681,6 +820,123 @@ function assetsPlugin(config) {
|
|
|
681
820
|
// src/build/index.ts
|
|
682
821
|
init_html();
|
|
683
822
|
init_transformer();
|
|
823
|
+
init_env();
|
|
824
|
+
|
|
825
|
+
// src/core/plugin-container.ts
|
|
826
|
+
var PluginContainer = class {
|
|
827
|
+
plugins;
|
|
828
|
+
config;
|
|
829
|
+
ctx;
|
|
830
|
+
emittedFiles = /* @__PURE__ */ new Map();
|
|
831
|
+
constructor(config) {
|
|
832
|
+
this.config = config;
|
|
833
|
+
this.plugins = sortPlugins(config.plugins);
|
|
834
|
+
this.ctx = this.createContext();
|
|
835
|
+
}
|
|
836
|
+
createContext() {
|
|
837
|
+
const container = this;
|
|
838
|
+
return {
|
|
839
|
+
async resolve(source, importer) {
|
|
840
|
+
return container.resolveId(source, importer);
|
|
841
|
+
},
|
|
842
|
+
emitFile(file) {
|
|
843
|
+
const fileName = file.fileName ?? file.name ?? `asset-${container.emittedFiles.size}`;
|
|
844
|
+
const id = `emitted:${fileName}`;
|
|
845
|
+
container.emittedFiles.set(id, {
|
|
846
|
+
fileName,
|
|
847
|
+
source: file.source ?? ""
|
|
848
|
+
});
|
|
849
|
+
return id;
|
|
850
|
+
},
|
|
851
|
+
getModuleInfo(_id) {
|
|
852
|
+
return null;
|
|
853
|
+
}
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
/** 返回所有通过 emitFile() 输出的文件 */
|
|
857
|
+
getEmittedFiles() {
|
|
858
|
+
return Array.from(this.emittedFiles.values());
|
|
859
|
+
}
|
|
860
|
+
async buildStart() {
|
|
861
|
+
for (const plugin of this.plugins) {
|
|
862
|
+
if (plugin.buildStart) {
|
|
863
|
+
await plugin.buildStart.call(this.ctx);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
async buildEnd(error) {
|
|
868
|
+
for (const plugin of this.plugins) {
|
|
869
|
+
if (plugin.buildEnd) {
|
|
870
|
+
await plugin.buildEnd.call(this.ctx, error);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
async resolveId(source, importer, options = {}) {
|
|
875
|
+
for (const plugin of this.plugins) {
|
|
876
|
+
if (!plugin.resolveId) continue;
|
|
877
|
+
const result = await plugin.resolveId.call(
|
|
878
|
+
this.ctx,
|
|
879
|
+
source,
|
|
880
|
+
importer ?? void 0,
|
|
881
|
+
{ isEntry: options.isEntry ?? false, ssr: false }
|
|
882
|
+
);
|
|
883
|
+
if (result != null) return result;
|
|
884
|
+
}
|
|
885
|
+
return null;
|
|
886
|
+
}
|
|
887
|
+
async load(id) {
|
|
888
|
+
for (const plugin of this.plugins) {
|
|
889
|
+
if (!plugin.load) continue;
|
|
890
|
+
const result = await plugin.load.call(this.ctx, id);
|
|
891
|
+
if (result != null) return result;
|
|
892
|
+
}
|
|
893
|
+
return null;
|
|
894
|
+
}
|
|
895
|
+
async transform(code, id) {
|
|
896
|
+
let currentCode = code;
|
|
897
|
+
for (const plugin of this.plugins) {
|
|
898
|
+
if (!plugin.transform) continue;
|
|
899
|
+
const result = await plugin.transform.call(this.ctx, currentCode, id);
|
|
900
|
+
if (result == null) continue;
|
|
901
|
+
if (typeof result === "string") {
|
|
902
|
+
currentCode = result;
|
|
903
|
+
} else {
|
|
904
|
+
currentCode = result.code;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
return currentCode === code ? null : { code: currentCode };
|
|
908
|
+
}
|
|
909
|
+
/** 完整的模块处理管道: resolveId → load → transform */
|
|
910
|
+
async processModule(source, importer) {
|
|
911
|
+
const resolveResult = await this.resolveId(source, importer, {
|
|
912
|
+
isEntry: !importer
|
|
913
|
+
});
|
|
914
|
+
if (resolveResult == null) return null;
|
|
915
|
+
const id = typeof resolveResult === "string" ? resolveResult : resolveResult.id;
|
|
916
|
+
const loadResult = await this.load(id);
|
|
917
|
+
if (loadResult == null) return null;
|
|
918
|
+
const loadedCode = typeof loadResult === "string" ? loadResult : loadResult.code;
|
|
919
|
+
const transformResult = await this.transform(loadedCode, id);
|
|
920
|
+
const finalCode = transformResult == null ? loadedCode : typeof transformResult === "string" ? transformResult : transformResult.code;
|
|
921
|
+
return { id, code: finalCode };
|
|
922
|
+
}
|
|
923
|
+
getPlugins() {
|
|
924
|
+
return this.plugins;
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
function sortPlugins(plugins) {
|
|
928
|
+
const pre = [];
|
|
929
|
+
const normal = [];
|
|
930
|
+
const post = [];
|
|
931
|
+
for (const plugin of plugins) {
|
|
932
|
+
if (plugin.enforce === "pre") pre.push(plugin);
|
|
933
|
+
else if (plugin.enforce === "post") post.push(plugin);
|
|
934
|
+
else normal.push(plugin);
|
|
935
|
+
}
|
|
936
|
+
return [...pre, ...normal, ...post];
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// src/build/index.ts
|
|
684
940
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
685
941
|
async function build(inlineConfig = {}) {
|
|
686
942
|
const config = await resolveConfig(inlineConfig, "build");
|
|
@@ -688,11 +944,11 @@ async function build(inlineConfig = {}) {
|
|
|
688
944
|
console.log(import_picocolors.default.cyan("\n\u{1F528} nasti build") + import_picocolors.default.dim(` v${process.env.npm_package_version ?? "0.0.1"}`));
|
|
689
945
|
console.log(import_picocolors.default.dim(` root: ${config.root}`));
|
|
690
946
|
console.log(import_picocolors.default.dim(` mode: ${config.mode}`));
|
|
691
|
-
const outDir =
|
|
692
|
-
if (config.build.emptyOutDir &&
|
|
693
|
-
|
|
947
|
+
const outDir = import_node_path7.default.resolve(config.root, config.build.outDir);
|
|
948
|
+
if (config.build.emptyOutDir && import_node_fs6.default.existsSync(outDir)) {
|
|
949
|
+
import_node_fs6.default.rmSync(outDir, { recursive: true, force: true });
|
|
694
950
|
}
|
|
695
|
-
|
|
951
|
+
import_node_fs6.default.mkdirSync(outDir, { recursive: true });
|
|
696
952
|
const html = await readHtmlFile(config.root);
|
|
697
953
|
let entryPoints = [];
|
|
698
954
|
if (html) {
|
|
@@ -700,15 +956,15 @@ async function build(inlineConfig = {}) {
|
|
|
700
956
|
for (const match of scriptMatches) {
|
|
701
957
|
const src = match[1];
|
|
702
958
|
if (src && !src.startsWith("http")) {
|
|
703
|
-
entryPoints.push(
|
|
959
|
+
entryPoints.push(import_node_path7.default.resolve(config.root, src.replace(/^\//, "")));
|
|
704
960
|
}
|
|
705
961
|
}
|
|
706
962
|
}
|
|
707
963
|
if (entryPoints.length === 0) {
|
|
708
964
|
const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
|
|
709
965
|
for (const entry of fallbackEntries) {
|
|
710
|
-
const fullPath =
|
|
711
|
-
if (
|
|
966
|
+
const fullPath = import_node_path7.default.resolve(config.root, entry);
|
|
967
|
+
if (import_node_fs6.default.existsSync(fullPath)) {
|
|
712
968
|
entryPoints.push(fullPath);
|
|
713
969
|
break;
|
|
714
970
|
}
|
|
@@ -723,6 +979,8 @@ async function build(inlineConfig = {}) {
|
|
|
723
979
|
assetsPlugin(config)
|
|
724
980
|
];
|
|
725
981
|
const allPlugins = [...builtinPlugins, ...config.plugins];
|
|
982
|
+
const pluginContainer = new PluginContainer(config);
|
|
983
|
+
await pluginContainer.buildStart();
|
|
726
984
|
const oxcTransformPlugin = {
|
|
727
985
|
name: "nasti:oxc-transform",
|
|
728
986
|
transform(code, id) {
|
|
@@ -735,8 +993,11 @@ async function build(inlineConfig = {}) {
|
|
|
735
993
|
return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
|
|
736
994
|
}
|
|
737
995
|
};
|
|
996
|
+
const env = loadEnv(config.mode, config.root, config.envPrefix);
|
|
997
|
+
const envDefine = buildEnvDefine(env, config.mode);
|
|
738
998
|
const bundle = await (0, import_rolldown.rolldown)({
|
|
739
999
|
input: entryPoints,
|
|
1000
|
+
define: envDefine,
|
|
740
1001
|
plugins: [
|
|
741
1002
|
oxcTransformPlugin,
|
|
742
1003
|
// 转换 Nasti 插件为 Rolldown 插件格式
|
|
@@ -755,11 +1016,18 @@ async function build(inlineConfig = {}) {
|
|
|
755
1016
|
dir: outDir,
|
|
756
1017
|
format: "esm",
|
|
757
1018
|
sourcemap: !!config.build.sourcemap,
|
|
1019
|
+
minify: !!config.build.minify,
|
|
758
1020
|
entryFileNames: "assets/[name].[hash].js",
|
|
759
1021
|
chunkFileNames: "assets/[name].[hash].js",
|
|
760
1022
|
assetFileNames: "assets/[name].[hash][extname]"
|
|
761
1023
|
});
|
|
762
1024
|
await bundle.close();
|
|
1025
|
+
await pluginContainer.buildEnd();
|
|
1026
|
+
for (const ef of pluginContainer.getEmittedFiles()) {
|
|
1027
|
+
const dest = import_node_path7.default.resolve(outDir, ef.fileName);
|
|
1028
|
+
import_node_fs6.default.mkdirSync(import_node_path7.default.dirname(dest), { recursive: true });
|
|
1029
|
+
import_node_fs6.default.writeFileSync(dest, ef.source);
|
|
1030
|
+
}
|
|
763
1031
|
if (html) {
|
|
764
1032
|
let processedHtml = html;
|
|
765
1033
|
const htmlPlugin_ = htmlPlugin(config);
|
|
@@ -774,15 +1042,15 @@ async function build(inlineConfig = {}) {
|
|
|
774
1042
|
}
|
|
775
1043
|
}
|
|
776
1044
|
for (const chunk of output) {
|
|
777
|
-
if (chunk.type === "chunk" && chunk.isEntry) {
|
|
778
|
-
const originalEntry =
|
|
1045
|
+
if (chunk.type === "chunk" && chunk.isEntry && chunk.facadeModuleId) {
|
|
1046
|
+
const originalEntry = import_node_path7.default.relative(config.root, chunk.facadeModuleId);
|
|
779
1047
|
processedHtml = processedHtml.replace(
|
|
780
1048
|
new RegExp(`(src=["'])/?(${escapeRegExp(originalEntry)})(["'])`, "g"),
|
|
781
1049
|
`$1${config.base}${chunk.fileName}$3`
|
|
782
1050
|
);
|
|
783
1051
|
}
|
|
784
1052
|
}
|
|
785
|
-
|
|
1053
|
+
import_node_fs6.default.writeFileSync(import_node_path7.default.resolve(outDir, "index.html"), processedHtml);
|
|
786
1054
|
}
|
|
787
1055
|
const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
|
|
788
1056
|
const totalSize = output.reduce((sum, chunk) => {
|
|
@@ -807,115 +1075,13 @@ function escapeRegExp(string) {
|
|
|
807
1075
|
|
|
808
1076
|
// src/server/index.ts
|
|
809
1077
|
var import_node_http = __toESM(require("http"), 1);
|
|
810
|
-
var
|
|
1078
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
1079
|
+
var import_node_os = __toESM(require("os"), 1);
|
|
811
1080
|
var import_connect = __toESM(require("connect"), 1);
|
|
812
1081
|
var import_sirv = __toESM(require("sirv"), 1);
|
|
813
1082
|
var import_chokidar = require("chokidar");
|
|
814
1083
|
var import_picocolors2 = __toESM(require("picocolors"), 1);
|
|
815
1084
|
|
|
816
|
-
// src/core/plugin-container.ts
|
|
817
|
-
var PluginContainer = class {
|
|
818
|
-
plugins;
|
|
819
|
-
config;
|
|
820
|
-
ctx;
|
|
821
|
-
constructor(config) {
|
|
822
|
-
this.config = config;
|
|
823
|
-
this.plugins = sortPlugins(config.plugins);
|
|
824
|
-
this.ctx = this.createContext();
|
|
825
|
-
}
|
|
826
|
-
createContext() {
|
|
827
|
-
const container = this;
|
|
828
|
-
return {
|
|
829
|
-
async resolve(source, importer) {
|
|
830
|
-
return container.resolveId(source, importer);
|
|
831
|
-
},
|
|
832
|
-
emitFile(_file) {
|
|
833
|
-
return "";
|
|
834
|
-
},
|
|
835
|
-
getModuleInfo(_id) {
|
|
836
|
-
return null;
|
|
837
|
-
}
|
|
838
|
-
};
|
|
839
|
-
}
|
|
840
|
-
async buildStart() {
|
|
841
|
-
for (const plugin of this.plugins) {
|
|
842
|
-
if (plugin.buildStart) {
|
|
843
|
-
await plugin.buildStart.call(this.ctx);
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
async buildEnd(error) {
|
|
848
|
-
for (const plugin of this.plugins) {
|
|
849
|
-
if (plugin.buildEnd) {
|
|
850
|
-
await plugin.buildEnd.call(this.ctx, error);
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
async resolveId(source, importer, options = {}) {
|
|
855
|
-
for (const plugin of this.plugins) {
|
|
856
|
-
if (!plugin.resolveId) continue;
|
|
857
|
-
const result = await plugin.resolveId.call(
|
|
858
|
-
this.ctx,
|
|
859
|
-
source,
|
|
860
|
-
importer ?? void 0,
|
|
861
|
-
{ isEntry: options.isEntry ?? false, ssr: false }
|
|
862
|
-
);
|
|
863
|
-
if (result != null) return result;
|
|
864
|
-
}
|
|
865
|
-
return null;
|
|
866
|
-
}
|
|
867
|
-
async load(id) {
|
|
868
|
-
for (const plugin of this.plugins) {
|
|
869
|
-
if (!plugin.load) continue;
|
|
870
|
-
const result = await plugin.load.call(this.ctx, id);
|
|
871
|
-
if (result != null) return result;
|
|
872
|
-
}
|
|
873
|
-
return null;
|
|
874
|
-
}
|
|
875
|
-
async transform(code, id) {
|
|
876
|
-
let currentCode = code;
|
|
877
|
-
for (const plugin of this.plugins) {
|
|
878
|
-
if (!plugin.transform) continue;
|
|
879
|
-
const result = await plugin.transform.call(this.ctx, currentCode, id);
|
|
880
|
-
if (result == null) continue;
|
|
881
|
-
if (typeof result === "string") {
|
|
882
|
-
currentCode = result;
|
|
883
|
-
} else {
|
|
884
|
-
currentCode = result.code;
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
return currentCode === code ? null : { code: currentCode };
|
|
888
|
-
}
|
|
889
|
-
/** 完整的模块处理管道: resolveId → load → transform */
|
|
890
|
-
async processModule(source, importer) {
|
|
891
|
-
const resolveResult = await this.resolveId(source, importer, {
|
|
892
|
-
isEntry: !importer
|
|
893
|
-
});
|
|
894
|
-
if (resolveResult == null) return null;
|
|
895
|
-
const id = typeof resolveResult === "string" ? resolveResult : resolveResult.id;
|
|
896
|
-
const loadResult = await this.load(id);
|
|
897
|
-
if (loadResult == null) return null;
|
|
898
|
-
const loadedCode = typeof loadResult === "string" ? loadResult : loadResult.code;
|
|
899
|
-
const transformResult = await this.transform(loadedCode, id);
|
|
900
|
-
const finalCode = transformResult == null ? loadedCode : typeof transformResult === "string" ? transformResult : transformResult.code;
|
|
901
|
-
return { id, code: finalCode };
|
|
902
|
-
}
|
|
903
|
-
getPlugins() {
|
|
904
|
-
return this.plugins;
|
|
905
|
-
}
|
|
906
|
-
};
|
|
907
|
-
function sortPlugins(plugins) {
|
|
908
|
-
const pre = [];
|
|
909
|
-
const normal = [];
|
|
910
|
-
const post = [];
|
|
911
|
-
for (const plugin of plugins) {
|
|
912
|
-
if (plugin.enforce === "pre") pre.push(plugin);
|
|
913
|
-
else if (plugin.enforce === "post") post.push(plugin);
|
|
914
|
-
else normal.push(plugin);
|
|
915
|
-
}
|
|
916
|
-
return [...pre, ...normal, ...post];
|
|
917
|
-
}
|
|
918
|
-
|
|
919
1085
|
// src/core/module-graph.ts
|
|
920
1086
|
var ModuleGraph = class {
|
|
921
1087
|
urlToModuleMap = /* @__PURE__ */ new Map();
|
|
@@ -1065,11 +1231,11 @@ function createWebSocketServer(server) {
|
|
|
1065
1231
|
init_middleware();
|
|
1066
1232
|
|
|
1067
1233
|
// src/server/hmr.ts
|
|
1068
|
-
var
|
|
1069
|
-
var
|
|
1234
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
1235
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
1070
1236
|
async function handleFileChange(file, server) {
|
|
1071
1237
|
const { moduleGraph, ws, config } = server;
|
|
1072
|
-
const relativePath = "/" +
|
|
1238
|
+
const relativePath = "/" + import_node_path9.default.relative(config.root, file);
|
|
1073
1239
|
const mods = moduleGraph.getModulesByFile(file);
|
|
1074
1240
|
if (!mods || mods.size === 0) {
|
|
1075
1241
|
return;
|
|
@@ -1082,7 +1248,7 @@ async function handleFileChange(file, server) {
|
|
|
1082
1248
|
file,
|
|
1083
1249
|
timestamp,
|
|
1084
1250
|
modules: [mod],
|
|
1085
|
-
read: () =>
|
|
1251
|
+
read: () => import_node_fs8.default.readFileSync(file, "utf-8"),
|
|
1086
1252
|
server
|
|
1087
1253
|
};
|
|
1088
1254
|
let affectedModules = [mod];
|
|
@@ -1135,7 +1301,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
1135
1301
|
pluginContainer,
|
|
1136
1302
|
moduleGraph
|
|
1137
1303
|
}));
|
|
1138
|
-
const publicDir =
|
|
1304
|
+
const publicDir = import_node_path10.default.resolve(config.root, "public");
|
|
1139
1305
|
app.use((0, import_sirv.default)(publicDir, { dev: true, etag: true }));
|
|
1140
1306
|
app.use((0, import_sirv.default)(config.root, { dev: true, etag: true }));
|
|
1141
1307
|
const httpServer = import_node_http.default.createServer(app);
|
|
@@ -1212,8 +1378,7 @@ async function createServer(inlineConfig = {}) {
|
|
|
1212
1378
|
return server;
|
|
1213
1379
|
}
|
|
1214
1380
|
function getNetworkAddress() {
|
|
1215
|
-
const
|
|
1216
|
-
const interfaces = os.networkInterfaces();
|
|
1381
|
+
const interfaces = import_node_os.default.networkInterfaces();
|
|
1217
1382
|
for (const name of Object.keys(interfaces)) {
|
|
1218
1383
|
for (const iface of interfaces[name] ?? []) {
|
|
1219
1384
|
if (iface.family === "IPv4" && !iface.internal) {
|