@ubean/build 0.6.0 → 0.6.1-beta.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.
@@ -1,2 +1,2 @@
1
- import { C as getUbeanAutoImportConfig, D as toArray, E as resolveComponentsConfig, S as getBuiltinComposables, T as resolveAutoImportsConfig, _ as VUE_PRESET, a as generateOpenApiTypesFromServer, b as generateImportsTransform, c as generateI18nTypes, f as HONO_OPENAPI_PRESET, g as VUE_MACROS_PRESET, h as VUE_I18N_PRESET, i as generateOpenApiTypes, l as messagesToTsType, m as UBEAN_SERVER_PRESET, n as CODEGEN_FILES, o as generatePageTypes, p as UBEAN_CLIENT_PRESET, r as generateTypes, s as generateRouteTypes, t as CODEGEN_CONTRACT_VERSION, u as BUILTIN_PRESETS, v as VUE_ROUTER_PRESET, w as getUbeanComponentsConfig, x as getAutoImportPresets, y as generateAutoImports } from "../codegen-Up8-XhRo.js";
1
+ import { C as getUbeanAutoImportConfig, D as toArray, E as resolveComponentsConfig, S as getBuiltinComposables, T as resolveAutoImportsConfig, _ as VUE_PRESET, a as generateOpenApiTypesFromServer, b as generateImportsTransform, c as generateI18nTypes, f as HONO_OPENAPI_PRESET, g as VUE_MACROS_PRESET, h as VUE_I18N_PRESET, i as generateOpenApiTypes, l as messagesToTsType, m as UBEAN_SERVER_PRESET, n as CODEGEN_FILES, o as generatePageTypes, p as UBEAN_CLIENT_PRESET, r as generateTypes, s as generateRouteTypes, t as CODEGEN_CONTRACT_VERSION, u as BUILTIN_PRESETS, v as VUE_ROUTER_PRESET, w as getUbeanComponentsConfig, x as getAutoImportPresets, y as generateAutoImports } from "../codegen-DNUCCW3C.js";
2
2
  export { BUILTIN_PRESETS, CODEGEN_CONTRACT_VERSION, CODEGEN_FILES, HONO_OPENAPI_PRESET, UBEAN_CLIENT_PRESET, UBEAN_SERVER_PRESET, VUE_I18N_PRESET, VUE_MACROS_PRESET, VUE_PRESET, VUE_ROUTER_PRESET, generateAutoImports, generateI18nTypes, generateImportsTransform, generateOpenApiTypes, generateOpenApiTypesFromServer, generatePageTypes, generateRouteTypes, generateTypes, getAutoImportPresets, getBuiltinComposables, getUbeanAutoImportConfig, getUbeanComponentsConfig, messagesToTsType, resolveAutoImportsConfig, resolveComponentsConfig, toArray };
