@ubean/build 0.5.2 → 0.6.0-beta.1

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.
@@ -0,0 +1,218 @@
1
+ import "node:module";
2
+ //#region \0rolldown/runtime.js
3
+ var __defProp = Object.defineProperty;
4
+ var __exportAll = (all, no_symbols) => {
5
+ let target = {};
6
+ for (var name in all) __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
11
+ return target;
12
+ };
13
+ //#endregion
14
+ //#region src/virtual-registry.ts
15
+ var VirtualModuleRegistry = class {
16
+ modules = /* @__PURE__ */ new Map();
17
+ invalidated = /* @__PURE__ */ new Set();
18
+ register(mod) {
19
+ this.modules.set(mod.id, mod);
20
+ }
21
+ resolveId(id, importer) {
22
+ if (this.modules.has(id)) return id;
23
+ for (const mod of this.modules.values()) {
24
+ const resolved = mod.resolve(id, importer);
25
+ if (resolved) return resolved;
26
+ }
27
+ }
28
+ async load(id) {
29
+ const exactMod = this.modules.get(id);
30
+ if (exactMod) return exactMod.load(id);
31
+ for (const [modId, mod] of this.modules) {
32
+ if (modId === id) continue;
33
+ if (mod.resolve(id)) return mod.load(id);
34
+ }
35
+ }
36
+ invalidate(id) {
37
+ this.invalidated.add(id);
38
+ }
39
+ isInvalidated(id) {
40
+ return this.invalidated.has(id);
41
+ }
42
+ clearInvalidated() {
43
+ this.invalidated.clear();
44
+ }
45
+ getModules() {
46
+ return [...this.modules.values()];
47
+ }
48
+ clear() {
49
+ this.modules.clear();
50
+ this.invalidated.clear();
51
+ }
52
+ };
53
+ let _registry = null;
54
+ /**
55
+ * 建一个独立的注册表实例(RM-V02)。
56
+ *
57
+ * 框架路径(build / dev / 主包 vite 入口)各自建一个并**显式注入**给插件,不再依赖模块级
58
+ * 单例。单例上的 `clear()` 曾用于在两次构建之间重置状态,正是跨构建污染的来源。
59
+ */
60
+ function createVirtualRegistry(modules = []) {
61
+ const registry = new VirtualModuleRegistry();
62
+ for (const mod of modules) registry.register(mod);
63
+ return registry;
64
+ }
65
+ /**
66
+ * @deprecated RM-V02 起框架路径改为显式注入(`createVirtualRegistry()` + 插件 `registry`
67
+ * 选项)。保留此单例仅供既有测试与外部一次性用法,新代码不要使用。
68
+ */
69
+ function useVirtualRegistry() {
70
+ if (!_registry) _registry = new VirtualModuleRegistry();
71
+ return _registry;
72
+ }
73
+ /** @deprecated 见 `useVirtualRegistry()`。 */
74
+ function resetVirtualRegistry() {
75
+ _registry = null;
76
+ }
77
+ function defineVirtualModule(id, loader) {
78
+ return {
79
+ id,
80
+ resolve(resolvedId) {
81
+ return resolvedId === id ? id : void 0;
82
+ },
83
+ load: loader
84
+ };
85
+ }
86
+ function defineVirtualModulePrefix(prefix, loader) {
87
+ return {
88
+ id: prefix,
89
+ resolve(id) {
90
+ if (id.startsWith(prefix)) return id;
91
+ },
92
+ load(id) {
93
+ return loader(id || prefix);
94
+ }
95
+ };
96
+ }
97
+ //#endregion
98
+ //#region src/registry.ts
99
+ const REGISTRY_KEY = "__ubean_module_registry__";
100
+ function getRegistry() {
101
+ const g = globalThis;
102
+ if (!g[REGISTRY_KEY]) g[REGISTRY_KEY] = {
103
+ componentResolvers: [],
104
+ cssImports: []
105
+ };
106
+ return g[REGISTRY_KEY];
107
+ }
108
+ /**
109
+ * Register a component resolver (e.g. `UiResolver()` from `@soybeanjs/ui/resolver`).
110
+ * The resolver will be merged into `unplugin-vue-components`'s `resolvers` array.
111
+ */
112
+ function registerComponentResolver(resolver) {
113
+ getRegistry().componentResolvers.push(resolver);
114
+ }
115
+ /**
116
+ * Get all registered component resolvers.
117
+ * Called by `ubeanVite` when constructing the `Components()` plugin.
118
+ */
119
+ function getComponentResolvers() {
120
+ return [...getRegistry().componentResolvers];
121
+ }
122
+ /**
123
+ * Register a CSS import path to be injected into the client entry.
124
+ * e.g. `registerCssImport('@soybeanjs/ui/styles.css')` makes the client
125
+ * entry module prepend `import '@soybeanjs/ui/styles.css'`.
126
+ */
127
+ function registerCssImport(cssPath) {
128
+ const reg = getRegistry();
129
+ if (!reg.cssImports.includes(cssPath)) reg.cssImports.push(cssPath);
130
+ }
131
+ /**
132
+ * Get all registered CSS import paths.
133
+ * Called by `createClientEntryVirtualModule` to prepend CSS imports.
134
+ */
135
+ function getCssImports() {
136
+ return [...getRegistry().cssImports];
137
+ }
138
+ /**
139
+ * Reset the registry (for testing).
140
+ * @internal
141
+ */
142
+ function resetModuleRegistry() {
143
+ const reg = getRegistry();
144
+ reg.componentResolvers.length = 0;
145
+ reg.cssImports.length = 0;
146
+ }
147
+ //#endregion
148
+ //#region src/ssr-singleton.ts
149
+ var ssr_singleton_exports = /* @__PURE__ */ __exportAll({
150
+ SSR_SINGLETON_DEDUPE: () => SSR_SINGLETON_DEDUPE,
151
+ SSR_SINGLETON_OPTIMIZE_EXCLUDE: () => SSR_SINGLETON_OPTIMIZE_EXCLUDE,
152
+ SSR_SINGLETON_PACKAGES: () => SSR_SINGLETON_PACKAGES,
153
+ ssrSingletonDevPolicy: () => ssrSingletonDevPolicy,
154
+ ssrSingletonProdOptimizeExclude: () => ssrSingletonProdOptimizeExclude,
155
+ ssrSingletonProdSsr: () => ssrSingletonProdSsr
156
+ });
157
+ /**
158
+ * Single-copy runtime policy for Vite client / SSR graphs.
159
+ *
160
+ * `@ubean/i18n` (ALS + catalogs) and `@ubean/client` (locale runtime) must
161
+ * resolve to one module instance per process. Dev and production use the
162
+ * same package lists; only the SSR externalization differs:
163
+ *
164
+ * - Dev: Vite `ssrLoadModule` and the CLI-created app share Node's
165
+ * `@ubean/i18n` (external). `ubean` stays noExternal so virtual ids resolve.
166
+ * - Prod: `ubean` is bundled (`noExternal`). Do **not** also externalize
167
+ * `@ubean/i18n` — that would create a second copy beside the bundle.
168
+ */
169
+ const SSR_SINGLETON_PACKAGES = [
170
+ "ubean",
171
+ "@ubean/client",
172
+ "@ubean/i18n",
173
+ "vue-i18n",
174
+ "@intlify/core",
175
+ "@intlify/core-base"
176
+ ];
177
+ const SSR_SINGLETON_DEDUPE = [
178
+ "vue",
179
+ "vue-i18n",
180
+ "@ubean/client",
181
+ "@ubean/i18n"
182
+ ];
183
+ const SSR_SINGLETON_OPTIMIZE_EXCLUDE = [
184
+ "ubean",
185
+ "@ubean/client",
186
+ "@ubean/i18n"
187
+ ];
188
+ function ssrSingletonDevPolicy() {
189
+ return {
190
+ resolve: { dedupe: [...SSR_SINGLETON_DEDUPE] },
191
+ optimizeDeps: {
192
+ exclude: [...SSR_SINGLETON_OPTIMIZE_EXCLUDE],
193
+ include: ["vue-i18n"]
194
+ },
195
+ ssr: {
196
+ noExternal: [
197
+ "ubean",
198
+ "vue-i18n",
199
+ "@intlify/core",
200
+ "@intlify/core-base"
201
+ ],
202
+ external: ["@ubean/i18n"]
203
+ }
204
+ };
205
+ }
206
+ function ssrSingletonProdSsr() {
207
+ return { noExternal: [
208
+ "ubean",
209
+ "vue-i18n",
210
+ "@intlify/core",
211
+ "@intlify/core-base"
212
+ ] };
213
+ }
214
+ function ssrSingletonProdOptimizeExclude(extra = []) {
215
+ return [...SSR_SINGLETON_OPTIMIZE_EXCLUDE, ...extra];
216
+ }
217
+ //#endregion
218
+ export { resetVirtualRegistry as _, ssrSingletonProdOptimizeExclude as a, getComponentResolvers as c, registerCssImport as d, resetModuleRegistry as f, defineVirtualModulePrefix as g, defineVirtualModule as h, ssrSingletonDevPolicy as i, getCssImports as l, createVirtualRegistry as m, SSR_SINGLETON_OPTIMIZE_EXCLUDE as n, ssrSingletonProdSsr as o, VirtualModuleRegistry as p, SSR_SINGLETON_PACKAGES as r, ssr_singleton_exports as s, SSR_SINGLETON_DEDUPE as t, registerComponentResolver as u, useVirtualRegistry as v, __exportAll as y };
@@ -1,6 +1,6 @@
1
1
  import { resolve } from "pathe";
