@nasti-toolchain/nasti 1.1.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/index.cjs ADDED
@@ -0,0 +1,1233 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // src/plugins/html.ts
34
+ function htmlPlugin(config) {
35
+ return {
36
+ name: "nasti:html",
37
+ enforce: "post",
38
+ transformIndexHtml(html) {
39
+ const tags = [];
40
+ if (config.command === "serve") {
41
+ tags.push({
42
+ tag: "script",
43
+ attrs: { type: "module", src: "/@nasti/client" },
44
+ injectTo: "head-prepend"
45
+ });
46
+ }
47
+ return { html, tags };
48
+ }
49
+ };
50
+ }
51
+ function processHtml(html, tags) {
52
+ const headPrepend = tags.filter((t) => t.injectTo === "head-prepend");
53
+ const head = tags.filter((t) => t.injectTo === "head" || !t.injectTo);
54
+ const bodyPrepend = tags.filter((t) => t.injectTo === "body-prepend");
55
+ const body = tags.filter((t) => t.injectTo === "body");
56
+ if (headPrepend.length) {
57
+ html = html.replace(/<head([^>]*)>/i, `<head$1>
58
+ ${serializeTags(headPrepend)}`);
59
+ }
60
+ if (head.length) {
61
+ html = html.replace(/<\/head>/i, `${serializeTags(head)}
62
+ </head>`);
63
+ }
64
+ if (bodyPrepend.length) {
65
+ html = html.replace(/<body([^>]*)>/i, `<body$1>
66
+ ${serializeTags(bodyPrepend)}`);
67
+ }
68
+ if (body.length) {
69
+ html = html.replace(/<\/body>/i, `${serializeTags(body)}
70
+ </body>`);
71
+ }
72
+ return html;
73
+ }
74
+ function serializeTags(tags) {
75
+ return tags.map(serializeTag).join("\n");
76
+ }
77
+ function serializeTag(tag) {
78
+ const attrs = tag.attrs ? " " + Object.entries(tag.attrs).map(([k, v]) => v === true ? k : `${k}="${v}"`).join(" ") : "";
79
+ const children = typeof tag.children === "string" ? tag.children : tag.children ? serializeTags(tag.children) : "";
80
+ const selfClosing = ["link", "meta", "br", "hr", "img", "input"].includes(tag.tag);
81
+ if (selfClosing && !children) {
82
+ return ` <${tag.tag}${attrs} />`;
83
+ }
84
+ return ` <${tag.tag}${attrs}>${children}</${tag.tag}>`;
85
+ }
86
+ async function readHtmlFile(root) {
87
+ const htmlPath = import_node_path5.default.resolve(root, "index.html");
88
+ if (!import_node_fs4.default.existsSync(htmlPath)) return null;
89
+ return import_node_fs4.default.readFileSync(htmlPath, "utf-8");
90
+ }
91
+ var import_node_path5, import_node_fs4;
92
+ var init_html = __esm({
93
+ "src/plugins/html.ts"() {
94
+ "use strict";
95
+ import_node_path5 = __toESM(require("path"), 1);
96
+ import_node_fs4 = __toESM(require("fs"), 1);
97
+ }
98
+ });
99
+
100
+ // src/core/transformer.ts
101
+ function shouldTransform(id) {
102
+ return TS_EXTENSIONS.test(id) || JSX_EXTENSIONS.test(id) || JS_EXTENSIONS.test(id) && false;
103
+ }
104
+ function transformCode(filename, code, options = {}) {
105
+ const isTS = TS_EXTENSIONS.test(filename) || /\.tsx$/.test(filename);
106
+ const isJSX = JSX_EXTENSIONS.test(filename);
107
+ const result = (0, import_oxc_transform.transformSync)(filename, code, {
108
+ typescript: isTS ? {} : void 0,
109
+ jsx: isJSX || /\.tsx$/.test(filename) ? {
110
+ runtime: options.jsxRuntime ?? "automatic",
111
+ importSource: options.jsxImportSource ?? "react",
112
+ refresh: options.reactRefresh ?? false
113
+ } : void 0,
114
+ sourcemap: options.sourcemap ?? true
115
+ });
116
+ return {
117
+ code: result.code,
118
+ map: result.map ? JSON.stringify(result.map) : null
119
+ };
120
+ }
121
+ var import_oxc_transform, JS_EXTENSIONS, TS_EXTENSIONS, JSX_EXTENSIONS;
122
+ var init_transformer = __esm({
123
+ "src/core/transformer.ts"() {
124
+ "use strict";
125
+ import_oxc_transform = require("oxc-transform");
126
+ JS_EXTENSIONS = /\.(js|mjs|cjs)$/;
127
+ TS_EXTENSIONS = /\.(ts|mts|cts)$/;
128
+ JSX_EXTENSIONS = /\.(jsx|tsx)$/;
129
+ }
130
+ });
131
+
132
+ // src/server/middleware.ts
133
+ var middleware_exports = {};
134
+ __export(middleware_exports, {
135
+ transformMiddleware: () => transformMiddleware,
136
+ transformRequest: () => transformRequest
137
+ });
138
+ function transformMiddleware(ctx) {
139
+ return async (req, res, next) => {
140
+ const url = req.url ?? "/";
141
+ if (req.method !== "GET") return next();
142
+ if (url === "/@nasti/client") {
143
+ res.setHeader("Content-Type", "application/javascript");
144
+ res.end(getHmrClientCode());
145
+ return;
146
+ }
147
+ if (url === "/" || url.endsWith(".html")) {
148
+ const html = await readHtmlFile(ctx.config.root);
149
+ if (html) {
150
+ let processedHtml = html;
151
+ for (const plugin of ctx.config.plugins) {
152
+ if (plugin.transformIndexHtml) {
153
+ const result = await plugin.transformIndexHtml(processedHtml);
154
+ if (typeof result === "string") {
155
+ processedHtml = result;
156
+ } else if (result && "html" in result) {
157
+ processedHtml = processHtml(result.html, result.tags);
158
+ } else if (Array.isArray(result)) {
159
+ processedHtml = processHtml(processedHtml, result);
160
+ }
161
+ }
162
+ }
163
+ processedHtml = processedHtml.replace(
164
+ "<head>",
165
+ '<head>\n <script type="module" src="/@nasti/client"></script>'
166
+ );
167
+ res.setHeader("Content-Type", "text/html");
168
+ res.end(processedHtml);
169
+ return;
170
+ }
171
+ }
172
+ if (isModuleRequest(url)) {
173
+ try {
174
+ const result = await transformRequest(url, ctx);
175
+ if (result) {
176
+ const contentType = url.endsWith(".css") ? "application/javascript" : "application/javascript";
177
+ res.setHeader("Content-Type", contentType);
178
+ res.setHeader("Cache-Control", "no-cache");
179
+ res.end(typeof result === "string" ? result : result.code);
180
+ return;
181
+ }
182
+ } catch (err) {
183
+ console.error(`[nasti] Transform error: ${url}`, err.message);
184
+ res.statusCode = 500;
185
+ res.end(`Transform error: ${err.message}`);
186
+ return;
187
+ }
188
+ }
189
+ next();
190
+ };
191
+ }
192
+ async function transformRequest(url, ctx) {
193
+ const { config, pluginContainer, moduleGraph } = ctx;
194
+ const cached = moduleGraph.getModuleByUrl(url);
195
+ if (cached?.transformResult) {
196
+ return cached.transformResult;
197
+ }
198
+ const filePath = resolveUrlToFile(url, config.root);
199
+ if (!filePath || !import_node_fs6.default.existsSync(filePath)) return null;
200
+ const mod = await moduleGraph.ensureEntryFromUrl(url);
201
+ moduleGraph.registerModule(mod, filePath);
202
+ let code = import_node_fs6.default.readFileSync(filePath, "utf-8");
203
+ const pluginResult = await pluginContainer.transform(code, filePath);
204
+ if (pluginResult) {
205
+ code = typeof pluginResult === "string" ? pluginResult : pluginResult.code;
206
+ }
207
+ if (shouldTransform(filePath)) {
208
+ const result = transformCode(filePath, code, {
209
+ sourcemap: true,
210
+ jsxRuntime: "automatic",
211
+ jsxImportSource: config.framework === "vue" ? "vue" : "react",
212
+ reactRefresh: config.framework !== "vue"
213
+ });
214
+ code = result.code;
215
+ }
216
+ code = rewriteImports(code, config);
217
+ const transformResult = { code };
218
+ mod.transformResult = transformResult;
219
+ return transformResult;
220
+ }
221
+ function rewriteImports(code, config) {
222
+ return code.replace(
223
+ /from\s+['"]([^'"./][^'"]*)['"]/g,
224
+ (match, specifier) => {
225
+ if (specifier.startsWith("/") || specifier.startsWith(".")) return match;
226
+ return `from "/@modules/${specifier}"`;
227
+ }
228
+ ).replace(
229
+ /import\s+['"]([^'"./][^'"]*)['"]/g,
230
+ (match, specifier) => {
231
+ if (specifier.startsWith("/") || specifier.startsWith(".")) return match;
232
+ return `import "/@modules/${specifier}"`;
233
+ }
234
+ );
235
+ }
236
+ function resolveUrlToFile(url, root) {
237
+ const cleanUrl = url.split("?")[0];
238
+ if (cleanUrl.startsWith("/@modules/")) {
239
+ const moduleName = cleanUrl.slice("/@modules/".length);
240
+ try {
241
+ const { createRequire: createRequire2 } = require("module");
242
+ const req = createRequire2(import_node_path7.default.resolve(root, "package.json"));
243
+ return req.resolve(moduleName);
244
+ } catch {
245
+ return null;
246
+ }
247
+ }
248
+ return import_node_path7.default.resolve(root, cleanUrl.replace(/^\//, ""));
249
+ }
250
+ function isModuleRequest(url) {
251
+ const cleanUrl = url.split("?")[0];
252
+ return /\.(ts|tsx|jsx|js|mjs|vue|css|json)$/.test(cleanUrl) || cleanUrl.startsWith("/@modules/");
253
+ }
254
+ function getHmrClientCode() {
255
+ return `
256
+ // Nasti HMR Client
257
+ const socket = new WebSocket(\`ws://\${location.host}\`, 'nasti-hmr');
258
+ const hotModulesMap = new Map();
259
+
260
+ socket.addEventListener('message', ({ data }) => {
261
+ const payload = JSON.parse(data);
262
+ switch (payload.type) {
263
+ case 'connected':
264
+ console.log('[nasti] connected.');
265
+ break;
266
+ case 'update':
267
+ payload.updates.forEach((update) => {
268
+ if (update.type === 'js-update') {
269
+ fetchUpdate(update);
270
+ } else if (update.type === 'css-update') {
271
+ updateCss(update.path);
272
+ }
273
+ });
274
+ break;
275
+ case 'full-reload':
276
+ console.log('[nasti] full reload');
277
+ location.reload();
278
+ break;
279
+ case 'error':
280
+ console.error('[nasti] error:', payload.err.message);
281
+ showErrorOverlay(payload.err);
282
+ break;
283
+ }
284
+ });
285
+
286
+ async function fetchUpdate(update) {
287
+ const mod = hotModulesMap.get(update.path);
288
+ if (mod) {
289
+ const newMod = await import(update.acceptedPath + '?t=' + update.timestamp);
290
+ mod.callbacks.forEach((cb) => cb(newMod));
291
+ } else {
292
+ // \u6CA1\u6709\u6CE8\u518C hot \u56DE\u8C03\uFF0C\u5C1D\u8BD5\u91CD\u65B0 import
293
+ await import(update.path + '?t=' + update.timestamp);
294
+ }
295
+ }
296
+
297
+ function updateCss(path) {
298
+ const el = document.querySelector(\`style[data-nasti-css="\${path}"]\`);
299
+ if (el) {
300
+ fetch(path + '?t=' + Date.now())
301
+ .then(r => r.text())
302
+ .then(css => { el.textContent = css; });
303
+ }
304
+ }
305
+
306
+ function showErrorOverlay(err) {
307
+ const overlay = document.createElement('div');
308
+ overlay.id = 'nasti-error-overlay';
309
+ 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
+ overlay.innerHTML = \`<h2 style="color:#ff5555">Build Error</h2><pre>\${err.message}\\n\${err.stack || ''}</pre><button onclick="this.parentElement.remove()" style="margin-top:1rem;padding:0.5rem 1rem;cursor:pointer">Close</button>\`;
311
+ document.body.appendChild(overlay);
312
+ }
313
+
314
+ // import.meta.hot API
315
+ const createHotContext = (ownerPath) => ({
316
+ accept(deps, callback) {
317
+ if (typeof deps === 'function' || !deps) {
318
+ // self-accepting
319
+ const callbacks = hotModulesMap.get(ownerPath)?.callbacks || [];
320
+ callbacks.push(deps || (() => {}));
321
+ hotModulesMap.set(ownerPath, { callbacks });
322
+ }
323
+ },
324
+ prune(callback) {
325
+ // \u6A21\u5757\u88AB\u79FB\u9664\u65F6\u6267\u884C
326
+ },
327
+ dispose(callback) {
328
+ // \u6A21\u5757\u66F4\u65B0\u524D\u6267\u884C\u6E05\u7406
329
+ },
330
+ invalidate() {
331
+ location.reload();
332
+ },
333
+ data: {},
334
+ });
335
+
336
+ // \u66B4\u9732\u7ED9\u6A21\u5757\u4F7F\u7528
337
+ if (!window.__nasti_hot_map) window.__nasti_hot_map = new Map();
338
+ window.__NASTI_HMR__ = { createHotContext };
339
+ `;
340
+ }
341
+ var import_node_path7, import_node_fs6;
342
+ var init_middleware = __esm({
343
+ "src/server/middleware.ts"() {
344
+ "use strict";
345
+ import_node_path7 = __toESM(require("path"), 1);
346
+ import_node_fs6 = __toESM(require("fs"), 1);
347
+ init_transformer();
348
+ init_html();
349
+ }
350
+ });
351
+
352
+ // src/index.ts
353
+ var src_exports = {};
354
+ __export(src_exports, {
355
+ build: () => build,
356
+ createServer: () => createServer,
357
+ defineConfig: () => defineConfig,
358
+ resolveConfig: () => resolveConfig
359
+ });
360
+ module.exports = __toCommonJS(src_exports);
361
+
362
+ // src/config/index.ts
363
+ var import_node_url = require("url");
364
+ var import_node_path = __toESM(require("path"), 1);
365
+ var import_node_fs = __toESM(require("fs"), 1);
366
+
367
+ // src/config/defaults.ts
368
+ var defaultResolve = {
369
+ alias: {},
370
+ extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".json", ".vue"],
371
+ conditions: ["import", "module", "browser", "default"],
372
+ mainFields: ["module", "jsnext:main", "jsnext", "main"]
373
+ };
374
+ var defaultServer = {
375
+ port: 3e3,
376
+ host: "localhost",
377
+ https: false,
378
+ open: false,
379
+ proxy: {},
380
+ cors: true,
381
+ hmr: true
382
+ };
383
+ var defaultBuild = {
384
+ outDir: "dist",
385
+ assetsDir: "assets",
386
+ minify: true,
387
+ sourcemap: false,
388
+ target: "es2022",
389
+ rolldownOptions: {},
390
+ emptyOutDir: true
391
+ };
392
+ var defaults = {
393
+ root: ".",
394
+ base: "/",
395
+ mode: "development",
396
+ framework: "auto",
397
+ resolve: defaultResolve,
398
+ server: defaultServer,
399
+ build: defaultBuild,
400
+ plugins: [],
401
+ envPrefix: ["NASTI_", "VITE_"],
402
+ logLevel: "info"
403
+ };
404
+
405
+ // src/config/index.ts
406
+ function defineConfig(config) {
407
+ return config;
408
+ }
409
+ var CONFIG_FILES = [
410
+ "nasti.config.ts",
411
+ "nasti.config.js",
412
+ "nasti.config.mjs",
413
+ "nasti.config.mts"
414
+ ];
415
+ async function loadConfigFromFile(root) {
416
+ for (const file of CONFIG_FILES) {
417
+ const filePath = import_node_path.default.resolve(root, file);
418
+ if (!import_node_fs.default.existsSync(filePath)) continue;
419
+ if (file.endsWith(".ts") || file.endsWith(".mts")) {
420
+ return await loadTsConfig(filePath);
421
+ }
422
+ const mod = await import((0, import_node_url.pathToFileURL)(filePath).href);
423
+ return mod.default ?? mod;
424
+ }
425
+ return {};
426
+ }
427
+ async function loadTsConfig(filePath) {
428
+ const { transformSync: transformSync2 } = await import("oxc-transform");
429
+ const code = import_node_fs.default.readFileSync(filePath, "utf-8");
430
+ const result = transformSync2(filePath, code, {
431
+ typescript: {}
432
+ });
433
+ const tmpFile = filePath + ".timestamp-" + Date.now() + ".mjs";
434
+ try {
435
+ import_node_fs.default.writeFileSync(tmpFile, result.code);
436
+ const mod = await import((0, import_node_url.pathToFileURL)(tmpFile).href);
437
+ return mod.default ?? mod;
438
+ } finally {
439
+ import_node_fs.default.unlinkSync(tmpFile);
440
+ }
441
+ }
442
+ async function resolveConfig(inlineConfig = {}, command) {
443
+ const root = import_node_path.default.resolve(inlineConfig.root ?? defaults.root);
444
+ const fileConfig = await loadConfigFromFile(root);
445
+ const merged = deepMerge(deepMerge({}, fileConfig), inlineConfig);
446
+ const rawPlugins = [
447
+ ...fileConfig.plugins ?? [],
448
+ ...inlineConfig.plugins ?? []
449
+ ];
450
+ const env = { mode: merged.mode ?? defaults.mode, command };
451
+ for (const plugin of rawPlugins) {
452
+ if (plugin.config) {
453
+ const result = await plugin.config(merged, env);
454
+ if (result) Object.assign(merged, result);
455
+ }
456
+ }
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
+ const resolved = {
463
+ root,
464
+ base: merged.base ?? defaults.base,
465
+ mode: command === "build" ? "production" : "development",
466
+ framework: merged.framework ?? defaults.framework,
467
+ command,
468
+ resolve: {
469
+ alias: { ...defaults.resolve.alias, ...merged.resolve?.alias },
470
+ extensions: merged.resolve?.extensions ?? defaults.resolve.extensions,
471
+ conditions: merged.resolve?.conditions ?? defaults.resolve.conditions,
472
+ mainFields: merged.resolve?.mainFields ?? defaults.resolve.mainFields
473
+ },
474
+ plugins: filteredPlugins,
475
+ server: { ...defaults.server, ...merged.server },
476
+ build: { ...defaults.build, ...merged.build },
477
+ envPrefix: Array.isArray(merged.envPrefix) ? merged.envPrefix : merged.envPrefix ? [merged.envPrefix] : [...defaults.envPrefix],
478
+ logLevel: merged.logLevel ?? defaults.logLevel
479
+ };
480
+ for (const plugin of resolved.plugins) {
481
+ if (plugin.configResolved) {
482
+ await plugin.configResolved(resolved);
483
+ }
484
+ }
485
+ return resolved;
486
+ }
487
+ function deepMerge(target, source) {
488
+ const result = { ...target };
489
+ for (const key of Object.keys(source)) {
490
+ const val = source[key];
491
+ if (val && typeof val === "object" && !Array.isArray(val)) {
492
+ result[key] = deepMerge(
493
+ result[key] ?? {},
494
+ val
495
+ );
496
+ } else if (val !== void 0) {
497
+ result[key] = val;
498
+ }
499
+ }
500
+ return result;
501
+ }
502
+
503
+ // src/build/index.ts
504
+ var import_node_path6 = __toESM(require("path"), 1);
505
+ var import_node_fs5 = __toESM(require("fs"), 1);
506
+ var import_rolldown = require("rolldown");
507
+
508
+ // src/plugins/resolve.ts
509
+ var import_node_path2 = __toESM(require("path"), 1);
510
+ var import_node_fs2 = __toESM(require("fs"), 1);
511
+ var import_node_module = require("module");
512
+ function resolvePlugin(config) {
513
+ const { alias, extensions } = config.resolve;
514
+ const require2 = (0, import_node_module.createRequire)(import_node_path2.default.resolve(config.root, "package.json"));
515
+ return {
516
+ name: "nasti:resolve",
517
+ enforce: "pre",
518
+ resolveId(source, importer) {
519
+ for (const [key, value] of Object.entries(alias)) {
520
+ if (source === key || source.startsWith(key + "/")) {
521
+ source = source.replace(key, value);
522
+ if (!import_node_path2.default.isAbsolute(source)) {
523
+ source = import_node_path2.default.resolve(config.root, source);
524
+ }
525
+ break;
526
+ }
527
+ }
528
+ if (import_node_path2.default.isAbsolute(source)) {
529
+ const resolved = tryResolveFile(source, extensions);
530
+ if (resolved) return resolved;
531
+ }
532
+ if (source.startsWith(".")) {
533
+ const dir = importer ? import_node_path2.default.dirname(importer) : config.root;
534
+ const absolute = import_node_path2.default.resolve(dir, source);
535
+ const resolved = tryResolveFile(absolute, extensions);
536
+ if (resolved) return resolved;
537
+ }
538
+ if (!source.startsWith("/") && !source.startsWith(".")) {
539
+ try {
540
+ const resolved = require2.resolve(source, {
541
+ paths: [importer ? import_node_path2.default.dirname(importer) : config.root]
542
+ });
543
+ return resolved;
544
+ } catch {
545
+ return null;
546
+ }
547
+ }
548
+ return null;
549
+ },
550
+ load(id) {
551
+ if (import_node_fs2.default.existsSync(id)) {
552
+ return import_node_fs2.default.readFileSync(id, "utf-8");
553
+ }
554
+ return null;
555
+ }
556
+ };
557
+ }
558
+ function tryResolveFile(file, extensions) {
559
+ if (import_node_fs2.default.existsSync(file) && import_node_fs2.default.statSync(file).isFile()) {
560
+ return file;
561
+ }
562
+ for (const ext of extensions) {
563
+ const withExt = file + ext;
564
+ if (import_node_fs2.default.existsSync(withExt) && import_node_fs2.default.statSync(withExt).isFile()) {
565
+ return withExt;
566
+ }
567
+ }
568
+ if (import_node_fs2.default.existsSync(file) && import_node_fs2.default.statSync(file).isDirectory()) {
569
+ for (const ext of extensions) {
570
+ const indexFile = import_node_path2.default.join(file, "index" + ext);
571
+ if (import_node_fs2.default.existsSync(indexFile)) {
572
+ return indexFile;
573
+ }
574
+ }
575
+ }
576
+ return null;
577
+ }
578
+
579
+ // src/plugins/css.ts
580
+ var import_node_path3 = __toESM(require("path"), 1);
581
+ function cssPlugin(config) {
582
+ return {
583
+ name: "nasti:css",
584
+ resolveId(source) {
585
+ if (source.endsWith(".css")) return null;
586
+ return null;
587
+ },
588
+ transform(code, id) {
589
+ if (!id.endsWith(".css")) return null;
590
+ if (config.command === "serve") {
591
+ const escaped = JSON.stringify(code);
592
+ return {
593
+ code: `
594
+ const css = ${escaped};
595
+ const style = document.createElement('style');
596
+ style.setAttribute('data-nasti-css', ${JSON.stringify(id)});
597
+ style.textContent = css;
598
+ document.head.appendChild(style);
599
+
600
+ // HMR
601
+ if (import.meta.hot) {
602
+ import.meta.hot.accept();
603
+ import.meta.hot.prune(() => {
604
+ style.remove();
605
+ });
606
+ }
607
+
608
+ export default css;
609
+ `
610
+ };
611
+ }
612
+ return null;
613
+ }
614
+ };
615
+ }
616
+
617
+ // src/plugins/assets.ts
618
+ var import_node_path4 = __toESM(require("path"), 1);
619
+ var import_node_fs3 = __toESM(require("fs"), 1);
620
+ var import_node_crypto = __toESM(require("crypto"), 1);
621
+ var ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
622
+ ".png",
623
+ ".jpg",
624
+ ".jpeg",
625
+ ".gif",
626
+ ".svg",
627
+ ".ico",
628
+ ".webp",
629
+ ".avif",
630
+ ".mp4",
631
+ ".webm",
632
+ ".ogg",
633
+ ".mp3",
634
+ ".wav",
635
+ ".flac",
636
+ ".aac",
637
+ ".woff",
638
+ ".woff2",
639
+ ".eot",
640
+ ".ttf",
641
+ ".otf",
642
+ ".pdf",
643
+ ".txt"
644
+ ]);
645
+ function assetsPlugin(config) {
646
+ return {
647
+ name: "nasti:assets",
648
+ resolveId(source) {
649
+ if (source.endsWith("?url") || source.endsWith("?raw")) {
650
+ return source;
651
+ }
652
+ return null;
653
+ },
654
+ load(id) {
655
+ const ext = import_node_path4.default.extname(id.replace(/\?.*$/, ""));
656
+ if (id.endsWith("?raw")) {
657
+ const file = id.slice(0, -4);
658
+ if (import_node_fs3.default.existsSync(file)) {
659
+ const content = import_node_fs3.default.readFileSync(file, "utf-8");
660
+ return `export default ${JSON.stringify(content)}`;
661
+ }
662
+ }
663
+ if (id.endsWith("?url") || ASSET_EXTENSIONS.has(ext)) {
664
+ const file = id.replace(/\?.*$/, "");
665
+ if (!import_node_fs3.default.existsSync(file)) return null;
666
+ if (config.command === "serve") {
667
+ const url = "/" + import_node_path4.default.relative(config.root, file);
668
+ return `export default ${JSON.stringify(url)}`;
669
+ }
670
+ const content = import_node_fs3.default.readFileSync(file);
671
+ const hash = import_node_crypto.default.createHash("sha256").update(content).digest("hex").slice(0, 8);
672
+ const basename = import_node_path4.default.basename(file, ext);
673
+ const hashedName = `${config.build.assetsDir}/${basename}.${hash}${ext}`;
674
+ return `export default ${JSON.stringify(config.base + hashedName)}`;
675
+ }
676
+ return null;
677
+ }
678
+ };
679
+ }
680
+
681
+ // src/build/index.ts
682
+ init_html();
683
+ init_transformer();
684
+ var import_picocolors = __toESM(require("picocolors"), 1);
685
+ async function build(inlineConfig = {}) {
686
+ const config = await resolveConfig(inlineConfig, "build");
687
+ const startTime = performance.now();
688
+ 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
+ console.log(import_picocolors.default.dim(` root: ${config.root}`));
690
+ console.log(import_picocolors.default.dim(` mode: ${config.mode}`));
691
+ const outDir = import_node_path6.default.resolve(config.root, config.build.outDir);
692
+ if (config.build.emptyOutDir && import_node_fs5.default.existsSync(outDir)) {
693
+ import_node_fs5.default.rmSync(outDir, { recursive: true, force: true });
694
+ }
695
+ import_node_fs5.default.mkdirSync(outDir, { recursive: true });
696
+ const html = await readHtmlFile(config.root);
697
+ let entryPoints = [];
698
+ if (html) {
699
+ const scriptMatches = html.matchAll(/<script[^>]+src=["']([^"']+)["'][^>]*>/gi);
700
+ for (const match of scriptMatches) {
701
+ const src = match[1];
702
+ if (src && !src.startsWith("http")) {
703
+ entryPoints.push(import_node_path6.default.resolve(config.root, src.replace(/^\//, "")));
704
+ }
705
+ }
706
+ }
707
+ if (entryPoints.length === 0) {
708
+ const fallbackEntries = ["src/main.ts", "src/main.tsx", "src/main.js", "src/index.ts", "src/index.tsx", "src/index.js"];
709
+ for (const entry of fallbackEntries) {
710
+ const fullPath = import_node_path6.default.resolve(config.root, entry);
711
+ if (import_node_fs5.default.existsSync(fullPath)) {
712
+ entryPoints.push(fullPath);
713
+ break;
714
+ }
715
+ }
716
+ }
717
+ if (entryPoints.length === 0) {
718
+ throw new Error("No entry point found. Add a <script> tag to index.html or create src/main.ts");
719
+ }
720
+ const builtinPlugins = [
721
+ resolvePlugin(config),
722
+ cssPlugin(config),
723
+ assetsPlugin(config)
724
+ ];
725
+ const allPlugins = [...builtinPlugins, ...config.plugins];
726
+ const oxcTransformPlugin = {
727
+ name: "nasti:oxc-transform",
728
+ transform(code, id) {
729
+ if (!shouldTransform(id)) return null;
730
+ const result = transformCode(id, code, {
731
+ sourcemap: !!config.build.sourcemap,
732
+ jsxRuntime: "automatic",
733
+ jsxImportSource: config.framework === "vue" ? "vue" : "react"
734
+ });
735
+ return { code: result.code, map: result.map ? JSON.parse(result.map) : void 0 };
736
+ }
737
+ };
738
+ const bundle = await (0, import_rolldown.rolldown)({
739
+ input: entryPoints,
740
+ plugins: [
741
+ oxcTransformPlugin,
742
+ // 转换 Nasti 插件为 Rolldown 插件格式
743
+ ...allPlugins.map((p) => ({
744
+ name: p.name,
745
+ resolveId: p.resolveId,
746
+ load: p.load,
747
+ transform: p.transform,
748
+ buildStart: p.buildStart,
749
+ buildEnd: p.buildEnd
750
+ }))
751
+ ],
752
+ ...config.build.rolldownOptions
753
+ });
754
+ const { output } = await bundle.write({
755
+ dir: outDir,
756
+ format: "esm",
757
+ sourcemap: !!config.build.sourcemap,
758
+ entryFileNames: "assets/[name].[hash].js",
759
+ chunkFileNames: "assets/[name].[hash].js",
760
+ assetFileNames: "assets/[name].[hash][extname]"
761
+ });
762
+ await bundle.close();
763
+ if (html) {
764
+ let processedHtml = html;
765
+ const htmlPlugin_ = htmlPlugin(config);
766
+ if (htmlPlugin_.transformIndexHtml) {
767
+ const result = await htmlPlugin_.transformIndexHtml(processedHtml);
768
+ if (typeof result === "string") {
769
+ processedHtml = result;
770
+ } else if (result && "html" in result) {
771
+ processedHtml = processHtml(result.html, result.tags);
772
+ } else if (Array.isArray(result)) {
773
+ processedHtml = processHtml(processedHtml, result);
774
+ }
775
+ }
776
+ for (const chunk of output) {
777
+ if (chunk.type === "chunk" && chunk.isEntry) {
778
+ const originalEntry = import_node_path6.default.relative(config.root, entryPoints[0]);
779
+ processedHtml = processedHtml.replace(
780
+ new RegExp(`(src=["'])/?(${escapeRegExp(originalEntry)})(["'])`, "g"),
781
+ `$1${config.base}${chunk.fileName}$3`
782
+ );
783
+ }
784
+ }
785
+ import_node_fs5.default.writeFileSync(import_node_path6.default.resolve(outDir, "index.html"), processedHtml);
786
+ }
787
+ const elapsed = ((performance.now() - startTime) / 1e3).toFixed(2);
788
+ const totalSize = output.reduce((sum, chunk) => {
789
+ if (chunk.type === "chunk" && chunk.code) return sum + chunk.code.length;
790
+ return sum;
791
+ }, 0);
792
+ console.log(import_picocolors.default.green(`
793
+ \u2713 Built in ${elapsed}s`));
794
+ console.log(import_picocolors.default.dim(` ${output.length} files, ${formatSize(totalSize)} total`));
795
+ console.log(import_picocolors.default.dim(` output: ${config.build.outDir}/
796
+ `));
797
+ return { output };
798
+ }
799
+ function formatSize(bytes) {
800
+ if (bytes < 1024) return `${bytes} B`;
801
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} kB`;
802
+ return `${(bytes / 1024 / 1024).toFixed(2)} MB`;
803
+ }
804
+ function escapeRegExp(string) {
805
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
806
+ }
807
+
808
+ // src/server/index.ts
809
+ var import_node_http = __toESM(require("http"), 1);
810
+ var import_node_path9 = __toESM(require("path"), 1);
811
+ var import_connect = __toESM(require("connect"), 1);
812
+ var import_sirv = __toESM(require("sirv"), 1);
813
+ var import_chokidar = require("chokidar");
814
+ var import_picocolors2 = __toESM(require("picocolors"), 1);
815
+
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
+ // src/core/module-graph.ts
920
+ var ModuleGraph = class {
921
+ urlToModuleMap = /* @__PURE__ */ new Map();
922
+ idToModuleMap = /* @__PURE__ */ new Map();
923
+ fileToModulesMap = /* @__PURE__ */ new Map();
924
+ getModuleByUrl(url) {
925
+ return this.urlToModuleMap.get(url);
926
+ }
927
+ getModuleById(id) {
928
+ return this.idToModuleMap.get(id);
929
+ }
930
+ getModulesByFile(file) {
931
+ return this.fileToModulesMap.get(file);
932
+ }
933
+ async ensureEntryFromUrl(url) {
934
+ let mod = this.urlToModuleMap.get(url);
935
+ if (mod) return mod;
936
+ mod = this.createModule(url);
937
+ this.urlToModuleMap.set(url, mod);
938
+ return mod;
939
+ }
940
+ createModule(url, id) {
941
+ const mod = {
942
+ id: id ?? url,
943
+ file: null,
944
+ url,
945
+ type: url.endsWith(".css") ? "css" : "js",
946
+ importers: /* @__PURE__ */ new Set(),
947
+ importedModules: /* @__PURE__ */ new Set(),
948
+ acceptedHmrDeps: /* @__PURE__ */ new Set(),
949
+ transformResult: null,
950
+ lastHMRTimestamp: 0,
951
+ isSelfAccepting: false
952
+ };
953
+ this.idToModuleMap.set(mod.id, mod);
954
+ return mod;
955
+ }
956
+ /** 注册文件路径到模块的映射 */
957
+ registerModule(mod, file) {
958
+ mod.file = file;
959
+ let mods = this.fileToModulesMap.get(file);
960
+ if (!mods) {
961
+ mods = /* @__PURE__ */ new Set();
962
+ this.fileToModulesMap.set(file, mods);
963
+ }
964
+ mods.add(mod);
965
+ }
966
+ /** 更新模块依赖关系 */
967
+ updateModuleImports(mod, importedIds) {
968
+ for (const imported of mod.importedModules) {
969
+ imported.importers.delete(mod);
970
+ }
971
+ mod.importedModules.clear();
972
+ for (const id of importedIds) {
973
+ const importedMod = this.idToModuleMap.get(id);
974
+ if (importedMod) {
975
+ mod.importedModules.add(importedMod);
976
+ importedMod.importers.add(mod);
977
+ }
978
+ }
979
+ }
980
+ /** 使模块的转换缓存失效 */
981
+ invalidateModule(mod) {
982
+ mod.transformResult = null;
983
+ mod.lastHMRTimestamp = Date.now();
984
+ }
985
+ /** 使所有模块缓存失效 */
986
+ invalidateAll() {
987
+ for (const mod of this.idToModuleMap.values()) {
988
+ this.invalidateModule(mod);
989
+ }
990
+ }
991
+ /** 获取 HMR 传播边界 - 从变更模块向上遍历找到接受更新的边界 */
992
+ getHmrBoundaries(mod) {
993
+ const boundaries = [];
994
+ const visited = /* @__PURE__ */ new Set();
995
+ const propagate = (node, via) => {
996
+ if (visited.has(node)) return true;
997
+ visited.add(node);
998
+ if (node.isSelfAccepting) {
999
+ boundaries.push({ boundary: node, acceptedVia: via });
1000
+ return true;
1001
+ }
1002
+ if (node.acceptedHmrDeps.has(via)) {
1003
+ boundaries.push({ boundary: node, acceptedVia: via });
1004
+ return true;
1005
+ }
1006
+ if (node.importers.size === 0) return false;
1007
+ for (const importer of node.importers) {
1008
+ if (!propagate(importer, node)) return false;
1009
+ }
1010
+ return true;
1011
+ };
1012
+ if (mod.isSelfAccepting) {
1013
+ boundaries.push({ boundary: mod, acceptedVia: mod });
1014
+ return boundaries;
1015
+ }
1016
+ for (const importer of mod.importers) {
1017
+ if (!propagate(importer, mod)) {
1018
+ return [];
1019
+ }
1020
+ }
1021
+ return boundaries;
1022
+ }
1023
+ };
1024
+
1025
+ // src/server/ws.ts
1026
+ var import_ws = require("ws");
1027
+ function createWebSocketServer(server) {
1028
+ const wss = new import_ws.WebSocketServer({ noServer: true });
1029
+ const clients = /* @__PURE__ */ new Set();
1030
+ server.on("upgrade", (req, socket, head) => {
1031
+ if (req.headers["sec-websocket-protocol"] === "nasti-hmr") {
1032
+ wss.handleUpgrade(req, socket, head, (ws) => {
1033
+ wss.emit("connection", ws, req);
1034
+ });
1035
+ }
1036
+ });
1037
+ wss.on("connection", (ws) => {
1038
+ clients.add(ws);
1039
+ ws.send(JSON.stringify({ type: "connected" }));
1040
+ ws.on("close", () => {
1041
+ clients.delete(ws);
1042
+ });
1043
+ ws.on("error", (err) => {
1044
+ console.error("[nasti] WebSocket error:", err);
1045
+ clients.delete(ws);
1046
+ });
1047
+ });
1048
+ return {
1049
+ send(payload) {
1050
+ const data = JSON.stringify(payload);
1051
+ for (const client of clients) {
1052
+ if (client.readyState === 1) {
1053
+ client.send(data);
1054
+ }
1055
+ }
1056
+ },
1057
+ close() {
1058
+ clients.clear();
1059
+ wss.close();
1060
+ }
1061
+ };
1062
+ }
1063
+
1064
+ // src/server/index.ts
1065
+ init_middleware();
1066
+
1067
+ // src/server/hmr.ts
1068
+ var import_node_path8 = __toESM(require("path"), 1);
1069
+ var import_node_fs7 = __toESM(require("fs"), 1);
1070
+ async function handleFileChange(file, server) {
1071
+ const { moduleGraph, ws, config } = server;
1072
+ const relativePath = "/" + import_node_path8.default.relative(config.root, file);
1073
+ const mods = moduleGraph.getModulesByFile(file);
1074
+ if (!mods || mods.size === 0) {
1075
+ return;
1076
+ }
1077
+ const updates = [];
1078
+ const timestamp = Date.now();
1079
+ for (const mod of mods) {
1080
+ moduleGraph.invalidateModule(mod);
1081
+ const ctx = {
1082
+ file,
1083
+ timestamp,
1084
+ modules: [mod],
1085
+ read: () => import_node_fs7.default.readFileSync(file, "utf-8"),
1086
+ server
1087
+ };
1088
+ let affectedModules = [mod];
1089
+ for (const plugin of config.plugins) {
1090
+ if (plugin.handleHotUpdate) {
1091
+ const result = await plugin.handleHotUpdate(ctx);
1092
+ if (result) {
1093
+ affectedModules = result;
1094
+ }
1095
+ }
1096
+ }
1097
+ for (const affected of affectedModules) {
1098
+ const boundaries = moduleGraph.getHmrBoundaries(affected);
1099
+ if (boundaries.length === 0) {
1100
+ ws.send({ type: "full-reload", path: relativePath });
1101
+ return;
1102
+ }
1103
+ for (const { boundary } of boundaries) {
1104
+ updates.push({
1105
+ type: boundary.type === "css" ? "css-update" : "js-update",
1106
+ path: boundary.url,
1107
+ acceptedPath: affected.url,
1108
+ timestamp
1109
+ });
1110
+ }
1111
+ }
1112
+ }
1113
+ if (updates.length > 0) {
1114
+ ws.send({ type: "update", updates });
1115
+ }
1116
+ }
1117
+
1118
+ // src/server/index.ts
1119
+ init_html();
1120
+ async function createServer(inlineConfig = {}) {
1121
+ const config = await resolveConfig(inlineConfig, "serve");
1122
+ const allPlugins = [
1123
+ resolvePlugin(config),
1124
+ cssPlugin(config),
1125
+ assetsPlugin(config),
1126
+ htmlPlugin(config),
1127
+ ...config.plugins
1128
+ ];
1129
+ const configWithPlugins = { ...config, plugins: allPlugins };
1130
+ const moduleGraph = new ModuleGraph();
1131
+ const pluginContainer = new PluginContainer(configWithPlugins);
1132
+ const app = (0, import_connect.default)();
1133
+ app.use(transformMiddleware({
1134
+ config: configWithPlugins,
1135
+ pluginContainer,
1136
+ moduleGraph
1137
+ }));
1138
+ const publicDir = import_node_path9.default.resolve(config.root, "public");
1139
+ app.use((0, import_sirv.default)(publicDir, { dev: true, etag: true }));
1140
+ app.use((0, import_sirv.default)(config.root, { dev: true, etag: true }));
1141
+ const httpServer = import_node_http.default.createServer(app);
1142
+ const ws = createWebSocketServer(httpServer);
1143
+ const watcher = (0, import_chokidar.watch)(config.root, {
1144
+ ignored: [
1145
+ "**/node_modules/**",
1146
+ "**/.git/**",
1147
+ `**/${config.build.outDir}/**`
1148
+ ],
1149
+ ignoreInitial: true
1150
+ });
1151
+ let server;
1152
+ watcher.on("change", (file) => {
1153
+ handleFileChange(file, server);
1154
+ });
1155
+ watcher.on("add", (file) => {
1156
+ handleFileChange(file, server);
1157
+ });
1158
+ const postMiddlewares = [];
1159
+ for (const plugin of allPlugins) {
1160
+ if (plugin.configureServer) {
1161
+ const result = await plugin.configureServer(server);
1162
+ if (typeof result === "function") {
1163
+ postMiddlewares.push(result);
1164
+ }
1165
+ }
1166
+ }
1167
+ server = {
1168
+ config: configWithPlugins,
1169
+ middlewares: app,
1170
+ moduleGraph,
1171
+ watcher,
1172
+ ws,
1173
+ async listen(port) {
1174
+ const finalPort = port ?? config.server.port;
1175
+ const host = config.server.host === true ? "0.0.0.0" : config.server.host;
1176
+ await pluginContainer.buildStart();
1177
+ return new Promise((resolve, reject) => {
1178
+ httpServer.listen(finalPort, host, () => {
1179
+ const localUrl = `http://localhost:${finalPort}`;
1180
+ const networkUrl = host === "0.0.0.0" ? `http://${getNetworkAddress()}:${finalPort}` : null;
1181
+ console.log();
1182
+ console.log(import_picocolors2.default.cyan(" nasti dev server") + import_picocolors2.default.dim(` v0.0.1`));
1183
+ console.log();
1184
+ console.log(` ${import_picocolors2.default.green(">")} Local: ${import_picocolors2.default.cyan(localUrl)}`);
1185
+ if (networkUrl) {
1186
+ console.log(` ${import_picocolors2.default.green(">")} Network: ${import_picocolors2.default.cyan(networkUrl)}`);
1187
+ }
1188
+ console.log();
1189
+ resolve(server);
1190
+ });
1191
+ httpServer.on("error", (err) => {
1192
+ if (err.code === "EADDRINUSE") {
1193
+ console.log(import_picocolors2.default.yellow(`Port ${finalPort} is in use, trying ${finalPort + 1}...`));
1194
+ httpServer.listen(finalPort + 1, host);
1195
+ } else {
1196
+ reject(err);
1197
+ }
1198
+ });
1199
+ });
1200
+ },
1201
+ async transformRequest(url) {
1202
+ const { transformRequest: transformRequest2 } = await Promise.resolve().then(() => (init_middleware(), middleware_exports));
1203
+ return transformRequest2(url, { config: configWithPlugins, pluginContainer, moduleGraph });
1204
+ },
1205
+ async close() {
1206
+ await pluginContainer.buildEnd();
1207
+ watcher.close();
1208
+ ws.close();
1209
+ httpServer.close();
1210
+ }
1211
+ };
1212
+ return server;
1213
+ }
1214
+ function getNetworkAddress() {
1215
+ const os = require("os");
1216
+ const interfaces = os.networkInterfaces();
1217
+ for (const name of Object.keys(interfaces)) {
1218
+ for (const iface of interfaces[name] ?? []) {
1219
+ if (iface.family === "IPv4" && !iface.internal) {
1220
+ return iface.address;
1221
+ }
1222
+ }
1223
+ }
1224
+ return "localhost";
1225
+ }
1226
+ // Annotate the CommonJS export names for ESM import in node:
1227
+ 0 && (module.exports = {
1228
+ build,
1229
+ createServer,
1230
+ defineConfig,
1231
+ resolveConfig
1232
+ });
1233
+ //# sourceMappingURL=index.cjs.map