@@ -799,7 +799,10 @@ async function generateOpenApiTypes(schema, options) {
799
799
  async function generateOpenApiTypesFromServer(baseUrl, options) {
800
800
  const url = `${baseUrl.replace(/\/$/, "")}/_openapi.json`;
801
801
  const response = await fetch(url);
802
- if (!response.ok) throw new Error(`[openapi-types] Failed to fetch OpenAPI schema from ${url}: ${response.status} ${response.statusText}`);
802
+ if (!response.ok) {
803
+ const detail = await response.clone().text().then((t) => t.slice(0, 300)).catch(() => "");
804
+ throw new Error(`[openapi-types] Failed to fetch OpenAPI schema from ${url}: ${response.status} ${response.statusText}${detail ? ` — ${detail}` : ""}`);
805
+ }
803
806
  if (!(response.headers.get("content-type") || "").includes("json")) return null;
804
807
  return generateOpenApiTypes(await response.json(), options);
805
808
  }
@@ -1,2 +1,2 @@
1
- import { C as getPresetBuildConfig, S as generateVirtualModulesToDisk, T as buildWithEnvironments, b as generateNodeServerEntry, v as createIslandsSsrStubPlugin, w as serializePagesForEntry, x as generateStandardHandlerEntry, y as generateCloudflareWorkerEntry } from "./vite-C2bhAcof.js";
1
+ import { C as getPresetBuildConfig, S as generateVirtualModulesToDisk, T as buildWithEnvironments, b as generateNodeServerEntry, v as createIslandsSsrStubPlugin, w as serializePagesForEntry, x as generateStandardHandlerEntry, y as generateCloudflareWorkerEntry } from "./vite-KFKQ41Jy.js";
2
2
  export { buildWithEnvironments, createIslandsSsrStubPlugin, generateCloudflareWorkerEntry, generateNodeServerEntry, generateStandardHandlerEntry, generateVirtualModulesToDisk, getPresetBuildConfig, serializePagesForEntry };
@@ -1,10 +1,10 @@
1
1
  import { a as ssrSingletonProdOptimizeExclude, m as createVirtualRegistry, o as ssrSingletonProdSsr, y as __exportAll } from "./ssr-singleton-Bbds29jS.js";
2
2
  import { a as createRoutingVirtualModule, i as createPagesVirtualModule, n as createLocalesVirtualModule, r as createMetaVirtualModule, s as transformMacros, t as createAppVirtualModule } from "./virtual-modules-BK0L1Op-.js";
3
- import { i as generateOpenApiTypes, r as generateTypes } from "./codegen-Up8-XhRo.js";
4
- import { _ as toWebRequest, a as createVueAppEntryVirtualModule, b as getDevScanCoordinator, g as sendWebResponse, i as createServerEntryVirtualModule, n as ubeanVite, o as createVuePagesVirtualModule, r as createClientEntryVirtualModule, u as ensureDevApp } from "./vue-DR8VizGq.js";
3
+ import { i as generateOpenApiTypes, r as generateTypes } from "./codegen-DNUCCW3C.js";
4
+ import { _ as toWebRequest, a as createVueAppEntryVirtualModule, b as getDevScanCoordinator, g as sendWebResponse, i as createServerEntryVirtualModule, n as ubeanVite, o as createVuePagesVirtualModule, r as createClientEntryVirtualModule, u as ensureDevApp } from "./vue-Dh1dtOIU.js";
5
5
  import { createStaticSsgRenderer } from "./static-render.js";
6
6
  import { prerender, resolvePrerenderStaticDir } from "./prerender.js";
7
- import { join, relative, resolve } from "pathe";
7
+ import { dirname, join, relative, resolve } from "pathe";
8
8
  import * as nodeFs from "node:fs";
9
9
  import { existsSync, readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
10
10
  import { loadUbeanConfig, resolveModules, resolvePrerenderConfig, tryGetConfig } from "@ubean/config";
@@ -16,7 +16,7 @@ import * as nodeFsPromises from "node:fs/promises";
16
16
  import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
17
17
  import { getVueLocaleParam } from "@ubean/i18n";
18
18
  import { getColorModeScript, resolveColorModeConfig } from "@ubean/client";
19
- import { DevEnvironment, createBuilder, normalizePath, perEnvironmentPlugin } from "vite";
19
+ import { DevEnvironment, createBuilder, perEnvironmentPlugin } from "vite";
20
20
  import { ubeanIslandsPlugin } from "@ubean/islands/vite";
21
21
  import { findUserViteConfig } from "@ubean/shared/node";
22
22
  import { dirname as dirname$1, extname, join as join$1, normalize as normalize$1, relative as relative$1, resolve as resolve$1, sep } from "node:path";
@@ -374,7 +374,7 @@ function computeAssetTags(manifest, favicon) {
374
374
  }
375
375
  /** 从磁盘读 client manifest(`<publicDir>/.vite/manifest.json`)。 */
376
376
  function readClientManifestFromDisk(publicDir) {
377
- const manifestPath = join$1(publicDir, ".vite", "manifest.json");
377
+ const manifestPath = join(publicDir, ".vite", "manifest.json");
378
378
  if (!existsSync(manifestPath)) return null;
379
379
  try {
380
380
  return JSON.parse(readFileSync(manifestPath, "utf-8"));
@@ -389,7 +389,7 @@ function readClientManifestFromDisk(publicDir) {
389
389
  * 可能来自用户 `vite.config.ts`(另一份模块实例、另一份配置对象),读配置会拿到过期的值。
390
390
  */
391
391
  function clientPublicDirFor(serverOutDir) {
392
- return join$1(dirname$1(serverOutDir), "public");
392
+ return join(dirname(serverOutDir), "public");
393
393
  }
394
394
  /**
395
395
  * 解析要注入的资产标签:内存 manifest 优先,其次读服务端 outDir 旁的磁盘清单。
@@ -532,7 +532,8 @@ async function createCloudflarePreviewRunner(options) {
532
532
  return instance.dispatchFetch(request.url, {
533
533
  method,
534
534
  headers: request.headers,
535
- body: hasBody ? await request.arrayBuffer() : void 0
535
+ body: hasBody ? await request.arrayBuffer() : void 0,
536
+ redirect: request.redirect
536
537
  });
537
538
  },
538
539
  dispose: () => instance.dispose()
@@ -956,7 +957,10 @@ const logger$4 = getLogger("build");
956
957
  */
957
958
  async function generateOpenApiTypesFromApp(app, options) {
958
959
  const response = await app.fetch(new Request("http://localhost/_openapi.json"));
959
- if (!response.ok) return { skipped: `/_openapi.json responded ${response.status}` };
960
+ if (!response.ok) {
961
+ const detail = await response.clone().text().then((t) => t.slice(0, 300)).catch(() => "");
962
+ return { skipped: `/_openapi.json responded ${response.status}${detail ? ` — ${detail}` : ""}` };
963
+ }
960
964
  if (!(response.headers.get("content-type") || "").includes("json")) return { skipped: "no JSON response" };
961
965
  const schema = await response.json();
962
966
  return { filePath: await generateOpenApiTypes(schema, { outDir: join(options.cwd, options.buildDir) }) };
@@ -2100,7 +2104,12 @@ function ubeanPreviewPlugin(options) {
2100
2104
  * 把桩源码内联,与包布局无关。也**不能用 `resolve.alias`**:Vite 解析器对 `node:` 前缀会短路,
2101
2105
  * alias 命不中(实测配了 alias 产物里照样有 `node:fs`)。
2102
2106
  *
2103
- * 只覆盖运行时不支持、且实测会出现在服务端图里的两个:`node:fs` / `node:fs/promises`。
2107
+ * 覆盖三类:
2108
+ * - `node:fs` / `node:fs/promises`:运行时不支持,且实测会出现在服务端图里;
2109
+ * - `nodemailer`:**可选依赖**,`@ubean/server` 的 SMTP provider 用变量化 specifier 延迟加载,
2110
+ * 但 worker 目标全量内联(`noExternal: [/./]` + `codeSplitting: false`)会把动态 import 一起
2111
+ * 打包。10.x 起 nodemailer 是 ESM,入口图顶层静态 `import 'node:http'` → workerd 实例化即失败。
2112
+ *
2104
2113
  * `node:crypto` / `node:async_hooks` / `node:path` 由 `nodejs_compat` 兼容标志支持,保持原样。
2105
2114
  *
2106
2115
  * 桩**抛错而不是静默返回空值**:静默降级会把「静态资源没被服务」「缓存没落盘」变成谜题。
@@ -2152,7 +2161,17 @@ const STUB_SOURCES = {
2152
2161
  "node:fs": FS_STUB_SOURCE,
2153
2162
  fs: FS_STUB_SOURCE,
2154
2163
  "node:fs/promises": FS_PROMISES_STUB_SOURCE,
2155
- "fs/promises": FS_PROMISES_STUB_SOURCE
2164
+ "fs/promises": FS_PROMISES_STUB_SOURCE,
2165
+ nodemailer: `const MESSAGE = (api) =>
2166
+ api + ' 需要 Node 系运行时(SMTP 依赖 net/tls)。当前运行时(Cloudflare Workers 等)不支持:' +
2167
+ '请在 Node 系平台上发送邮件,或改用提供 HTTP API 的邮件服务商。';
2168
+ function unsupported(api) {
2169
+ throw new Error(MESSAGE(api));
2170
+ }
2171
+ export function createTransport() { return unsupported('nodemailer.createTransport'); }
2172
+ export function createTestAccount() { return unsupported('nodemailer.createTestAccount'); }
2173
+ export default new Proxy({}, { get: (_t, prop) => () => unsupported('nodemailer.' + String(prop)) });
2174
+ `
2156
2175
  };
2157
2176
  /** 该 id 在 worker 目标下是否要换成桩;命中时返回虚拟模块 id。 */
2158
2177
  function resolveWorkerNodeStub(id) {
@@ -2242,7 +2261,7 @@ export default {
2242
2261
  /** 把 worker 入口写到 `<dir>/dev-worker.mjs`,返回其绝对路径(供 env-runner 的 `data.entry`)。 */
2243
2262
  async function writeDevWorkerEntry(dir, options) {
2244
2263
  await mkdir(dir, { recursive: true });
2245
- const target = join$1(dir, DEV_WORKER_FILE);
2264
+ const target = join(dir, DEV_WORKER_FILE);
2246
2265
  await writeFile(target, getDevWorkerEntrySource(options), "utf8");
2247
2266
  return target;
2248
2267
  }
@@ -2269,11 +2288,20 @@ function invalidateDevWorkerModules(environment, runner, files) {
2269
2288
  urls: [...urls]
2270
2289
  };
2271
2290
  }
2272
- /** 模块图可能用原始路径或 realpath 建索引,两种都试(去重、保序)。 */
2291
+ /**
2292
+ * 模块图可能用原始路径或 realpath 建索引,两种都试(去重、保序)。
2293
+ *
2294
+ * 这里不能用 vite 的 `normalizePath`:它只在 `pathNeedsCleaning(path)` 为真时才动手,而那把
2295
+ * `isWindows` 写死了 —— Windows 上输入已是反斜杠形态,判定反而为假,于是**原样返回反斜杠**。
2296
+ * 可 Vite 的模块图键来自 `normalizePath(resolvedId)`,两边的形态必须一致,所以这条候选链的
2297
+ * 每个键都得自己把 `\` 换成 `/`。这是一处静默失效:dev 下 Windows 的模块失效全部落空,热重载
2298
+ * 无报错、也不命中(`dev-worker-invalidate.test.ts` 的符号链接用例就是它暴露的)。
2299
+ */
2273
2300
  function candidateFileKeys(file) {
2274
- const keys = [normalizePath(file)];
2301
+ const toPosix = (p) => p.replace(/\\/g, "/");
2302
+ const keys = [toPosix(file)];
2275
2303
  try {
2276
- keys.push(normalizePath(realpathSync.native(file)));
2304
+ keys.push(toPosix(realpathSync.native(file)));
2277
2305
  } catch {}
2278
2306
  return [...new Set(keys)];
2279
2307
  }
@@ -2637,7 +2665,25 @@ function ubeanPlugin(options) {
2637
2665
  data: { file }
2638
2666
  });
2639
2667
  });
2640
- if (process.env.UBEAN_CODEGEN_BY_CLI !== "1") {
2668
+ const announceMissingOpenApiTypes = async () => {
2669
+ if (!ubeanConfig) return;
2670
+ const filePath = join(ubeanConfig.rootDir, ".ubean", "openapi.d.ts");
2671
+ try {
2672
+ const app = await ensureDevApp(server);
2673
+ if (app) {
2674
+ const response = await app.fetch(new Request("http://localhost/_openapi.json"));
2675
+ if (!response.ok) {
2676
+ const detail = await response.clone().text().then((t) => t.slice(0, 300)).catch(() => "");
2677
+ logger.warn(`openapi.d.ts was NOT generated: /_openapi.json responded ${response.status}${detail ? ` — ${detail}` : ""}`);
2678
+ }
2679
+ }
2680
+ } catch {}
2681
+ if (!existsSync(filePath)) logger.warn("`.ubean/openapi.d.ts` is missing — typecheck of `import type { paths } from .../.ubean/openapi` will fail.");
2682
+ };
2683
+ if (process.env.UBEAN_CODEGEN_BY_CLI === "1") {
2684
+ if (server.httpServer) server.httpServer.once("listening", () => void announceMissingOpenApiTypes());
2685
+ else announceMissingOpenApiTypes();
2686
+ } else {
2641
2687
  const runOpenApiTypes = async () => {
2642
2688
  if (!ubeanConfig) return;
2643
2689
  try {
@@ -2648,6 +2694,7 @@ function ubeanPlugin(options) {
2648
2694
  buildDir: ".ubean"
2649
2695
  });
2650
2696
  if (result.filePath) logger.info(`OpenAPI types generated: ${result.filePath}`);
2697
+ else if (result.skipped) logger.warn(`OpenAPI types skipped (${result.skipped}).`);
2651
2698
  } catch (err) {
2652
2699
  logger.warn(`Failed to generate OpenAPI types: ${err instanceof Error ? err.message : String(err)}`);
2653
2700
  }
package/dist/vite.d.ts CHANGED
@@ -251,6 +251,12 @@ interface MiniflareInstanceLike {
251
251
  method?: string;
252
252
  headers?: Headers | Record<string, string>;
253
253
  body?: BodyInit;
254
+ /**
255
+ * 必须显式转发:`dispatchFetch` 走的是 fetch 语义,默认 `redirect: 'follow'`。
256
+ * 不转发时 worker 返回的 302 会被**跟随**到目标页,调用方只看到最终的 200 ——
257
+ * i18n 语言重定向这类断言会因此假绿(实测 cloudflare + miniflare)。
258
+ */
259
+ redirect?: RequestRedirect;
254
260
  }): Promise<Response>;
255
261
  dispose(): Promise<void>;
256
262
  }
package/dist/vite.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { m as createVirtualRegistry } from "./ssr-singleton-Bbds29jS.js";
2
- import { A as toVueRouterPagePath, C as bootstrapDevApp, D as resolveLocaleVueParam, E as resolveDevSecurityHeaders, O as enhanceDevApp, S as peekDevScanCoordinator, T as createDevAppReady, _ as toWebRequest, b as getDevScanCoordinator, c as collectDevCssLinks, d as getDevApp, f as injectStylesheetLinks, g as sendWebResponse, h as ubeanDevRequestPlugin, k as buildDevSsrRoutes, l as createUbeanRequestHandlers, m as isViteResourceRequest, p as isFrameworkHtmlPage, s as DEVTOOLS_PASS_THROUGH_PREFIXES, u as ensureDevApp, v as DEV_SCAN_DIRS, w as createDevApp, x as onDevScan, y as createDevScanCoordinator } from "./vue-DR8VizGq.js";
3
- import { D as createCloudflarePreviewRunner, E as MINIFLARE_INSTALL_HINT, O as defaultLoadMiniflare, _ as ubeanPreviewPlugin, a as createEnvRunnerTransport, c as getDevWorkerEntrySource, d as attachPreviewMiddleware, f as createPreviewMiddleware, g as sendPreviewStatus, h as sendPreviewFile, i as bridgeEnvRunnerInvokes, k as readCompatibilityDate, l as invalidateDevWorkerModules, m as resolvePreviewFile, n as UBEAN_DEV_ENV_NAME, o as createUbeanDevEnvironmentFactory, p as previewMimeType, r as UbeanDevEnvironment, s as DEV_WORKER_FILE, t as ubeanPlugin, u as writeDevWorkerEntry } from "./vite-C2bhAcof.js";
2
+ import { A as toVueRouterPagePath, C as bootstrapDevApp, D as resolveLocaleVueParam, E as resolveDevSecurityHeaders, O as enhanceDevApp, S as peekDevScanCoordinator, T as createDevAppReady, _ as toWebRequest, b as getDevScanCoordinator, c as collectDevCssLinks, d as getDevApp, f as injectStylesheetLinks, g as sendWebResponse, h as ubeanDevRequestPlugin, k as buildDevSsrRoutes, l as createUbeanRequestHandlers, m as isViteResourceRequest, p as isFrameworkHtmlPage, s as DEVTOOLS_PASS_THROUGH_PREFIXES, u as ensureDevApp, v as DEV_SCAN_DIRS, w as createDevApp, x as onDevScan, y as createDevScanCoordinator } from "./vue-Dh1dtOIU.js";
3
+ import { D as createCloudflarePreviewRunner, E as MINIFLARE_INSTALL_HINT, O as defaultLoadMiniflare, _ as ubeanPreviewPlugin, a as createEnvRunnerTransport, c as getDevWorkerEntrySource, d as attachPreviewMiddleware, f as createPreviewMiddleware, g as sendPreviewStatus, h as sendPreviewFile, i as bridgeEnvRunnerInvokes, k as readCompatibilityDate, l as invalidateDevWorkerModules, m as resolvePreviewFile, n as UBEAN_DEV_ENV_NAME, o as createUbeanDevEnvironmentFactory, p as previewMimeType, r as UbeanDevEnvironment, s as DEV_WORKER_FILE, t as ubeanPlugin, u as writeDevWorkerEntry } from "./vite-KFKQ41Jy.js";
4
4
  export { DEVTOOLS_PASS_THROUGH_PREFIXES, DEV_SCAN_DIRS, DEV_WORKER_FILE, MINIFLARE_INSTALL_HINT, UBEAN_DEV_ENV_NAME, UbeanDevEnvironment, attachPreviewMiddleware, bootstrapDevApp, bridgeEnvRunnerInvokes, buildDevSsrRoutes, collectDevCssLinks, createCloudflarePreviewRunner, createDevApp, createDevAppReady, createDevScanCoordinator, createEnvRunnerTransport, createPreviewMiddleware, createUbeanDevEnvironmentFactory, createUbeanRequestHandlers, createVirtualRegistry, defaultLoadMiniflare, enhanceDevApp, ensureDevApp, getDevApp, getDevScanCoordinator, getDevWorkerEntrySource, injectStylesheetLinks, invalidateDevWorkerModules, isFrameworkHtmlPage, isViteResourceRequest, onDevScan, peekDevScanCoordinator, previewMimeType, readCompatibilityDate, resolveDevSecurityHeaders, resolveLocaleVueParam, resolvePreviewFile, sendPreviewFile, sendPreviewStatus, sendWebResponse, toVueRouterPagePath, toWebRequest, ubeanDevRequestPlugin, ubeanPlugin, ubeanPreviewPlugin, writeDevWorkerEntry };
@@ -1,7 +1,8 @@
1
1
  import { c as getComponentResolvers, h as defineVirtualModule, i as ssrSingletonDevPolicy, l as getCssImports, m as createVirtualRegistry } from "./ssr-singleton-Bbds29jS.js";
2
- import { D as toArray, E as resolveComponentsConfig, T as resolveAutoImportsConfig, d as COMPONENT_HALF_GLOBS, x as getAutoImportPresets } from "./codegen-Up8-XhRo.js";
2
+ import { D as toArray, E as resolveComponentsConfig, T as resolveAutoImportsConfig, d as COMPONENT_HALF_GLOBS, x as getAutoImportPresets } from "./codegen-DNUCCW3C.js";
3
3
  import { createRequire } from "node:module";
4
- import { join, relative, resolve } from "pathe";
4
+ import { isAbsolute, join, normalize, relative, resolve } from "pathe";
5
+ import { existsSync } from "node:fs";
5
6
  import { loadUbeanConfig } from "@ubean/config";
6
7
  import { scanProject } from "@ubean/scan";
7
8
  import { applyServerConfig, createUbeanApp } from "@ubean/app";
@@ -419,10 +420,12 @@ const SCAN_FILE_EXTENSIONS = /\.(ts|js|mjs|cjs|mts|cts|vue|json|md|mdx)$/;
419
420
  const ENTRY_FILE_PATTERN = /^(app|App)(\.(server|client))?\.(ts|js|mjs|mts|vue)$|^server(\.(dev|prod))?\.(ts|js|mjs|mts)$/;
420
421
  function createDevScanCoordinator(options) {
421
422
  const { rootDir, source, debounceMs = 150 } = options;
422
- const srcDir = options.srcDir.startsWith("/") ? options.srcDir : `${rootDir}/${options.srcDir}`;
423
+ const srcDir = normalize(isAbsolute(options.srcDir) ? options.srcDir : join(rootDir, options.srcDir));
423
424
  const srcDirNormalized = srcDir.replace(/\/+$/, "");
424
425
  const subscribers = /* @__PURE__ */ new Set();
425
426
  const pending = /* @__PURE__ */ new Set();
427
+ /** 排障用:start() 实际 add 进 watcher 的目录(UBEAN_DEBUG_WATCH=1 时随事件一起输出)。 */
428
+ const addedDirs = [];
426
429
  let debounceTimer = null;
427
430
  let running = null;
428
431
  let rerunRequested = false;
@@ -430,6 +433,7 @@ function createDevScanCoordinator(options) {
430
433
  /** 上一次扫描产物 = 「当前结构」。由 `prime()` 登记,之后每次扫描后更新。 */
431
434
  let baseline;
432
435
  const warn = options.onError ?? ((error) => console.error("[ubean] scan failed:", error));
436
+ const debugWatch = process.env.UBEAN_DEBUG_WATCH === "1";
433
437
  /** 扫描目录(绝对)与「额外监听的文件」(入口文件,由扫描结果给出)。 */
434
438
  const scanDirPaths = DEV_SCAN_DIRS.map((dir) => `${srcDirNormalized}/${dir}`);
435
439
  const extraWatchFiles = /* @__PURE__ */ new Set();
@@ -494,6 +498,7 @@ function createDevScanCoordinator(options) {
494
498
  const structural = structureChanged(result);
495
499
  baseline = result;
496
500
  for (const subscriber of subscribers) await subscriber(result, changed);
501
+ if (debugWatch) process.stderr.write(`[ubean:watch] scan changed=[${changed.join(", ")}] structural=${structural} subscribers=${subscribers.size}\n`);
497
502
  if (structural) options.reload?.();
498
503
  else options.onStructureUnchanged?.(changed);
499
504
  return result;
@@ -528,8 +533,15 @@ function createDevScanCoordinator(options) {
528
533
  }, debounceMs);
529
534
  }
530
535
  const onFileEvent = (file) => {
531
- if (isIgnored(file) || !isScanRelevant(file)) return;
532
- queue(file);
536
+ const normalized = normalize(file);
537
+ if (debugWatch) {
538
+ const relevant = !isIgnored(normalized) && isScanRelevant(normalized);
539
+ process.stderr.write(`[ubean:watch] event=${file} relevant=${relevant} srcDir=${srcDirNormalized} addedDirs=[${addedDirs.join(", ")}]\n`);
540
+ if (relevant) queue(normalized);
541
+ return;
542
+ }
543
+ if (isIgnored(normalized) || !isScanRelevant(normalized)) return;
544
+ queue(normalized);
533
545
  };
534
546
  return {
535
547
  subscribe(fn) {
@@ -539,7 +551,10 @@ function createDevScanCoordinator(options) {
539
551
  start() {
540
552
  if (started) return;
541
553
  started = true;
542
- for (const dir of scanDirPaths) source.add(dir);
554
+ for (const dir of scanDirPaths) if (existsSync(dir)) {
555
+ addedDirs.push(dir);
556
+ source.add(dir);
557
+ }
543
558
  source.on("add", onFileEvent);
544
559
  source.on("unlink", onFileEvent);
545
560
  source.on("change", onFileEvent);
package/dist/vue.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as createVueAppEntryVirtualModule, i as createServerEntryVirtualModule, n as ubeanVite, o as createVuePagesVirtualModule, r as createClientEntryVirtualModule, t as VUE_PLUGIN_INCLUDE } from "./vue-DR8VizGq.js";
1
+ import { a as createVueAppEntryVirtualModule, i as createServerEntryVirtualModule, n as ubeanVite, o as createVuePagesVirtualModule, r as createClientEntryVirtualModule, t as VUE_PLUGIN_INCLUDE } from "./vue-Dh1dtOIU.js";
2
2
  export { VUE_PLUGIN_INCLUDE, createClientEntryVirtualModule, createServerEntryVirtualModule, createVueAppEntryVirtualModule, createVuePagesVirtualModule, ubeanVite as default, ubeanVite };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ubean/build",
3
- "version": "0.6.0",
3
+ "version": "0.6.1-beta.3",
4
4
  "description": "Vite plugins, production build, SSG prerender, type codegen, and Server Actions plugin for ubean",
5
5
  "files": [
6
6
  "dist"
@@ -45,19 +45,19 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@intlify/unplugin-vue-i18n": "11.2.5",
48
- "@ubean/app": "0.6.0",
49
- "@ubean/client": "0.6.0",
50
- "@ubean/config": "0.6.0",
51
- "@ubean/i18n": "0.6.0",
52
- "@ubean/islands": "0.6.0",
53
- "@ubean/markdown": "0.6.0",
54
- "@ubean/pages": "0.6.0",
55
- "@ubean/preset": "0.6.0",
56
- "@ubean/routes": "0.6.0",
57
- "@ubean/scan": "0.6.0",
58
- "@ubean/server": "0.6.0",
59
- "@ubean/shared": "0.6.0",
60
- "@ubean/vue": "0.6.0",
48
+ "@ubean/app": "0.6.1-beta.3",
49
+ "@ubean/client": "0.6.1-beta.3",
50
+ "@ubean/config": "0.6.1-beta.3",
51
+ "@ubean/i18n": "0.6.1-beta.3",
52
+ "@ubean/islands": "0.6.1-beta.3",
53
+ "@ubean/markdown": "0.6.1-beta.3",
54
+ "@ubean/pages": "0.6.1-beta.3",
55
+ "@ubean/preset": "0.6.1-beta.3",
56
+ "@ubean/routes": "0.6.1-beta.3",
57
+ "@ubean/scan": "0.6.1-beta.3",
58
+ "@ubean/server": "0.6.1-beta.3",
59
+ "@ubean/shared": "0.6.1-beta.3",
60
+ "@ubean/vue": "0.6.1-beta.3",
61
61
  "@vitejs/plugin-vue": "^6.0.9",
62
62
  "openapi-typescript": "^7.13.0",
63
63
  "pathe": "^2.0.3",
@@ -70,13 +70,14 @@
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^26.6.4",
73
- "hono": "4.13.12",
73
+ "@vue/compiler-sfc": "^3.5.43",
74
+ "hono": "4.13.13",
74
75
  "typescript": "npm:typescript-native-bridge@latest",
75
- "vite": "npm:@voidzero-dev/vite-plus-core@1.0.0",
76
- "vite-plus": "1.0.0"
76
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.1.0",
77
+ "vite-plus": "1.1.0"
77
78
  },
78
79
  "peerDependencies": {
79
- "vite": "npm:@voidzero-dev/vite-plus-core@1.0.0"
80
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.1.0"
80
81
  },
81
82
  "peerDependenciesMeta": {
82
83
  "vite": {