2
- import { extractLocaleFromPath } from "@ubean/i18n";
3
2
  import { getLogger } from "@ubean/shared/logger";
3
+ import { extractLocaleFromPath } from "@ubean/i18n";
4
4
  import { pathToFileURL } from "node:url";
5
5
  //#region src/static-render.ts
6
6
  /**
@@ -1,4 +1,4 @@
1
- import { n as defineVirtualModule } from "./virtual-registry-BWkaQHXN.js";
1
+ import { h as defineVirtualModule } from "./ssr-singleton-DPTawJSx.js";
2
2
  import { isAbsolute, relative } from "pathe";
3
3
  //#region src/macros.ts
4
4
  const MACRO_NAMES = ["definePage"];
@@ -100,9 +100,25 @@ function transformMacros(code, id) {
100
100
  if (/\.(ts|js|mjs|mts|tsx|jsx)$/.test(id)) return stripMacros(code);
101
101
  return null;
102
102
  }
103
+ /** 仅 `<script>`(非 setup)块——用于判断组件是否把默认导出交给普通脚本块。 */
104
+ const PLAIN_SCRIPT_RE = /<script(?![^>]*\bsetup\b)[^>]*>/;
105
+ /**
106
+ * 剥离宏后为空的 `<script setup>` 块保留一个注释,避免整个块「消失」。
107
+ *
108
+ * `@vue/compiler-sfc` 把**只有空白**的 `<script setup>` 视为没有 setup 块;此时若组件另有一个
109
+ * 普通 `<script>` 块,编译产物就只剩那个脚本块的内容 —— 没有 `export default`,而
110
+ * `@vitejs/plugin-vue` 的主模块仍然按「有脚本块就有默认导出」去 import it,
111
+ * 于是生产构建报 `MISSING_EXPORT "default"`(dev 下则是浏览器链接期报同样的错)。
112
+ *
113
+ * 这不是稀奇形状:页面约定就是「`loader` 写在 `<script>`,`definePage` 写在 `<script setup>`」,
114
+ * 而 `definePage` 是宏、必被剥掉 —— 一个只有 loader 的页面正好落在坑里。
115
+ */
116
+ const EMPTY_SETUP_KEEP_ALIVE = "\n// ubean: 宏已剥离,保留此块以维持组件的默认导出(见 builder/src/macros.ts)\n";
103
117
  function transformVueMacros(code) {
118
+ const hasPlainScript = PLAIN_SCRIPT_RE.test(code);
104
119
  return code.replace(/<script([^>]*)>([\s\S]*?)<\/script>/g, (_match, attrs, content) => {
105
- return `<script${attrs}>${stripMacros(content)}<\/script>`;
120
+ const stripped = stripMacros(content);
121
+ return `<script${attrs}>${/\bsetup\b/.test(attrs) && hasPlainScript && !stripped.trim() ? EMPTY_SETUP_KEEP_ALIVE : stripped}<\/script>`;
106
122
  });
107
123
  }
