@nocobase/build 2.1.0-beta.14 → 2.1.0-beta.16

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/lib/build.js CHANGED
@@ -28,12 +28,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
28
28
  var build_exports = {};
29
29
  __export(build_exports, {
30
30
  build: () => build,
31
- buildPackage: () => buildPackage,
32
31
  buildPackages: () => buildPackages
33
32
  });
34
33
  module.exports = __toCommonJS(build_exports);
35
34
  var import_chalk = __toESM(require("chalk"));
36
- var import_execa = __toESM(require("execa"));
37
35
  var import_path = __toESM(require("path"));
38
36
  var import_buildCjs = require("./buildCjs");
39
37
  var import_buildClient = require("./buildClient");
@@ -46,107 +44,297 @@ var import_utils = require("./utils");
46
44
  var import_addlicense = require("./utils/addlicense");
47
45
  var import_getPackages = require("./utils/getPackages");
48
46
  const BUILD_ERROR = "build-error";
47
+ const DEFAULT_LAYER_CONCURRENCY = 2;
48
+ const DEFAULT_PLUGIN_LAYER_CONCURRENCY = 1;
49
+ const ENABLE_BUILD_PROFILE = process.env.BUILD_PROFILE === "true";
49
50
  async function build(pkgs) {
51
+ const profile = ENABLE_BUILD_PROFILE ? (0, import_utils.createBuildProfileCollector)() : null;
52
+ const buildStart = (0, import_utils.nowMs)();
50
53
  const isDev = process.argv.includes("--development");
51
54
  process.env.NODE_ENV = isDev ? "development" : "production";
52
- let packages = (0, import_getPackages.getPackages)(pkgs);
53
- const cachePkg = (0, import_utils.readFromCache)(BUILD_ERROR);
54
- if (process.argv.includes("--retry") && cachePkg?.pkg) {
55
- packages = packages.slice(packages.findIndex((item) => item.name === cachePkg.pkg));
55
+ try {
56
+ let packages = (0, import_getPackages.getPackages)(pkgs);
57
+ const cachePkg = (0, import_utils.readFromCache)(BUILD_ERROR);
58
+ if (process.argv.includes("--retry") && cachePkg?.pkg) {
59
+ packages = packages.slice(packages.findIndex((item) => item.name === cachePkg.pkg));
60
+ }
61
+ const cliPackages = packages.find((item) => item.name === "@nocobase/cli");
62
+ if (cliPackages) {
63
+ const log = (0, import_utils.getPkgLog)(cliPackages.name);
64
+ log('running package script "build" (clean + tsc)');
65
+ await (0, import_utils.runScript)(["build"], cliPackages.location);
66
+ if (packages.length === 1) {
67
+ return;
68
+ }
69
+ }
70
+ if (packages.length === 0) {
71
+ let msg = "";
72
+ if (pkgs.length) {
73
+ msg = `'${pkgs.join(", ")}' did not match any packages`;
74
+ } else {
75
+ msg = "No package matched";
76
+ }
77
+ console.warn(import_chalk.default.yellow(`[@nocobase/build]: ${msg}`));
78
+ return;
79
+ }
80
+ const pluginPackages = (0, import_constant.getPluginPackages)(packages);
81
+ const cjsPackages = (0, import_constant.getCjsPackages)(packages);
82
+ const presetsPackages = (0, import_constant.getPresetsPackages)(packages);
83
+ await buildPackages(cjsPackages, "lib", import_buildCjs.buildCjs, {
84
+ sourceConcurrency: DEFAULT_LAYER_CONCURRENCY,
85
+ declarationConcurrency: 1,
86
+ stageName: "core cjs",
87
+ profile
88
+ });
89
+ const clientCore = packages.find((item) => item.location === import_constant.CORE_CLIENT);
90
+ if (clientCore) {
91
+ await buildSinglePackage(clientCore, "es", import_buildClient.buildClient, {
92
+ stageName: "core client",
93
+ profile
94
+ });
95
+ }
96
+ const esmPackages = packages.filter((pkg) => import_constant.ESM_PACKAGES.includes(pkg.name));
97
+ await buildPackages(esmPackages, "lib", import_buildCjs.buildCjs, {
98
+ sourceConcurrency: DEFAULT_LAYER_CONCURRENCY,
99
+ declarationConcurrency: 1,
100
+ stageName: "esm cjs",
101
+ profile
102
+ });
103
+ await buildPackages(esmPackages, "es", import_buildEsm.buildEsm, {
104
+ sourceConcurrency: DEFAULT_LAYER_CONCURRENCY,
105
+ declarationConcurrency: 1,
106
+ stageName: "esm",
107
+ profile
108
+ });
109
+ await buildPackages(pluginPackages, "dist", import_buildPlugin.buildPlugin, {
110
+ sourceConcurrency: DEFAULT_PLUGIN_LAYER_CONCURRENCY,
111
+ declarationConcurrency: 1,
112
+ stageName: "plugins",
113
+ profile
114
+ });
115
+ await buildPackages(presetsPackages, "lib", import_buildCjs.buildCjs, {
116
+ sourceConcurrency: DEFAULT_LAYER_CONCURRENCY,
117
+ declarationConcurrency: 1,
118
+ stageName: "presets",
119
+ profile
120
+ });
121
+ const appClient = packages.find((item) => item.location === import_constant.CORE_APP);
122
+ if (appClient) {
123
+ await (0, import_utils.runProfiledStage)(profile, "app shell", async () => {
124
+ await (0, import_utils.runScript)(["rsbuild", "build", "--config", import_path.default.join(import_constant.CORE_APP, "client", "rsbuild.config.ts")], import_constant.ROOT_PATH, {
125
+ APP_ROOT: import_path.default.join(import_constant.CORE_APP, "client"),
126
+ ANALYZE: process.env.BUILD_ANALYZE === "true" ? "1" : void 0
127
+ });
128
+ });
129
+ }
130
+ (0, import_utils.writeToCache)(BUILD_ERROR, {});
131
+ } finally {
132
+ if (profile) {
133
+ (0, import_utils.printBuildProfile)(profile, (0, import_utils.nowMs)() - buildStart);
134
+ }
56
135
  }
57
- if (packages.length === 0) {
58
- let msg = "";
59
- if (pkgs.length) {
60
- msg = `'${pkgs.join(", ")}' did not match any packages`;
61
- } else {
62
- msg = "No package matched";
136
+ }
137
+ async function buildPackages(packages, targetDir, doBuildPackage, options = {}) {
138
+ const {
139
+ sourceConcurrency = DEFAULT_LAYER_CONCURRENCY,
140
+ declarationConcurrency = 1,
141
+ stageName = "packages",
142
+ profile = null
143
+ } = options;
144
+ const layers = (0, import_getPackages.groupPackagesByTopoLevel)(packages);
145
+ const shouldRunDeclaration = !process.argv.includes("--no-dts") && !process.argv.includes("--only-tar");
146
+ await (0, import_utils.runProfiledStage)(profile, `${stageName} source`, async () => {
147
+ for (let index = 0; index < layers.length; index++) {
148
+ const layer = layers[index];
149
+ console.log(import_chalk.default.cyan(`[@nocobase/build]: ${stageName} source layer ${index + 1}/${layers.length} (${layer.length} packages)`));
150
+ const layerStart = (0, import_utils.nowMs)();
151
+ await (0, import_utils.runWithConcurrency)(layer, sourceConcurrency, async (pkg) => {
152
+ await buildPackageSourceLifecycle(pkg, targetDir, doBuildPackage, profile);
153
+ });
154
+ const layerDurationMs = (0, import_utils.nowMs)() - layerStart;
155
+ if (profile) {
156
+ profile.layers.push({
157
+ stageName: `${stageName} source`,
158
+ layerIndex: index + 1,
159
+ layerCount: layers.length,
160
+ packageCount: layer.length,
161
+ durationMs: layerDurationMs
162
+ });
163
+ }
164
+ if (ENABLE_BUILD_PROFILE) {
165
+ console.log(import_chalk.default.gray(`[@nocobase/build]: ${stageName} source layer ${index + 1}/${layers.length} finished in ${(0, import_utils.formatDuration)(layerDurationMs)}`));
166
+ }
63
167
  }
64
- console.warn(import_chalk.default.yellow(`[@nocobase/build]: ${msg}`));
168
+ });
169
+ if (!shouldRunDeclaration) {
65
170
  return;
66
171
  }
67
- const pluginPackages = (0, import_constant.getPluginPackages)(packages);
68
- const cjsPackages = (0, import_constant.getCjsPackages)(packages);
69
- const presetsPackages = (0, import_constant.getPresetsPackages)(packages);
70
- await buildPackages(cjsPackages, "lib", import_buildCjs.buildCjs);
71
- const clientCore = packages.find((item) => item.location === import_constant.CORE_CLIENT);
72
- if (clientCore) {
73
- await buildPackage(clientCore, "es", import_buildClient.buildClient);
74
- }
75
- const esmPackages = packages.filter((pkg) => import_constant.ESM_PACKAGES.includes(pkg.name));
76
- await buildPackages(esmPackages, "lib", import_buildCjs.buildCjs);
77
- await buildPackages(esmPackages, "es", import_buildEsm.buildEsm);
78
- await buildPackages(pluginPackages, "dist", import_buildPlugin.buildPlugin);
79
- await buildPackages(presetsPackages, "lib", import_buildCjs.buildCjs);
80
- const appClient = packages.find((item) => item.location === import_constant.CORE_APP);
81
- if (appClient) {
82
- await runScript(["umi", "build"], import_constant.ROOT_PATH, {
83
- APP_ROOT: import_path.default.join(import_constant.CORE_APP, "client"),
84
- ANALYZE: process.env.BUILD_ANALYZE === "true" ? "1" : void 0
85
- });
86
- }
87
- (0, import_utils.writeToCache)(BUILD_ERROR, {});
172
+ await (0, import_utils.runProfiledStage)(profile, `${stageName} declaration`, async () => {
173
+ for (let index = 0; index < layers.length; index++) {
174
+ const layer = layers[index];
175
+ console.log(import_chalk.default.cyan(`[@nocobase/build]: ${stageName} declaration layer ${index + 1}/${layers.length} (${layer.length} packages)`));
176
+ const layerStart = (0, import_utils.nowMs)();
177
+ await (0, import_utils.runWithConcurrency)(layer, declarationConcurrency, async (pkg) => {
178
+ await buildPackageDeclarationLifecycle(pkg, targetDir, profile);
179
+ });
180
+ const layerDurationMs = (0, import_utils.nowMs)() - layerStart;
181
+ if (profile) {
182
+ profile.layers.push({
183
+ stageName: `${stageName} declaration`,
184
+ layerIndex: index + 1,
185
+ layerCount: layers.length,
186
+ packageCount: layer.length,
187
+ durationMs: layerDurationMs
188
+ });
189
+ }
190
+ if (ENABLE_BUILD_PROFILE) {
191
+ console.log(import_chalk.default.gray(`[@nocobase/build]: ${stageName} declaration layer ${index + 1}/${layers.length} finished in ${(0, import_utils.formatDuration)(layerDurationMs)}`));
192
+ }
193
+ }
194
+ });
88
195
  }
89
- async function buildPackages(packages, targetDir, doBuildPackage) {
90
- for await (const pkg of packages) {
91
- (0, import_utils.writeToCache)(BUILD_ERROR, { pkg: pkg.name });
92
- await buildPackage(pkg, targetDir, doBuildPackage);
196
+ async function buildSinglePackage(pkg, targetDir, doBuildPackage, options) {
197
+ const { stageName, profile = null } = options;
198
+ await (0, import_utils.runProfiledStage)(profile, `${stageName} source`, async () => {
199
+ await buildPackageSourceLifecycle(pkg, targetDir, doBuildPackage, profile);
200
+ });
201
+ if (process.argv.includes("--no-dts") || process.argv.includes("--only-tar")) {
202
+ return;
93
203
  }
204
+ await (0, import_utils.runProfiledStage)(profile, `${stageName} declaration`, async () => {
205
+ await buildPackageDeclarationLifecycle(pkg, targetDir, profile);
206
+ });
94
207
  }
95
- async function buildPackage(pkg, targetDir, doBuildPackage) {
208
+ async function buildPackageSourceLifecycle(pkg, targetDir, doBuildPackage, profile = null) {
96
209
  const sourcemap = process.argv.includes("--sourcemap");
97
- const noDeclaration = process.argv.includes("--no-dts");
98
210
  const hasTar = process.argv.includes("--tar");
99
211
  const onlyTar = process.argv.includes("--only-tar");
100
212
  const log = (0, import_utils.getPkgLog)(pkg.name);
101
213
  const packageJson = (0, import_utils.getPackageJson)(pkg.location);
102
214
  if (onlyTar) {
215
+ const packageStart2 = (0, import_utils.nowMs)();
103
216
  await (0, import_tarPlugin.tarPlugin)(pkg.location, log);
217
+ if (profile) {
218
+ profile.packages.push({
219
+ name: pkg.name,
220
+ targetDir,
221
+ kind: "source",
222
+ durationMs: (0, import_utils.nowMs)() - packageStart2,
223
+ status: "success",
224
+ phases: { tar: (0, import_utils.nowMs)() - packageStart2 }
225
+ });
226
+ }
104
227
  return;
105
228
  }
106
229
  log(`${import_chalk.default.bold((0, import_utils.toUnixPath)(pkg.location.replace(import_constant.PACKAGES_PATH, "").slice(1)))} build start`);
107
230
  const userConfig = (0, import_utils.getUserConfig)(pkg.location);
231
+ const packageStart = (0, import_utils.nowMs)();
232
+ const phaseDurations = {};
233
+ let status = "success";
234
+ const runPhase = async (phaseName, task) => {
235
+ const phaseStart = (0, import_utils.nowMs)();
236
+ await task();
237
+ phaseDurations[phaseName] = (phaseDurations[phaseName] || 0) + ((0, import_utils.nowMs)() - phaseStart);
238
+ };
108
239
  if (packageJson?.scripts?.prebuild) {
109
240
  log("prebuild");
110
- await runScript(["prebuild"], pkg.location);
111
- await packageJson.prebuild(pkg.location);
241
+ await runPhase("prebuild", async () => {
242
+ await (0, import_utils.runScript)(["prebuild"], pkg.location);
243
+ await packageJson.prebuild(pkg.location);
244
+ });
112
245
  }
113
246
  if (userConfig.beforeBuild) {
114
247
  log("beforeBuild");
115
- await userConfig.beforeBuild(log);
116
- }
117
- await doBuildPackage(pkg.location, userConfig, sourcemap, log);
118
- if (!noDeclaration) {
119
- log("build declaration");
120
- await (0, import_buildDeclaration.buildDeclaration)(pkg.location, targetDir);
121
- }
122
- if (packageJson?.scripts?.postbuild) {
123
- log("postbuild");
124
- await runScript(["postbuild"], pkg.location);
125
- }
126
- if (userConfig.afterBuild) {
127
- log("afterBuild");
128
- await userConfig.afterBuild(log);
248
+ await runPhase("beforeBuild", async () => {
249
+ await userConfig.beforeBuild(log);
250
+ });
129
251
  }
130
- await (0, import_addlicense.addLicense)(import_path.default.join(pkg.location, targetDir), log);
131
- if (hasTar) {
132
- await (0, import_tarPlugin.tarPlugin)(pkg.location, log);
252
+ try {
253
+ await runPhase("build", async () => {
254
+ await doBuildPackage(pkg.location, userConfig, sourcemap, log);
255
+ });
256
+ if (packageJson?.scripts?.postbuild) {
257
+ log("postbuild");
258
+ await runPhase("postbuild", async () => {
259
+ await (0, import_utils.runScript)(["postbuild"], pkg.location);
260
+ });
261
+ }
262
+ if (userConfig.afterBuild) {
263
+ log("afterBuild");
264
+ await runPhase("afterBuild", async () => {
265
+ await userConfig.afterBuild(log);
266
+ });
267
+ }
268
+ await runPhase("addLicense", async () => {
269
+ await (0, import_addlicense.addLicense)(import_path.default.join(pkg.location, targetDir), log);
270
+ });
271
+ if (hasTar) {
272
+ await runPhase("tar", async () => {
273
+ await (0, import_tarPlugin.tarPlugin)(pkg.location, log);
274
+ });
275
+ }
276
+ } catch (error) {
277
+ status = "failed";
278
+ (0, import_utils.writeToCache)(BUILD_ERROR, { pkg: pkg.name });
279
+ throw error;
280
+ } finally {
281
+ if (profile) {
282
+ profile.packages.push({
283
+ name: pkg.name,
284
+ targetDir,
285
+ kind: "source",
286
+ durationMs: (0, import_utils.nowMs)() - packageStart,
287
+ status,
288
+ phases: phaseDurations
289
+ });
290
+ if (ENABLE_BUILD_PROFILE) {
291
+ const summary = Object.entries(phaseDurations).sort((a, b) => b[1] - a[1]).map(([name, duration]) => `${name}=${(0, import_utils.formatDuration)(duration)}`).join(", ");
292
+ console.log(
293
+ import_chalk.default.gray(
294
+ `[@nocobase/build:profile] ${pkg.name} ${status} in ${(0, import_utils.formatDuration)((0, import_utils.nowMs)() - packageStart)}${summary ? ` (${summary})` : ""}`
295
+ )
296
+ );
297
+ }
298
+ }
133
299
  }
134
300
  }
135
- function runScript(args, cwd, envs = {}) {
136
- return (0, import_execa.default)("yarn", args, {
137
- cwd,
138
- stdio: "inherit",
139
- env: {
140
- ...process.env,
141
- ...envs,
142
- sourcemap: process.argv.includes("--sourcemap") ? "sourcemap" : void 0,
143
- NODE_ENV: process.env.NODE_ENV || "production"
301
+ async function buildPackageDeclarationLifecycle(pkg, targetDir, profile = null) {
302
+ const log = (0, import_utils.getPkgLog)(pkg.name);
303
+ const packageStart = (0, import_utils.nowMs)();
304
+ const phaseDurations = {};
305
+ let status = "success";
306
+ try {
307
+ log("build declaration");
308
+ const phaseStart = (0, import_utils.nowMs)();
309
+ await (0, import_buildDeclaration.buildDeclaration)(pkg.location, targetDir);
310
+ phaseDurations.declaration = (0, import_utils.nowMs)() - phaseStart;
311
+ } catch (error) {
312
+ status = "failed";
313
+ (0, import_utils.writeToCache)(BUILD_ERROR, { pkg: pkg.name });
314
+ throw error;
315
+ } finally {
316
+ if (profile) {
317
+ profile.packages.push({
318
+ name: pkg.name,
319
+ targetDir,
320
+ kind: "declaration",
321
+ durationMs: (0, import_utils.nowMs)() - packageStart,
322
+ status,
323
+ phases: phaseDurations
324
+ });
325
+ if (ENABLE_BUILD_PROFILE) {
326
+ const summary = Object.entries(phaseDurations).sort((a, b) => b[1] - a[1]).map(([name, duration]) => `${name}=${(0, import_utils.formatDuration)(duration)}`).join(", ");
327
+ console.log(
328
+ import_chalk.default.gray(
329
+ `[@nocobase/build:profile] ${pkg.name} declaration ${status} in ${(0, import_utils.formatDuration)((0, import_utils.nowMs)() - packageStart)}${summary ? ` (${summary})` : ""}`
330
+ )
331
+ );
332
+ }
144
333
  }
145
- });
334
+ }
146
335
  }
147
336
  // Annotate the CommonJS export names for ESM import in node:
148
337
  0 && (module.exports = {
149
338
  build,
150
- buildPackage,
151
339
  buildPackages
152
340
  });
@@ -31,13 +31,14 @@ __export(buildClient_exports, {
31
31
  buildLocale: () => buildLocale
32
32
  });
33
33
  module.exports = __toCommonJS(buildClient_exports);
34
- var import_plugin_react = __toESM(require("@vitejs/plugin-react"));
34
+ var import_core = require("@rsbuild/core");
35
+ var import_plugin_less = require("@rsbuild/plugin-less");
36
+ var import_plugin_react = require("@rsbuild/plugin-react");
37
+ var import_plugin_svgr = require("@rsbuild/plugin-svgr");
35
38
  var import_fast_glob = __toESM(require("fast-glob"));
36
39
  var import_fs_extra = __toESM(require("fs-extra"));
37
40
  var import_path = __toESM(require("path"));
38
41
  var import_tsup = require("tsup");
39
- var import_vite = require("vite");
40
- var import_vite_plugin_lib_inject_css = require("vite-plugin-lib-inject-css");
41
42
  var import_constant = require("./constant");
42
43
  var import_utils = require("./utils");
43
44
  async function buildClient(cwd, userConfig, sourcemap = false, log) {
@@ -45,7 +46,7 @@ async function buildClient(cwd, userConfig, sourcemap = false, log) {
45
46
  const cwdWin = cwd.replaceAll(/\\/g, "/");
46
47
  const cwdUnix = cwd.replaceAll(/\//g, "\\");
47
48
  const external = function(id) {
48
- if (id.startsWith(".") || id.startsWith(cwdUnix) || id.startsWith(cwdWin)) {
49
+ if (!id || import_path.default.isAbsolute(id) || id.startsWith(".") || id.startsWith(cwdUnix) || id.startsWith(cwdWin)) {
49
50
  return false;
50
51
  }
51
52
  return true;
@@ -54,35 +55,12 @@ async function buildClient(cwd, userConfig, sourcemap = false, log) {
54
55
  await buildClientLib(cwd, userConfig, sourcemap, external, log);
55
56
  await buildLocale(cwd, userConfig, log);
56
57
  }
57
- function buildClientEsm(cwd, userConfig, sourcemap, external, log) {
58
+ async function buildClientEsm(cwd, userConfig, sourcemap, external, log) {
58
59
  log("build client esm");
59
60
  const entry = import_path.default.join(cwd, "src/index.ts").replaceAll(/\\/g, "/");
60
61
  const outDir = import_path.default.resolve(cwd, "es");
61
- return (0, import_vite.build)(
62
- userConfig.modifyViteConfig({
63
- mode: process.env.NODE_ENV || "production",
64
- define: (0, import_utils.getEnvDefine)(),
65
- build: {
66
- minify: process.env.NODE_ENV === "production",
67
- outDir,
68
- cssCodeSplit: true,
69
- emptyOutDir: true,
70
- sourcemap,
71
- lib: {
72
- entry,
73
- formats: ["es"],
74
- fileName: "index"
75
- },
76
- target: ["es2015", "edge88", "firefox78", "chrome87", "safari14"],
77
- rollupOptions: {
78
- cache: true,
79
- treeshake: true,
80
- external
81
- }
82
- },
83
- plugins: [(0, import_plugin_react.default)(), (0, import_vite_plugin_lib_inject_css.libInjectCss)()]
84
- })
85
- );
62
+ await buildClientWithRsbuild(cwd, userConfig, sourcemap, external, entry, outDir, "esm");
63
+ await injectEntryStyleReference(import_path.default.join(outDir, "index.mjs"), 'import "./index.css";');
86
64
  }
87
65
  async function buildClientLib(cwd, userConfig, sourcemap, external, log) {
88
66
  log("build client lib");
@@ -91,32 +69,114 @@ async function buildClientLib(cwd, userConfig, sourcemap, external, log) {
91
69
  const entry = import_path.default.join(esDir, "index.ts");
92
70
  import_fs_extra.default.removeSync(entry);
93
71
  import_fs_extra.default.linkSync(import_path.default.join(cwd, "es/index.mjs"), entry);
94
- await (0, import_vite.build)(
95
- userConfig.modifyViteConfig({
96
- mode: process.env.NODE_ENV || "production",
97
- esbuild: {
98
- format: "cjs"
72
+ try {
73
+ await buildClientWithRsbuild(cwd, userConfig, sourcemap, external, entry, outDir, "cjs");
74
+ } finally {
75
+ import_fs_extra.default.removeSync(entry);
76
+ }
77
+ await injectEntryStyleReference(import_path.default.join(outDir, "index.js"), 'require("./index.css");');
78
+ }
79
+ async function buildClientWithRsbuild(cwd, userConfig, sourcemap, external, entry, outDir, format) {
80
+ const config = createClientRsbuildConfig(cwd, entry, outDir, sourcemap, external, format);
81
+ const rsbuild = await (0, import_core.createRsbuild)({
82
+ cwd,
83
+ config: userConfig.modifyRsbuildConfig?.(config) ?? config
84
+ });
85
+ const result = await rsbuild.build();
86
+ await result.close();
87
+ }
88
+ function createClientRsbuildConfig(cwd, entry, outDir, sourcemap, external, format) {
89
+ return {
90
+ plugins: [(0, import_plugin_react.pluginReact)(), (0, import_plugin_less.pluginLess)(), (0, import_plugin_svgr.pluginSvgr)()],
91
+ source: {
92
+ entry: {
93
+ index: {
94
+ import: entry,
95
+ html: false
96
+ }
97
+ },
98
+ tsconfigPath: import_path.default.join(cwd, "tsconfig.json"),
99
+ define: (0, import_utils.getEnvDefine)(),
100
+ decorators: {
101
+ version: "legacy"
102
+ }
103
+ },
104
+ output: {
105
+ target: "web",
106
+ distPath: {
107
+ root: outDir,
108
+ js: ".",
109
+ jsAsync: ".",
110
+ css: ".",
111
+ cssAsync: ".",
112
+ svg: ".",
113
+ font: ".",
114
+ image: ".",
115
+ media: ".",
116
+ assets: "."
99
117
  },
100
- build: {
101
- outDir,
102
- minify: process.env.NODE_ENV === "production",
103
- sourcemap,
104
- lib: {
105
- entry: import_path.default.join(cwd, "es/index.ts"),
106
- formats: ["cjs"],
107
- fileName: "index"
108
- },
109
- rollupOptions: {
110
- external
118
+ filename: {
119
+ js: format === "esm" ? "[name].mjs" : "[name].js",
120
+ css: "[name].css",
121
+ svg: "[name][ext][query]",
122
+ font: "[name][ext][query]",
123
+ image: "[name][ext][query]",
124
+ media: "[name][ext][query]",
125
+ assets: "[name][ext][query]"
126
+ },
127
+ cleanDistPath: true,
128
+ sourceMap: sourcemap,
129
+ minify: process.env.NODE_ENV === "production",
130
+ emitCss: true,
131
+ externals: [
132
+ function({ request }, callback) {
133
+ if (request && external(request)) {
134
+ return callback(null, true);
135
+ }
136
+ callback();
111
137
  }
138
+ ]
139
+ },
140
+ performance: {
141
+ chunkSplit: {
142
+ strategy: "all-in-one"
112
143
  }
113
- })
114
- );
115
- import_fs_extra.default.removeSync(entry);
116
- const css = import_fast_glob.default.sync("*.css", { cwd: esDir, absolute: true });
117
- css.forEach((file) => {
118
- import_fs_extra.default.copySync(file, import_path.default.join(outDir, import_path.default.basename(file)));
119
- });
144
+ },
145
+ tools: {
146
+ rspack(config) {
147
+ config.output = config.output || {};
148
+ config.output.asyncChunks = false;
149
+ if (format === "esm") {
150
+ config.output.library = { type: "module" };
151
+ config.output.module = true;
152
+ config.output.chunkFormat = "module";
153
+ config.output.chunkLoading = "import";
154
+ config.output.workerChunkLoading = "import";
155
+ config.experiments = {
156
+ ...config.experiments,
157
+ outputModule: true
158
+ };
159
+ config.externalsType = "module-import";
160
+ } else {
161
+ config.output.library = { type: "commonjs-static" };
162
+ }
163
+ config.performance = false;
164
+ config.stats = "errors-warnings";
165
+ }
166
+ }
167
+ };
168
+ }
169
+ async function injectEntryStyleReference(entryFile, styleReference) {
170
+ const cssFile = import_path.default.join(import_path.default.dirname(entryFile), "index.css");
171
+ if (!import_fs_extra.default.existsSync(entryFile) || !import_fs_extra.default.existsSync(cssFile)) {
172
+ return;
173
+ }
174
+ const content = await import_fs_extra.default.readFile(entryFile, "utf8");
175
+ if (content.startsWith(styleReference)) {
176
+ return;
177
+ }
178
+ await import_fs_extra.default.writeFile(entryFile, `${styleReference}
179
+ ${content}`);
120
180
  }
121
181
  function buildLocale(cwd, userConfig, log) {
122
182
  log("build client locale");
@@ -53,7 +53,11 @@ const diagnosticHost = {
53
53
  getCanonicalFileName: (fileName) => import_typescript.default.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(),
54
54
  getNewLine: () => import_typescript.default.sys.newLine
55
55
  };
56
+ let cachedBaseCompilerOptions = null;
56
57
  function loadCompilerOptions() {
58
+ if (cachedBaseCompilerOptions) {
59
+ return { ...cachedBaseCompilerOptions };
60
+ }
57
61
  const configPath = import_path.default.join(import_constant.ROOT_PATH, "tsconfig.json");
58
62
  const configFile = import_typescript.default.readConfigFile(configPath, import_typescript.default.sys.readFile);
59
63
  if (configFile.error) {
@@ -70,7 +74,8 @@ function loadCompilerOptions() {
70
74
  ...parsedConfig.options
71
75
  };
72
76
  delete options.paths;
73
- return options;
77
+ cachedBaseCompilerOptions = Object.freeze({ ...options });
78
+ return { ...cachedBaseCompilerOptions };
74
79
  }
75
80
  const buildDeclaration = async (cwd, targetDir) => {
76
81
  const srcPath = import_path.default.join(cwd, "src");
@@ -92,7 +97,17 @@ const buildDeclaration = async (cwd, targetDir) => {
92
97
  outDir: targetPath,
93
98
  rootDir: srcPath
94
99
  };
95
- const program = import_typescript.default.createProgram(files, compilerOptions);
100
+ const host = import_typescript.default.createCompilerHost(compilerOptions);
101
+ const originalDirectoryExists = host.directoryExists?.bind(host);
102
+ const rootPrefix = import_constant.ROOT_PATH.endsWith(import_path.default.sep) ? import_constant.ROOT_PATH : import_constant.ROOT_PATH + import_path.default.sep;
103
+ host.directoryExists = (dirPath) => {
104
+ const resolved = import_path.default.resolve(dirPath);
105
+ if (resolved !== import_constant.ROOT_PATH && !resolved.startsWith(rootPrefix) && resolved.includes(`${import_path.default.sep}node_modules`)) {
106
+ return false;
107
+ }
108
+ return originalDirectoryExists ? originalDirectoryExists(dirPath) : import_typescript.default.sys.directoryExists(dirPath);
109
+ };
110
+ const program = import_typescript.default.createProgram(files, compilerOptions, host);
96
111
  const emitResult = program.emit(void 0, void 0, void 0, true);
97
112
  const diagnostics = import_typescript.default.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
98
113
  if (diagnostics.length) {
@@ -51,10 +51,29 @@ var import_utils = require("./utils");
51
51
  var import_buildPluginUtils = require("./utils/buildPluginUtils");
52
52
  var import_getDepsConfig = require("./utils/getDepsConfig");
53
53
  var import_obfuscationResult = require("./utils/obfuscationResult");
54
+ var import_injectPublicPathPlugin = require("./injectPublicPathPlugin");
54
55
  const validExts = [".ts", ".tsx", ".js", ".jsx", ".mjs"];
55
- const serverGlobalFiles = ["src/**", "!src/client/**", ...import_constant.globExcludeFiles];
56
- const clientGlobalFiles = ["src/**", "!src/server/**", ...import_constant.globExcludeFiles];
56
+ const serverGlobalFiles = ["src/**", "!src/client/**", "!src/client-v2/**", ...import_constant.globExcludeFiles];
57
57
  const sourceGlobalFiles = ["src/**/*.{ts,js,tsx,jsx,mjs}", "!src/**/__tests__", "!src/**/__benchmarks__"];
58
+ const pluginClientLaneConfig = {
59
+ client: {
60
+ distDir: "client",
61
+ entryDir: "client",
62
+ rootEntryFile: "client.js",
63
+ externalSubpaths: ["client"]
64
+ },
65
+ "client-v2": {
66
+ distDir: "client-v2",
67
+ entryDir: "client-v2",
68
+ rootEntryFile: "client-v2.js",
69
+ externalSubpaths: ["client", "client-v2"]
70
+ }
71
+ };
72
+ function getClientGlobalFiles(lane) {
73
+ const entryDir = pluginClientLaneConfig[lane].entryDir;
74
+ const excludedClientDirs = Object.values(pluginClientLaneConfig).map((item) => item.entryDir).filter((dir) => dir !== entryDir).map((dir) => `!src/${dir}/**`);
75
+ return ["src/**", "!src/server/**", ...excludedClientDirs, ...import_constant.globExcludeFiles];
76
+ }
58
77
  const external = [
59
78
  // nocobase
60
79
  "@nocobase/ai",
@@ -148,12 +167,12 @@ const external = [
148
167
  "@langchain/classic",
149
168
  "@langchain/langgraph",
150
169
  "@langchain/langgraph-checkpoint",
151
- "@langchain/community",
152
170
  "@langchain/openai",
153
171
  "@langchain/anthropic",
154
172
  "@langchain/google-genai",
155
173
  "@langchain/deepseek",
156
- "@langchain/ollama"
174
+ "@langchain/ollama",
175
+ "@langchain/mcp-adapters"
157
176
  ];
158
177
  const pluginPrefix = (process.env.PLUGIN_PACKAGE_PREFIX || "@nocobase/plugin-,@nocobase/preset-,@nocobase/plugin-pro-").split(",");
159
178
  const target_dir = "dist";
@@ -244,7 +263,19 @@ function deleteServerFiles(cwd, log) {
244
263
  deep: 1,
245
264
  onlyDirectories: true
246
265
  });
247
- [...files, ...dirs].forEach((item) => {
266
+ const extraClientDirs = import_fast_glob.default.globSync(["client-v2"], {
267
+ cwd: import_path.default.join(cwd, target_dir),
268
+ absolute: true,
269
+ deep: 1,
270
+ onlyDirectories: true
271
+ });
272
+ [...files, ...dirs.filter((item) => !extraClientDirs.includes(item)), ...extraClientDirs].forEach((item) => {
273
+ if (item.endsWith(`${import_path.default.sep}client-v2`)) {
274
+ return;
275
+ }
276
+ if (item.endsWith(`${import_path.default.sep}client`)) {
277
+ return;
278
+ }
248
279
  import_fs_extra.default.removeSync(item);
249
280
  });
250
281
  }
@@ -469,9 +500,27 @@ async function buildProPluginServer(cwd, userConfig, sourcemap, log) {
469
500
  import_fs_extra.default.removeSync(tsconfig.path);
470
501
  await buildServerDeps(cwd, serverFiles, log);
471
502
  }
472
- async function buildPluginClient(cwd, userConfig, sourcemap, log, isCommercial = false) {
473
- log("build plugin client");
503
+ async function buildPluginClient(cwd, userConfig, sourcemap, log, lane = "client", isCommercial = false) {
504
+ const laneConfig = pluginClientLaneConfig[lane];
505
+ const entryDir = import_path.default.join(cwd, "src", laneConfig.entryDir);
506
+ const rootEntryFile = import_path.default.join(cwd, laneConfig.rootEntryFile);
507
+ if (!import_fs_extra.default.existsSync(rootEntryFile)) {
508
+ log("skip plugin %s build, root entry not found", lane);
509
+ return false;
510
+ }
511
+ if (!import_fs_extra.default.existsSync(entryDir)) {
512
+ log("Missing %s. Please create it.", import_chalk.default.red(`src/${laneConfig.entryDir}`));
513
+ process.exit(-1);
514
+ }
515
+ const entry = import_fast_glob.default.globSync("index.{ts,tsx,js,jsx}", { absolute: false, cwd: entryDir });
516
+ if (!entry[0]) {
517
+ log("Missing %s entry file.", import_chalk.default.red(`src/${laneConfig.entryDir}/index.{ts,tsx,js,jsx}`));
518
+ process.exit(-1);
519
+ return false;
520
+ }
521
+ log("build plugin %s", lane);
474
522
  const packageJson = (0, import_utils.getPackageJson)(cwd);
523
+ const clientGlobalFiles = getClientGlobalFiles(lane);
475
524
  const clientFiles = import_fast_glob.default.globSync(clientGlobalFiles, { cwd, absolute: true });
476
525
  if (isCommercial) {
477
526
  const commercialFiles = import_fast_glob.default.globSync(clientGlobalFiles, {
@@ -484,22 +533,23 @@ async function buildPluginClient(cwd, userConfig, sourcemap, log, isCommercial =
484
533
  const sourcePackages = (0, import_buildPluginUtils.getPackagesFromFiles)(clientFileSource);
485
534
  const excludePackages = (0, import_buildPluginUtils.getExcludePackages)(sourcePackages, external, pluginPrefix);
486
535
  (0, import_buildPluginUtils.checkRequire)(clientFiles, log);
487
- (0, import_buildPluginUtils.buildCheck)({ cwd, packageJson, entry: "client", files: clientFiles, log });
488
- const outDir = import_path.default.join(cwd, target_dir, "client");
536
+ (0, import_buildPluginUtils.buildCheck)({ cwd, packageJson, entry: lane, files: clientFiles, log });
537
+ const outDir = import_path.default.join(cwd, target_dir, laneConfig.distDir);
489
538
  const globals = excludePackages.reduce((prev, curr) => {
490
539
  if (curr.startsWith("@nocobase")) {
491
- prev[`${curr}/client`] = `${curr}/client`;
540
+ laneConfig.externalSubpaths.forEach((subpath) => {
541
+ prev[`${curr}/${subpath}`] = `${curr}/${subpath}`;
542
+ });
492
543
  }
493
544
  prev[curr] = curr;
494
545
  return prev;
495
546
  }, {});
496
- const entry = import_fast_glob.default.globSync("index.{ts,tsx,js,jsx}", { absolute: false, cwd: import_path.default.join(cwd, "src/client") });
497
547
  const outputFileName = "index.js";
498
548
  const compiler = (0, import_core.rspack)({
499
549
  mode: "production",
500
550
  // mode: "development",
501
551
  context: cwd,
502
- entry: "./src/client/" + entry[0],
552
+ entry: `./src/${laneConfig.entryDir}/` + entry[0],
503
553
  target: ["web", "es5"],
504
554
  output: {
505
555
  path: outDir,
@@ -581,18 +631,6 @@ async function buildPluginClient(cwd, userConfig, sourcemap, log, isCommercial =
581
631
  // *.svg?react
582
632
  use: ["@svgr/webpack"]
583
633
  },
584
- {
585
- test: /\.(?:js|mjs|cjs|ts|tsx)$/,
586
- exclude: /node_modules/,
587
- use: {
588
- loader: "babel-loader",
589
- options: {
590
- targets: "defaults",
591
- // presets: [['@babel/preset-env']],
592
- plugins: ["react-imported-component/babel"]
593
- }
594
- }
595
- },
596
634
  {
597
635
  test: /\.jsx$/,
598
636
  exclude: /[\\/]node_modules[\\/]/,
@@ -672,27 +710,7 @@ async function buildPluginClient(cwd, userConfig, sourcemap, log, isCommercial =
672
710
  "process.env.NODE_ENV": JSON.stringify("production"),
673
711
  "process.env.NODE_DEBUG": false
674
712
  }),
675
- {
676
- apply(compiler2) {
677
- compiler2.hooks.compilation.tap("CustomPublicPathPlugin", (compilation) => {
678
- compilation.hooks.runtimeModule.tap("CustomPublicPathPlugin", (module2) => {
679
- if (module2.name === "auto_public_path") {
680
- module2.source = {
681
- source: `
682
- __webpack_require__.p = (function() {
683
- var publicPath = window['__webpack_public_path__'] || '/';
684
- // \u786E\u4FDD\u8DEF\u5F84\u4EE5 / \u7ED3\u5C3E
685
- if (!publicPath.endsWith('/')) {
686
- publicPath += '/';
687
- }
688
- return publicPath + 'static/plugins/${packageJson.name}/dist/client/';
689
- })();`
690
- };
691
- }
692
- });
693
- });
694
- }
695
- },
713
+ new import_injectPublicPathPlugin.AutoInjectPublicPathPlugin(packageJson.name, laneConfig.distDir),
696
714
  process.env.BUILD_ANALYZE === "true" && new import_rspack_plugin.RsdoctorRspackPlugin({
697
715
  // plugin options
698
716
  // supports: {
@@ -729,10 +747,12 @@ __webpack_require__.p = (function() {
729
747
  }
730
748
  async function buildPlugin(cwd, userConfig, sourcemap, log) {
731
749
  if (cwd.includes("/pro-plugins/") && import_fs_extra.default.existsSync(import_path.default.join(process.cwd(), "packages/pro-plugins/", import_constant.PLUGIN_COMMERCIAL))) {
732
- await buildPluginClient(cwd, userConfig, sourcemap, log, true);
750
+ await buildPluginClient(cwd, userConfig, sourcemap, log, "client", true);
751
+ await buildPluginClient(cwd, userConfig, sourcemap, log, "client-v2", true);
733
752
  await buildProPluginServer(cwd, userConfig, sourcemap, log);
734
753
  } else {
735
- await buildPluginClient(cwd, userConfig, sourcemap, log);
754
+ await buildPluginClient(cwd, userConfig, sourcemap, log, "client");
755
+ await buildPluginClient(cwd, userConfig, sourcemap, log, "client-v2");
736
756
  await buildPluginServer(cwd, userConfig, sourcemap, log);
737
757
  }
738
758
  writeExternalPackageVersion(cwd, log);
package/lib/constant.js CHANGED
@@ -30,6 +30,7 @@ __export(constant_exports, {
30
30
  CJS_EXCLUDE_PACKAGES: () => CJS_EXCLUDE_PACKAGES,
31
31
  CORE_APP: () => CORE_APP,
32
32
  CORE_CLIENT: () => CORE_CLIENT,
33
+ CORE_CLIENT_V2: () => CORE_CLIENT_V2,
33
34
  ESM_PACKAGES: () => ESM_PACKAGES,
34
35
  EsbuildSupportExts: () => EsbuildSupportExts,
35
36
  NODE_MODULES: () => NODE_MODULES,
@@ -90,20 +91,31 @@ const getPluginPackages = (packages) => packages.filter((item) => PLUGINS_DIR.so
90
91
  const getPresetsPackages = (packages) => packages.filter((item) => item.location.startsWith(PRESETS_DIR));
91
92
  const CORE_APP = import_path.default.join(PACKAGES_PATH, "core/app");
92
93
  const CORE_CLIENT = import_path.default.join(PACKAGES_PATH, "core/client");
93
- const ESM_PACKAGES = ["@nocobase/test"];
94
+ const CORE_CLIENT_V2 = import_path.default.join(PACKAGES_PATH, "core/client-v2");
95
+ const ESM_PACKAGES = ["@nocobase/client-v2", "@nocobase/test"];
94
96
  const CJS_EXCLUDE_PACKAGES = [
95
97
  import_path.default.join(PACKAGES_PATH, "core/build"),
98
+ import_path.default.join(PACKAGES_PATH, "core/cli-v1"),
96
99
  import_path.default.join(PACKAGES_PATH, "core/cli"),
97
- CORE_CLIENT
100
+ CORE_CLIENT,
101
+ CORE_CLIENT_V2
98
102
  ];
99
103
  const getCjsPackages = (packages) => packages.filter((item) => !PLUGINS_DIR.some((dir) => item.location.startsWith(dir))).filter((item) => !item.location.startsWith(PRESETS_DIR)).filter((item) => !ESM_PACKAGES.includes(item.name)).filter((item) => !CJS_EXCLUDE_PACKAGES.includes(item.location));
100
104
  const tarIncludesFiles = ["package.json", "README.md", "LICENSE", "dist", "!node_modules"];
101
- const TAR_OUTPUT_DIR = process.env.TAR_PATH ? process.env.TAR_PATH : import_path.default.join(ROOT_PATH, "storage", "tar");
105
+ function resolveStorageRoot() {
106
+ const raw = process.env.STORAGE_PATH;
107
+ if (raw) {
108
+ return import_path.default.isAbsolute(raw) ? raw : import_path.default.resolve(process.cwd(), raw);
109
+ }
110
+ return import_path.default.join(ROOT_PATH, "storage");
111
+ }
112
+ const TAR_OUTPUT_DIR = process.env.TAR_PATH || import_path.default.join(resolveStorageRoot(), "tar");
102
113
  // Annotate the CommonJS export names for ESM import in node:
103
114
  0 && (module.exports = {
104
115
  CJS_EXCLUDE_PACKAGES,
105
116
  CORE_APP,
106
117
  CORE_CLIENT,
118
+ CORE_CLIENT_V2,
107
119
  ESM_PACKAGES,
108
120
  EsbuildSupportExts,
109
121
  NODE_MODULES,
package/lib/index.d.ts CHANGED
@@ -7,15 +7,14 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
-
10
+ import type { RsbuildConfig } from '@rsbuild/core'
11
11
  import { Options as TsupConfig } from 'tsup'
12
- import { InlineConfig as ViteConfig } from 'vite'
13
12
 
14
13
  export type PkgLog = (msg: string, ...args: any[]) => void;
15
14
 
16
15
  interface UserConfig {
17
16
  modifyTsupConfig?: (config: TsupConfig) => TsupConfig;
18
- modifyViteConfig?: (config: ViteConfig) => ViteConfig;
17
+ modifyRsbuildConfig?: (config: RsbuildConfig) => RsbuildConfig;
19
18
  beforeBuild?: (log: PkgLog) => void | Promise<void>;
20
19
  afterBuild?: (log: PkgLog) => void | Promise<void>;
21
20
  }
@@ -0,0 +1,109 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var injectPublicPathPlugin_exports = {};
19
+ __export(injectPublicPathPlugin_exports, {
20
+ AutoInjectPublicPathPlugin: () => AutoInjectPublicPathPlugin
21
+ });
22
+ module.exports = __toCommonJS(injectPublicPathPlugin_exports);
23
+ function createPluginClientPublicPathDataUri(packageName, clientDistDir) {
24
+ const code = `
25
+ var publicPath = '';
26
+ var currentScript = typeof document !== 'undefined' ? document.currentScript : null;
27
+ if (currentScript && currentScript.src) {
28
+ publicPath = currentScript.src
29
+ .replace(/^blob:/, '')
30
+ .replace(/#.*$/, '')
31
+ .replace(/\\?.*$/, '')
32
+ .replace(/\\/[^\\/]+$/, '/');
33
+ }
34
+ if (!publicPath) {
35
+ var runtimeAssetBase = window['__webpack_public_path__'] || '';
36
+ if (runtimeAssetBase) {
37
+ if (runtimeAssetBase.charAt(runtimeAssetBase.length - 1) !== '/') {
38
+ runtimeAssetBase += '/';
39
+ }
40
+ publicPath = runtimeAssetBase + 'static/plugins/${packageName}/dist/${clientDistDir}/';
41
+ }
42
+ }
43
+ if (!publicPath) {
44
+ publicPath = window['__nocobase_public_path__'] || '';
45
+ if (!publicPath && window.location && window.location.pathname) {
46
+ var marker = '/v2/';
47
+ var pathname = window.location.pathname || '/';
48
+ var index = pathname.indexOf(marker);
49
+ publicPath = index >= 0 ? pathname.slice(0, index + 1) : '/';
50
+ }
51
+ if (publicPath) {
52
+ publicPath = publicPath.replace(/\\/v2\\/?$/, '/');
53
+ }
54
+ if (!publicPath) {
55
+ publicPath = '/';
56
+ }
57
+ if (publicPath.charAt(publicPath.length - 1) !== '/') {
58
+ publicPath += '/';
59
+ }
60
+ publicPath += 'static/plugins/${packageName}/dist/${clientDistDir}/';
61
+ }
62
+ __webpack_public_path__ = publicPath;
63
+ `;
64
+ return `data:text/javascript,${encodeURIComponent(code)}`;
65
+ }
66
+ function prependPluginClientPublicPathEntry(entry, packageName, clientDistDir) {
67
+ const dataUri = createPluginClientPublicPathDataUri(packageName, clientDistDir);
68
+ if (typeof entry === "string") {
69
+ return [dataUri, entry];
70
+ }
71
+ if (Array.isArray(entry)) {
72
+ return [dataUri, ...entry];
73
+ }
74
+ if (!entry || typeof entry !== "object") {
75
+ return entry;
76
+ }
77
+ const entryConfig = entry;
78
+ if (entryConfig.import) {
79
+ return {
80
+ ...entryConfig,
81
+ import: Array.isArray(entryConfig.import) ? [dataUri, ...entryConfig.import] : [dataUri, entryConfig.import]
82
+ };
83
+ }
84
+ return Object.fromEntries(
85
+ Object.entries(entryConfig).map(([name, value]) => [
86
+ name,
87
+ prependPluginClientPublicPathEntry(value, packageName, clientDistDir)
88
+ ])
89
+ );
90
+ }
91
+ class AutoInjectPublicPathPlugin {
92
+ constructor(pluginName, clientDistDir = "client") {
93
+ this.pluginName = pluginName;
94
+ this.clientDistDir = clientDistDir;
95
+ }
96
+ apply(compiler) {
97
+ compiler.hooks.environment.tap("AutoInjectPublicPathPlugin", () => {
98
+ compiler.options.entry = prependPluginClientPublicPathEntry(
99
+ compiler.options.entry,
100
+ this.pluginName,
101
+ this.clientDistDir
102
+ );
103
+ });
104
+ }
105
+ }
106
+ // Annotate the CommonJS export names for ESM import in node:
107
+ 0 && (module.exports = {
108
+ AutoInjectPublicPathPlugin
109
+ });
@@ -54,7 +54,7 @@ function isNotBuiltinModule(packageName) {
54
54
  return !import_module.builtinModules.includes(packageName);
55
55
  }
56
56
  const isValidPackageName = (str) => {
57
- const pattern = /^(?:@[a-zA-Z0-9_-]+\/)?[a-zA-Z0-9_-]+$/;
57
+ const pattern = /^(?:@[a-zA-Z0-9._-]+\/)?[a-zA-Z0-9._-]+$/;
58
58
  return pattern.test(str);
59
59
  };
60
60
  function getPackageNameFromString(str) {
@@ -76,7 +76,7 @@ function getDepsConfig(cwd, outDir, depsName, external) {
76
76
  acc[depEntryPath] = {
77
77
  nccConfig: {
78
78
  minify: true,
79
- target: "es5",
79
+ target: "es2020",
80
80
  quiet: true,
81
81
  externals: {}
82
82
  },
@@ -28,6 +28,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
28
28
  var getPackages_exports = {};
29
29
  __export(getPackages_exports, {
30
30
  getPackages: () => getPackages,
31
+ groupPackagesByTopoLevel: () => groupPackagesByTopoLevel,
31
32
  sortPackages: () => sortPackages
32
33
  });
33
34
  module.exports = __toCommonJS(getPackages_exports);
@@ -76,8 +77,55 @@ function sortPackages(packages) {
76
77
  }
77
78
  return sorter.nodes;
78
79
  }
80
+ function groupPackagesByTopoLevel(packages) {
81
+ const filteredPackages = packages.filter((pkg) => pkg.name !== "@nocobase/docs");
82
+ const packageMap = new Map(filteredPackages.map((pkg) => [pkg.name, pkg]));
83
+ const dependencyMap = /* @__PURE__ */ new Map();
84
+ const reverseDependencyMap = /* @__PURE__ */ new Map();
85
+ for (const pkg of filteredPackages) {
86
+ const pkgJson = require(`${pkg.location}/package.json`);
87
+ const internalDeps = Object.keys({
88
+ ...pkgJson.dependencies,
89
+ ...pkgJson.devDependencies,
90
+ ...pkgJson.peerDependencies
91
+ }).filter((dep) => packageMap.has(dep));
92
+ dependencyMap.set(pkg.name, new Set(internalDeps));
93
+ for (const dep of internalDeps) {
94
+ if (!reverseDependencyMap.has(dep)) {
95
+ reverseDependencyMap.set(dep, /* @__PURE__ */ new Set());
96
+ }
97
+ reverseDependencyMap.get(dep).add(pkg.name);
98
+ }
99
+ }
100
+ const remainingDeps = new Map(
101
+ Array.from(dependencyMap.entries()).map(([name, deps]) => [name, new Set(deps)])
102
+ );
103
+ const pending = new Set(filteredPackages.map((pkg) => pkg.name));
104
+ const layers = [];
105
+ while (pending.size > 0) {
106
+ const layer = Array.from(pending).filter((name) => (remainingDeps.get(name)?.size ?? 0) === 0).map((name) => packageMap.get(name)).filter(Boolean);
107
+ if (layer.length === 0) {
108
+ throw new Error(
109
+ `Unable to group packages by topo level, possible circular dependency among: ${Array.from(pending).join(", ")}`
110
+ );
111
+ }
112
+ layers.push(layer);
113
+ for (const pkg of layer) {
114
+ pending.delete(pkg.name);
115
+ const dependents = reverseDependencyMap.get(pkg.name);
116
+ if (!dependents) {
117
+ continue;
118
+ }
119
+ for (const dependent of dependents) {
120
+ remainingDeps.get(dependent)?.delete(pkg.name);
121
+ }
122
+ }
123
+ }
124
+ return layers;
125
+ }
79
126
  // Annotate the CommonJS export names for ESM import in node:
80
127
  0 && (module.exports = {
81
128
  getPackages,
129
+ groupPackagesByTopoLevel,
82
130
  sortPackages
83
131
  });
@@ -27,17 +27,25 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
  var utils_exports = {};
29
29
  __export(utils_exports, {
30
+ createBuildProfileCollector: () => createBuildProfileCollector,
30
31
  defineConfig: () => defineConfig,
32
+ formatDuration: () => formatDuration,
31
33
  getEnvDefine: () => getEnvDefine,
32
34
  getPackageJson: () => getPackageJson,
33
35
  getPkgLog: () => getPkgLog,
34
36
  getUserConfig: () => getUserConfig,
37
+ nowMs: () => nowMs,
38
+ printBuildProfile: () => printBuildProfile,
35
39
  readFromCache: () => readFromCache,
40
+ runProfiledStage: () => runProfiledStage,
41
+ runScript: () => runScript,
42
+ runWithConcurrency: () => runWithConcurrency,
36
43
  toUnixPath: () => toUnixPath,
37
44
  writeToCache: () => writeToCache
38
45
  });
39
46
  module.exports = __toCommonJS(utils_exports);
40
47
  var import_chalk = __toESM(require("chalk"));
48
+ var import_execa = __toESM(require("execa"));
41
49
  var import_path = __toESM(require("path"));
42
50
  var import_fast_glob = __toESM(require("fast-glob"));
43
51
  var import_fs_extra = __toESM(require("fs-extra"));
@@ -86,7 +94,7 @@ function defineConfig(config) {
86
94
  function getUserConfig(cwd) {
87
95
  const config = defineConfig({
88
96
  modifyTsupConfig: (config2) => config2,
89
- modifyViteConfig: (config2) => config2
97
+ modifyRsbuildConfig: (config2) => config2
90
98
  });
91
99
  const buildConfigs = import_fast_glob.default.sync(["build.config.js", "build.config.ts"], { cwd });
92
100
  if (buildConfigs.length > 1) {
@@ -121,14 +129,128 @@ function getEnvDefine() {
121
129
  "process.env.APP_ENV": process.env.APP_ENV
122
130
  };
123
131
  }
132
+ function createBuildProfileCollector() {
133
+ return {
134
+ stages: [],
135
+ layers: [],
136
+ packages: []
137
+ };
138
+ }
139
+ async function runProfiledStage(profile, stageName, task) {
140
+ const startedAt = nowMs();
141
+ await task();
142
+ if (profile) {
143
+ profile.stages.push({
144
+ name: stageName,
145
+ durationMs: nowMs() - startedAt
146
+ });
147
+ }
148
+ }
149
+ async function runWithConcurrency(items, concurrency, worker) {
150
+ const queue = [...items];
151
+ const workers = Array.from({ length: Math.min(concurrency, queue.length) }, async () => {
152
+ while (queue.length > 0) {
153
+ const item = queue.shift();
154
+ if (!item) {
155
+ return;
156
+ }
157
+ await worker(item);
158
+ }
159
+ });
160
+ await Promise.all(workers);
161
+ }
162
+ function printBuildProfile(profile, totalDurationMs) {
163
+ const phaseTotals = /* @__PURE__ */ new Map();
164
+ for (const pkg of profile.packages) {
165
+ for (const [phaseName, duration] of Object.entries(pkg.phases)) {
166
+ phaseTotals.set(phaseName, (phaseTotals.get(phaseName) || 0) + duration);
167
+ }
168
+ }
169
+ console.log(import_chalk.default.cyan(`[@nocobase/build:profile] total build time ${formatDuration(totalDurationMs)}`));
170
+ if (profile.stages.length > 0) {
171
+ console.log(import_chalk.default.cyan("[@nocobase/build:profile] stage totals"));
172
+ for (const stage of [...profile.stages].sort((a, b) => b.durationMs - a.durationMs)) {
173
+ console.log(import_chalk.default.gray(` ${stage.name}: ${formatDuration(stage.durationMs)}`));
174
+ }
175
+ }
176
+ if (profile.layers.length > 0) {
177
+ console.log(import_chalk.default.cyan("[@nocobase/build:profile] slowest layers"));
178
+ for (const layer of [...profile.layers].sort((a, b) => b.durationMs - a.durationMs).slice(0, 12)) {
179
+ console.log(
180
+ import_chalk.default.gray(
181
+ ` ${layer.stageName} layer ${layer.layerIndex}/${layer.layerCount} (${layer.packageCount} packages): ${formatDuration(layer.durationMs)}`
182
+ )
183
+ );
184
+ }
185
+ }
186
+ if (phaseTotals.size > 0) {
187
+ console.log(import_chalk.default.cyan("[@nocobase/build:profile] aggregated package phases"));
188
+ for (const [phaseName, duration] of [...phaseTotals.entries()].sort((a, b) => b[1] - a[1])) {
189
+ console.log(import_chalk.default.gray(` ${phaseName}: ${formatDuration(duration)}`));
190
+ }
191
+ }
192
+ if (profile.packages.length > 0) {
193
+ const sourcePackages = profile.packages.filter((pkg) => pkg.kind === "source");
194
+ const declarationPackages = profile.packages.filter((pkg) => pkg.kind === "declaration");
195
+ console.log(import_chalk.default.cyan("[@nocobase/build:profile] slowest source packages"));
196
+ for (const pkg of [...sourcePackages].sort((a, b) => b.durationMs - a.durationMs).slice(0, 20)) {
197
+ const summary = Object.entries(pkg.phases).sort((a, b) => b[1] - a[1]).slice(0, 4).map(([name, duration]) => `${name}=${formatDuration(duration)}`).join(", ");
198
+ console.log(
199
+ import_chalk.default.gray(
200
+ ` ${pkg.name} [${pkg.status}] ${formatDuration(pkg.durationMs)}${summary ? ` (${summary})` : ""}`
201
+ )
202
+ );
203
+ }
204
+ console.log(import_chalk.default.cyan("[@nocobase/build:profile] slowest declaration packages"));
205
+ for (const pkg of [...declarationPackages].sort((a, b) => b.durationMs - a.durationMs).slice(0, 20)) {
206
+ const summary = Object.entries(pkg.phases).sort((a, b) => b[1] - a[1]).slice(0, 4).map(([name, duration]) => `${name}=${formatDuration(duration)}`).join(", ");
207
+ console.log(
208
+ import_chalk.default.gray(
209
+ ` ${pkg.name} [${pkg.status}] ${formatDuration(pkg.durationMs)}${summary ? ` (${summary})` : ""}`
210
+ )
211
+ );
212
+ }
213
+ }
214
+ }
215
+ function nowMs() {
216
+ return Date.now();
217
+ }
218
+ function formatDuration(durationMs) {
219
+ if (durationMs >= 6e4) {
220
+ return `${(durationMs / 6e4).toFixed(2)}m`;
221
+ }
222
+ if (durationMs >= 1e3) {
223
+ return `${(durationMs / 1e3).toFixed(2)}s`;
224
+ }
225
+ return `${Math.round(durationMs)}ms`;
226
+ }
227
+ function runScript(args, cwd, envs = {}) {
228
+ return (0, import_execa.default)("yarn", args, {
229
+ cwd,
230
+ stdio: "inherit",
231
+ env: {
232
+ ...process.env,
233
+ ...envs,
234
+ sourcemap: process.argv.includes("--sourcemap") ? "sourcemap" : void 0,
235
+ NODE_ENV: process.env.NODE_ENV || "production"
236
+ }
237
+ });
238
+ }
124
239
  // Annotate the CommonJS export names for ESM import in node:
125
240
  0 && (module.exports = {
241
+ createBuildProfileCollector,
126
242
  defineConfig,
243
+ formatDuration,
127
244
  getEnvDefine,
128
245
  getPackageJson,
129
246
  getPkgLog,
130
247
  getUserConfig,
248
+ nowMs,
249
+ printBuildProfile,
131
250
  readFromCache,
251
+ runProfiledStage,
252
+ runScript,
253
+ runWithConcurrency,
132
254
  toUnixPath,
133
255
  writeToCache
134
256
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/build",
3
- "version": "2.1.0-beta.14",
3
+ "version": "2.1.0-beta.16",
4
4
  "description": "Library build tool based on rollup.",
5
5
  "main": "lib/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -15,9 +15,13 @@
15
15
  "@babel/preset-env": "^7.26.0",
16
16
  "@hapi/topo": "^6.0.0",
17
17
  "@lerna/project": "4.0.0",
18
+ "@rsbuild/core": "1.7.3",
18
19
  "@rsbuild/plugin-babel": "^1.0.3",
20
+ "@rsbuild/plugin-less": "^1.6.2",
21
+ "@rsbuild/plugin-react": "1.4.6",
22
+ "@rsbuild/plugin-svgr": "^1.3.1",
19
23
  "@rsdoctor/rspack-plugin": "^0.4.8",
20
- "@rspack/core": "1.3.2",
24
+ "@rspack/core": "1.7.8",
21
25
  "@svgr/webpack": "^8.1.0",
22
26
  "@types/lerna__package": "5.1.0",
23
27
  "@types/lerna__project": "5.1.0",
@@ -42,8 +46,6 @@
42
46
  "tsup": "8.2.4",
43
47
  "typescript": "5.1.3",
44
48
  "update-notifier": "3.0.0",
45
- "vite-plugin-css-injected-by-js": "^3.2.1",
46
- "vite-plugin-lib-inject-css": "1.2.0",
47
49
  "yargs-parser": "13.1.2"
48
50
  },
49
51
  "license": "Apache-2.0",
@@ -51,5 +53,5 @@
51
53
  "build": "tsup",
52
54
  "build:watch": "tsup --watch"
53
55
  },
54
- "gitHead": "cd55c9a14596d834c30c83a82c38f1f719f7aac4"
56
+ "gitHead": "b9a191705a440a336c85d82fd877fdf152bec70f"
55
57
  }