@halo-dev/ui-plugin-bundler-kit 2.23.0 → 2.25.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/README.md +85 -13
- package/dist/index.d.mts +16 -4
- package/dist/index.mjs +118 -11
- package/package.json +12 -8
- package/src/__tests__/halo-plugin.spec.ts +102 -0
- package/src/__tests__/legacy.spec.ts +128 -0
- package/src/__tests__/provider.spec.ts +301 -0
- package/src/constants/build.ts +12 -1
- package/src/constants/externals.ts +1 -0
- package/src/constants/halo-plugin.ts +8 -2
- package/src/rsbuild.ts +79 -11
- package/src/utils/halo-plugin.ts +60 -4
- package/src/vite.ts +79 -10
- package/vite.config.ts +11 -0
- package/tsdown.config.ts +0 -10
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import type { ConfigParams, RsbuildConfig } from "@rsbuild/core";
|
|
5
|
+
import type { ConfigEnv, UserConfig } from "vite";
|
|
6
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
7
|
+
import { rsbuildConfig } from "../rsbuild";
|
|
8
|
+
import { viteConfig } from "../vite";
|
|
9
|
+
|
|
10
|
+
const originalCwd = process.cwd();
|
|
11
|
+
const tempDirs: string[] = [];
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
process.chdir(originalCwd);
|
|
15
|
+
while (tempDirs.length > 0) {
|
|
16
|
+
const tempDir = tempDirs.pop();
|
|
17
|
+
if (tempDir) {
|
|
18
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe("provider defaults", () => {
|
|
24
|
+
it("keeps plugin provider defaults when provider is omitted", () => {
|
|
25
|
+
const uiDir = setupPluginProject();
|
|
26
|
+
process.chdir(uiDir);
|
|
27
|
+
|
|
28
|
+
const vite = resolveViteConfig(viteConfig({ vite: {} }), "development");
|
|
29
|
+
expect(vite.base).toBeUndefined();
|
|
30
|
+
expect(vite.build?.outDir).toBe("../build/resources/main/ui");
|
|
31
|
+
expect(vite.build?.lib).toMatchObject({
|
|
32
|
+
entry: "src/index.ts",
|
|
33
|
+
name: "fake-plugin",
|
|
34
|
+
formats: ["iife"],
|
|
35
|
+
cssFileName: "style",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const rsbuild = resolveRsbuildConfig(
|
|
39
|
+
rsbuildConfig({ rsbuild: {} }),
|
|
40
|
+
"development"
|
|
41
|
+
);
|
|
42
|
+
expect(rsbuild.output?.distPath?.root).toBe("../build/resources/main/ui");
|
|
43
|
+
expect(rsbuild.tools?.rspack?.output?.publicPath).toBe(
|
|
44
|
+
"/plugins/fake-plugin/assets/ui/"
|
|
45
|
+
);
|
|
46
|
+
expect(rsbuild.tools?.rspack?.output?.library).toMatchObject({
|
|
47
|
+
type: "window",
|
|
48
|
+
export: "default",
|
|
49
|
+
name: "fake-plugin",
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const productionVite = resolveViteConfig(viteConfig({ vite: {} }));
|
|
53
|
+
expect(productionVite.build?.outDir).toBe("./build/dist");
|
|
54
|
+
|
|
55
|
+
const productionRsbuild = resolveRsbuildConfig(
|
|
56
|
+
rsbuildConfig({ rsbuild: {} })
|
|
57
|
+
);
|
|
58
|
+
expect(productionRsbuild.output?.distPath?.root).toBe("./build/dist");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("keeps plugin provider defaults when provider is explicit", () => {
|
|
62
|
+
const uiDir = setupPluginProject();
|
|
63
|
+
process.chdir(uiDir);
|
|
64
|
+
|
|
65
|
+
const vite = resolveViteConfig(
|
|
66
|
+
viteConfig({ provider: "plugin", vite: {} }),
|
|
67
|
+
"development"
|
|
68
|
+
);
|
|
69
|
+
expect(vite.build?.outDir).toBe("../build/resources/main/ui");
|
|
70
|
+
|
|
71
|
+
const rsbuild = resolveRsbuildConfig(
|
|
72
|
+
rsbuildConfig({ provider: "plugin", rsbuild: {} }),
|
|
73
|
+
"development"
|
|
74
|
+
);
|
|
75
|
+
expect(rsbuild.tools?.rspack?.output?.publicPath).toBe(
|
|
76
|
+
"/plugins/fake-plugin/assets/ui/"
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("uses custom manifest paths for plugin and theme providers", () => {
|
|
81
|
+
const projectRoot = createTempDir();
|
|
82
|
+
const pluginManifestPath = path.join(projectRoot, "custom-plugin.yaml");
|
|
83
|
+
const themeManifestPath = path.join(projectRoot, "custom-theme.yaml");
|
|
84
|
+
fs.writeFileSync(
|
|
85
|
+
pluginManifestPath,
|
|
86
|
+
[
|
|
87
|
+
"metadata:",
|
|
88
|
+
" name: custom-plugin",
|
|
89
|
+
"spec:",
|
|
90
|
+
" requires: '>=2.25.0'",
|
|
91
|
+
"",
|
|
92
|
+
].join("\n")
|
|
93
|
+
);
|
|
94
|
+
fs.writeFileSync(
|
|
95
|
+
themeManifestPath,
|
|
96
|
+
["metadata:", " name: custom-theme", ""].join("\n")
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const pluginConfig = resolveViteConfig(
|
|
100
|
+
viteConfig({
|
|
101
|
+
manifestPath: pluginManifestPath,
|
|
102
|
+
vite: {},
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
expect(pluginConfig.build?.lib).toMatchObject({
|
|
106
|
+
name: "custom-plugin",
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const themeConfig = resolveRsbuildConfig(
|
|
110
|
+
rsbuildConfig({
|
|
111
|
+
provider: "theme",
|
|
112
|
+
manifestPath: themeManifestPath,
|
|
113
|
+
rsbuild: {},
|
|
114
|
+
})
|
|
115
|
+
);
|
|
116
|
+
expect(themeConfig.tools?.rspack?.output?.publicPath).toBe(
|
|
117
|
+
"/themes/custom-theme/ui-plugin/assets/"
|
|
118
|
+
);
|
|
119
|
+
expect(themeConfig.tools?.rspack?.output?.library).toMatchObject({
|
|
120
|
+
name: "theme:custom-theme",
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("generates Vite theme provider defaults", () => {
|
|
125
|
+
const uiPluginDir = setupThemeProject();
|
|
126
|
+
process.chdir(uiPluginDir);
|
|
127
|
+
|
|
128
|
+
const config = resolveViteConfig(
|
|
129
|
+
viteConfig({ provider: "theme", vite: {} })
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
expect(config.base).toBe("/themes/earth/ui-plugin/assets/");
|
|
133
|
+
expect(config.build?.outDir).toBe("dist");
|
|
134
|
+
expect(config.build?.lib).toMatchObject({
|
|
135
|
+
entry: "src/index.ts",
|
|
136
|
+
name: "theme:earth",
|
|
137
|
+
formats: ["iife"],
|
|
138
|
+
cssFileName: "style",
|
|
139
|
+
});
|
|
140
|
+
expect(config.build?.rollupOptions?.external).toContain("vue");
|
|
141
|
+
expect(config.build?.rollupOptions?.output).toMatchObject({
|
|
142
|
+
globals: expect.objectContaining({
|
|
143
|
+
vue: "Vue",
|
|
144
|
+
}),
|
|
145
|
+
extend: true,
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("generates Rsbuild theme provider defaults", () => {
|
|
150
|
+
const uiPluginDir = setupThemeProject();
|
|
151
|
+
process.chdir(uiPluginDir);
|
|
152
|
+
|
|
153
|
+
const config = resolveRsbuildConfig(
|
|
154
|
+
rsbuildConfig({ provider: "theme", rsbuild: {} })
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
expect(config.output?.distPath?.root).toBe("dist");
|
|
158
|
+
expect(config.output?.filename?.js).toBeDefined();
|
|
159
|
+
expect(config.output?.filename?.css).toBeDefined();
|
|
160
|
+
expect(config.output?.externals).toMatchObject({
|
|
161
|
+
vue: "Vue",
|
|
162
|
+
});
|
|
163
|
+
expect(config.tools?.rspack?.output?.publicPath).toBe(
|
|
164
|
+
"/themes/earth/ui-plugin/assets/"
|
|
165
|
+
);
|
|
166
|
+
expect(config.tools?.rspack?.output?.library).toMatchObject({
|
|
167
|
+
type: "window",
|
|
168
|
+
export: "default",
|
|
169
|
+
name: "theme:earth",
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("merges user config after provider defaults", () => {
|
|
174
|
+
const uiPluginDir = setupThemeProject();
|
|
175
|
+
process.chdir(uiPluginDir);
|
|
176
|
+
|
|
177
|
+
const vite = resolveViteConfig(
|
|
178
|
+
viteConfig({
|
|
179
|
+
provider: "theme",
|
|
180
|
+
vite: {
|
|
181
|
+
base: "/custom/",
|
|
182
|
+
build: {
|
|
183
|
+
outDir: "custom-dist",
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
})
|
|
187
|
+
);
|
|
188
|
+
expect(vite.base).toBe("/custom/");
|
|
189
|
+
expect(vite.build?.outDir).toBe("custom-dist");
|
|
190
|
+
|
|
191
|
+
const rsbuild = resolveRsbuildConfig(
|
|
192
|
+
rsbuildConfig({
|
|
193
|
+
provider: "theme",
|
|
194
|
+
rsbuild: {
|
|
195
|
+
output: {
|
|
196
|
+
distPath: {
|
|
197
|
+
root: "custom-dist",
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
tools: {
|
|
201
|
+
rspack: {
|
|
202
|
+
output: {
|
|
203
|
+
publicPath: "/custom/",
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
})
|
|
209
|
+
);
|
|
210
|
+
expect(rsbuild.output?.distPath?.root).toBe("custom-dist");
|
|
211
|
+
expect(rsbuild.tools?.rspack?.output?.publicPath).toBe("/custom/");
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it("merges function user config after provider defaults", () => {
|
|
215
|
+
const uiPluginDir = setupThemeProject();
|
|
216
|
+
process.chdir(uiPluginDir);
|
|
217
|
+
|
|
218
|
+
const vite = resolveViteConfig(
|
|
219
|
+
viteConfig({
|
|
220
|
+
provider: "theme",
|
|
221
|
+
vite: ({ mode }) => ({
|
|
222
|
+
define: {
|
|
223
|
+
__MODE__: JSON.stringify(mode),
|
|
224
|
+
},
|
|
225
|
+
}),
|
|
226
|
+
})
|
|
227
|
+
);
|
|
228
|
+
expect(vite.define).toMatchObject({
|
|
229
|
+
"process.env.NODE_ENV": "'production'",
|
|
230
|
+
__MODE__: '"production"',
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const rsbuild = resolveRsbuildConfig(
|
|
234
|
+
rsbuildConfig({
|
|
235
|
+
provider: "theme",
|
|
236
|
+
rsbuild: ({ envMode }) => ({
|
|
237
|
+
output: {
|
|
238
|
+
filename: {
|
|
239
|
+
js: `custom-${envMode}.js`,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
}),
|
|
243
|
+
})
|
|
244
|
+
);
|
|
245
|
+
expect(rsbuild.output?.filename?.js).toBe("custom-production.js");
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
function setupPluginProject() {
|
|
250
|
+
const projectRoot = createTempDir();
|
|
251
|
+
const uiDir = path.join(projectRoot, "ui");
|
|
252
|
+
fs.mkdirSync(path.join(projectRoot, "src/main/resources"), {
|
|
253
|
+
recursive: true,
|
|
254
|
+
});
|
|
255
|
+
fs.mkdirSync(uiDir, { recursive: true });
|
|
256
|
+
fs.writeFileSync(
|
|
257
|
+
path.join(projectRoot, "src/main/resources/plugin.yaml"),
|
|
258
|
+
[
|
|
259
|
+
"metadata:",
|
|
260
|
+
" name: fake-plugin",
|
|
261
|
+
"spec:",
|
|
262
|
+
" requires: '>=2.25.0'",
|
|
263
|
+
"",
|
|
264
|
+
].join("\n")
|
|
265
|
+
);
|
|
266
|
+
return uiDir;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function setupThemeProject() {
|
|
270
|
+
const projectRoot = createTempDir();
|
|
271
|
+
const uiPluginDir = path.join(projectRoot, "ui-plugin");
|
|
272
|
+
fs.mkdirSync(uiPluginDir, { recursive: true });
|
|
273
|
+
fs.writeFileSync(
|
|
274
|
+
path.join(projectRoot, "theme.yaml"),
|
|
275
|
+
["metadata:", " name: earth", ""].join("\n")
|
|
276
|
+
);
|
|
277
|
+
return uiPluginDir;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function createTempDir() {
|
|
281
|
+
const tempDir = fs.mkdtempSync(
|
|
282
|
+
path.join(os.tmpdir(), "halo-ui-plugin-bundler-kit-")
|
|
283
|
+
);
|
|
284
|
+
tempDirs.push(tempDir);
|
|
285
|
+
return tempDir;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function resolveViteConfig(config: unknown, mode = "production") {
|
|
289
|
+
return (config as (env: ConfigEnv) => UserConfig)({
|
|
290
|
+
command: "build",
|
|
291
|
+
mode,
|
|
292
|
+
isSsrBuild: false,
|
|
293
|
+
isPreview: false,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function resolveRsbuildConfig(config: unknown, envMode = "production") {
|
|
298
|
+
return (config as (env: ConfigParams) => RsbuildConfig)({
|
|
299
|
+
envMode,
|
|
300
|
+
} as ConfigParams);
|
|
301
|
+
}
|
package/src/constants/build.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
const DEFAULT_OUT_DIR_DEV = "../build/resources/main/console";
|
|
2
|
+
const DEFAULT_OUT_DIR_DEV_BASE = "../build/resources/main";
|
|
2
3
|
const DEFAULT_OUT_DIR_PROD = "./build/dist";
|
|
4
|
+
const DEFAULT_THEME_OUT_DIR = "dist";
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
function getDefaultOutDirDev(bundleLocation: string) {
|
|
7
|
+
return `${DEFAULT_OUT_DIR_DEV_BASE}/${bundleLocation}`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
DEFAULT_OUT_DIR_DEV,
|
|
12
|
+
DEFAULT_OUT_DIR_PROD,
|
|
13
|
+
DEFAULT_THEME_OUT_DIR,
|
|
14
|
+
getDefaultOutDirDev,
|
|
15
|
+
};
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
const
|
|
1
|
+
const DEFAULT_PLUGIN_MANIFEST_PATH = "../src/main/resources/plugin.yaml";
|
|
2
|
+
const DEFAULT_THEME_MANIFEST_PATH = "../theme.yaml";
|
|
3
|
+
const DEFAULT_MANIFEST_PATH = DEFAULT_PLUGIN_MANIFEST_PATH;
|
|
2
4
|
|
|
3
|
-
export {
|
|
5
|
+
export {
|
|
6
|
+
DEFAULT_MANIFEST_PATH,
|
|
7
|
+
DEFAULT_PLUGIN_MANIFEST_PATH,
|
|
8
|
+
DEFAULT_THEME_MANIFEST_PATH,
|
|
9
|
+
};
|
package/src/rsbuild.ts
CHANGED
|
@@ -6,16 +6,39 @@ import {
|
|
|
6
6
|
type RsbuildMode,
|
|
7
7
|
} from "@rsbuild/core";
|
|
8
8
|
import { pluginVue } from "@rsbuild/plugin-vue";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
DEFAULT_OUT_DIR_PROD,
|
|
11
|
+
DEFAULT_THEME_OUT_DIR,
|
|
12
|
+
getDefaultOutDirDev,
|
|
13
|
+
} from "./constants/build";
|
|
10
14
|
import { GLOBALS } from "./constants/externals";
|
|
11
|
-
import {
|
|
12
|
-
|
|
15
|
+
import {
|
|
16
|
+
DEFAULT_PLUGIN_MANIFEST_PATH,
|
|
17
|
+
DEFAULT_THEME_MANIFEST_PATH,
|
|
18
|
+
} from "./constants/halo-plugin";
|
|
19
|
+
import {
|
|
20
|
+
getHaloPluginBundleLocation,
|
|
21
|
+
getHaloPluginManifest,
|
|
22
|
+
getHaloThemeAssetPublicPath,
|
|
23
|
+
getHaloThemeManifest,
|
|
24
|
+
getHaloThemeModuleName,
|
|
25
|
+
getManifestName,
|
|
26
|
+
} from "./utils/halo-plugin";
|
|
27
|
+
|
|
28
|
+
type Provider = "plugin" | "theme";
|
|
13
29
|
|
|
14
30
|
export interface RsBuildUserConfig {
|
|
15
31
|
/**
|
|
16
|
-
*
|
|
32
|
+
* UI plugin provider type.
|
|
33
|
+
*
|
|
34
|
+
* @default "plugin"
|
|
35
|
+
*/
|
|
36
|
+
provider?: "plugin" | "theme";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Halo plugin or theme manifest path.
|
|
17
40
|
*
|
|
18
|
-
* @default "../src/main/resources/plugin.yaml"
|
|
41
|
+
* @default "../src/main/resources/plugin.yaml" for plugins, "../theme.yaml" for themes
|
|
19
42
|
*/
|
|
20
43
|
manifestPath?: string;
|
|
21
44
|
|
|
@@ -25,13 +48,16 @@ export interface RsBuildUserConfig {
|
|
|
25
48
|
rsbuild: RsbuildConfig | ((env: ConfigParams) => RsbuildConfig);
|
|
26
49
|
}
|
|
27
50
|
|
|
28
|
-
function createRsbuildPresetsConfig(manifestPath: string) {
|
|
29
|
-
const
|
|
51
|
+
function createRsbuildPresetsConfig(provider: Provider, manifestPath: string) {
|
|
52
|
+
const defaults =
|
|
53
|
+
provider === "theme"
|
|
54
|
+
? getThemeProviderDefaults(manifestPath)
|
|
55
|
+
: getPluginProviderDefaults(manifestPath);
|
|
30
56
|
|
|
31
57
|
return defineConfig(({ envMode }) => {
|
|
32
58
|
const isProduction = envMode === "production";
|
|
33
59
|
|
|
34
|
-
const outDir = isProduction ?
|
|
60
|
+
const outDir = isProduction ? defaults.outDir.prod : defaults.outDir.dev;
|
|
35
61
|
|
|
36
62
|
return {
|
|
37
63
|
mode: (envMode as RsbuildMode) || "production",
|
|
@@ -72,11 +98,11 @@ function createRsbuildPresetsConfig(manifestPath: string) {
|
|
|
72
98
|
},
|
|
73
99
|
},
|
|
74
100
|
output: {
|
|
75
|
-
publicPath:
|
|
101
|
+
publicPath: defaults.publicPath,
|
|
76
102
|
library: {
|
|
77
103
|
type: "window",
|
|
78
104
|
export: "default",
|
|
79
|
-
name:
|
|
105
|
+
name: defaults.moduleName,
|
|
80
106
|
},
|
|
81
107
|
globalObject: "window",
|
|
82
108
|
iife: true,
|
|
@@ -113,6 +139,46 @@ function createRsbuildPresetsConfig(manifestPath: string) {
|
|
|
113
139
|
});
|
|
114
140
|
}
|
|
115
141
|
|
|
142
|
+
function getPluginProviderDefaults(manifestPath: string) {
|
|
143
|
+
const manifest = getHaloPluginManifest(manifestPath);
|
|
144
|
+
const bundleLocation = getHaloPluginBundleLocation(manifest);
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
moduleName: getManifestName(manifest),
|
|
148
|
+
outDir: {
|
|
149
|
+
prod: DEFAULT_OUT_DIR_PROD,
|
|
150
|
+
dev: getDefaultOutDirDev(bundleLocation),
|
|
151
|
+
},
|
|
152
|
+
publicPath: `/plugins/${getManifestName(manifest)}/assets/${bundleLocation}/`,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function getThemeProviderDefaults(manifestPath: string) {
|
|
157
|
+
const manifest = getHaloThemeManifest(manifestPath);
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
moduleName: getHaloThemeModuleName(manifest),
|
|
161
|
+
outDir: {
|
|
162
|
+
prod: DEFAULT_THEME_OUT_DIR,
|
|
163
|
+
dev: DEFAULT_THEME_OUT_DIR,
|
|
164
|
+
},
|
|
165
|
+
publicPath: getHaloThemeAssetPublicPath(manifest),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function getProvider(config?: RsBuildUserConfig): Provider {
|
|
170
|
+
return config?.provider || "plugin";
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function getManifestPath(provider: Provider, config?: RsBuildUserConfig) {
|
|
174
|
+
if (config?.manifestPath) {
|
|
175
|
+
return config.manifestPath;
|
|
176
|
+
}
|
|
177
|
+
return provider === "theme"
|
|
178
|
+
? DEFAULT_THEME_MANIFEST_PATH
|
|
179
|
+
: DEFAULT_PLUGIN_MANIFEST_PATH;
|
|
180
|
+
}
|
|
181
|
+
|
|
116
182
|
/**
|
|
117
183
|
* Rsbuild config for Halo UI Plugin.
|
|
118
184
|
*
|
|
@@ -132,8 +198,10 @@ function createRsbuildPresetsConfig(manifestPath: string) {
|
|
|
132
198
|
export function rsbuildConfig(
|
|
133
199
|
config?: RsBuildUserConfig
|
|
134
200
|
): (env: ConfigParams) => RsbuildConfig {
|
|
201
|
+
const provider = getProvider(config);
|
|
135
202
|
const presetsConfigFn = createRsbuildPresetsConfig(
|
|
136
|
-
|
|
203
|
+
provider,
|
|
204
|
+
getManifestPath(provider, config)
|
|
137
205
|
);
|
|
138
206
|
return defineConfig((env) => {
|
|
139
207
|
const presetsConfig = presetsConfigFn(env);
|
package/src/utils/halo-plugin.ts
CHANGED
|
@@ -1,11 +1,67 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import type { Plugin as HaloPlugin } from "@halo-dev/api-client";
|
|
3
3
|
import yaml from "js-yaml";
|
|
4
|
+
import { gte, minVersion } from "semver";
|
|
5
|
+
|
|
6
|
+
const UI_BUNDLE_MIN_HALO_VERSION = "2.25.0";
|
|
7
|
+
const UI_BUNDLE_LOCATION = "ui";
|
|
8
|
+
const CONSOLE_BUNDLE_LOCATION = "console";
|
|
9
|
+
const THEME_MODULE_NAME_PREFIX = "theme:";
|
|
10
|
+
|
|
11
|
+
interface HaloThemeManifest {
|
|
12
|
+
metadata: {
|
|
13
|
+
name: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
4
16
|
|
|
5
17
|
export function getHaloPluginManifest(manifestPath: string) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
18
|
+
return readManifest<HaloPlugin>(manifestPath);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getHaloThemeManifest(manifestPath: string) {
|
|
22
|
+
return readManifest<HaloThemeManifest>(manifestPath);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getManifestName(
|
|
26
|
+
manifest: Pick<HaloPlugin, "metadata"> | HaloThemeManifest
|
|
27
|
+
) {
|
|
28
|
+
return manifest.metadata.name;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getHaloThemeModuleName(manifest: HaloThemeManifest) {
|
|
32
|
+
return `${THEME_MODULE_NAME_PREFIX}${getManifestName(manifest)}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getHaloThemeAssetPublicPath(manifest: HaloThemeManifest) {
|
|
36
|
+
return `/themes/${getManifestName(manifest)}/ui-plugin/assets/`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getHaloPluginBundleLocation(manifest: HaloPlugin) {
|
|
40
|
+
const requiresMinVersion = getRequiresMinVersion(manifest.spec.requires);
|
|
41
|
+
return requiresMinVersion &&
|
|
42
|
+
gte(requiresMinVersion, UI_BUNDLE_MIN_HALO_VERSION)
|
|
43
|
+
? UI_BUNDLE_LOCATION
|
|
44
|
+
: CONSOLE_BUNDLE_LOCATION;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getRequiresMinVersion(requires: string | undefined) {
|
|
48
|
+
const normalizedRequires = requires?.trim();
|
|
49
|
+
|
|
50
|
+
if (!normalizedRequires) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
return minVersion(normalizedRequires);
|
|
56
|
+
} catch {
|
|
57
|
+
console.warn(
|
|
58
|
+
`[ui-plugin-bundler-kit] Invalid semver range in plugin manifest "spec.requires": "${requires}". ` +
|
|
59
|
+
`Falling back to "${CONSOLE_BUNDLE_LOCATION}" bundle location.`
|
|
60
|
+
);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
9
64
|
|
|
10
|
-
|
|
65
|
+
function readManifest<T>(manifestPath: string) {
|
|
66
|
+
return yaml.load(fs.readFileSync(manifestPath, "utf8")) as T;
|
|
11
67
|
}
|
package/src/vite.ts
CHANGED
|
@@ -5,16 +5,39 @@ import {
|
|
|
5
5
|
UserConfig,
|
|
6
6
|
UserConfigFnObject,
|
|
7
7
|
} from "vite";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
DEFAULT_OUT_DIR_PROD,
|
|
10
|
+
DEFAULT_THEME_OUT_DIR,
|
|
11
|
+
getDefaultOutDirDev,
|
|
12
|
+
} from "./constants/build";
|
|
9
13
|
import { EXTERNALS, GLOBALS } from "./constants/externals";
|
|
10
|
-
import {
|
|
11
|
-
|
|
14
|
+
import {
|
|
15
|
+
DEFAULT_PLUGIN_MANIFEST_PATH,
|
|
16
|
+
DEFAULT_THEME_MANIFEST_PATH,
|
|
17
|
+
} from "./constants/halo-plugin";
|
|
18
|
+
import {
|
|
19
|
+
getHaloPluginBundleLocation,
|
|
20
|
+
getHaloPluginManifest,
|
|
21
|
+
getHaloThemeAssetPublicPath,
|
|
22
|
+
getHaloThemeManifest,
|
|
23
|
+
getHaloThemeModuleName,
|
|
24
|
+
getManifestName,
|
|
25
|
+
} from "./utils/halo-plugin";
|
|
26
|
+
|
|
27
|
+
type Provider = "plugin" | "theme";
|
|
12
28
|
|
|
13
29
|
export interface ViteUserConfig {
|
|
14
30
|
/**
|
|
15
|
-
*
|
|
31
|
+
* UI plugin provider type.
|
|
32
|
+
*
|
|
33
|
+
* @default "plugin"
|
|
34
|
+
*/
|
|
35
|
+
provider?: "plugin" | "theme";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Halo plugin or theme manifest path.
|
|
16
39
|
*
|
|
17
|
-
* @default "../src/main/resources/plugin.yaml"
|
|
40
|
+
* @default "../src/main/resources/plugin.yaml" for plugins, "../theme.yaml" for themes
|
|
18
41
|
*/
|
|
19
42
|
manifestPath?: string;
|
|
20
43
|
|
|
@@ -24,22 +47,26 @@ export interface ViteUserConfig {
|
|
|
24
47
|
vite: UserConfig | UserConfigFnObject;
|
|
25
48
|
}
|
|
26
49
|
|
|
27
|
-
function createVitePresetsConfig(manifestPath: string) {
|
|
28
|
-
const
|
|
50
|
+
function createVitePresetsConfig(provider: Provider, manifestPath: string) {
|
|
51
|
+
const defaults =
|
|
52
|
+
provider === "theme"
|
|
53
|
+
? getThemeProviderDefaults(manifestPath)
|
|
54
|
+
: getPluginProviderDefaults(manifestPath);
|
|
29
55
|
|
|
30
56
|
return defineConfig(({ mode }) => {
|
|
31
57
|
const isProduction = mode === "production";
|
|
32
58
|
|
|
33
59
|
return {
|
|
34
60
|
mode: mode || "production",
|
|
61
|
+
base: defaults.base,
|
|
35
62
|
plugins: [Vue()],
|
|
36
63
|
define: { "process.env.NODE_ENV": "'production'" },
|
|
37
64
|
build: {
|
|
38
|
-
outDir: isProduction ?
|
|
65
|
+
outDir: isProduction ? defaults.outDir.prod : defaults.outDir.dev,
|
|
39
66
|
emptyOutDir: true,
|
|
40
67
|
lib: {
|
|
41
68
|
entry: "src/index.ts",
|
|
42
|
-
name:
|
|
69
|
+
name: defaults.moduleName,
|
|
43
70
|
formats: ["iife"],
|
|
44
71
|
fileName: () => "main.js",
|
|
45
72
|
cssFileName: "style",
|
|
@@ -56,6 +83,46 @@ function createVitePresetsConfig(manifestPath: string) {
|
|
|
56
83
|
});
|
|
57
84
|
}
|
|
58
85
|
|
|
86
|
+
function getPluginProviderDefaults(manifestPath: string) {
|
|
87
|
+
const manifest = getHaloPluginManifest(manifestPath);
|
|
88
|
+
const bundleLocation = getHaloPluginBundleLocation(manifest);
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
moduleName: getManifestName(manifest),
|
|
92
|
+
outDir: {
|
|
93
|
+
prod: DEFAULT_OUT_DIR_PROD,
|
|
94
|
+
dev: getDefaultOutDirDev(bundleLocation),
|
|
95
|
+
},
|
|
96
|
+
base: undefined,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function getThemeProviderDefaults(manifestPath: string) {
|
|
101
|
+
const manifest = getHaloThemeManifest(manifestPath);
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
moduleName: getHaloThemeModuleName(manifest),
|
|
105
|
+
outDir: {
|
|
106
|
+
prod: DEFAULT_THEME_OUT_DIR,
|
|
107
|
+
dev: DEFAULT_THEME_OUT_DIR,
|
|
108
|
+
},
|
|
109
|
+
base: getHaloThemeAssetPublicPath(manifest),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function getProvider(config?: ViteUserConfig): Provider {
|
|
114
|
+
return config?.provider || "plugin";
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function getManifestPath(provider: Provider, config?: ViteUserConfig) {
|
|
118
|
+
if (config?.manifestPath) {
|
|
119
|
+
return config.manifestPath;
|
|
120
|
+
}
|
|
121
|
+
return provider === "theme"
|
|
122
|
+
? DEFAULT_THEME_MANIFEST_PATH
|
|
123
|
+
: DEFAULT_PLUGIN_MANIFEST_PATH;
|
|
124
|
+
}
|
|
125
|
+
|
|
59
126
|
/**
|
|
60
127
|
* Vite config for Halo UI Plugin.
|
|
61
128
|
*
|
|
@@ -71,8 +138,10 @@ function createVitePresetsConfig(manifestPath: string) {
|
|
|
71
138
|
* ```
|
|
72
139
|
*/
|
|
73
140
|
export function viteConfig(config?: ViteUserConfig) {
|
|
141
|
+
const provider = getProvider(config);
|
|
74
142
|
const presetsConfigFn = createVitePresetsConfig(
|
|
75
|
-
|
|
143
|
+
provider,
|
|
144
|
+
getManifestPath(provider, config)
|
|
76
145
|
);
|
|
77
146
|
return defineConfig((env) => {
|
|
78
147
|
const presetsConfig = presetsConfigFn(env);
|