108
124
  //#endregion
@@ -0,0 +1,53 @@
1
+ //#region src/virtual-registry.d.ts
2
+ interface VirtualModuleContext {
3
+ resolveId(id: string): string | undefined;
4
+ load(id: string): string | undefined;
5
+ invalidate(id: string): void;
6
+ }
7
+ type VirtualModuleTransform = (id: string, code: string) => string | Promise<string>;
8
+ interface VirtualModule {
9
+ id: string;
10
+ resolve(id: string, importer?: string): string | undefined;
11
+ load(id?: string): string | Promise<string>;
12
+ }
13
+ /**
14
+ * 注册表的**只读视图**(RM-V02)。
15
+ *
16
+ * 插件只读;写入由 scan 层构建出注册表后注入。这样插件实例不再持有跨构建的可变状态 ——
17
+ * Phase 2 的单 builder 多环境共享插件实例时,环境之间不会互相污染。
18
+ */
19
+ interface VirtualModuleResolver {
20
+ resolveId(id: string, importer?: string): string | undefined;
21
+ load(id: string): Promise<string | undefined> | string | undefined;
22
+ getModules(): VirtualModule[];
23
+ }
24
+ declare class VirtualModuleRegistry implements VirtualModuleResolver {
25
+ private modules;
26
+ private invalidated;
27
+ register(mod: VirtualModule): void;
28
+ resolveId(id: string, importer?: string): string | undefined;
29
+ load(id: string): Promise<string | undefined>;
30
+ invalidate(id: string): void;
31
+ isInvalidated(id: string): boolean;
32
+ clearInvalidated(): void;
33
+ getModules(): VirtualModule[];
34
+ clear(): void;
35
+ }
36
+ /**
37
+ * 建一个独立的注册表实例(RM-V02)。
38
+ *
39
+ * 框架路径(build / dev / 主包 vite 入口)各自建一个并**显式注入**给插件,不再依赖模块级
40
+ * 单例。单例上的 `clear()` 曾用于在两次构建之间重置状态,正是跨构建污染的来源。
41
+ */
42
+ declare function createVirtualRegistry(modules?: VirtualModule[]): VirtualModuleRegistry;
43
+ /**
44
+ * @deprecated RM-V02 起框架路径改为显式注入(`createVirtualRegistry()` + 插件 `registry`
45
+ * 选项)。保留此单例仅供既有测试与外部一次性用法,新代码不要使用。
46
+ */
47
+ declare function useVirtualRegistry(): VirtualModuleRegistry;
48
+ /** @deprecated 见 `useVirtualRegistry()`。 */
49
+ declare function resetVirtualRegistry(): void;
50
+ declare function defineVirtualModule(id: string, loader: () => string | Promise<string>): VirtualModule;
51
+ declare function defineVirtualModulePrefix(prefix: string, loader: (id: string) => string | Promise<string>): VirtualModule;
52
+ //#endregion
53
+ export { VirtualModuleTransform as a, defineVirtualModulePrefix as c, VirtualModuleResolver as i, resetVirtualRegistry as l, VirtualModuleContext as n, createVirtualRegistry as o, VirtualModuleRegistry as r, defineVirtualModule as s, VirtualModule as t, useVirtualRegistry as u };