@ubean/build 0.1.12 → 0.2.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.d.ts +8 -89
- package/dist/index.js +2 -51
- package/dist/production.d.ts +1 -1
- package/dist/production.js +40 -14
- package/dist/{virtual-modules-DR_ynMd0.js → virtual-modules-BDgTqx3t.js} +3 -173
- package/dist/vite.d.ts +2 -2
- package/dist/vite.js +11 -10
- package/package.json +20 -15
package/dist/index.d.ts
CHANGED
|
@@ -1,92 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
resolveId(id: string): string | undefined;
|
|
5
|
-
load(id: string): string | undefined;
|
|
6
|
-
invalidate(id: string): void;
|
|
7
|
-
}
|
|
8
|
-
type VirtualModuleTransform = (id: string, code: string) => string | Promise<string>;
|
|
9
|
-
interface VirtualModule {
|
|
10
|
-
id: string;
|
|
11
|
-
resolve(id: string, importer?: string): string | undefined;
|
|
12
|
-
load(): string | Promise<string>;
|
|
13
|
-
}
|
|
14
|
-
declare class VirtualModuleRegistry {
|
|
15
|
-
private modules;
|
|
16
|
-
private invalidated;
|
|
17
|
-
register(mod: VirtualModule): void;
|
|
18
|
-
resolveId(id: string, importer?: string): string | undefined;
|
|
19
|
-
load(id: string): Promise<string | undefined>;
|
|
20
|
-
invalidate(id: string): void;
|
|
21
|
-
isInvalidated(id: string): boolean;
|
|
22
|
-
clearInvalidated(): void;
|
|
23
|
-
getModules(): VirtualModule[];
|
|
24
|
-
clear(): void;
|
|
25
|
-
}
|
|
26
|
-
declare function useVirtualRegistry(): VirtualModuleRegistry;
|
|
27
|
-
declare function resetVirtualRegistry(): void;
|
|
28
|
-
declare function defineVirtualModule(id: string, loader: () => string | Promise<string>): VirtualModule;
|
|
29
|
-
declare function defineVirtualModulePrefix(prefix: string, loader: (id: string) => string | Promise<string>): VirtualModule;
|
|
30
|
-
//#endregion
|
|
31
|
-
//#region src/macros.d.ts
|
|
32
|
-
declare function stripMacros(code: string, macros?: readonly string[]): string;
|
|
33
|
-
declare function transformMacros(code: string, id: string): string | null;
|
|
34
|
-
//#endregion
|
|
1
|
+
import { VirtualModule, VirtualModuleContext, VirtualModuleRegistry, VirtualModuleTransform, defineVirtualModule, defineVirtualModulePrefix, getComponentResolvers, getCssImports, registerComponentResolver, registerCssImport, resetModuleRegistry, resetVirtualRegistry, stripMacros, transformMacros, useVirtualRegistry } from "@ubean/build-core";
|
|
2
|
+
import { CompiledLayout, CompiledMiddleware, CompiledPage, CompiledRoute } from "@ubean/routes";
|
|
3
|
+
import { ScannedApiRoute, ScannedLocale, ScannedMiddleware, ScannedPageRoute } from "@ubean/scan";
|
|
35
4
|
//#region src/virtual-modules.d.ts
|
|
36
|
-
declare function createRoutingVirtualModule(routes: CompiledRoute[], middlewares: CompiledMiddleware[], cwd: string):
|
|
37
|
-
declare function createPagesVirtualModule(pages: CompiledPage[], layouts: CompiledLayout[], cwd: string):
|
|
38
|
-
declare function createMetaVirtualModule():
|
|
39
|
-
declare function createAppVirtualModule(apiRoutes: ScannedApiRoute[], middlewares: ScannedMiddleware[], pages: ScannedPageRoute[], srcDir: string):
|
|
40
|
-
declare function createLocalesVirtualModule(_locales: ScannedLocale[], defaultLocale: string | undefined, srcDir?: string):
|
|
41
|
-
//#endregion
|
|
42
|
-
//#region src/registry.d.ts
|
|
43
|
-
/**
|
|
44
|
-
* Module extension registry.
|
|
45
|
-
*
|
|
46
|
-
* Allows built-in extension modules (@ubean/ui, @ubean/icon, etc.) to inject
|
|
47
|
-
* component resolvers and CSS imports into the core Vite plugin pipeline
|
|
48
|
-
* without modifying ubeanVuePlugin directly.
|
|
49
|
-
*
|
|
50
|
-
* Registration happens at module load time (when ubeanUiPlugin() etc. are
|
|
51
|
-
* called by the module system, before ubeanVuePlugin reads the registry).
|
|
52
|
-
*
|
|
53
|
-
* Uses globalThis for storage to ensure state is shared across multiple
|
|
54
|
-
* copies of @ubean/build that may exist due to package manager duplication
|
|
55
|
-
* (e.g. pnpm creating separate instances for different version ranges).
|
|
56
|
-
*/
|
|
57
|
-
/**
|
|
58
|
-
* Generic component resolver type compatible with unplugin-vue-components.
|
|
59
|
-
* Accepts both function resolvers and object resolvers (ComponentResolverObject).
|
|
60
|
-
*/
|
|
61
|
-
type ComponentResolver = ((name: string) => any) | {
|
|
62
|
-
type: 'component' | 'directive';
|
|
63
|
-
resolve: (name: string) => any;
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
* Register a component resolver (e.g. `UiResolver()` from `@soybeanjs/ui/resolver`).
|
|
67
|
-
* The resolver will be merged into `unplugin-vue-components`'s `resolvers` array.
|
|
68
|
-
*/
|
|
69
|
-
declare function registerComponentResolver(resolver: ComponentResolver): void;
|
|
70
|
-
/**
|
|
71
|
-
* Get all registered component resolvers.
|
|
72
|
-
* Called by `ubeanVuePlugin` when constructing the `Components()` plugin.
|
|
73
|
-
*/
|
|
74
|
-
declare function getComponentResolvers(): ComponentResolver[];
|
|
75
|
-
/**
|
|
76
|
-
* Register a CSS import path to be injected into the client entry.
|
|
77
|
-
* e.g. `registerCssImport('@soybeanjs/ui/styles.css')` makes the client
|
|
78
|
-
* entry module prepend `import '@soybeanjs/ui/styles.css'`.
|
|
79
|
-
*/
|
|
80
|
-
declare function registerCssImport(cssPath: string): void;
|
|
81
|
-
/**
|
|
82
|
-
* Get all registered CSS import paths.
|
|
83
|
-
* Called by `createClientEntryVirtualModule` to prepend CSS imports.
|
|
84
|
-
*/
|
|
85
|
-
declare function getCssImports(): string[];
|
|
86
|
-
/**
|
|
87
|
-
* Reset the registry (for testing).
|
|
88
|
-
* @internal
|
|
89
|
-
*/
|
|
90
|
-
declare function resetModuleRegistry(): void;
|
|
5
|
+
declare function createRoutingVirtualModule(routes: CompiledRoute[], middlewares: CompiledMiddleware[], cwd: string): any;
|
|
6
|
+
declare function createPagesVirtualModule(pages: CompiledPage[], layouts: CompiledLayout[], cwd: string): any;
|
|
7
|
+
declare function createMetaVirtualModule(): any;
|
|
8
|
+
declare function createAppVirtualModule(apiRoutes: ScannedApiRoute[], middlewares: ScannedMiddleware[], pages: ScannedPageRoute[], srcDir: string): any;
|
|
9
|
+
declare function createLocalesVirtualModule(_locales: ScannedLocale[], defaultLocale: string | undefined, srcDir?: string): any;
|
|
91
10
|
//#endregion
|
|
92
11
|
export { type VirtualModule, type VirtualModuleContext, VirtualModuleRegistry, type VirtualModuleTransform, createAppVirtualModule, createLocalesVirtualModule, createMetaVirtualModule, createPagesVirtualModule, createRoutingVirtualModule, defineVirtualModule, defineVirtualModulePrefix, getComponentResolvers, getCssImports, registerComponentResolver, registerCssImport, resetModuleRegistry, resetVirtualRegistry, stripMacros, transformMacros, useVirtualRegistry };
|
package/dist/index.js
CHANGED
|
@@ -1,52 +1,3 @@
|
|
|
1
|
-
import { a as createRoutingVirtualModule,
|
|
2
|
-
|
|
3
|
-
const REGISTRY_KEY = "__ubean_module_registry__";
|
|
4
|
-
function getRegistry() {
|
|
5
|
-
const g = globalThis;
|
|
6
|
-
if (!g[REGISTRY_KEY]) g[REGISTRY_KEY] = {
|
|
7
|
-
componentResolvers: [],
|
|
8
|
-
cssImports: []
|
|
9
|
-
};
|
|
10
|
-
return g[REGISTRY_KEY];
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Register a component resolver (e.g. `UiResolver()` from `@soybeanjs/ui/resolver`).
|
|
14
|
-
* The resolver will be merged into `unplugin-vue-components`'s `resolvers` array.
|
|
15
|
-
*/
|
|
16
|
-
function registerComponentResolver(resolver) {
|
|
17
|
-
getRegistry().componentResolvers.push(resolver);
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Get all registered component resolvers.
|
|
21
|
-
* Called by `ubeanVuePlugin` when constructing the `Components()` plugin.
|
|
22
|
-
*/
|
|
23
|
-
function getComponentResolvers() {
|
|
24
|
-
return [...getRegistry().componentResolvers];
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Register a CSS import path to be injected into the client entry.
|
|
28
|
-
* e.g. `registerCssImport('@soybeanjs/ui/styles.css')` makes the client
|
|
29
|
-
* entry module prepend `import '@soybeanjs/ui/styles.css'`.
|
|
30
|
-
*/
|
|
31
|
-
function registerCssImport(cssPath) {
|
|
32
|
-
const reg = getRegistry();
|
|
33
|
-
if (!reg.cssImports.includes(cssPath)) reg.cssImports.push(cssPath);
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Get all registered CSS import paths.
|
|
37
|
-
* Called by `createClientEntryVirtualModule` to prepend CSS imports.
|
|
38
|
-
*/
|
|
39
|
-
function getCssImports() {
|
|
40
|
-
return [...getRegistry().cssImports];
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Reset the registry (for testing).
|
|
44
|
-
* @internal
|
|
45
|
-
*/
|
|
46
|
-
function resetModuleRegistry() {
|
|
47
|
-
const reg = getRegistry();
|
|
48
|
-
reg.componentResolvers.length = 0;
|
|
49
|
-
reg.cssImports.length = 0;
|
|
50
|
-
}
|
|
51
|
-
//#endregion
|
|
1
|
+
import { a as createRoutingVirtualModule, i as createPagesVirtualModule, n as createLocalesVirtualModule, r as createMetaVirtualModule, t as createAppVirtualModule } from "./virtual-modules-BDgTqx3t.js";
|
|
2
|
+
import { VirtualModuleRegistry, defineVirtualModule, defineVirtualModulePrefix, getComponentResolvers, getCssImports, registerComponentResolver, registerCssImport, resetModuleRegistry, resetVirtualRegistry, stripMacros, transformMacros, useVirtualRegistry } from "@ubean/build-core";
|
|
52
3
|
export { VirtualModuleRegistry, createAppVirtualModule, createLocalesVirtualModule, createMetaVirtualModule, createPagesVirtualModule, createRoutingVirtualModule, defineVirtualModule, defineVirtualModulePrefix, getComponentResolvers, getCssImports, registerComponentResolver, registerCssImport, resetModuleRegistry, resetVirtualRegistry, stripMacros, transformMacros, useVirtualRegistry };
|
package/dist/production.d.ts
CHANGED
package/dist/production.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import { a as createRoutingVirtualModule,
|
|
1
|
+
import { a as createRoutingVirtualModule, i as createPagesVirtualModule, n as createLocalesVirtualModule, r as createMetaVirtualModule, t as createAppVirtualModule } from "./virtual-modules-BDgTqx3t.js";
|
|
2
2
|
import { ubeanPlugin } from "./vite.js";
|
|
3
|
+
import { useVirtualRegistry } from "@ubean/build-core";
|
|
3
4
|
import { join, relative, resolve } from "pathe";
|
|
4
5
|
import { existsSync } from "node:fs";
|
|
5
6
|
import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
6
7
|
import { build } from "vite";
|
|
7
8
|
import vue from "@vitejs/plugin-vue";
|
|
8
|
-
import {
|
|
9
|
+
import { getColorModeScript, resolveColorModeConfig } from "@ubean/client";
|
|
10
|
+
import { ubeanIslandsPlugin } from "@ubean/islands/vite";
|
|
11
|
+
import { getLogger } from "@ubean/logger";
|
|
9
12
|
import { resolveModules } from "@ubean/modules";
|
|
10
|
-
import { findUserViteConfig } from "@ubean/
|
|
11
|
-
import { VUE_PLUGIN_INCLUDE, createClientEntryVirtualModule, createServerEntryVirtualModule, createVueAppEntryVirtualModule, createVuePagesVirtualModule,
|
|
12
|
-
import { consola } from "consola";
|
|
13
|
+
import { findUserViteConfig } from "@ubean/shared/node";
|
|
14
|
+
import { VUE_PLUGIN_INCLUDE, createClientEntryVirtualModule, createServerEntryVirtualModule, createVueAppEntryVirtualModule, createVuePagesVirtualModule, ubeanVite } from "@ubean/vite";
|
|
13
15
|
//#region src/production.ts
|
|
14
|
-
const logger =
|
|
16
|
+
const logger = getLogger("build");
|
|
15
17
|
function getOutDirs(cwd, outputDir) {
|
|
16
18
|
const outputRoot = resolve(cwd, outputDir);
|
|
17
19
|
return {
|
|
@@ -33,7 +35,8 @@ async function generateVirtualModulesToDisk(cwd, config, scanResult, virtualDir)
|
|
|
33
35
|
await mkdir(virtualDir, { recursive: true });
|
|
34
36
|
const registry = useVirtualRegistry();
|
|
35
37
|
registry.clear();
|
|
36
|
-
const
|
|
38
|
+
const srcDirAbs = resolve(cwd, config.srcDir);
|
|
39
|
+
const viteSrcDir = toVitePath(relative(cwd, srcDirAbs));
|
|
37
40
|
const viteSrcPrefix = viteSrcDir ? `/${viteSrcDir}` : "";
|
|
38
41
|
registry.register(createRoutingVirtualModule(scanResult.apiRoutes.map((r) => ({
|
|
39
42
|
method: r.method?.toUpperCase() || "ALL",
|
|
@@ -59,7 +62,7 @@ async function generateVirtualModulesToDisk(cwd, config, scanResult, virtualDir)
|
|
|
59
62
|
isDefault: l.isDefault
|
|
60
63
|
})), cwd));
|
|
61
64
|
registry.register(createMetaVirtualModule());
|
|
62
|
-
registry.register(createVuePagesVirtualModule(scanResult.pages, scanResult.layouts));
|
|
65
|
+
registry.register(createVuePagesVirtualModule(scanResult.pages, scanResult.layouts, scanResult.notFoundPage, scanResult.loadingPage, scanResult.errorPage));
|
|
63
66
|
registry.register(createVueAppEntryVirtualModule(scanResult.appEntry));
|
|
64
67
|
registry.register(createClientEntryVirtualModule());
|
|
65
68
|
}
|
|
@@ -82,11 +85,13 @@ async function generateVirtualModulesToDisk(cwd, config, scanResult, virtualDir)
|
|
|
82
85
|
await writeModule("virtual:ubean-client-entry", "client-entry.mjs", "");
|
|
83
86
|
}
|
|
84
87
|
if (hasServer) await writeModule("virtual:ubean-server", "server-entry.ts", "");
|
|
88
|
+
await writeFile(join(virtualDir, "islands-registry.ts"), "export const islands = {};\n", "utf-8");
|
|
85
89
|
const pagesGlob = JSON.stringify(`${viteSrcPrefix}/pages/**/*.{vue,ts,tsx,js,jsx,md,mdx}`);
|
|
86
90
|
const routesGlob = JSON.stringify(`${viteSrcPrefix}/routes/**/*.{ts,js,mjs}`);
|
|
87
91
|
const middlewareGlob = JSON.stringify(`${viteSrcPrefix}/middleware/**/*.{ts,js,mjs}`);
|
|
88
92
|
const layoutsGlob = JSON.stringify(`${viteSrcPrefix}/layouts/**/*.{vue,ts}`);
|
|
89
|
-
const
|
|
93
|
+
const outputDir = config.build.outputDir || "dist";
|
|
94
|
+
const publicDir = toVitePath(resolve(cwd, outputDir, "public"));
|
|
90
95
|
const routesJson = JSON.stringify(scanResult.apiRoutes.map((r) => ({
|
|
91
96
|
relativePath: r.relativePath,
|
|
92
97
|
route: r.route,
|
|
@@ -112,6 +117,14 @@ async function generateVirtualModulesToDisk(cwd, config, scanResult, virtualDir)
|
|
|
112
117
|
relativePath: l.relativePath,
|
|
113
118
|
isDefault: l.isDefault
|
|
114
119
|
})));
|
|
120
|
+
const notFoundPageJson = JSON.stringify(scanResult.notFoundPage ? {
|
|
121
|
+
relativePath: scanResult.notFoundPage.relativePath,
|
|
122
|
+
name: scanResult.notFoundPage.name,
|
|
123
|
+
route: scanResult.notFoundPage.route,
|
|
124
|
+
layout: scanResult.notFoundPage.layout,
|
|
125
|
+
pageMeta: scanResult.notFoundPage.pageMeta
|
|
126
|
+
} : null);
|
|
127
|
+
const colorModeScript = config.colorMode !== false ? getColorModeScript(resolveColorModeConfig(config.colorMode)) : "";
|
|
115
128
|
const rendererImport = ssrEnabled ? `import { createVueRenderer } from 'ubean/vue-ssr';` : "";
|
|
116
129
|
const rendererSetup = ssrEnabled ? `
|
|
117
130
|
// --- SSR renderer setup ---
|
|
@@ -217,10 +230,11 @@ const _routes = ${routesJson};
|
|
|
217
230
|
const _middleware = ${middlewareJson};
|
|
218
231
|
const _pages = ${pagesJson};
|
|
219
232
|
const _layouts = ${layoutsJson};
|
|
233
|
+
const _notFoundPage = ${notFoundPageJson};
|
|
220
234
|
${rendererSetup}
|
|
221
235
|
// --- Client asset tags from Vite manifest ---
|
|
222
236
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
223
|
-
let _assetTags = { css: '', preloads: '', body: '' };
|
|
237
|
+
let _assetTags = { css: '', preloads: '', body: '', favicon: ${JSON.stringify(config.favicon)} };
|
|
224
238
|
try {
|
|
225
239
|
const manifestPath = join(__dirname, '..', 'public', '.vite', 'manifest.json');
|
|
226
240
|
const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
@@ -250,6 +264,9 @@ export async function createApp(options = {}) {
|
|
|
250
264
|
publicDir: ${JSON.stringify(publicDir)},
|
|
251
265
|
i18nConfig: ${JSON.stringify(config.i18n)},
|
|
252
266
|
ssrExclude: ${JSON.stringify(config.ssr?.exclude ?? [])},
|
|
267
|
+
streaming: ${JSON.stringify(config.ssr?.streaming ?? false)},
|
|
268
|
+
notFoundPage: _notFoundPage || undefined,
|
|
269
|
+
colorModeScript: ${JSON.stringify(colorModeScript)},
|
|
253
270
|
...options
|
|
254
271
|
});
|
|
255
272
|
|
|
@@ -441,7 +458,7 @@ async function buildProduction(options) {
|
|
|
441
458
|
}));
|
|
442
459
|
if (!userViteConfig) {
|
|
443
460
|
builtinPlugins.push(ubeanPlugin({ config }));
|
|
444
|
-
if (hasPages) builtinPlugins.push(...
|
|
461
|
+
if (hasPages) builtinPlugins.push(...ubeanVite({ config }), ubeanIslandsPlugin());
|
|
445
462
|
}
|
|
446
463
|
const { plugins } = await resolveModules({
|
|
447
464
|
cwd,
|
|
@@ -547,7 +564,7 @@ async function buildProduction(options) {
|
|
|
547
564
|
sourcemap,
|
|
548
565
|
rollupOptions: {
|
|
549
566
|
input: serverEntryPath,
|
|
550
|
-
external: presetBuildConfig.external,
|
|
567
|
+
external: presetBuildConfig.external.filter((e) => !(e instanceof RegExp && e.source.startsWith("^ubean"))),
|
|
551
568
|
output: {
|
|
552
569
|
format: presetBuildConfig.format,
|
|
553
570
|
entryFileNames: "entry.mjs",
|
|
@@ -557,7 +574,16 @@ async function buildProduction(options) {
|
|
|
557
574
|
},
|
|
558
575
|
emptyOutDir: false
|
|
559
576
|
},
|
|
560
|
-
plugins: [...plugins
|
|
577
|
+
plugins: [...plugins, {
|
|
578
|
+
name: "ubean:islands-ssr-stub",
|
|
579
|
+
enforce: "pre",
|
|
580
|
+
resolveId(id) {
|
|
581
|
+
if (id === "virtual:ubean-islands-registry") return "\0virtual:ubean-islands-registry";
|
|
582
|
+
},
|
|
583
|
+
load(id) {
|
|
584
|
+
if (id === "\0virtual:ubean-islands-registry") return "export const islands = {};";
|
|
585
|
+
}
|
|
586
|
+
}],
|
|
561
587
|
resolve: commonResolve
|
|
562
588
|
});
|
|
563
589
|
serverEntry = "entry.mjs";
|
|
@@ -600,7 +626,7 @@ assets = { directory = "./public" }
|
|
|
600
626
|
preset: preset.name || "standard"
|
|
601
627
|
};
|
|
602
628
|
await writeFile(join(outDirs.root, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
|
|
603
|
-
logger.
|
|
629
|
+
logger.info(`Build complete! Output: ${outDirs.root}`);
|
|
604
630
|
if (hasPages) logger.info(` Client assets: ${outDirs.public}`);
|
|
605
631
|
if (hasServer) {
|
|
606
632
|
logger.info(` Server bundle: ${outDirs.server}`);
|
|
@@ -1,175 +1,5 @@
|
|
|
1
|
+
import { defineVirtualModule } from "@ubean/build-core";
|
|
1
2
|
import { isAbsolute, relative } from "pathe";
|
|
2
|
-
//#region src/virtual-registry.ts
|
|
3
|
-
var VirtualModuleRegistry = class {
|
|
4
|
-
modules = /* @__PURE__ */ new Map();
|
|
5
|
-
invalidated = /* @__PURE__ */ new Set();
|
|
6
|
-
register(mod) {
|
|
7
|
-
this.modules.set(mod.id, mod);
|
|
8
|
-
}
|
|
9
|
-
resolveId(id, importer) {
|
|
10
|
-
if (this.modules.has(id)) return id;
|
|
11
|
-
for (const mod of this.modules.values()) {
|
|
12
|
-
const resolved = mod.resolve(id, importer);
|
|
13
|
-
if (resolved) return resolved;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
async load(id) {
|
|
17
|
-
const mod = this.modules.get(id);
|
|
18
|
-
if (!mod) return void 0;
|
|
19
|
-
return mod.load();
|
|
20
|
-
}
|
|
21
|
-
invalidate(id) {
|
|
22
|
-
this.invalidated.add(id);
|
|
23
|
-
}
|
|
24
|
-
isInvalidated(id) {
|
|
25
|
-
return this.invalidated.has(id);
|
|
26
|
-
}
|
|
27
|
-
clearInvalidated() {
|
|
28
|
-
this.invalidated.clear();
|
|
29
|
-
}
|
|
30
|
-
getModules() {
|
|
31
|
-
return [...this.modules.values()];
|
|
32
|
-
}
|
|
33
|
-
clear() {
|
|
34
|
-
this.modules.clear();
|
|
35
|
-
this.invalidated.clear();
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
let _registry = null;
|
|
39
|
-
function useVirtualRegistry() {
|
|
40
|
-
if (!_registry) _registry = new VirtualModuleRegistry();
|
|
41
|
-
return _registry;
|
|
42
|
-
}
|
|
43
|
-
function resetVirtualRegistry() {
|
|
44
|
-
_registry = null;
|
|
45
|
-
}
|
|
46
|
-
function defineVirtualModule(id, loader) {
|
|
47
|
-
return {
|
|
48
|
-
id,
|
|
49
|
-
resolve(resolvedId) {
|
|
50
|
-
return resolvedId === id ? id : void 0;
|
|
51
|
-
},
|
|
52
|
-
load: loader
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
function defineVirtualModulePrefix(prefix, loader) {
|
|
56
|
-
return {
|
|
57
|
-
id: prefix,
|
|
58
|
-
resolve(id) {
|
|
59
|
-
if (id.startsWith(prefix)) return id;
|
|
60
|
-
},
|
|
61
|
-
load(id) {
|
|
62
|
-
return loader(id || prefix);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
//#endregion
|
|
67
|
-
//#region src/macros.ts
|
|
68
|
-
const MACRO_NAMES = ["definePage"];
|
|
69
|
-
function findBalancedCall(code, funcName, startSearch = 0) {
|
|
70
|
-
const pattern = new RegExp(`\\b${funcName}\\s*\\(`, "g");
|
|
71
|
-
pattern.lastIndex = startSearch;
|
|
72
|
-
const match = pattern.exec(code);
|
|
73
|
-
if (!match) return null;
|
|
74
|
-
const startIdx = match.index;
|
|
75
|
-
const parenStart = match.index + match[0].length;
|
|
76
|
-
let depth = 1;
|
|
77
|
-
let i = parenStart;
|
|
78
|
-
let inString = null;
|
|
79
|
-
let escaped = false;
|
|
80
|
-
let inTemplateExpr = 0;
|
|
81
|
-
while (i < code.length && depth > 0) {
|
|
82
|
-
const ch = code[i];
|
|
83
|
-
if (escaped) {
|
|
84
|
-
escaped = false;
|
|
85
|
-
i++;
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
if (ch === "\\") {
|
|
89
|
-
escaped = true;
|
|
90
|
-
i++;
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
if (inString) {
|
|
94
|
-
if (inString === "`" && ch === "$" && code[i + 1] === "{") {
|
|
95
|
-
inTemplateExpr++;
|
|
96
|
-
i += 2;
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
if (inString === "`" && ch === "}" && inTemplateExpr > 0) {
|
|
100
|
-
inTemplateExpr--;
|
|
101
|
-
i++;
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
if (ch === inString) inString = null;
|
|
105
|
-
i++;
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
if (ch === "\"" || ch === "'" || ch === "`") {
|
|
109
|
-
inString = ch;
|
|
110
|
-
i++;
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
if (ch === "/" && code[i + 1] === "/") {
|
|
114
|
-
while (i < code.length && code[i] !== "\n") i++;
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
if (ch === "/" && code[i + 1] === "*") {
|
|
118
|
-
i += 2;
|
|
119
|
-
while (i < code.length && !(code[i] === "*" && code[i + 1] === "/")) i++;
|
|
120
|
-
i += 2;
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
if (ch === "(" || ch === "{" || ch === "[") depth++;
|
|
124
|
-
else if (ch === ")" || ch === "}" || ch === "]") {
|
|
125
|
-
depth--;
|
|
126
|
-
if (depth === 0 && ch === ")") return {
|
|
127
|
-
start: startIdx,
|
|
128
|
-
end: i + 1
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
i++;
|
|
132
|
-
}
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
function stripStatement(code, callStart, callEnd) {
|
|
136
|
-
let start = callStart;
|
|
137
|
-
let end = callEnd;
|
|
138
|
-
while (start > 0 && /[ \t]/.test(code[start - 1])) start--;
|
|
139
|
-
const exportDefaultMatch = code.slice(0, start).match(/export\s+default\s*$/);
|
|
140
|
-
if (exportDefaultMatch) {
|
|
141
|
-
start -= exportDefaultMatch[0].length;
|
|
142
|
-
while (start > 0 && /[ \t\n\r]/.test(code[start - 1])) start--;
|
|
143
|
-
}
|
|
144
|
-
if (code[end] === ";") end++;
|
|
145
|
-
while (end < code.length && /[ \t]/.test(code[end])) end++;
|
|
146
|
-
return code.slice(0, start) + code.slice(end);
|
|
147
|
-
}
|
|
148
|
-
function stripMacros(code, macros = MACRO_NAMES) {
|
|
149
|
-
let result = code;
|
|
150
|
-
for (const macro of macros) {
|
|
151
|
-
let offset = 0;
|
|
152
|
-
while (true) {
|
|
153
|
-
const found = findBalancedCall(result, macro, offset);
|
|
154
|
-
if (!found) break;
|
|
155
|
-
result = stripStatement(result, found.start, found.end);
|
|
156
|
-
offset = found.start;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return result;
|
|
160
|
-
}
|
|
161
|
-
function transformMacros(code, id) {
|
|
162
|
-
if (!(id.includes("/src/pages/") || id.includes("/src/routes/") || id.includes("/src/middleware/"))) return null;
|
|
163
|
-
if (id.endsWith(".vue")) return transformVueMacros(code);
|
|
164
|
-
if (/\.(ts|js|mjs|mts|tsx|jsx)$/.test(id)) return stripMacros(code);
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
function transformVueMacros(code) {
|
|
168
|
-
return code.replace(/<script([^>]*)>([\s\S]*?)<\/script>/g, (_match, attrs, content) => {
|
|
169
|
-
return `<script${attrs}>${stripMacros(content)}<\/script>`;
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
//#endregion
|
|
173
3
|
//#region src/virtual-modules.ts
|
|
174
4
|
function toVitePath(p) {
|
|
175
5
|
return p.replace(/\\/g, "/");
|
|
@@ -266,7 +96,7 @@ export default { routeLoaders, middlewareLoaders, pageLoaders, apiRoutes, middle
|
|
|
266
96
|
}
|
|
267
97
|
function createLocalesVirtualModule(_locales, defaultLocale, srcDir = "src") {
|
|
268
98
|
return defineVirtualModule("ubean:locales", () => {
|
|
269
|
-
const defaultCode = JSON.stringify(defaultLocale);
|
|
99
|
+
const defaultCode = defaultLocale == null ? "null" : JSON.stringify(defaultLocale);
|
|
270
100
|
const viteSrcDir = toVitePath(srcDir);
|
|
271
101
|
const prefix = viteSrcDir === "/" || viteSrcDir === "" ? "" : viteSrcDir;
|
|
272
102
|
return `
|
|
@@ -414,4 +244,4 @@ if (import.meta.hot) {
|
|
|
414
244
|
});
|
|
415
245
|
}
|
|
416
246
|
//#endregion
|
|
417
|
-
export { createRoutingVirtualModule as a,
|
|
247
|
+
export { createRoutingVirtualModule as a, createPagesVirtualModule as i, createLocalesVirtualModule as n, createMetaVirtualModule as r, createAppVirtualModule as t };
|
package/dist/vite.d.ts
CHANGED
|
@@ -16,10 +16,10 @@ interface UbeanPluginOptions {
|
|
|
16
16
|
* - 虚拟模块(`ubean:routes`、`ubean:pages`、`ubean:meta`、`ubean:app-config`、`ubean:locales`)
|
|
17
17
|
* - 宏转换(`definePage` / `defineMeta` 在 `.ts` / `.vue` 中被剥离)
|
|
18
18
|
* - 文件监听(dev 模式下扫描 `routes` / `middleware` / `pages` / `layouts` / `plugins` / `locales`)
|
|
19
|
-
* - 实体路由文件生成(当 `routing.mode` 为 `'file'` 或 `'both'` 时触发 `@ubean/
|
|
19
|
+
* - 实体路由文件生成(当 `routing.mode` 为 `'file'` 或 `'both'` 时触发 `@ubean/vue/generator`)
|
|
20
20
|
*
|
|
21
21
|
* Vue 专属的虚拟模块(`virtual:ubean-pages`、`virtual:ubean-app` 等)由 `@ubean/vite` 的
|
|
22
|
-
* `
|
|
22
|
+
* `ubeanVite` 提供,二者共用 `useVirtualRegistry()` 注册表。
|
|
23
23
|
*
|
|
24
24
|
* @example 在 vite.config.ts 中使用(自动加载 ubean.config)
|
|
25
25
|
* ```typescript
|
package/dist/vite.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { a as createRoutingVirtualModule,
|
|
1
|
+
import { a as createRoutingVirtualModule, i as createPagesVirtualModule, n as createLocalesVirtualModule, r as createMetaVirtualModule, t as createAppVirtualModule } from "./virtual-modules-BDgTqx3t.js";
|
|
2
|
+
import { transformMacros, useVirtualRegistry } from "@ubean/build-core";
|
|
2
3
|
import { join, relative, resolve } from "pathe";
|
|
3
4
|
import { loadUbeanConfig, tryGetConfig } from "@ubean/config";
|
|
4
|
-
import {
|
|
5
|
+
import { createServerRouter } from "@ubean/routes";
|
|
6
|
+
import { scanProject } from "@ubean/scan";
|
|
5
7
|
//#region src/vite.ts
|
|
6
8
|
const VIRTUAL_MODULES = [
|
|
7
9
|
"ubean:routes",
|
|
@@ -18,10 +20,10 @@ const VIRTUAL_PREFIX = "\0ubean:";
|
|
|
18
20
|
* - 虚拟模块(`ubean:routes`、`ubean:pages`、`ubean:meta`、`ubean:app-config`、`ubean:locales`)
|
|
19
21
|
* - 宏转换(`definePage` / `defineMeta` 在 `.ts` / `.vue` 中被剥离)
|
|
20
22
|
* - 文件监听(dev 模式下扫描 `routes` / `middleware` / `pages` / `layouts` / `plugins` / `locales`)
|
|
21
|
-
* - 实体路由文件生成(当 `routing.mode` 为 `'file'` 或 `'both'` 时触发 `@ubean/
|
|
23
|
+
* - 实体路由文件生成(当 `routing.mode` 为 `'file'` 或 `'both'` 时触发 `@ubean/vue/generator`)
|
|
22
24
|
*
|
|
23
25
|
* Vue 专属的虚拟模块(`virtual:ubean-pages`、`virtual:ubean-app` 等)由 `@ubean/vite` 的
|
|
24
|
-
* `
|
|
26
|
+
* `ubeanVite` 提供,二者共用 `useVirtualRegistry()` 注册表。
|
|
25
27
|
*
|
|
26
28
|
* @example 在 vite.config.ts 中使用(自动加载 ubean.config)
|
|
27
29
|
* ```typescript
|
|
@@ -107,7 +109,6 @@ function ubeanPlugin(options) {
|
|
|
107
109
|
event: "ubean:locale-update",
|
|
108
110
|
data: { file }
|
|
109
111
|
});
|
|
110
|
-
else server.ws.send({ type: "full-reload" });
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
114
|
}
|
|
@@ -120,7 +121,7 @@ function ubeanPlugin(options) {
|
|
|
120
121
|
dirs: ubeanConfig.dir,
|
|
121
122
|
ignore: ubeanConfig.scanOptions?.ignore
|
|
122
123
|
});
|
|
123
|
-
const router =
|
|
124
|
+
const router = createServerRouter();
|
|
124
125
|
for (const mw of result.middlewares) router.addMiddleware(mw);
|
|
125
126
|
for (const route of result.apiRoutes) router.addApiRoute(route);
|
|
126
127
|
for (const page of result.pages) router.addPage(page);
|
|
@@ -162,15 +163,15 @@ function ubeanPlugin(options) {
|
|
|
162
163
|
* - `'file'`:额外生成 `routes.ts`/`imports.ts` 到 `outputDir`(实体文件,可编辑 `meta`)
|
|
163
164
|
* - `'both'`:同 `'file'`,且虚拟模块也加载实体文件
|
|
164
165
|
*
|
|
165
|
-
* `typed-router.d.ts` 包含 `@ubean/
|
|
166
|
+
* `typed-router.d.ts` 包含 `@ubean/scan` 和 `vue-router`/`vue-router/auto-routes`
|
|
166
167
|
* 的模块增强(让 `useRoute<Name>(name)` 能推断 `route.params` 类型),所有模式
|
|
167
168
|
* 都会生成到 `.ubean/typed-router.d.ts`,与 `auto-imports.d.ts`/`components.d.ts`
|
|
168
169
|
* 等其他纯类型声明产物同目录,由 `.gitignore` 忽略。
|
|
169
170
|
*
|
|
170
|
-
* 由于 `@ubean/
|
|
171
|
+
* 由于 `@ubean/vue/generator` 通过动态 import 加载,前端-only 项目
|
|
171
172
|
* (不依赖实体路由文件)即使没有安装 generator 相关依赖也能运行。
|
|
172
173
|
*
|
|
173
|
-
* 注意:`@ubean/config` 与 `@ubean/
|
|
174
|
+
* 注意:`@ubean/config` 与 `@ubean/vue/generator` 的 `getRouteMeta` /
|
|
174
175
|
* `onGenerated` 签名略有差异(配置层面向用户,生成器层面向内部)。本函数
|
|
175
176
|
* 负责适配:把 `(filePath, frontmatter) => meta` 包装为 `(page) => meta`,
|
|
176
177
|
* 把 `GeneratorResult` 转换为 `string[]` 文件路径列表。
|
|
@@ -183,7 +184,7 @@ async function maybeGenerateRouteFiles(config, scanResult) {
|
|
|
183
184
|
const dtsPath = resolve(config.rootDir, ".ubean", "typed-router.d.ts");
|
|
184
185
|
const configGetRouteMeta = routing.getRouteMeta;
|
|
185
186
|
const generatorGetRouteMeta = configGetRouteMeta ? (page) => configGetRouteMeta(page.relativePath, page.frontmatter ?? {}) : void 0;
|
|
186
|
-
const { generateRouteFiles } = await import("@ubean/
|
|
187
|
+
const { generateRouteFiles } = await import("@ubean/vue/generator");
|
|
187
188
|
const result = await generateRouteFiles(scanResult, {
|
|
188
189
|
cwd: config.rootDir,
|
|
189
190
|
srcDir: config.srcDir,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ubean/build",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Core Vite plugin (framework-agnostic) for ubean (ubeanPlugin, virtual modules: routes/pages/meta/app-config/locales, macros)",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -25,26 +25,30 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@vitejs/plugin-vue": "^6.0.8",
|
|
28
|
-
"
|
|
29
|
-
"oxc-transform": "^0.142.0",
|
|
28
|
+
"oxc-transform": "^0.144.0",
|
|
30
29
|
"pathe": "^2.0.3",
|
|
31
|
-
"@ubean/
|
|
32
|
-
"@ubean/
|
|
33
|
-
"@ubean/
|
|
34
|
-
"@ubean/
|
|
35
|
-
"@ubean/
|
|
36
|
-
"@ubean/
|
|
37
|
-
"@ubean/
|
|
38
|
-
"@ubean/
|
|
30
|
+
"@ubean/build-core": "0.2.0",
|
|
31
|
+
"@ubean/logger": "0.2.0",
|
|
32
|
+
"@ubean/client": "0.2.0",
|
|
33
|
+
"@ubean/islands": "0.2.0",
|
|
34
|
+
"@ubean/config": "0.2.0",
|
|
35
|
+
"@ubean/preset": "0.2.0",
|
|
36
|
+
"@ubean/modules": "0.2.0",
|
|
37
|
+
"@ubean/routes": "0.2.0",
|
|
38
|
+
"@ubean/scan": "0.2.0",
|
|
39
|
+
"@ubean/ssr": "0.2.0",
|
|
40
|
+
"@ubean/shared": "0.2.0",
|
|
41
|
+
"@ubean/vue": "0.2.0",
|
|
42
|
+
"@ubean/vite": "0.2.0"
|
|
39
43
|
},
|
|
40
44
|
"devDependencies": {
|
|
41
|
-
"@types/node": "^26.
|
|
45
|
+
"@types/node": "^26.2.0",
|
|
42
46
|
"typescript": "7.0.2",
|
|
43
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.
|
|
44
|
-
"vite-plus": "0.2.
|
|
47
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.9",
|
|
48
|
+
"vite-plus": "0.2.9"
|
|
45
49
|
},
|
|
46
50
|
"peerDependencies": {
|
|
47
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.
|
|
51
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.9"
|
|
48
52
|
},
|
|
49
53
|
"peerDependenciesMeta": {
|
|
50
54
|
"vite": {
|
|
@@ -54,6 +58,7 @@
|
|
|
54
58
|
"scripts": {
|
|
55
59
|
"build": "vp pack",
|
|
56
60
|
"dev": "vp pack --watch",
|
|
61
|
+
"test": "vp test",
|
|
57
62
|
"typecheck": "tsc --noEmit --skipLibCheck"
|
|
58
63
|
}
|
|
59
64
|
}
|