@ubean/build 0.1.13 → 0.2.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.
- package/dist/index.d.ts +8 -89
- package/dist/index.js +2 -51
- package/dist/production.d.ts +1 -1
- package/dist/production.js +29 -12
- 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 -9
- 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",
|
|
@@ -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,
|
|
@@ -119,6 +124,7 @@ async function generateVirtualModulesToDisk(cwd, config, scanResult, virtualDir)
|
|
|
119
124
|
layout: scanResult.notFoundPage.layout,
|
|
120
125
|
pageMeta: scanResult.notFoundPage.pageMeta
|
|
121
126
|
} : null);
|
|
127
|
+
const colorModeScript = config.colorMode !== false ? getColorModeScript(resolveColorModeConfig(config.colorMode)) : "";
|
|
122
128
|
const rendererImport = ssrEnabled ? `import { createVueRenderer } from 'ubean/vue-ssr';` : "";
|
|
123
129
|
const rendererSetup = ssrEnabled ? `
|
|
124
130
|
// --- SSR renderer setup ---
|
|
@@ -258,7 +264,9 @@ export async function createApp(options = {}) {
|
|
|
258
264
|
publicDir: ${JSON.stringify(publicDir)},
|
|
259
265
|
i18nConfig: ${JSON.stringify(config.i18n)},
|
|
260
266
|
ssrExclude: ${JSON.stringify(config.ssr?.exclude ?? [])},
|
|
267
|
+
streaming: ${JSON.stringify(config.ssr?.streaming ?? false)},
|
|
261
268
|
notFoundPage: _notFoundPage || undefined,
|
|
269
|
+
colorModeScript: ${JSON.stringify(colorModeScript)},
|
|
262
270
|
...options
|
|
263
271
|
});
|
|
264
272
|
|
|
@@ -450,7 +458,7 @@ async function buildProduction(options) {
|
|
|
450
458
|
}));
|
|
451
459
|
if (!userViteConfig) {
|
|
452
460
|
builtinPlugins.push(ubeanPlugin({ config }));
|
|
453
|
-
if (hasPages) builtinPlugins.push(...
|
|
461
|
+
if (hasPages) builtinPlugins.push(...ubeanVite({ config }), ubeanIslandsPlugin());
|
|
454
462
|
}
|
|
455
463
|
const { plugins } = await resolveModules({
|
|
456
464
|
cwd,
|
|
@@ -556,7 +564,7 @@ async function buildProduction(options) {
|
|
|
556
564
|
sourcemap,
|
|
557
565
|
rollupOptions: {
|
|
558
566
|
input: serverEntryPath,
|
|
559
|
-
external: presetBuildConfig.external,
|
|
567
|
+
external: presetBuildConfig.external.filter((e) => !(e instanceof RegExp && e.source.startsWith("^ubean"))),
|
|
560
568
|
output: {
|
|
561
569
|
format: presetBuildConfig.format,
|
|
562
570
|
entryFileNames: "entry.mjs",
|
|
@@ -566,7 +574,16 @@ async function buildProduction(options) {
|
|
|
566
574
|
},
|
|
567
575
|
emptyOutDir: false
|
|
568
576
|
},
|
|
569
|
-
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
|
+
}],
|
|
570
587
|
resolve: commonResolve
|
|
571
588
|
});
|
|
572
589
|
serverEntry = "entry.mjs";
|
|
@@ -609,7 +626,7 @@ assets = { directory = "./public" }
|
|
|
609
626
|
preset: preset.name || "standard"
|
|
610
627
|
};
|
|
611
628
|
await writeFile(join(outDirs.root, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
|
|
612
|
-
logger.
|
|
629
|
+
logger.info(`Build complete! Output: ${outDirs.root}`);
|
|
613
630
|
if (hasPages) logger.info(` Client assets: ${outDirs.public}`);
|
|
614
631
|
if (hasServer) {
|
|
615
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
|
|
@@ -119,7 +121,7 @@ function ubeanPlugin(options) {
|
|
|
119
121
|
dirs: ubeanConfig.dir,
|
|
120
122
|
ignore: ubeanConfig.scanOptions?.ignore
|
|
121
123
|
});
|
|
122
|
-
const router =
|
|
124
|
+
const router = createServerRouter();
|
|
123
125
|
for (const mw of result.middlewares) router.addMiddleware(mw);
|
|
124
126
|
for (const route of result.apiRoutes) router.addApiRoute(route);
|
|
125
127
|
for (const page of result.pages) router.addPage(page);
|
|
@@ -161,15 +163,15 @@ function ubeanPlugin(options) {
|
|
|
161
163
|
* - `'file'`:额外生成 `routes.ts`/`imports.ts` 到 `outputDir`(实体文件,可编辑 `meta`)
|
|
162
164
|
* - `'both'`:同 `'file'`,且虚拟模块也加载实体文件
|
|
163
165
|
*
|
|
164
|
-
* `typed-router.d.ts` 包含 `@ubean/
|
|
166
|
+
* `typed-router.d.ts` 包含 `@ubean/scan` 和 `vue-router`/`vue-router/auto-routes`
|
|
165
167
|
* 的模块增强(让 `useRoute<Name>(name)` 能推断 `route.params` 类型),所有模式
|
|
166
168
|
* 都会生成到 `.ubean/typed-router.d.ts`,与 `auto-imports.d.ts`/`components.d.ts`
|
|
167
169
|
* 等其他纯类型声明产物同目录,由 `.gitignore` 忽略。
|
|
168
170
|
*
|
|
169
|
-
* 由于 `@ubean/
|
|
171
|
+
* 由于 `@ubean/vue/generator` 通过动态 import 加载,前端-only 项目
|
|
170
172
|
* (不依赖实体路由文件)即使没有安装 generator 相关依赖也能运行。
|
|
171
173
|
*
|
|
172
|
-
* 注意:`@ubean/config` 与 `@ubean/
|
|
174
|
+
* 注意:`@ubean/config` 与 `@ubean/vue/generator` 的 `getRouteMeta` /
|
|
173
175
|
* `onGenerated` 签名略有差异(配置层面向用户,生成器层面向内部)。本函数
|
|
174
176
|
* 负责适配:把 `(filePath, frontmatter) => meta` 包装为 `(page) => meta`,
|
|
175
177
|
* 把 `GeneratorResult` 转换为 `string[]` 文件路径列表。
|
|
@@ -182,7 +184,7 @@ async function maybeGenerateRouteFiles(config, scanResult) {
|
|
|
182
184
|
const dtsPath = resolve(config.rootDir, ".ubean", "typed-router.d.ts");
|
|
183
185
|
const configGetRouteMeta = routing.getRouteMeta;
|
|
184
186
|
const generatorGetRouteMeta = configGetRouteMeta ? (page) => configGetRouteMeta(page.relativePath, page.frontmatter ?? {}) : void 0;
|
|
185
|
-
const { generateRouteFiles } = await import("@ubean/
|
|
187
|
+
const { generateRouteFiles } = await import("@ubean/vue/generator");
|
|
186
188
|
const result = await generateRouteFiles(scanResult, {
|
|
187
189
|
cwd: config.rootDir,
|
|
188
190
|
srcDir: config.srcDir,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ubean/build",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
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.146.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.1",
|
|
31
|
+
"@ubean/client": "0.2.1",
|
|
32
|
+
"@ubean/islands": "0.2.1",
|
|
33
|
+
"@ubean/logger": "0.2.1",
|
|
34
|
+
"@ubean/config": "0.2.1",
|
|
35
|
+
"@ubean/modules": "0.2.1",
|
|
36
|
+
"@ubean/preset": "0.2.1",
|
|
37
|
+
"@ubean/routes": "0.2.1",
|
|
38
|
+
"@ubean/scan": "0.2.1",
|
|
39
|
+
"@ubean/shared": "0.2.1",
|
|
40
|
+
"@ubean/ssr": "0.2.1",
|
|
41
|
+
"@ubean/vite": "0.2.1",
|
|
42
|
+
"@ubean/vue": "0.2.1"
|
|
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
|
}
|