@4399ywkf/core 5.0.18 → 5.0.19
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/cli/index.js +550 -640
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.js +8 -13
- package/dist/config/index.js.map +1 -1
- package/dist/index.d.ts +249 -184
- package/dist/index.js +2143 -2122
- package/dist/index.js.map +1 -1
- package/dist/plugin/index.d.ts +3 -3
- package/dist/plugin/index.js +10 -28
- package/dist/plugin/index.js.map +1 -1
- package/dist/router/index.js +34 -61
- package/dist/router/index.js.map +1 -1
- package/dist/rspack/index.d.ts +2 -2
- package/dist/rspack/index.js +99 -155
- package/dist/rspack/index.js.map +1 -1
- package/dist/runtime/index.d.ts +57 -57
- package/dist/runtime/index.js +11 -15
- package/dist/runtime/index.js.map +1 -1
- package/dist/{schema-VPH72NAR.d.ts → schema-CGQSqjRr.d.ts} +12 -12
- package/dist/{types-BztKUufh.d.ts → types-DbUq-VY8.d.ts} +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
// src/cli/build.ts
|
|
2
|
+
import { rspack as rspack3 } from "@rspack/core";
|
|
3
|
+
import chalk2 from "chalk";
|
|
4
|
+
|
|
5
|
+
// src/config/loader.ts
|
|
6
|
+
import { existsSync } from "fs";
|
|
7
|
+
import { extname, resolve } from "path";
|
|
8
|
+
import { pathToFileURL } from "url";
|
|
9
|
+
import deepmerge from "deepmerge";
|
|
10
|
+
|
|
1
11
|
// src/config/schema.ts
|
|
2
12
|
function defineConfig(config) {
|
|
3
13
|
return config;
|
|
@@ -61,16 +71,7 @@ var defaultConfig = {
|
|
|
61
71
|
};
|
|
62
72
|
|
|
63
73
|
// src/config/loader.ts
|
|
64
|
-
|
|
65
|
-
import { resolve, extname } from "path";
|
|
66
|
-
import { pathToFileURL } from "url";
|
|
67
|
-
import deepmerge from "deepmerge";
|
|
68
|
-
var CONFIG_FILES = [
|
|
69
|
-
"ywkf.config.ts",
|
|
70
|
-
"ywkf.config.mts",
|
|
71
|
-
"ywkf.config.js",
|
|
72
|
-
"ywkf.config.mjs"
|
|
73
|
-
];
|
|
74
|
+
var CONFIG_FILES = ["ywkf.config.ts", "ywkf.config.mts", "ywkf.config.js", "ywkf.config.mjs"];
|
|
74
75
|
function findConfigFile(cwd) {
|
|
75
76
|
for (const file of CONFIG_FILES) {
|
|
76
77
|
const configPath = resolve(cwd, file);
|
|
@@ -108,9 +109,7 @@ function mergeConfig(userConfig, baseConfig = defaultConfig) {
|
|
|
108
109
|
async function resolveConfig(cwd) {
|
|
109
110
|
const configPath = findConfigFile(cwd);
|
|
110
111
|
if (!configPath) {
|
|
111
|
-
console.warn(
|
|
112
|
-
"\u26A0\uFE0F \u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6 (ywkf.config.ts)\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E"
|
|
113
|
-
);
|
|
112
|
+
console.warn("\u26A0\uFE0F \u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6 (ywkf.config.ts)\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E");
|
|
114
113
|
return {
|
|
115
114
|
config: defaultConfig,
|
|
116
115
|
configPath: null
|
|
@@ -132,36 +131,257 @@ function createPathResolver(cwd) {
|
|
|
132
131
|
};
|
|
133
132
|
}
|
|
134
133
|
|
|
134
|
+
// src/plugin/manager.ts
|
|
135
|
+
function createLogger(pluginName) {
|
|
136
|
+
const prefix = `[${pluginName}]`;
|
|
137
|
+
const verbose = !!process.env.DEBUG;
|
|
138
|
+
return {
|
|
139
|
+
info: (msg) => {
|
|
140
|
+
if (verbose) console.log(`${prefix} ${msg}`);
|
|
141
|
+
},
|
|
142
|
+
warn: (msg) => console.warn(`${prefix} ${msg}`),
|
|
143
|
+
error: (msg) => console.error(`${prefix} ${msg}`),
|
|
144
|
+
debug: (msg) => {
|
|
145
|
+
if (verbose) console.debug(`${prefix} ${msg}`);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
async function resolvePlugin(pluginConfig, _cwd) {
|
|
150
|
+
let plugin;
|
|
151
|
+
let options = {};
|
|
152
|
+
if (typeof pluginConfig === "string") {
|
|
153
|
+
const module = await import(pluginConfig);
|
|
154
|
+
plugin = module.default || module;
|
|
155
|
+
} else if (Array.isArray(pluginConfig)) {
|
|
156
|
+
const [pluginOrName, pluginOptions] = pluginConfig;
|
|
157
|
+
options = pluginOptions;
|
|
158
|
+
if (typeof pluginOrName === "string") {
|
|
159
|
+
const module = await import(pluginOrName);
|
|
160
|
+
plugin = module.default || module;
|
|
161
|
+
} else {
|
|
162
|
+
plugin = pluginOrName;
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
plugin = pluginConfig;
|
|
166
|
+
}
|
|
167
|
+
if (typeof plugin === "function") {
|
|
168
|
+
plugin = plugin(options);
|
|
169
|
+
}
|
|
170
|
+
return { plugin, options };
|
|
171
|
+
}
|
|
172
|
+
var PluginManager = class {
|
|
173
|
+
plugins = /* @__PURE__ */ new Map();
|
|
174
|
+
context;
|
|
175
|
+
constructor(config, cwd, isDev) {
|
|
176
|
+
this.context = {
|
|
177
|
+
cwd,
|
|
178
|
+
isDev,
|
|
179
|
+
isProd: !isDev,
|
|
180
|
+
config,
|
|
181
|
+
logger: createLogger("PluginManager")
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* 加载并初始化所有插件
|
|
186
|
+
*/
|
|
187
|
+
async loadPlugins(pluginConfigs) {
|
|
188
|
+
for (const pluginConfig of pluginConfigs) {
|
|
189
|
+
try {
|
|
190
|
+
const { plugin } = await resolvePlugin(pluginConfig, this.context.cwd);
|
|
191
|
+
if (this.plugins.has(plugin.name)) {
|
|
192
|
+
this.context.logger.warn(`\u63D2\u4EF6 ${plugin.name} \u5DF2\u52A0\u8F7D\uFF0C\u8DF3\u8FC7\u91CD\u590D\u52A0\u8F7D`);
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
const pluginContext = {
|
|
196
|
+
...this.context,
|
|
197
|
+
logger: createLogger(plugin.name)
|
|
198
|
+
};
|
|
199
|
+
const hooks = await plugin.setup(pluginContext);
|
|
200
|
+
this.plugins.set(plugin.name, { plugin, hooks });
|
|
201
|
+
this.context.logger.info(`\u5DF2\u52A0\u8F7D\u63D2\u4EF6: ${plugin.name}`);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
this.context.logger.error(`\u52A0\u8F7D\u63D2\u4EF6\u5931\u8D25: ${String(pluginConfig)} - ${error}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* 执行 modifyRspackConfig 钩子
|
|
209
|
+
*/
|
|
210
|
+
async applyRspackConfigHooks(config) {
|
|
211
|
+
let result = config;
|
|
212
|
+
for (const [name, { hooks }] of this.plugins) {
|
|
213
|
+
if (hooks.modifyRspackConfig) {
|
|
214
|
+
try {
|
|
215
|
+
const modified = await hooks.modifyRspackConfig(result, this.context);
|
|
216
|
+
if (modified) {
|
|
217
|
+
result = modified;
|
|
218
|
+
}
|
|
219
|
+
} catch (error) {
|
|
220
|
+
this.context.logger.error(`\u63D2\u4EF6 ${name} modifyRspackConfig \u6267\u884C\u5931\u8D25: ${error}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* 执行 modifyRoutes 钩子
|
|
228
|
+
*/
|
|
229
|
+
async applyRoutesHooks(routes) {
|
|
230
|
+
let result = routes;
|
|
231
|
+
for (const [name, { hooks }] of this.plugins) {
|
|
232
|
+
if (hooks.modifyRoutes) {
|
|
233
|
+
try {
|
|
234
|
+
const modified = await hooks.modifyRoutes(result, this.context);
|
|
235
|
+
if (modified) {
|
|
236
|
+
result = modified;
|
|
237
|
+
}
|
|
238
|
+
} catch (error) {
|
|
239
|
+
this.context.logger.error(`\u63D2\u4EF6 ${name} modifyRoutes \u6267\u884C\u5931\u8D25: ${error}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return result;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* 执行 modifyAppConfig 钩子
|
|
247
|
+
*/
|
|
248
|
+
applyAppConfigHooks(appConfig) {
|
|
249
|
+
let result = appConfig;
|
|
250
|
+
for (const [name, { hooks }] of this.plugins) {
|
|
251
|
+
if (hooks.modifyAppConfig) {
|
|
252
|
+
try {
|
|
253
|
+
const modified = hooks.modifyAppConfig(result, this.context);
|
|
254
|
+
if (modified) {
|
|
255
|
+
result = modified;
|
|
256
|
+
}
|
|
257
|
+
} catch (error) {
|
|
258
|
+
this.context.logger.error(`\u63D2\u4EF6 ${name} modifyAppConfig \u6267\u884C\u5931\u8D25: ${error}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* 收集所有插件的 Provider
|
|
266
|
+
*/
|
|
267
|
+
collectProviders() {
|
|
268
|
+
const providers = [];
|
|
269
|
+
for (const [name, { hooks }] of this.plugins) {
|
|
270
|
+
if (hooks.addProvider) {
|
|
271
|
+
try {
|
|
272
|
+
const result = hooks.addProvider(this.context);
|
|
273
|
+
if (Array.isArray(result)) {
|
|
274
|
+
providers.push(...result);
|
|
275
|
+
} else if (result) {
|
|
276
|
+
providers.push(result);
|
|
277
|
+
}
|
|
278
|
+
} catch (error) {
|
|
279
|
+
this.context.logger.error(`\u63D2\u4EF6 ${name} addProvider \u6267\u884C\u5931\u8D25: ${error}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return providers;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* 执行 beforeBuild 钩子
|
|
287
|
+
*/
|
|
288
|
+
async runBeforeBuild() {
|
|
289
|
+
for (const [name, { hooks }] of this.plugins) {
|
|
290
|
+
if (hooks.beforeBuild) {
|
|
291
|
+
try {
|
|
292
|
+
await hooks.beforeBuild(this.context);
|
|
293
|
+
} catch (error) {
|
|
294
|
+
this.context.logger.error(`\u63D2\u4EF6 ${name} beforeBuild \u6267\u884C\u5931\u8D25: ${error}`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* 执行 afterBuild 钩子
|
|
301
|
+
*/
|
|
302
|
+
async runAfterBuild(stats) {
|
|
303
|
+
for (const [name, { hooks }] of this.plugins) {
|
|
304
|
+
if (hooks.afterBuild) {
|
|
305
|
+
try {
|
|
306
|
+
await hooks.afterBuild(this.context, stats);
|
|
307
|
+
} catch (error) {
|
|
308
|
+
this.context.logger.error(`\u63D2\u4EF6 ${name} afterBuild \u6267\u884C\u5931\u8D25: ${error}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* 执行 beforeDevServer 钩子
|
|
315
|
+
*/
|
|
316
|
+
async runBeforeDevServer() {
|
|
317
|
+
for (const [name, { hooks }] of this.plugins) {
|
|
318
|
+
if (hooks.beforeDevServer) {
|
|
319
|
+
try {
|
|
320
|
+
await hooks.beforeDevServer(this.context);
|
|
321
|
+
} catch (error) {
|
|
322
|
+
this.context.logger.error(`\u63D2\u4EF6 ${name} beforeDevServer \u6267\u884C\u5931\u8D25: ${error}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* 执行 afterDevServer 钩子
|
|
329
|
+
*/
|
|
330
|
+
async runAfterDevServer(server) {
|
|
331
|
+
for (const [name, { hooks }] of this.plugins) {
|
|
332
|
+
if (hooks.afterDevServer) {
|
|
333
|
+
try {
|
|
334
|
+
await hooks.afterDevServer(this.context, server);
|
|
335
|
+
} catch (error) {
|
|
336
|
+
this.context.logger.error(`\u63D2\u4EF6 ${name} afterDevServer \u6267\u884C\u5931\u8D25: ${error}`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* 获取所有已加载的插件名称
|
|
343
|
+
*/
|
|
344
|
+
getPluginNames() {
|
|
345
|
+
return Array.from(this.plugins.keys());
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* 获取所有已加载的插件
|
|
349
|
+
*/
|
|
350
|
+
getPlugins() {
|
|
351
|
+
return Array.from(this.plugins.values()).map((p) => p.plugin);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* 获取所有已加载的插件钩子
|
|
355
|
+
*/
|
|
356
|
+
getPluginHooks() {
|
|
357
|
+
return Array.from(this.plugins.values()).map((p) => p.hooks);
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
|
|
135
361
|
// src/rspack/index.ts
|
|
136
362
|
import { RsdoctorRspackPlugin } from "@rsdoctor/rspack-plugin";
|
|
137
363
|
|
|
138
364
|
// src/rspack/dev.ts
|
|
365
|
+
import { createRequire as createRequire2 } from "module";
|
|
139
366
|
import ReactRefreshPlugin from "@rspack/plugin-react-refresh";
|
|
140
367
|
import { merge } from "webpack-merge";
|
|
141
|
-
import { createRequire as createRequire2 } from "module";
|
|
142
368
|
|
|
143
369
|
// src/rspack/base.ts
|
|
144
|
-
import { rspack } from "@rspack/core";
|
|
145
370
|
import { createRequire } from "module";
|
|
146
|
-
import { fileURLToPath } from "url";
|
|
147
371
|
import { dirname, join as join5 } from "path";
|
|
372
|
+
import { fileURLToPath } from "url";
|
|
373
|
+
import { rspack } from "@rspack/core";
|
|
148
374
|
|
|
149
375
|
// src/generator/plugin.ts
|
|
150
|
-
import {
|
|
376
|
+
import { existsSync as existsSync5, watch } from "fs";
|
|
151
377
|
import { join as join4 } from "path";
|
|
152
378
|
|
|
153
379
|
// src/generator/generator.ts
|
|
154
|
-
import { existsSync as existsSync4, mkdirSync as mkdirSync2,
|
|
380
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
155
381
|
import { join as join3 } from "path";
|
|
156
382
|
|
|
157
383
|
// src/router/generator.ts
|
|
158
|
-
import {
|
|
159
|
-
existsSync as existsSync2,
|
|
160
|
-
readdirSync,
|
|
161
|
-
statSync,
|
|
162
|
-
mkdirSync,
|
|
163
|
-
writeFileSync
|
|
164
|
-
} from "fs";
|
|
384
|
+
import { existsSync as existsSync2, mkdirSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
165
385
|
import { join, relative } from "path";
|
|
166
386
|
function winPath(path) {
|
|
167
387
|
const isExtendedLengthPath = /^\\\\\?\\/.test(path);
|
|
@@ -221,9 +441,7 @@ var ConventionalRouteGenerator = class {
|
|
|
221
441
|
const subDirPath = join(dir, subDir);
|
|
222
442
|
if (subDir.startsWith("__")) {
|
|
223
443
|
const pathlessRoutes = this.scanDirectory(subDirPath, routePath);
|
|
224
|
-
const pathlessLayout = readdirSync(subDirPath).find(
|
|
225
|
-
(e) => CONVENTION_FILES.layout.test(e)
|
|
226
|
-
);
|
|
444
|
+
const pathlessLayout = readdirSync(subDirPath).find((e) => CONVENTION_FILES.layout.test(e));
|
|
227
445
|
if (pathlessLayout) {
|
|
228
446
|
const pathlessChildren = this.scanDirectory(subDirPath, routePath);
|
|
229
447
|
const pathlessLayoutRel = winPath(
|
|
@@ -235,9 +453,7 @@ var ConventionalRouteGenerator = class {
|
|
|
235
453
|
layoutFile: pathlessLayoutRel,
|
|
236
454
|
isLayout: true,
|
|
237
455
|
pathless: true,
|
|
238
|
-
children: pathlessChildren.filter(
|
|
239
|
-
(r) => r.layoutFile !== pathlessLayoutRel
|
|
240
|
-
)
|
|
456
|
+
children: pathlessChildren.filter((r) => r.layoutFile !== pathlessLayoutRel)
|
|
241
457
|
});
|
|
242
458
|
} else {
|
|
243
459
|
childRoutes.push(...pathlessRoutes);
|
|
@@ -255,7 +471,7 @@ var ConventionalRouteGenerator = class {
|
|
|
255
471
|
layoutChildren.push({
|
|
256
472
|
path: routePath,
|
|
257
473
|
file: relPath(pageFile),
|
|
258
|
-
name: routeName
|
|
474
|
+
name: `${routeName}Index`,
|
|
259
475
|
index: true
|
|
260
476
|
});
|
|
261
477
|
}
|
|
@@ -263,7 +479,7 @@ var ConventionalRouteGenerator = class {
|
|
|
263
479
|
layoutChildren.push({
|
|
264
480
|
path: "*",
|
|
265
481
|
file: relPath(catchAllFile),
|
|
266
|
-
name: routeName
|
|
482
|
+
name: `${routeName}CatchAll`
|
|
267
483
|
});
|
|
268
484
|
}
|
|
269
485
|
layoutChildren.push(...childRoutes);
|
|
@@ -292,7 +508,7 @@ var ConventionalRouteGenerator = class {
|
|
|
292
508
|
result.push({
|
|
293
509
|
path: "*",
|
|
294
510
|
file: relPath(catchAllFile),
|
|
295
|
-
name: routeName
|
|
511
|
+
name: `${routeName}CatchAll`
|
|
296
512
|
});
|
|
297
513
|
}
|
|
298
514
|
result.push(...childRoutes);
|
|
@@ -327,15 +543,13 @@ var ConventionalRouteGenerator = class {
|
|
|
327
543
|
* 生成有效的 JS 标识符名称
|
|
328
544
|
*/
|
|
329
545
|
generateRouteName(path) {
|
|
330
|
-
const name = path.split("/").filter(Boolean).map(
|
|
331
|
-
(s) => s.replace(/^:/, "Param").replace(/\?$/, "Optional").replace(/^\*$/, "CatchAll")
|
|
332
|
-
).map((s) => {
|
|
546
|
+
const name = path.split("/").filter(Boolean).map((s) => s.replace(/^:/, "Param").replace(/\?$/, "Optional").replace(/^\*$/, "CatchAll")).map((s) => {
|
|
333
547
|
const cleaned = s.replace(/[^a-zA-Z0-9]/g, "");
|
|
334
548
|
if (!cleaned) return "";
|
|
335
549
|
return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);
|
|
336
550
|
}).join("");
|
|
337
551
|
if (!name || /^\d/.test(name)) {
|
|
338
|
-
return
|
|
552
|
+
return `Page${name || "Root"}`;
|
|
339
553
|
}
|
|
340
554
|
return name;
|
|
341
555
|
}
|
|
@@ -354,8 +568,12 @@ import { createBrowserRouter, type RouteObject } from "react-router";
|
|
|
354
568
|
|
|
355
569
|
// \u61D2\u52A0\u8F7D\u9875\u9762\u7EC4\u4EF6
|
|
356
570
|
${lazyImports.join("\n")}
|
|
357
|
-
${errorImports.length > 0 ?
|
|
358
|
-
|
|
571
|
+
${errorImports.length > 0 ? `
|
|
572
|
+
// \u9519\u8BEF\u8FB9\u754C\u7EC4\u4EF6
|
|
573
|
+
${errorImports.join("\n")}` : ""}
|
|
574
|
+
${loadingImports.length > 0 ? `
|
|
575
|
+
// \u52A0\u8F7D\u72B6\u6001\u7EC4\u4EF6
|
|
576
|
+
${loadingImports.join("\n")}` : ""}
|
|
359
577
|
|
|
360
578
|
// \u9ED8\u8BA4\u52A0\u8F7D\u72B6\u6001
|
|
361
579
|
const DefaultLoading = () => <div style={{ padding: 24, textAlign: "center" }}>\u52A0\u8F7D\u4E2D...</div>;
|
|
@@ -394,23 +612,17 @@ export default routes;
|
|
|
394
612
|
const toImportPath = (f) => f.replace(/\.(tsx?|jsx?)$/, "");
|
|
395
613
|
if (route.isLayout && route.layoutFile) {
|
|
396
614
|
lazyImports.push(
|
|
397
|
-
`const ${name}Layout = lazy(() => import("@/pages/${toImportPath(
|
|
398
|
-
route.layoutFile
|
|
399
|
-
)}"));`
|
|
615
|
+
`const ${name}Layout = lazy(() => import("@/pages/${toImportPath(route.layoutFile)}"));`
|
|
400
616
|
);
|
|
401
617
|
}
|
|
402
618
|
if (route.file) {
|
|
403
619
|
lazyImports.push(
|
|
404
|
-
`const ${name}Page = lazy(() => import("@/pages/${toImportPath(
|
|
405
|
-
route.file
|
|
406
|
-
)}"));`
|
|
620
|
+
`const ${name}Page = lazy(() => import("@/pages/${toImportPath(route.file)}"));`
|
|
407
621
|
);
|
|
408
622
|
}
|
|
409
623
|
if (route.errorFile) {
|
|
410
624
|
errorImports.push(
|
|
411
|
-
`const ${name}Error = lazy(() => import("@/pages/${toImportPath(
|
|
412
|
-
route.errorFile
|
|
413
|
-
)}"));`
|
|
625
|
+
`const ${name}Error = lazy(() => import("@/pages/${toImportPath(route.errorFile)}"));`
|
|
414
626
|
);
|
|
415
627
|
}
|
|
416
628
|
if (route.loadingFile) {
|
|
@@ -421,12 +633,7 @@ export default routes;
|
|
|
421
633
|
);
|
|
422
634
|
}
|
|
423
635
|
if (route.children) {
|
|
424
|
-
this.collectImports(
|
|
425
|
-
route.children,
|
|
426
|
-
lazyImports,
|
|
427
|
-
errorImports,
|
|
428
|
-
loadingImports
|
|
429
|
-
);
|
|
636
|
+
this.collectImports(route.children, lazyImports, errorImports, loadingImports);
|
|
430
637
|
}
|
|
431
638
|
}
|
|
432
639
|
}
|
|
@@ -452,9 +659,7 @@ export default routes;
|
|
|
452
659
|
}
|
|
453
660
|
if (route.isLayout && route.layoutFile) {
|
|
454
661
|
const loadingProp = route.loadingFile ? ` Loading={${name}Loading}` : "";
|
|
455
|
-
parts.push(
|
|
456
|
-
`element: <LazyRoute Component={${name}Layout}${loadingProp} />`
|
|
457
|
-
);
|
|
662
|
+
parts.push(`element: <LazyRoute Component={${name}Layout}${loadingProp} />`);
|
|
458
663
|
} else if (route.file) {
|
|
459
664
|
parts.push(`element: <LazyRoute Component={${name}Page} />`);
|
|
460
665
|
}
|
|
@@ -463,9 +668,7 @@ export default routes;
|
|
|
463
668
|
}
|
|
464
669
|
if (route.children && route.children.length > 0) {
|
|
465
670
|
const childParent = route.pathless ? parentPath : route.path;
|
|
466
|
-
parts.push(
|
|
467
|
-
`children: ${this.emitRouteArray(route.children, childParent)}`
|
|
468
|
-
);
|
|
671
|
+
parts.push(`children: ${this.emitRouteArray(route.children, childParent)}`);
|
|
469
672
|
}
|
|
470
673
|
return `{
|
|
471
674
|
${parts.join(",\n ")}
|
|
@@ -488,53 +691,13 @@ function generateConventionalRoutes(options) {
|
|
|
488
691
|
new ConventionalRouteGenerator(options).write();
|
|
489
692
|
}
|
|
490
693
|
|
|
491
|
-
// src/generator/templates/
|
|
492
|
-
function
|
|
694
|
+
// src/generator/templates/bootstrap.ts
|
|
695
|
+
function generateBootstrap(config, injections = {}) {
|
|
696
|
+
const { appName, router } = config;
|
|
697
|
+
const routerImport = router.conventional ? `import { createRouter } from "./routes";` : `import { createRouter } from "@/routes";`;
|
|
493
698
|
const imports = [
|
|
494
|
-
`import "
|
|
495
|
-
|
|
496
|
-
...injections.imports || []
|
|
497
|
-
];
|
|
498
|
-
const topLevel = injections.topLevel || [];
|
|
499
|
-
const exports = injections.exports || [];
|
|
500
|
-
const hasPluginExports = exports.length > 0;
|
|
501
|
-
const hasAsyncTopLevel = topLevel.some((line) => line.includes("await "));
|
|
502
|
-
let startupBody;
|
|
503
|
-
if (hasPluginExports) {
|
|
504
|
-
startupBody = [
|
|
505
|
-
...topLevel,
|
|
506
|
-
...exports,
|
|
507
|
-
``,
|
|
508
|
-
`if (shouldRunIndependently !== false) {`,
|
|
509
|
-
` runApp();`,
|
|
510
|
-
`}`
|
|
511
|
-
].join("\n");
|
|
512
|
-
} else if (hasAsyncTopLevel) {
|
|
513
|
-
startupBody = [
|
|
514
|
-
`(async () => {`,
|
|
515
|
-
...topLevel.map((l) => ` ${l}`),
|
|
516
|
-
` await runApp();`,
|
|
517
|
-
`})();`
|
|
518
|
-
].join("\n");
|
|
519
|
-
} else {
|
|
520
|
-
startupBody = topLevel.length > 0 ? [...topLevel, `runApp();`].join("\n") : `runApp();`;
|
|
521
|
-
}
|
|
522
|
-
return `// \u6B64\u6587\u4EF6\u7531 @4399ywkf/core \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u4FEE\u6539
|
|
523
|
-
// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
524
|
-
|
|
525
|
-
${imports.join("\n")}
|
|
526
|
-
|
|
527
|
-
${startupBody}
|
|
528
|
-
`;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// src/generator/templates/bootstrap.ts
|
|
532
|
-
function generateBootstrap(config, injections = {}) {
|
|
533
|
-
const { appName, router } = config;
|
|
534
|
-
const routerImport = router.conventional ? `import { createRouter } from "./routes";` : `import { createRouter } from "@/routes";`;
|
|
535
|
-
const imports = [
|
|
536
|
-
`import { bootstrap, type AppConfig } from "@4399ywkf/core/runtime";`,
|
|
537
|
-
routerImport,
|
|
699
|
+
`import { bootstrap, type AppConfig } from "@4399ywkf/core/runtime";`,
|
|
700
|
+
routerImport,
|
|
538
701
|
...injections.imports || []
|
|
539
702
|
];
|
|
540
703
|
const topLevel = injections.topLevel || [];
|
|
@@ -616,8 +779,50 @@ export async function runApp(): Promise<void> {
|
|
|
616
779
|
const userConfig = await getUserConfig();
|
|
617
780
|
await bootstrap(createAppConfig(userConfig));
|
|
618
781
|
}
|
|
619
|
-
${topLevel.length > 0 ?
|
|
620
|
-
${
|
|
782
|
+
${topLevel.length > 0 ? `
|
|
783
|
+
${topLevel.join("\n")}` : ""}
|
|
784
|
+
${exports.length > 0 ? `
|
|
785
|
+
${exports.join("\n")}` : ""}
|
|
786
|
+
`;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// src/generator/templates/entry.ts
|
|
790
|
+
function generateEntry(_config, injections = {}) {
|
|
791
|
+
const imports = [
|
|
792
|
+
`import "@/index.css";`,
|
|
793
|
+
`import { runApp } from "./bootstrap";`,
|
|
794
|
+
...injections.imports || []
|
|
795
|
+
];
|
|
796
|
+
const topLevel = injections.topLevel || [];
|
|
797
|
+
const exports = injections.exports || [];
|
|
798
|
+
const hasPluginExports = exports.length > 0;
|
|
799
|
+
const hasAsyncTopLevel = topLevel.some((line) => line.includes("await "));
|
|
800
|
+
let startupBody;
|
|
801
|
+
if (hasPluginExports) {
|
|
802
|
+
startupBody = [
|
|
803
|
+
...topLevel,
|
|
804
|
+
...exports,
|
|
805
|
+
``,
|
|
806
|
+
`if (shouldRunIndependently !== false) {`,
|
|
807
|
+
` runApp();`,
|
|
808
|
+
`}`
|
|
809
|
+
].join("\n");
|
|
810
|
+
} else if (hasAsyncTopLevel) {
|
|
811
|
+
startupBody = [
|
|
812
|
+
`(async () => {`,
|
|
813
|
+
...topLevel.map((l) => ` ${l}`),
|
|
814
|
+
` await runApp();`,
|
|
815
|
+
`})();`
|
|
816
|
+
].join("\n");
|
|
817
|
+
} else {
|
|
818
|
+
startupBody = topLevel.length > 0 ? [...topLevel, `runApp();`].join("\n") : `runApp();`;
|
|
819
|
+
}
|
|
820
|
+
return `// \u6B64\u6587\u4EF6\u7531 @4399ywkf/core \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u4FEE\u6539
|
|
821
|
+
// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
822
|
+
|
|
823
|
+
${imports.join("\n")}
|
|
824
|
+
|
|
825
|
+
${startupBody}
|
|
621
826
|
`;
|
|
622
827
|
}
|
|
623
828
|
|
|
@@ -781,17 +986,14 @@ var YwkfGenerator = class {
|
|
|
781
986
|
const { outputDir, config } = this.context;
|
|
782
987
|
const configPath = join3(outputDir, "config.json");
|
|
783
988
|
const serializableConfig = JSON.parse(
|
|
784
|
-
JSON.stringify(config, (
|
|
989
|
+
JSON.stringify(config, (_key, value) => {
|
|
785
990
|
if (typeof value === "function") {
|
|
786
991
|
return "[Function]";
|
|
787
992
|
}
|
|
788
993
|
return value;
|
|
789
994
|
})
|
|
790
995
|
);
|
|
791
|
-
this.writeFileIfChanged(
|
|
792
|
-
configPath,
|
|
793
|
-
JSON.stringify(serializableConfig, null, 2)
|
|
794
|
-
);
|
|
996
|
+
this.writeFileIfChanged(configPath, JSON.stringify(serializableConfig, null, 2));
|
|
795
997
|
}
|
|
796
998
|
/**
|
|
797
999
|
* 生成约定式路由
|
|
@@ -895,16 +1097,10 @@ var YwkfGenerator = class {
|
|
|
895
1097
|
generateTypes() {
|
|
896
1098
|
const { outputDir, config, cwd } = this.context;
|
|
897
1099
|
const envTypesContent = generateEnvTypes(cwd, config);
|
|
898
|
-
this.writeFileIfChanged(
|
|
899
|
-
join3(outputDir, "types", "env.d.ts"),
|
|
900
|
-
envTypesContent
|
|
901
|
-
);
|
|
1100
|
+
this.writeFileIfChanged(join3(outputDir, "types", "env.d.ts"), envTypesContent);
|
|
902
1101
|
if (config.router.conventional) {
|
|
903
1102
|
const routeTypesContent = generateRouteTypes();
|
|
904
|
-
this.writeFileIfChanged(
|
|
905
|
-
join3(outputDir, "types", "routes.d.ts"),
|
|
906
|
-
routeTypesContent
|
|
907
|
-
);
|
|
1103
|
+
this.writeFileIfChanged(join3(outputDir, "types", "routes.d.ts"), routeTypesContent);
|
|
908
1104
|
}
|
|
909
1105
|
}
|
|
910
1106
|
/**
|
|
@@ -1039,7 +1235,7 @@ var YwkfGeneratorPlugin = class {
|
|
|
1039
1235
|
}
|
|
1040
1236
|
apply(compiler) {
|
|
1041
1237
|
const pluginName = "YwkfGeneratorPlugin";
|
|
1042
|
-
compiler.hooks.beforeCompile.tapAsync(pluginName, async (
|
|
1238
|
+
compiler.hooks.beforeCompile.tapAsync(pluginName, async (_params, callback) => {
|
|
1043
1239
|
try {
|
|
1044
1240
|
await this.initialize();
|
|
1045
1241
|
if (!this.hasGenerated && this.generator) {
|
|
@@ -1067,24 +1263,20 @@ var YwkfGeneratorPlugin = class {
|
|
|
1067
1263
|
}
|
|
1068
1264
|
this.isWatching = true;
|
|
1069
1265
|
let debounceTimer = null;
|
|
1070
|
-
const watcher = watch(
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
(eventType, filename) => {
|
|
1074
|
-
if (!filename?.match(/\.(tsx?|jsx?)$/)) {
|
|
1075
|
-
return;
|
|
1076
|
-
}
|
|
1077
|
-
if (debounceTimer) {
|
|
1078
|
-
clearTimeout(debounceTimer);
|
|
1079
|
-
}
|
|
1080
|
-
debounceTimer = setTimeout(async () => {
|
|
1081
|
-
if (process.env.DEBUG) console.log(`[ywkf] \u68C0\u6D4B\u5230\u9875\u9762\u53D8\u5316: ${filename}`);
|
|
1082
|
-
if (this.generator) {
|
|
1083
|
-
await this.generator.generate();
|
|
1084
|
-
}
|
|
1085
|
-
}, 500);
|
|
1266
|
+
const watcher = watch(pagesDir, { recursive: true }, (_eventType, filename) => {
|
|
1267
|
+
if (!filename?.match(/\.(tsx?|jsx?)$/)) {
|
|
1268
|
+
return;
|
|
1086
1269
|
}
|
|
1087
|
-
|
|
1270
|
+
if (debounceTimer) {
|
|
1271
|
+
clearTimeout(debounceTimer);
|
|
1272
|
+
}
|
|
1273
|
+
debounceTimer = setTimeout(async () => {
|
|
1274
|
+
if (process.env.DEBUG) console.log(`[ywkf] \u68C0\u6D4B\u5230\u9875\u9762\u53D8\u5316: ${filename}`);
|
|
1275
|
+
if (this.generator) {
|
|
1276
|
+
await this.generator.generate();
|
|
1277
|
+
}
|
|
1278
|
+
}, 500);
|
|
1279
|
+
});
|
|
1088
1280
|
process.on("exit", () => {
|
|
1089
1281
|
watcher.close();
|
|
1090
1282
|
});
|
|
@@ -1115,8 +1307,10 @@ var YwkfGeneratorPlugin = class {
|
|
|
1115
1307
|
this.resetState();
|
|
1116
1308
|
await this.initialize();
|
|
1117
1309
|
await this.regenerate();
|
|
1118
|
-
console.log(
|
|
1119
|
-
`
|
|
1310
|
+
console.log(
|
|
1311
|
+
` [ywkf] .ywkf \u76EE\u5F55\u5DF2\u91CD\u65B0\u751F\u6210\u3002\u90E8\u5206\u914D\u7F6E\u53D8\u66F4\uFF08\u5982\u7AEF\u53E3\u3001\u4EE3\u7406\uFF09\u9700\u91CD\u542F dev server \u751F\u6548\u3002
|
|
1312
|
+
`
|
|
1313
|
+
);
|
|
1120
1314
|
} catch (error) {
|
|
1121
1315
|
console.error(` [ywkf] \u914D\u7F6E\u91CD\u8F7D\u5931\u8D25:`, error);
|
|
1122
1316
|
}
|
|
@@ -1135,15 +1329,7 @@ var coreNodeModules = join5(__dirname, "../../node_modules");
|
|
|
1135
1329
|
function createBaseConfig(config, cwd, options = {}) {
|
|
1136
1330
|
const isDev = options.isDev ?? process.env.NODE_ENV !== "production";
|
|
1137
1331
|
const { resolveApp } = createPathResolver(cwd);
|
|
1138
|
-
const {
|
|
1139
|
-
appName,
|
|
1140
|
-
appCName,
|
|
1141
|
-
output,
|
|
1142
|
-
html,
|
|
1143
|
-
alias: userAlias,
|
|
1144
|
-
microFrontend,
|
|
1145
|
-
router
|
|
1146
|
-
} = config;
|
|
1332
|
+
const { appName, appCName, output, html, alias: userAlias, microFrontend, router } = config;
|
|
1147
1333
|
const ywkfOutputDir = resolveApp(".ywkf");
|
|
1148
1334
|
const defaultAlias = {
|
|
1149
1335
|
"@": resolveApp("src"),
|
|
@@ -1319,7 +1505,7 @@ function createBaseConfig(config, cwd, options = {}) {
|
|
|
1319
1505
|
}
|
|
1320
1506
|
|
|
1321
1507
|
// src/rspack/dev.ts
|
|
1322
|
-
var
|
|
1508
|
+
var _require = createRequire2(import.meta.url);
|
|
1323
1509
|
function convertProxyToArray(proxy) {
|
|
1324
1510
|
if (!proxy || Object.keys(proxy).length === 0) {
|
|
1325
1511
|
return void 0;
|
|
@@ -1350,10 +1536,7 @@ function createDevConfig(config, cwd) {
|
|
|
1350
1536
|
// Less - antd
|
|
1351
1537
|
{
|
|
1352
1538
|
test: /\.less$/,
|
|
1353
|
-
include: [
|
|
1354
|
-
/[\\/]node_modules[\\/].*antd/,
|
|
1355
|
-
/[\\/]node_modules[\\/]@4399ywkf[\\/]design/
|
|
1356
|
-
],
|
|
1539
|
+
include: [/[\\/]node_modules[\\/].*antd/, /[\\/]node_modules[\\/]@4399ywkf[\\/]design/],
|
|
1357
1540
|
use: [
|
|
1358
1541
|
{ loader: "style-loader" },
|
|
1359
1542
|
{
|
|
@@ -1526,9 +1709,7 @@ function createDevConfig(config, cwd) {
|
|
|
1526
1709
|
clean: false
|
|
1527
1710
|
},
|
|
1528
1711
|
stats: "errors-only",
|
|
1529
|
-
plugins: [
|
|
1530
|
-
new ReactRefreshPlugin()
|
|
1531
|
-
],
|
|
1712
|
+
plugins: [new ReactRefreshPlugin()],
|
|
1532
1713
|
devServer: {
|
|
1533
1714
|
host: dev2.host,
|
|
1534
1715
|
port: dev2.port,
|
|
@@ -1559,10 +1740,7 @@ function createProdConfig(config, cwd) {
|
|
|
1559
1740
|
// Less - antd
|
|
1560
1741
|
{
|
|
1561
1742
|
test: /\.less$/,
|
|
1562
|
-
include: [
|
|
1563
|
-
/[\\/]node_modules[\\/].*antd/,
|
|
1564
|
-
/[\\/]node_modules[\\/]@4399ywkf[\\/]design/
|
|
1565
|
-
],
|
|
1743
|
+
include: [/[\\/]node_modules[\\/].*antd/, /[\\/]node_modules[\\/]@4399ywkf[\\/]design/],
|
|
1566
1744
|
use: [
|
|
1567
1745
|
{ loader: rspack2.CssExtractRspackPlugin.loader },
|
|
1568
1746
|
{
|
|
@@ -1778,10 +1956,7 @@ function createRspackConfig(config, cwd, options = {}) {
|
|
|
1778
1956
|
const isDev = options.isDev ?? process.env.NODE_ENV !== "production";
|
|
1779
1957
|
let rspackConfig = isDev ? createDevConfig(config, cwd) : createProdConfig(config, cwd);
|
|
1780
1958
|
if (config.performance.rsdoctor) {
|
|
1781
|
-
rspackConfig.plugins = [
|
|
1782
|
-
...rspackConfig.plugins || [],
|
|
1783
|
-
new RsdoctorRspackPlugin({})
|
|
1784
|
-
];
|
|
1959
|
+
rspackConfig.plugins = [...rspackConfig.plugins || [], new RsdoctorRspackPlugin({})];
|
|
1785
1960
|
}
|
|
1786
1961
|
if (config.tools.rspack) {
|
|
1787
1962
|
const userConfig = config.tools.rspack(rspackConfig, {
|
|
@@ -1795,477 +1970,484 @@ function createRspackConfig(config, cwd, options = {}) {
|
|
|
1795
1970
|
return rspackConfig;
|
|
1796
1971
|
}
|
|
1797
1972
|
|
|
1798
|
-
// src/
|
|
1799
|
-
import {
|
|
1800
|
-
import {
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
this.hasGenerated = true;
|
|
1815
|
-
}
|
|
1816
|
-
callback();
|
|
1817
|
-
});
|
|
1818
|
-
if (this.options.watch && !this.isWatching) {
|
|
1819
|
-
this.watchPages();
|
|
1973
|
+
// src/cli/env.ts
|
|
1974
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3 } from "fs";
|
|
1975
|
+
import { resolve as resolve2 } from "path";
|
|
1976
|
+
import dotenv from "dotenv";
|
|
1977
|
+
function preloadEnv(cwd, mode, nodeEnv) {
|
|
1978
|
+
process.env.NODE_ENV = nodeEnv;
|
|
1979
|
+
process.env.APP_MODE = mode;
|
|
1980
|
+
const defaultPaths = [
|
|
1981
|
+
resolve2(cwd, "config/env/.env.public"),
|
|
1982
|
+
resolve2(cwd, ".env.public"),
|
|
1983
|
+
resolve2(cwd, ".env")
|
|
1984
|
+
];
|
|
1985
|
+
for (const envPath of defaultPaths) {
|
|
1986
|
+
if (existsSync6(envPath)) {
|
|
1987
|
+
dotenv.config({ path: envPath });
|
|
1988
|
+
break;
|
|
1820
1989
|
}
|
|
1821
1990
|
}
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
const
|
|
1828
|
-
|
|
1829
|
-
outputDir: this.options.outputDir,
|
|
1830
|
-
basename: this.options.basename
|
|
1831
|
-
});
|
|
1832
|
-
const newContent = generator.generateCode();
|
|
1833
|
-
const outputPath = join6(this.options.outputDir, "routes.tsx");
|
|
1834
|
-
const normalizedNew = this.normalizeContent(newContent);
|
|
1835
|
-
const normalizedOld = this.normalizeContent(this.lastGeneratedContent);
|
|
1836
|
-
if (normalizedNew === normalizedOld) {
|
|
1837
|
-
return;
|
|
1991
|
+
const modeEnvPaths = [resolve2(cwd, `config/env/.env.${mode}`), resolve2(cwd, `.env.${mode}`)];
|
|
1992
|
+
for (const envPath of modeEnvPaths) {
|
|
1993
|
+
if (existsSync6(envPath)) {
|
|
1994
|
+
const envContent = readFileSync3(envPath, "utf-8");
|
|
1995
|
+
const parsed = dotenv.parse(envContent);
|
|
1996
|
+
for (const key in parsed) {
|
|
1997
|
+
process.env[key] = parsed[key];
|
|
1838
1998
|
}
|
|
1839
|
-
|
|
1840
|
-
this.lastGeneratedContent = newContent;
|
|
1841
|
-
} catch (error) {
|
|
1842
|
-
console.error("[ywkf] \u751F\u6210\u8DEF\u7531\u5931\u8D25:", error);
|
|
1999
|
+
break;
|
|
1843
2000
|
}
|
|
1844
2001
|
}
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
2002
|
+
process.env.NODE_ENV = nodeEnv;
|
|
2003
|
+
process.env.APP_MODE = mode;
|
|
2004
|
+
}
|
|
2005
|
+
function loadEnv(config, cwd, mode, nodeEnv) {
|
|
2006
|
+
const { env } = config;
|
|
2007
|
+
const publicEnvPath = resolve2(cwd, env.publicEnvFile ?? "config/env/.env.public");
|
|
2008
|
+
if (existsSync6(publicEnvPath)) {
|
|
2009
|
+
dotenv.config({ path: publicEnvPath });
|
|
1850
2010
|
}
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
2011
|
+
const modeEnvPath = resolve2(cwd, env.envDir ?? "config/env", `.env.${mode}`);
|
|
2012
|
+
if (existsSync6(modeEnvPath)) {
|
|
2013
|
+
const envContent = readFileSync3(modeEnvPath, "utf-8");
|
|
2014
|
+
const parsed = dotenv.parse(envContent);
|
|
2015
|
+
for (const key in parsed) {
|
|
2016
|
+
process.env[key] = parsed[key];
|
|
1857
2017
|
}
|
|
1858
|
-
this.isWatching = true;
|
|
1859
|
-
let debounceTimer = null;
|
|
1860
|
-
const watcher = watch2(
|
|
1861
|
-
this.options.pagesDir,
|
|
1862
|
-
{ recursive: true },
|
|
1863
|
-
(eventType, filename) => {
|
|
1864
|
-
if (!filename?.match(/\.(tsx?|jsx?)$/)) {
|
|
1865
|
-
return;
|
|
1866
|
-
}
|
|
1867
|
-
if (debounceTimer) {
|
|
1868
|
-
clearTimeout(debounceTimer);
|
|
1869
|
-
}
|
|
1870
|
-
debounceTimer = setTimeout(() => {
|
|
1871
|
-
if (process.env.DEBUG) console.log(`[ywkf] \u68C0\u6D4B\u5230\u9875\u9762\u53D8\u5316: ${filename}`);
|
|
1872
|
-
this.generateRoutes();
|
|
1873
|
-
}, 500);
|
|
1874
|
-
}
|
|
1875
|
-
);
|
|
1876
|
-
process.on("exit", () => {
|
|
1877
|
-
watcher.close();
|
|
1878
|
-
});
|
|
1879
2018
|
}
|
|
1880
|
-
|
|
2019
|
+
process.env.NODE_ENV = nodeEnv;
|
|
2020
|
+
process.env.APP_MODE = mode;
|
|
2021
|
+
process.env.APP_NAME = process.env.APP_NAME || config.appName;
|
|
2022
|
+
process.env.APP_CNAME = process.env.APP_CNAME || config.appCName;
|
|
2023
|
+
process.env.OUTPUT_PATH = process.env.OUTPUT_PATH || config.output.path;
|
|
2024
|
+
process.env.PUBLIC_PATH = process.env.PUBLIC_PATH || config.output.publicPath;
|
|
2025
|
+
process.env.APP_HOST = process.env.APP_HOST || config.dev.host;
|
|
2026
|
+
process.env.APP_PORT = process.env.APP_PORT || String(config.dev.port);
|
|
2027
|
+
}
|
|
1881
2028
|
|
|
1882
|
-
// src/
|
|
1883
|
-
import {
|
|
1884
|
-
import
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
var
|
|
1892
|
-
function
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
}
|
|
1903
|
-
};
|
|
1904
|
-
return /* @__PURE__ */ jsx(AppContext.Provider, { value: contextValue, children });
|
|
2029
|
+
// src/cli/printer.ts
|
|
2030
|
+
import { createRequire as createRequire3 } from "module";
|
|
2031
|
+
import os from "os";
|
|
2032
|
+
import { dirname as dirname2, join as join6 } from "path";
|
|
2033
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2034
|
+
import chalk from "chalk";
|
|
2035
|
+
var __filename = fileURLToPath2(import.meta.url);
|
|
2036
|
+
var __dirname2 = dirname2(__filename);
|
|
2037
|
+
var require3 = createRequire3(import.meta.url);
|
|
2038
|
+
var _version = null;
|
|
2039
|
+
function getFrameworkVersion() {
|
|
2040
|
+
if (_version) return _version;
|
|
2041
|
+
try {
|
|
2042
|
+
const pkgPath = join6(__dirname2, "../../package.json");
|
|
2043
|
+
const pkg = require3(pkgPath);
|
|
2044
|
+
_version = pkg.version || "0.0.0";
|
|
2045
|
+
} catch {
|
|
2046
|
+
_version = "0.0.0";
|
|
2047
|
+
}
|
|
2048
|
+
return _version;
|
|
1905
2049
|
}
|
|
1906
|
-
function
|
|
1907
|
-
const
|
|
1908
|
-
|
|
1909
|
-
|
|
2050
|
+
function getNetworkAddress(port) {
|
|
2051
|
+
const interfaces = os.networkInterfaces();
|
|
2052
|
+
for (const entries of Object.values(interfaces)) {
|
|
2053
|
+
if (!entries) continue;
|
|
2054
|
+
for (const entry of entries) {
|
|
2055
|
+
if (entry.family === "IPv4" && !entry.internal) {
|
|
2056
|
+
return `http://${entry.address}:${port}/`;
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
1910
2059
|
}
|
|
1911
|
-
return
|
|
2060
|
+
return null;
|
|
1912
2061
|
}
|
|
1913
|
-
|
|
1914
|
-
|
|
2062
|
+
var BAR_WIDTH = 30;
|
|
2063
|
+
function renderBar(percent) {
|
|
2064
|
+
const filled = Math.round(BAR_WIDTH * percent);
|
|
2065
|
+
const empty = BAR_WIDTH - filled;
|
|
2066
|
+
const bar = chalk.green("\u2501".repeat(filled)) + chalk.gray("\u2501".repeat(empty));
|
|
2067
|
+
return bar;
|
|
1915
2068
|
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
function useIsDev() {
|
|
1923
|
-
return useApp().isDev;
|
|
1924
|
-
}
|
|
1925
|
-
|
|
1926
|
-
// src/runtime/error-boundary.tsx
|
|
1927
|
-
import { Component } from "react";
|
|
1928
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
1929
|
-
var ErrorBoundary = class extends Component {
|
|
1930
|
-
constructor(props) {
|
|
1931
|
-
super(props);
|
|
1932
|
-
this.state = { hasError: false, error: null };
|
|
2069
|
+
var DevPrinter = class {
|
|
2070
|
+
constructor(_host, port, pluginNames, isBuild = false) {
|
|
2071
|
+
this._host = _host;
|
|
2072
|
+
this.port = port;
|
|
2073
|
+
this.pluginNames = pluginNames;
|
|
2074
|
+
this.isBuild = isBuild;
|
|
1933
2075
|
}
|
|
1934
|
-
|
|
1935
|
-
|
|
2076
|
+
startTime = 0;
|
|
2077
|
+
lastProgressLine = "";
|
|
2078
|
+
firstCompileDone = false;
|
|
2079
|
+
/**
|
|
2080
|
+
* 打印框架 banner
|
|
2081
|
+
*/
|
|
2082
|
+
printBanner() {
|
|
2083
|
+
const version = getFrameworkVersion();
|
|
2084
|
+
console.log();
|
|
2085
|
+
console.log(` ${chalk.bold.cyan("@4399ywkf/core")} ${chalk.green(`Framework v${version}`)}`);
|
|
2086
|
+
console.log();
|
|
1936
2087
|
}
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
2088
|
+
/**
|
|
2089
|
+
* 打印 "start build started..."
|
|
2090
|
+
*/
|
|
2091
|
+
printBuildStart() {
|
|
2092
|
+
this.startTime = Date.now();
|
|
2093
|
+
this.compileDone = false;
|
|
2094
|
+
const label = chalk.gray("start");
|
|
2095
|
+
console.log(` ${label} build started...`);
|
|
1940
2096
|
}
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
const
|
|
1946
|
-
const
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
2097
|
+
/**
|
|
2098
|
+
* 更新编译进度条(原地覆写同一行)
|
|
2099
|
+
*/
|
|
2100
|
+
updateProgress(percent, message) {
|
|
2101
|
+
const pct = Math.min(Math.round(percent * 100), 100);
|
|
2102
|
+
const bar = renderBar(percent);
|
|
2103
|
+
const status = message || "compiling";
|
|
2104
|
+
const line = ` ${chalk.yellow("\u25CF")} client ${bar} ${chalk.bold(`(${pct}%)`)} ${chalk.gray(status)}`;
|
|
2105
|
+
if (process.stdout.isTTY) {
|
|
2106
|
+
if (this.lastProgressLine) {
|
|
2107
|
+
process.stdout.write("\x1B[1A\x1B[2K");
|
|
1950
2108
|
}
|
|
1951
|
-
|
|
1952
|
-
|
|
2109
|
+
process.stdout.write(`${line}
|
|
2110
|
+
`);
|
|
2111
|
+
} else if (!this.firstCompileDone && pct === 100) {
|
|
2112
|
+
console.log(line);
|
|
2113
|
+
}
|
|
2114
|
+
this.lastProgressLine = line;
|
|
2115
|
+
}
|
|
2116
|
+
/**
|
|
2117
|
+
* 编译完成
|
|
2118
|
+
*/
|
|
2119
|
+
printBuildDone(hasErrors = false) {
|
|
2120
|
+
if (this.firstCompileDone) {
|
|
2121
|
+
if (!hasErrors) {
|
|
2122
|
+
const elapsed2 = ((Date.now() - this.startTime) / 1e3).toFixed(2);
|
|
2123
|
+
console.log(` ${chalk.green("hmr")} update in ${chalk.bold(`${elapsed2} s`)}`);
|
|
1953
2124
|
}
|
|
1954
|
-
return
|
|
2125
|
+
return;
|
|
2126
|
+
}
|
|
2127
|
+
this.firstCompileDone = true;
|
|
2128
|
+
this.lastProgressLine = "";
|
|
2129
|
+
if (hasErrors) return;
|
|
2130
|
+
const elapsed = ((Date.now() - this.startTime) / 1e3).toFixed(2);
|
|
2131
|
+
const label = chalk.green("ready");
|
|
2132
|
+
console.log(` ${label} built in ${chalk.bold(`${elapsed} s`)}`);
|
|
2133
|
+
console.log();
|
|
2134
|
+
if (this.isBuild) {
|
|
2135
|
+
this.printPluginList();
|
|
2136
|
+
} else {
|
|
2137
|
+
this.printServerInfo();
|
|
1955
2138
|
}
|
|
1956
|
-
return children;
|
|
1957
2139
|
}
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
style: {
|
|
1977
|
-
maxWidth: 600,
|
|
1978
|
-
padding: 32,
|
|
1979
|
-
backgroundColor: "#fff",
|
|
1980
|
-
borderRadius: 8,
|
|
1981
|
-
boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
|
|
1982
|
-
},
|
|
1983
|
-
children: [
|
|
1984
|
-
/* @__PURE__ */ jsx2("h1", { style: { color: "#ff4d4f", marginBottom: 16 }, children: "\u9875\u9762\u51FA\u9519\u4E86" }),
|
|
1985
|
-
/* @__PURE__ */ jsx2("p", { style: { color: "#666", marginBottom: 16 }, children: "\u62B1\u6B49\uFF0C\u9875\u9762\u9047\u5230\u4E86\u4E00\u4E9B\u95EE\u9898\u3002\u8BF7\u5C1D\u8BD5\u5237\u65B0\u9875\u9762\u6216\u8054\u7CFB\u7BA1\u7406\u5458\u3002" }),
|
|
1986
|
-
isDev && /* @__PURE__ */ jsxs(
|
|
1987
|
-
"details",
|
|
1988
|
-
{
|
|
1989
|
-
style: {
|
|
1990
|
-
marginBottom: 16,
|
|
1991
|
-
padding: 12,
|
|
1992
|
-
backgroundColor: "#fff2f0",
|
|
1993
|
-
borderRadius: 4,
|
|
1994
|
-
border: "1px solid #ffccc7"
|
|
1995
|
-
},
|
|
1996
|
-
children: [
|
|
1997
|
-
/* @__PURE__ */ jsx2("summary", { style: { cursor: "pointer", fontWeight: "bold" }, children: "\u9519\u8BEF\u8BE6\u60C5\uFF08\u4EC5\u5F00\u53D1\u73AF\u5883\u53EF\u89C1\uFF09" }),
|
|
1998
|
-
/* @__PURE__ */ jsxs(
|
|
1999
|
-
"pre",
|
|
2000
|
-
{
|
|
2001
|
-
style: {
|
|
2002
|
-
marginTop: 8,
|
|
2003
|
-
padding: 8,
|
|
2004
|
-
backgroundColor: "#fff",
|
|
2005
|
-
borderRadius: 4,
|
|
2006
|
-
overflow: "auto",
|
|
2007
|
-
fontSize: 12
|
|
2008
|
-
},
|
|
2009
|
-
children: [
|
|
2010
|
-
error.message,
|
|
2011
|
-
"\n\n",
|
|
2012
|
-
error.stack
|
|
2013
|
-
]
|
|
2014
|
-
}
|
|
2015
|
-
)
|
|
2016
|
-
]
|
|
2017
|
-
}
|
|
2018
|
-
),
|
|
2019
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8 }, children: [
|
|
2020
|
-
/* @__PURE__ */ jsx2(
|
|
2021
|
-
"button",
|
|
2022
|
-
{
|
|
2023
|
-
onClick: onReset,
|
|
2024
|
-
style: {
|
|
2025
|
-
padding: "8px 16px",
|
|
2026
|
-
backgroundColor: "#1890ff",
|
|
2027
|
-
color: "#fff",
|
|
2028
|
-
border: "none",
|
|
2029
|
-
borderRadius: 4,
|
|
2030
|
-
cursor: "pointer"
|
|
2031
|
-
},
|
|
2032
|
-
children: "\u91CD\u8BD5"
|
|
2033
|
-
}
|
|
2034
|
-
),
|
|
2035
|
-
/* @__PURE__ */ jsx2(
|
|
2036
|
-
"button",
|
|
2037
|
-
{
|
|
2038
|
-
onClick: () => window.location.reload(),
|
|
2039
|
-
style: {
|
|
2040
|
-
padding: "8px 16px",
|
|
2041
|
-
backgroundColor: "#fff",
|
|
2042
|
-
color: "#666",
|
|
2043
|
-
border: "1px solid #d9d9d9",
|
|
2044
|
-
borderRadius: 4,
|
|
2045
|
-
cursor: "pointer"
|
|
2046
|
-
},
|
|
2047
|
-
children: "\u5237\u65B0\u9875\u9762"
|
|
2048
|
-
}
|
|
2049
|
-
)
|
|
2050
|
-
] })
|
|
2051
|
-
]
|
|
2052
|
-
}
|
|
2053
|
-
)
|
|
2140
|
+
/**
|
|
2141
|
+
* 标记新一轮编译开始(HMR)
|
|
2142
|
+
*/
|
|
2143
|
+
markRebuildStart() {
|
|
2144
|
+
this.startTime = Date.now();
|
|
2145
|
+
this.lastProgressLine = "";
|
|
2146
|
+
}
|
|
2147
|
+
/**
|
|
2148
|
+
* 仅打印插件列表(build 模式使用)
|
|
2149
|
+
*/
|
|
2150
|
+
printPluginList() {
|
|
2151
|
+
if (this.pluginNames.length > 0) {
|
|
2152
|
+
console.log(` ${chalk.bold(">")} Plugins:`);
|
|
2153
|
+
for (const name of this.pluginNames) {
|
|
2154
|
+
const shortName = name.replace("@4399ywkf/plugin-", "").replace("@4399ywkf/", "");
|
|
2155
|
+
console.log(` ${chalk.green("\u2713")} ${shortName}`);
|
|
2156
|
+
}
|
|
2157
|
+
console.log();
|
|
2054
2158
|
}
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
import zhCN from "antd/locale/zh_CN.js";
|
|
2066
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
2067
|
-
function DefaultLoading() {
|
|
2068
|
-
return /* @__PURE__ */ jsx3(
|
|
2069
|
-
"div",
|
|
2070
|
-
{
|
|
2071
|
-
style: {
|
|
2072
|
-
display: "flex",
|
|
2073
|
-
alignItems: "center",
|
|
2074
|
-
justifyContent: "center",
|
|
2075
|
-
height: "100vh",
|
|
2076
|
-
fontSize: 16,
|
|
2077
|
-
color: "#999"
|
|
2078
|
-
},
|
|
2079
|
-
children: "\u52A0\u8F7D\u4E2D..."
|
|
2159
|
+
}
|
|
2160
|
+
/**
|
|
2161
|
+
* 打印服务器信息面板(dev 模式使用)
|
|
2162
|
+
*/
|
|
2163
|
+
printServerInfo() {
|
|
2164
|
+
const localUrl = `http://localhost:${this.port}/`;
|
|
2165
|
+
const networkUrl = getNetworkAddress(this.port);
|
|
2166
|
+
console.log(` ${chalk.bold(">")} Local: ${chalk.cyan(localUrl)}`);
|
|
2167
|
+
if (networkUrl) {
|
|
2168
|
+
console.log(` ${chalk.bold(">")} Network: ${chalk.cyan(networkUrl)}`);
|
|
2080
2169
|
}
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
(a, b) => (a.order ?? 100) - (b.order ?? 100)
|
|
2086
|
-
);
|
|
2087
|
-
return function ComposedProviders({ children }) {
|
|
2088
|
-
return sortedProviders.reduceRight((acc, { component: Provider, props }) => {
|
|
2089
|
-
return /* @__PURE__ */ jsx3(Provider, { ...props, children: acc });
|
|
2090
|
-
}, children);
|
|
2091
|
-
};
|
|
2092
|
-
}
|
|
2093
|
-
function RootProvider({ config, children }) {
|
|
2094
|
-
const {
|
|
2095
|
-
appName = "app",
|
|
2096
|
-
router,
|
|
2097
|
-
basename = "/",
|
|
2098
|
-
strictMode = true,
|
|
2099
|
-
antd = { enabled: true },
|
|
2100
|
-
providers = [],
|
|
2101
|
-
lifecycle
|
|
2102
|
-
} = config;
|
|
2103
|
-
const appContextValue = {
|
|
2104
|
-
appName,
|
|
2105
|
-
basename,
|
|
2106
|
-
isDev: process.env.NODE_ENV === "development",
|
|
2107
|
-
env: typeof process !== "undefined" ? process.env : {}
|
|
2108
|
-
};
|
|
2109
|
-
const allProviders = [
|
|
2110
|
-
// 应用上下文 Provider(最外层)
|
|
2111
|
-
{
|
|
2112
|
-
component: AppContextProvider,
|
|
2113
|
-
props: { value: appContextValue },
|
|
2114
|
-
order: 0
|
|
2115
|
-
},
|
|
2116
|
-
// Ant Design ConfigProvider
|
|
2117
|
-
...antd.enabled !== false ? [
|
|
2118
|
-
{
|
|
2119
|
-
component: ConfigProvider,
|
|
2120
|
-
props: {
|
|
2121
|
-
locale: antd.locale || zhCN,
|
|
2122
|
-
theme: antd.theme,
|
|
2123
|
-
...antd.configProvider
|
|
2124
|
-
},
|
|
2125
|
-
order: 10
|
|
2126
|
-
}
|
|
2127
|
-
] : [],
|
|
2128
|
-
// 用户自定义 Providers
|
|
2129
|
-
...providers.map((p) => ({ ...p, order: p.order ?? 50 }))
|
|
2130
|
-
];
|
|
2131
|
-
const ComposedProviders = composeProviders(allProviders);
|
|
2132
|
-
const content = router ? /* @__PURE__ */ jsx3(Suspense, { fallback: /* @__PURE__ */ jsx3(DefaultLoading, {}), children: /* @__PURE__ */ jsx3(RouterProvider, { router }) }) : children;
|
|
2133
|
-
const app = /* @__PURE__ */ jsx3(ErrorBoundary, { onError: lifecycle?.onError, children: /* @__PURE__ */ jsx3(ComposedProviders, { children: content }) });
|
|
2134
|
-
if (strictMode) {
|
|
2135
|
-
return /* @__PURE__ */ jsx3(StrictMode, { children: app });
|
|
2170
|
+
console.log();
|
|
2171
|
+
this.printPluginList();
|
|
2172
|
+
console.log(` ${chalk.bold(">")} press ${chalk.bold("h + enter")} to show shortcuts`);
|
|
2173
|
+
console.log();
|
|
2136
2174
|
}
|
|
2137
|
-
|
|
2175
|
+
/**
|
|
2176
|
+
* 打印快捷键帮助
|
|
2177
|
+
*/
|
|
2178
|
+
printShortcuts() {
|
|
2179
|
+
console.log();
|
|
2180
|
+
console.log(` ${chalk.bold("Shortcuts:")}`);
|
|
2181
|
+
console.log(` ${chalk.bold("o + enter")} open in browser`);
|
|
2182
|
+
console.log(` ${chalk.bold("c + enter")} clear console`);
|
|
2183
|
+
console.log(` ${chalk.bold("q + enter")} quit`);
|
|
2184
|
+
console.log();
|
|
2185
|
+
}
|
|
2186
|
+
};
|
|
2187
|
+
function createProgressHandler(printer) {
|
|
2188
|
+
return (percent, message, ..._details) => {
|
|
2189
|
+
printer.updateProgress(percent, message);
|
|
2190
|
+
};
|
|
2138
2191
|
}
|
|
2139
|
-
function
|
|
2140
|
-
return
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2192
|
+
function registerShortcuts(printer, opts) {
|
|
2193
|
+
if (!process.stdin.isTTY) return;
|
|
2194
|
+
process.stdin.setEncoding("utf-8");
|
|
2195
|
+
process.stdin.setRawMode?.(false);
|
|
2196
|
+
let buffer = "";
|
|
2197
|
+
const handler = (data) => {
|
|
2198
|
+
buffer += data;
|
|
2199
|
+
if (!buffer.includes("\n")) return;
|
|
2200
|
+
const cmd = buffer.trim().toLowerCase();
|
|
2201
|
+
buffer = "";
|
|
2202
|
+
switch (cmd) {
|
|
2203
|
+
case "h":
|
|
2204
|
+
printer.printShortcuts();
|
|
2205
|
+
break;
|
|
2206
|
+
case "o": {
|
|
2207
|
+
const url = `http://localhost:${opts.port}/`;
|
|
2208
|
+
import("child_process").then((cp) => {
|
|
2209
|
+
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
2210
|
+
cp.exec(`${command} ${url}`);
|
|
2211
|
+
});
|
|
2212
|
+
console.log(` ${chalk.green("\u279C")} Opening ${chalk.cyan(url)}...`);
|
|
2213
|
+
break;
|
|
2214
|
+
}
|
|
2215
|
+
case "c":
|
|
2216
|
+
console.clear();
|
|
2217
|
+
break;
|
|
2218
|
+
case "q":
|
|
2219
|
+
opts.onQuit();
|
|
2220
|
+
break;
|
|
2221
|
+
}
|
|
2144
2222
|
};
|
|
2223
|
+
process.stdin.on("data", handler);
|
|
2224
|
+
process.stdin.resume();
|
|
2145
2225
|
}
|
|
2146
2226
|
|
|
2147
|
-
// src/
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
}
|
|
2163
|
-
console.warn("[ywkf] @ywkf/routes \u672A\u5BFC\u51FA createRouter \u51FD\u6570");
|
|
2227
|
+
// src/cli/build.ts
|
|
2228
|
+
function formatSize(bytes) {
|
|
2229
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
2230
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
|
|
2231
|
+
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
2232
|
+
}
|
|
2233
|
+
function printBuildResult(stats) {
|
|
2234
|
+
const info = stats.toJson({
|
|
2235
|
+
assets: true,
|
|
2236
|
+
errors: true,
|
|
2237
|
+
warnings: true
|
|
2238
|
+
});
|
|
2239
|
+
if (info.errors && info.errors.length > 0) {
|
|
2240
|
+
console.log(chalk2.red("\n Compile errors:"));
|
|
2241
|
+
for (const error of info.errors) {
|
|
2242
|
+
console.log(chalk2.red(` ${error.message}`));
|
|
2164
2243
|
}
|
|
2165
|
-
|
|
2166
|
-
console.error("[ywkf] \u52A0\u8F7D\u7EA6\u5B9A\u5F0F\u8DEF\u7531\u5931\u8D25:", error);
|
|
2167
|
-
console.warn("[ywkf] \u8BF7\u786E\u4FDD\u5DF2\u542F\u7528\u7EA6\u5B9A\u5F0F\u8DEF\u7531\u4E14 src/pages \u76EE\u5F55\u5B58\u5728");
|
|
2244
|
+
return;
|
|
2168
2245
|
}
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
if (lifecycle?.onBeforeMount) {
|
|
2175
|
-
await lifecycle.onBeforeMount();
|
|
2246
|
+
if (info.warnings && info.warnings.length > 0) {
|
|
2247
|
+
console.log(chalk2.yellow("\n Warnings:"));
|
|
2248
|
+
for (const warning of info.warnings) {
|
|
2249
|
+
console.log(chalk2.yellow(` ${warning.message}`));
|
|
2250
|
+
}
|
|
2176
2251
|
}
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2252
|
+
console.log(chalk2.bold("\n Build output:"));
|
|
2253
|
+
console.log();
|
|
2254
|
+
const assets = info.assets || [];
|
|
2255
|
+
const sortedAssets = assets.filter((asset) => !asset.name.endsWith(".map")).sort((a, b) => b.size - a.size);
|
|
2256
|
+
for (const asset of sortedAssets.slice(0, 15)) {
|
|
2257
|
+
const sizeColor = asset.size > 500 * 1024 ? chalk2.yellow : chalk2.green;
|
|
2258
|
+
console.log(` ${chalk2.dim(asset.name.padEnd(50))} ${sizeColor(formatSize(asset.size))}`);
|
|
2180
2259
|
}
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
if (lifecycle?.onMounted) {
|
|
2184
|
-
setTimeout(() => {
|
|
2185
|
-
lifecycle.onMounted?.();
|
|
2186
|
-
}, 0);
|
|
2260
|
+
if (sortedAssets.length > 15) {
|
|
2261
|
+
console.log(chalk2.dim(` ... and ${sortedAssets.length - 15} more files`));
|
|
2187
2262
|
}
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2263
|
+
console.log();
|
|
2264
|
+
}
|
|
2265
|
+
async function build(options = {}) {
|
|
2266
|
+
const cwd = options.cwd || process.cwd();
|
|
2267
|
+
const mode = options.mode || "production";
|
|
2268
|
+
try {
|
|
2269
|
+
preloadEnv(cwd, mode, "production");
|
|
2270
|
+
const { config } = await resolveConfig(cwd);
|
|
2271
|
+
loadEnv(config, cwd, mode, "production");
|
|
2272
|
+
const pluginManager = new PluginManager(config, cwd, false);
|
|
2273
|
+
if (config.plugins && config.plugins.length > 0) {
|
|
2274
|
+
await pluginManager.loadPlugins(config.plugins);
|
|
2275
|
+
}
|
|
2276
|
+
await pluginManager.runBeforeBuild();
|
|
2277
|
+
let rspackConfig = createRspackConfig(config, cwd, { isDev: false });
|
|
2278
|
+
rspackConfig = await pluginManager.applyRspackConfigHooks(rspackConfig);
|
|
2279
|
+
const pluginNames = pluginManager.getPluginNames();
|
|
2280
|
+
const printer = new DevPrinter("localhost", 0, pluginNames, true);
|
|
2281
|
+
printer.printBanner();
|
|
2282
|
+
printer.printBuildStart();
|
|
2283
|
+
printer.updateProgress(0, "preparing");
|
|
2284
|
+
rspackConfig.plugins = rspackConfig.plugins || [];
|
|
2285
|
+
rspackConfig.plugins.push(new rspack3.ProgressPlugin(createProgressHandler(printer)));
|
|
2286
|
+
rspackConfig.stats = "none";
|
|
2287
|
+
rspackConfig.infrastructureLogging = { level: "none" };
|
|
2288
|
+
const compiler = rspack3(rspackConfig);
|
|
2289
|
+
const stats = await new Promise((resolve4, reject) => {
|
|
2290
|
+
compiler.run((err, stats2) => {
|
|
2291
|
+
if (err) {
|
|
2292
|
+
reject(err);
|
|
2293
|
+
return;
|
|
2294
|
+
}
|
|
2295
|
+
if (!stats2) {
|
|
2296
|
+
reject(new Error("Build failed: no stats available"));
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
resolve4(stats2);
|
|
2300
|
+
});
|
|
2301
|
+
});
|
|
2302
|
+
await new Promise((resolve4, reject) => {
|
|
2303
|
+
compiler.close((err) => {
|
|
2304
|
+
if (err) reject(err);
|
|
2305
|
+
else resolve4();
|
|
2306
|
+
});
|
|
2307
|
+
});
|
|
2308
|
+
const hasErrors = stats.hasErrors();
|
|
2309
|
+
const statsInfo = stats.toJson({ errors: true });
|
|
2310
|
+
await pluginManager.runAfterBuild({
|
|
2311
|
+
success: !hasErrors,
|
|
2312
|
+
errors: statsInfo.errors?.map((e) => e.message)
|
|
2191
2313
|
});
|
|
2314
|
+
printer.printBuildDone(hasErrors);
|
|
2315
|
+
if (hasErrors) {
|
|
2316
|
+
printBuildResult(stats);
|
|
2317
|
+
process.exit(1);
|
|
2318
|
+
}
|
|
2319
|
+
printBuildResult(stats);
|
|
2320
|
+
} catch (error) {
|
|
2321
|
+
console.error();
|
|
2322
|
+
console.error(chalk2.red(" \u2716 Build failed"));
|
|
2323
|
+
console.error(error);
|
|
2324
|
+
process.exit(1);
|
|
2192
2325
|
}
|
|
2193
2326
|
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2327
|
+
|
|
2328
|
+
// src/cli/dev.ts
|
|
2329
|
+
import { rspack as rspack4 } from "@rspack/core";
|
|
2330
|
+
import { RspackDevServer } from "@rspack/dev-server";
|
|
2331
|
+
import chalk3 from "chalk";
|
|
2332
|
+
|
|
2333
|
+
// src/cli/port.ts
|
|
2334
|
+
import net from "net";
|
|
2335
|
+
function isPortAvailable(port, host) {
|
|
2336
|
+
return new Promise((resolve4) => {
|
|
2337
|
+
const server = net.createServer();
|
|
2338
|
+
server.once("error", (err) => {
|
|
2339
|
+
if (err.code === "EADDRINUSE") {
|
|
2340
|
+
resolve4(false);
|
|
2341
|
+
} else {
|
|
2342
|
+
resolve4(false);
|
|
2343
|
+
}
|
|
2344
|
+
});
|
|
2345
|
+
server.once("listening", () => {
|
|
2346
|
+
server.close(() => resolve4(true));
|
|
2347
|
+
});
|
|
2348
|
+
server.listen(port, host);
|
|
2349
|
+
});
|
|
2350
|
+
}
|
|
2351
|
+
async function getAvailablePort(preferredPort, host) {
|
|
2352
|
+
const MAX_ATTEMPTS = 20;
|
|
2353
|
+
for (let i = 0; i < MAX_ATTEMPTS; i++) {
|
|
2354
|
+
const port = preferredPort + i;
|
|
2355
|
+
const available = await isPortAvailable(port, host);
|
|
2356
|
+
if (available) return port;
|
|
2198
2357
|
}
|
|
2358
|
+
throw new Error(
|
|
2359
|
+
`No available port found in range ${preferredPort}-${preferredPort + MAX_ATTEMPTS - 1}`
|
|
2360
|
+
);
|
|
2199
2361
|
}
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
}
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2362
|
+
|
|
2363
|
+
// src/cli/dev.ts
|
|
2364
|
+
async function dev(options = {}) {
|
|
2365
|
+
const cwd = options.cwd || process.cwd();
|
|
2366
|
+
const mode = options.mode || "development";
|
|
2367
|
+
try {
|
|
2368
|
+
preloadEnv(cwd, mode, "development");
|
|
2369
|
+
const { config } = await resolveConfig(cwd);
|
|
2370
|
+
loadEnv(config, cwd, mode, "development");
|
|
2371
|
+
const pluginManager = new PluginManager(config, cwd, true);
|
|
2372
|
+
if (config.plugins && config.plugins.length > 0) {
|
|
2373
|
+
await pluginManager.loadPlugins(config.plugins);
|
|
2374
|
+
}
|
|
2375
|
+
await pluginManager.runBeforeDevServer();
|
|
2376
|
+
let rspackConfig = createRspackConfig(config, cwd, { isDev: true });
|
|
2377
|
+
rspackConfig = await pluginManager.applyRspackConfigHooks(rspackConfig);
|
|
2378
|
+
const host = config.dev.host || "localhost";
|
|
2379
|
+
const preferredPort = config.dev.port || 3e3;
|
|
2380
|
+
const port = await getAvailablePort(preferredPort, host);
|
|
2381
|
+
const pluginNames = pluginManager.getPluginNames();
|
|
2382
|
+
if (port !== preferredPort) {
|
|
2383
|
+
console.log(chalk3.yellow(` Port ${preferredPort} is in use, using ${port} instead.
|
|
2384
|
+
`));
|
|
2385
|
+
}
|
|
2386
|
+
const printer = new DevPrinter(host, port, pluginNames);
|
|
2387
|
+
printer.printBanner();
|
|
2388
|
+
printer.printBuildStart();
|
|
2389
|
+
printer.updateProgress(0, "preparing");
|
|
2390
|
+
rspackConfig.plugins = rspackConfig.plugins || [];
|
|
2391
|
+
rspackConfig.plugins.push(new rspack4.ProgressPlugin(createProgressHandler(printer)));
|
|
2392
|
+
rspackConfig.stats = "none";
|
|
2393
|
+
rspackConfig.infrastructureLogging = { level: "none" };
|
|
2394
|
+
if (rspackConfig.devServer) {
|
|
2395
|
+
const ds = rspackConfig.devServer;
|
|
2396
|
+
const existingClient = ds.client ?? {};
|
|
2397
|
+
ds.client = {
|
|
2398
|
+
...existingClient,
|
|
2399
|
+
logging: "warn",
|
|
2400
|
+
overlay: false,
|
|
2401
|
+
progress: false
|
|
2402
|
+
};
|
|
2403
|
+
}
|
|
2404
|
+
const compiler = rspack4(rspackConfig);
|
|
2405
|
+
compiler.hooks.done.tap("ywkf-dev-printer", (stats) => {
|
|
2406
|
+
const hasErrors = stats.hasErrors();
|
|
2407
|
+
if (hasErrors) {
|
|
2408
|
+
const info = stats.toJson({ errors: true });
|
|
2409
|
+
console.log();
|
|
2410
|
+
console.log(chalk3.red(" Compile error:"));
|
|
2411
|
+
for (const err of info.errors || []) {
|
|
2412
|
+
console.log(chalk3.red(` ${err.message}`));
|
|
2413
|
+
}
|
|
2414
|
+
console.log();
|
|
2241
2415
|
}
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2416
|
+
printer.printBuildDone(hasErrors);
|
|
2417
|
+
});
|
|
2418
|
+
compiler.hooks.invalid.tap("ywkf-dev-printer", () => {
|
|
2419
|
+
printer.markRebuildStart();
|
|
2420
|
+
printer.updateProgress(0, "rebuilding");
|
|
2421
|
+
});
|
|
2422
|
+
const devServerOptions = {
|
|
2423
|
+
...rspackConfig.devServer || {},
|
|
2424
|
+
host,
|
|
2425
|
+
port
|
|
2426
|
+
};
|
|
2427
|
+
const server = new RspackDevServer(devServerOptions, compiler);
|
|
2428
|
+
await server.start();
|
|
2429
|
+
await pluginManager.runAfterDevServer({ host, port });
|
|
2430
|
+
registerShortcuts(printer, {
|
|
2431
|
+
port,
|
|
2432
|
+
onQuit: async () => {
|
|
2433
|
+
console.log(chalk3.gray("\n Shutting down...\n"));
|
|
2434
|
+
await server.stop();
|
|
2435
|
+
process.exit(0);
|
|
2245
2436
|
}
|
|
2246
|
-
}
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2437
|
+
});
|
|
2438
|
+
const signals = ["SIGINT", "SIGTERM"];
|
|
2439
|
+
for (const signal of signals) {
|
|
2440
|
+
process.on(signal, async () => {
|
|
2441
|
+
await server.stop();
|
|
2442
|
+
process.exit(0);
|
|
2443
|
+
});
|
|
2252
2444
|
}
|
|
2253
|
-
}
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
}
|
|
2259
|
-
if (window.__GARFISH__) {
|
|
2260
|
-
return true;
|
|
2261
|
-
}
|
|
2262
|
-
return false;
|
|
2263
|
-
}
|
|
2264
|
-
function getMicroAppPublicPath() {
|
|
2265
|
-
if (window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__) {
|
|
2266
|
-
return window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
|
|
2445
|
+
} catch (error) {
|
|
2446
|
+
console.error();
|
|
2447
|
+
console.error(chalk3.red(" \u2716 Dev server failed to start"));
|
|
2448
|
+
console.error(error);
|
|
2449
|
+
process.exit(1);
|
|
2267
2450
|
}
|
|
2268
|
-
return "/";
|
|
2269
2451
|
}
|
|
2270
2452
|
|
|
2271
2453
|
// src/plugin/define.ts
|
|
@@ -2276,250 +2458,200 @@ function createPlugin(factory) {
|
|
|
2276
2458
|
return factory;
|
|
2277
2459
|
}
|
|
2278
2460
|
|
|
2279
|
-
// src/plugin/
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2461
|
+
// src/plugin/builtin/analytics.ts
|
|
2462
|
+
var analyticsPlugin = createPlugin((options = {}) => ({
|
|
2463
|
+
name: "@4399ywkf/plugin-analytics",
|
|
2464
|
+
version: "1.0.0",
|
|
2465
|
+
description: "\u6784\u5EFA\u5206\u6790\u63D2\u4EF6",
|
|
2466
|
+
setup(context) {
|
|
2467
|
+
const {
|
|
2468
|
+
buildAnalysis = true,
|
|
2469
|
+
timing = true,
|
|
2470
|
+
bundleSize = true,
|
|
2471
|
+
sizeWarningThreshold = 500
|
|
2472
|
+
} = options;
|
|
2473
|
+
const { logger, isProd } = context;
|
|
2474
|
+
let buildStartTime;
|
|
2475
|
+
const hooks = {
|
|
2476
|
+
beforeBuild() {
|
|
2477
|
+
if (timing) {
|
|
2478
|
+
buildStartTime = Date.now();
|
|
2479
|
+
logger.info("\u5F00\u59CB\u6784\u5EFA...");
|
|
2480
|
+
}
|
|
2481
|
+
},
|
|
2482
|
+
afterBuild(_context, stats) {
|
|
2483
|
+
if (timing) {
|
|
2484
|
+
const duration = Date.now() - buildStartTime;
|
|
2485
|
+
logger.info(`\u6784\u5EFA\u5B8C\u6210\uFF0C\u8017\u65F6: ${(duration / 1e3).toFixed(2)}s`);
|
|
2486
|
+
}
|
|
2487
|
+
if (!stats.success && stats.errors) {
|
|
2488
|
+
logger.error(`\u6784\u5EFA\u5931\u8D25\uFF0C\u9519\u8BEF\u6570: ${stats.errors.length}`);
|
|
2489
|
+
}
|
|
2490
|
+
},
|
|
2491
|
+
modifyRspackConfig(config) {
|
|
2492
|
+
if (buildAnalysis && isProd) {
|
|
2493
|
+
logger.info("\u6784\u5EFA\u5206\u6790\u5DF2\u542F\u7528");
|
|
2494
|
+
}
|
|
2495
|
+
return config;
|
|
2496
|
+
}
|
|
2497
|
+
};
|
|
2498
|
+
return hooks;
|
|
2499
|
+
}
|
|
2500
|
+
}));
|
|
2501
|
+
|
|
2502
|
+
// src/plugin/builtin/biome.ts
|
|
2503
|
+
import { existsSync as existsSync7, writeFileSync as writeFileSync3 } from "fs";
|
|
2504
|
+
import { join as join7 } from "path";
|
|
2505
|
+
var DEFAULT_IGNORE = [".vscode/**/*", "node_modules/**/*", "dist/**/*", ".ywkf/**/*"];
|
|
2506
|
+
var biomePlugin = createPlugin((options = {}) => ({
|
|
2507
|
+
name: "@4399ywkf/plugin-biome",
|
|
2508
|
+
version: "1.0.0",
|
|
2509
|
+
description: "Biome \u4EE3\u7801\u89C4\u8303\u96C6\u6210",
|
|
2510
|
+
setup(context) {
|
|
2511
|
+
const {
|
|
2512
|
+
scaffold = true,
|
|
2513
|
+
indentStyle = "space",
|
|
2514
|
+
quoteStyle = "double",
|
|
2515
|
+
arrowParentheses = "always",
|
|
2516
|
+
lineWidth = 100,
|
|
2517
|
+
organizeImports = true,
|
|
2518
|
+
ignore = [],
|
|
2519
|
+
rules: customRules = {}
|
|
2520
|
+
} = options;
|
|
2521
|
+
const { cwd, logger } = context;
|
|
2522
|
+
if (scaffold) {
|
|
2523
|
+
const biomeConfigPath = join7(cwd, "biome.json");
|
|
2524
|
+
if (!existsSync7(biomeConfigPath)) {
|
|
2525
|
+
const config = buildBiomeConfig({
|
|
2526
|
+
indentStyle,
|
|
2527
|
+
quoteStyle,
|
|
2528
|
+
arrowParentheses,
|
|
2529
|
+
lineWidth,
|
|
2530
|
+
organizeImports,
|
|
2531
|
+
ignore: [...DEFAULT_IGNORE, ...ignore],
|
|
2532
|
+
customRules
|
|
2533
|
+
});
|
|
2534
|
+
writeFileSync3(biomeConfigPath, `${JSON.stringify(config, null, 2)}
|
|
2535
|
+
`, "utf-8");
|
|
2536
|
+
logger.info("\u5DF2\u751F\u6210 biome.json");
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
const hooks = {
|
|
2540
|
+
modifyRspackConfig(rspackConfig) {
|
|
2541
|
+
logger.info("Biome \u4EE3\u7801\u89C4\u8303\u5DF2\u542F\u7528");
|
|
2542
|
+
return rspackConfig;
|
|
2543
|
+
}
|
|
2544
|
+
};
|
|
2545
|
+
return hooks;
|
|
2546
|
+
}
|
|
2547
|
+
}));
|
|
2548
|
+
function buildBiomeConfig(params) {
|
|
2549
|
+
const {
|
|
2550
|
+
indentStyle,
|
|
2551
|
+
quoteStyle,
|
|
2552
|
+
arrowParentheses,
|
|
2553
|
+
lineWidth,
|
|
2554
|
+
organizeImports: enableOrganizeImports,
|
|
2555
|
+
ignore,
|
|
2556
|
+
customRules
|
|
2557
|
+
} = params;
|
|
2558
|
+
const defaultRules = {
|
|
2559
|
+
recommended: { "": "true" },
|
|
2560
|
+
style: {
|
|
2561
|
+
useNodejsImportProtocol: "off",
|
|
2562
|
+
noNonNullAssertion: "off",
|
|
2563
|
+
noUnusedTemplateLiteral: "off",
|
|
2564
|
+
noUselessElse: "off",
|
|
2565
|
+
useNumberNamespace: "off"
|
|
2566
|
+
},
|
|
2567
|
+
suspicious: {
|
|
2568
|
+
noExplicitAny: "off",
|
|
2569
|
+
noConfusingVoidType: "off",
|
|
2570
|
+
noImplicitAnyLet: "off",
|
|
2571
|
+
noAssignInExpressions: "off",
|
|
2572
|
+
noPrototypeBuiltins: "off"
|
|
2573
|
+
},
|
|
2574
|
+
complexity: {
|
|
2575
|
+
noForEach: "off",
|
|
2576
|
+
noBannedTypes: "off",
|
|
2577
|
+
useArrowFunction: "off"
|
|
2578
|
+
},
|
|
2579
|
+
correctness: {
|
|
2580
|
+
useExhaustiveDependencies: "off"
|
|
2581
|
+
},
|
|
2582
|
+
a11y: {
|
|
2583
|
+
useAltText: "off",
|
|
2584
|
+
useKeyWithClickEvents: "off",
|
|
2585
|
+
useButtonType: "off",
|
|
2586
|
+
noSvgWithoutTitle: "off"
|
|
2587
|
+
},
|
|
2588
|
+
performance: {
|
|
2589
|
+
noDelete: "off"
|
|
2590
|
+
},
|
|
2591
|
+
security: {
|
|
2592
|
+
noDangerouslySetInnerHtml: "off"
|
|
2593
|
+
}
|
|
2594
|
+
};
|
|
2595
|
+
const mergedRules = { recommended: true };
|
|
2596
|
+
for (const [category, categoryRules] of Object.entries(defaultRules)) {
|
|
2597
|
+
if (category === "recommended") continue;
|
|
2598
|
+
const customCategoryRules = customRules[category] || {};
|
|
2599
|
+
mergedRules[category] = { ...categoryRules, ...customCategoryRules };
|
|
2600
|
+
}
|
|
2601
|
+
const includesPatterns = ["**", ...ignore.map((p) => `!${p}`)];
|
|
2283
2602
|
return {
|
|
2284
|
-
|
|
2285
|
-
|
|
2603
|
+
$schema: "https://biomejs.dev/schemas/2.3.2/schema.json",
|
|
2604
|
+
vcs: {
|
|
2605
|
+
enabled: true,
|
|
2606
|
+
defaultBranch: "main",
|
|
2607
|
+
clientKind: "git",
|
|
2608
|
+
useIgnoreFile: true
|
|
2286
2609
|
},
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2610
|
+
formatter: {
|
|
2611
|
+
enabled: true,
|
|
2612
|
+
indentStyle
|
|
2613
|
+
},
|
|
2614
|
+
css: {
|
|
2615
|
+
formatter: {
|
|
2616
|
+
quoteStyle: "single"
|
|
2617
|
+
}
|
|
2618
|
+
},
|
|
2619
|
+
javascript: {
|
|
2620
|
+
formatter: {
|
|
2621
|
+
quoteStyle,
|
|
2622
|
+
arrowParentheses,
|
|
2623
|
+
jsxQuoteStyle: "double",
|
|
2624
|
+
lineWidth
|
|
2625
|
+
}
|
|
2626
|
+
},
|
|
2627
|
+
linter: {
|
|
2628
|
+
enabled: true,
|
|
2629
|
+
rules: mergedRules
|
|
2630
|
+
},
|
|
2631
|
+
assist: {
|
|
2632
|
+
actions: {
|
|
2633
|
+
source: {
|
|
2634
|
+
organizeImports: enableOrganizeImports ? "on" : "off"
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
},
|
|
2638
|
+
files: {
|
|
2639
|
+
ignoreUnknown: true,
|
|
2640
|
+
includes: includesPatterns
|
|
2291
2641
|
}
|
|
2292
2642
|
};
|
|
2293
2643
|
}
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
const module = await import(pluginOrName);
|
|
2305
|
-
plugin = module.default || module;
|
|
2306
|
-
} else {
|
|
2307
|
-
plugin = pluginOrName;
|
|
2308
|
-
}
|
|
2309
|
-
} else {
|
|
2310
|
-
plugin = pluginConfig;
|
|
2311
|
-
}
|
|
2312
|
-
if (typeof plugin === "function") {
|
|
2313
|
-
plugin = plugin(options);
|
|
2314
|
-
}
|
|
2315
|
-
return { plugin, options };
|
|
2644
|
+
function getDefaultBiomeConfig() {
|
|
2645
|
+
return buildBiomeConfig({
|
|
2646
|
+
indentStyle: "space",
|
|
2647
|
+
quoteStyle: "double",
|
|
2648
|
+
arrowParentheses: "always",
|
|
2649
|
+
lineWidth: 100,
|
|
2650
|
+
organizeImports: true,
|
|
2651
|
+
ignore: DEFAULT_IGNORE,
|
|
2652
|
+
customRules: {}
|
|
2653
|
+
});
|
|
2316
2654
|
}
|
|
2317
|
-
var PluginManager = class {
|
|
2318
|
-
plugins = /* @__PURE__ */ new Map();
|
|
2319
|
-
context;
|
|
2320
|
-
constructor(config, cwd, isDev) {
|
|
2321
|
-
this.context = {
|
|
2322
|
-
cwd,
|
|
2323
|
-
isDev,
|
|
2324
|
-
isProd: !isDev,
|
|
2325
|
-
config,
|
|
2326
|
-
logger: createLogger("PluginManager")
|
|
2327
|
-
};
|
|
2328
|
-
}
|
|
2329
|
-
/**
|
|
2330
|
-
* 加载并初始化所有插件
|
|
2331
|
-
*/
|
|
2332
|
-
async loadPlugins(pluginConfigs) {
|
|
2333
|
-
for (const pluginConfig of pluginConfigs) {
|
|
2334
|
-
try {
|
|
2335
|
-
const { plugin } = await resolvePlugin(pluginConfig, this.context.cwd);
|
|
2336
|
-
if (this.plugins.has(plugin.name)) {
|
|
2337
|
-
this.context.logger.warn(`\u63D2\u4EF6 ${plugin.name} \u5DF2\u52A0\u8F7D\uFF0C\u8DF3\u8FC7\u91CD\u590D\u52A0\u8F7D`);
|
|
2338
|
-
continue;
|
|
2339
|
-
}
|
|
2340
|
-
const pluginContext = {
|
|
2341
|
-
...this.context,
|
|
2342
|
-
logger: createLogger(plugin.name)
|
|
2343
|
-
};
|
|
2344
|
-
const hooks = await plugin.setup(pluginContext);
|
|
2345
|
-
this.plugins.set(plugin.name, { plugin, hooks });
|
|
2346
|
-
this.context.logger.info(`\u5DF2\u52A0\u8F7D\u63D2\u4EF6: ${plugin.name}`);
|
|
2347
|
-
} catch (error) {
|
|
2348
|
-
this.context.logger.error(
|
|
2349
|
-
`\u52A0\u8F7D\u63D2\u4EF6\u5931\u8D25: ${String(pluginConfig)} - ${error}`
|
|
2350
|
-
);
|
|
2351
|
-
}
|
|
2352
|
-
}
|
|
2353
|
-
}
|
|
2354
|
-
/**
|
|
2355
|
-
* 执行 modifyRspackConfig 钩子
|
|
2356
|
-
*/
|
|
2357
|
-
async applyRspackConfigHooks(config) {
|
|
2358
|
-
let result = config;
|
|
2359
|
-
for (const [name, { hooks }] of this.plugins) {
|
|
2360
|
-
if (hooks.modifyRspackConfig) {
|
|
2361
|
-
try {
|
|
2362
|
-
const modified = await hooks.modifyRspackConfig(result, this.context);
|
|
2363
|
-
if (modified) {
|
|
2364
|
-
result = modified;
|
|
2365
|
-
}
|
|
2366
|
-
} catch (error) {
|
|
2367
|
-
this.context.logger.error(
|
|
2368
|
-
`\u63D2\u4EF6 ${name} modifyRspackConfig \u6267\u884C\u5931\u8D25: ${error}`
|
|
2369
|
-
);
|
|
2370
|
-
}
|
|
2371
|
-
}
|
|
2372
|
-
}
|
|
2373
|
-
return result;
|
|
2374
|
-
}
|
|
2375
|
-
/**
|
|
2376
|
-
* 执行 modifyRoutes 钩子
|
|
2377
|
-
*/
|
|
2378
|
-
async applyRoutesHooks(routes) {
|
|
2379
|
-
let result = routes;
|
|
2380
|
-
for (const [name, { hooks }] of this.plugins) {
|
|
2381
|
-
if (hooks.modifyRoutes) {
|
|
2382
|
-
try {
|
|
2383
|
-
const modified = await hooks.modifyRoutes(result, this.context);
|
|
2384
|
-
if (modified) {
|
|
2385
|
-
result = modified;
|
|
2386
|
-
}
|
|
2387
|
-
} catch (error) {
|
|
2388
|
-
this.context.logger.error(
|
|
2389
|
-
`\u63D2\u4EF6 ${name} modifyRoutes \u6267\u884C\u5931\u8D25: ${error}`
|
|
2390
|
-
);
|
|
2391
|
-
}
|
|
2392
|
-
}
|
|
2393
|
-
}
|
|
2394
|
-
return result;
|
|
2395
|
-
}
|
|
2396
|
-
/**
|
|
2397
|
-
* 执行 modifyAppConfig 钩子
|
|
2398
|
-
*/
|
|
2399
|
-
applyAppConfigHooks(appConfig) {
|
|
2400
|
-
let result = appConfig;
|
|
2401
|
-
for (const [name, { hooks }] of this.plugins) {
|
|
2402
|
-
if (hooks.modifyAppConfig) {
|
|
2403
|
-
try {
|
|
2404
|
-
const modified = hooks.modifyAppConfig(result, this.context);
|
|
2405
|
-
if (modified) {
|
|
2406
|
-
result = modified;
|
|
2407
|
-
}
|
|
2408
|
-
} catch (error) {
|
|
2409
|
-
this.context.logger.error(
|
|
2410
|
-
`\u63D2\u4EF6 ${name} modifyAppConfig \u6267\u884C\u5931\u8D25: ${error}`
|
|
2411
|
-
);
|
|
2412
|
-
}
|
|
2413
|
-
}
|
|
2414
|
-
}
|
|
2415
|
-
return result;
|
|
2416
|
-
}
|
|
2417
|
-
/**
|
|
2418
|
-
* 收集所有插件的 Provider
|
|
2419
|
-
*/
|
|
2420
|
-
collectProviders() {
|
|
2421
|
-
const providers = [];
|
|
2422
|
-
for (const [name, { hooks }] of this.plugins) {
|
|
2423
|
-
if (hooks.addProvider) {
|
|
2424
|
-
try {
|
|
2425
|
-
const result = hooks.addProvider(this.context);
|
|
2426
|
-
if (Array.isArray(result)) {
|
|
2427
|
-
providers.push(...result);
|
|
2428
|
-
} else if (result) {
|
|
2429
|
-
providers.push(result);
|
|
2430
|
-
}
|
|
2431
|
-
} catch (error) {
|
|
2432
|
-
this.context.logger.error(
|
|
2433
|
-
`\u63D2\u4EF6 ${name} addProvider \u6267\u884C\u5931\u8D25: ${error}`
|
|
2434
|
-
);
|
|
2435
|
-
}
|
|
2436
|
-
}
|
|
2437
|
-
}
|
|
2438
|
-
return providers;
|
|
2439
|
-
}
|
|
2440
|
-
/**
|
|
2441
|
-
* 执行 beforeBuild 钩子
|
|
2442
|
-
*/
|
|
2443
|
-
async runBeforeBuild() {
|
|
2444
|
-
for (const [name, { hooks }] of this.plugins) {
|
|
2445
|
-
if (hooks.beforeBuild) {
|
|
2446
|
-
try {
|
|
2447
|
-
await hooks.beforeBuild(this.context);
|
|
2448
|
-
} catch (error) {
|
|
2449
|
-
this.context.logger.error(
|
|
2450
|
-
`\u63D2\u4EF6 ${name} beforeBuild \u6267\u884C\u5931\u8D25: ${error}`
|
|
2451
|
-
);
|
|
2452
|
-
}
|
|
2453
|
-
}
|
|
2454
|
-
}
|
|
2455
|
-
}
|
|
2456
|
-
/**
|
|
2457
|
-
* 执行 afterBuild 钩子
|
|
2458
|
-
*/
|
|
2459
|
-
async runAfterBuild(stats) {
|
|
2460
|
-
for (const [name, { hooks }] of this.plugins) {
|
|
2461
|
-
if (hooks.afterBuild) {
|
|
2462
|
-
try {
|
|
2463
|
-
await hooks.afterBuild(this.context, stats);
|
|
2464
|
-
} catch (error) {
|
|
2465
|
-
this.context.logger.error(
|
|
2466
|
-
`\u63D2\u4EF6 ${name} afterBuild \u6267\u884C\u5931\u8D25: ${error}`
|
|
2467
|
-
);
|
|
2468
|
-
}
|
|
2469
|
-
}
|
|
2470
|
-
}
|
|
2471
|
-
}
|
|
2472
|
-
/**
|
|
2473
|
-
* 执行 beforeDevServer 钩子
|
|
2474
|
-
*/
|
|
2475
|
-
async runBeforeDevServer() {
|
|
2476
|
-
for (const [name, { hooks }] of this.plugins) {
|
|
2477
|
-
if (hooks.beforeDevServer) {
|
|
2478
|
-
try {
|
|
2479
|
-
await hooks.beforeDevServer(this.context);
|
|
2480
|
-
} catch (error) {
|
|
2481
|
-
this.context.logger.error(
|
|
2482
|
-
`\u63D2\u4EF6 ${name} beforeDevServer \u6267\u884C\u5931\u8D25: ${error}`
|
|
2483
|
-
);
|
|
2484
|
-
}
|
|
2485
|
-
}
|
|
2486
|
-
}
|
|
2487
|
-
}
|
|
2488
|
-
/**
|
|
2489
|
-
* 执行 afterDevServer 钩子
|
|
2490
|
-
*/
|
|
2491
|
-
async runAfterDevServer(server) {
|
|
2492
|
-
for (const [name, { hooks }] of this.plugins) {
|
|
2493
|
-
if (hooks.afterDevServer) {
|
|
2494
|
-
try {
|
|
2495
|
-
await hooks.afterDevServer(this.context, server);
|
|
2496
|
-
} catch (error) {
|
|
2497
|
-
this.context.logger.error(
|
|
2498
|
-
`\u63D2\u4EF6 ${name} afterDevServer \u6267\u884C\u5931\u8D25: ${error}`
|
|
2499
|
-
);
|
|
2500
|
-
}
|
|
2501
|
-
}
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
|
-
/**
|
|
2505
|
-
* 获取所有已加载的插件名称
|
|
2506
|
-
*/
|
|
2507
|
-
getPluginNames() {
|
|
2508
|
-
return Array.from(this.plugins.keys());
|
|
2509
|
-
}
|
|
2510
|
-
/**
|
|
2511
|
-
* 获取所有已加载的插件
|
|
2512
|
-
*/
|
|
2513
|
-
getPlugins() {
|
|
2514
|
-
return Array.from(this.plugins.values()).map((p) => p.plugin);
|
|
2515
|
-
}
|
|
2516
|
-
/**
|
|
2517
|
-
* 获取所有已加载的插件钩子
|
|
2518
|
-
*/
|
|
2519
|
-
getPluginHooks() {
|
|
2520
|
-
return Array.from(this.plugins.values()).map((p) => p.hooks);
|
|
2521
|
-
}
|
|
2522
|
-
};
|
|
2523
2655
|
|
|
2524
2656
|
// src/plugin/builtin/garfish.ts
|
|
2525
2657
|
var garfishPlugin = createPlugin((options = {}) => ({
|
|
@@ -2563,23 +2695,16 @@ var garfishPlugin = createPlugin((options = {}) => ({
|
|
|
2563
2695
|
}
|
|
2564
2696
|
},
|
|
2565
2697
|
// ===== 代码生成阶段钩子 =====
|
|
2566
|
-
injectEntry(
|
|
2698
|
+
injectEntry(_ctx) {
|
|
2567
2699
|
if (master && apps.length > 0) {
|
|
2568
2700
|
return {
|
|
2569
|
-
imports: [
|
|
2570
|
-
|
|
2571
|
-
],
|
|
2572
|
-
topLevel: [
|
|
2573
|
-
`// Garfish \u4E3B\u5E94\u7528\uFF1A\u521D\u59CB\u5316\u5FAE\u524D\u7AEF\u5E76\u6CE8\u518C\u5B50\u5E94\u7528`,
|
|
2574
|
-
`await initGarfishMaster();`
|
|
2575
|
-
]
|
|
2701
|
+
imports: [`import { initGarfishMaster } from "./bootstrap";`],
|
|
2702
|
+
topLevel: [`// Garfish \u4E3B\u5E94\u7528\uFF1A\u521D\u59CB\u5316\u5FAE\u524D\u7AEF\u5E76\u6CE8\u518C\u5B50\u5E94\u7528`, `await initGarfishMaster();`]
|
|
2576
2703
|
};
|
|
2577
2704
|
}
|
|
2578
2705
|
if (!master) {
|
|
2579
2706
|
return {
|
|
2580
|
-
imports: [
|
|
2581
|
-
`import { garfishProvider, isMicroAppEnv } from "./bootstrap";`
|
|
2582
|
-
],
|
|
2707
|
+
imports: [`import { garfishProvider, isMicroAppEnv } from "./bootstrap";`],
|
|
2583
2708
|
exports: [
|
|
2584
2709
|
`// Garfish \u5B50\u5E94\u7528\u751F\u547D\u5468\u671F\u5BFC\u51FA\uFF08provider \u51FD\u6570\u683C\u5F0F\uFF09`,
|
|
2585
2710
|
`export const provider = garfishProvider;`
|
|
@@ -2592,7 +2717,7 @@ var garfishPlugin = createPlugin((options = {}) => ({
|
|
|
2592
2717
|
}
|
|
2593
2718
|
return {};
|
|
2594
2719
|
},
|
|
2595
|
-
injectBootstrap(
|
|
2720
|
+
injectBootstrap(_ctx) {
|
|
2596
2721
|
const imports = [];
|
|
2597
2722
|
const exports = [];
|
|
2598
2723
|
const topLevel = [];
|
|
@@ -2619,12 +2744,9 @@ var garfishPlugin = createPlugin((options = {}) => ({
|
|
|
2619
2744
|
}
|
|
2620
2745
|
return { imports, exports, topLevel };
|
|
2621
2746
|
},
|
|
2622
|
-
modifyBootstrapCode(code,
|
|
2747
|
+
modifyBootstrapCode(code, _ctx) {
|
|
2623
2748
|
if (!master) {
|
|
2624
|
-
return code.replace(
|
|
2625
|
-
/antd:\s*\{\s*enabled:\s*true/,
|
|
2626
|
-
"antd: { enabled: false"
|
|
2627
|
-
);
|
|
2749
|
+
return code.replace(/antd:\s*\{\s*enabled:\s*true/, "antd: { enabled: false");
|
|
2628
2750
|
}
|
|
2629
2751
|
return code;
|
|
2630
2752
|
},
|
|
@@ -2669,143 +2791,58 @@ export async function initGarfishMaster(): Promise<void> {
|
|
|
2669
2791
|
`;
|
|
2670
2792
|
}
|
|
2671
2793
|
|
|
2672
|
-
// src/plugin/builtin/
|
|
2673
|
-
import { existsSync as
|
|
2674
|
-
import { join as
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
name: "@4399ywkf/plugin-tailwind",
|
|
2794
|
+
// src/plugin/builtin/i18n.ts
|
|
2795
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
2796
|
+
import { join as join8 } from "path";
|
|
2797
|
+
var i18nPlugin = createPlugin((options = {}) => ({
|
|
2798
|
+
name: "@4399ywkf/plugin-i18n",
|
|
2678
2799
|
version: "1.0.0",
|
|
2679
|
-
description: "
|
|
2800
|
+
description: "\u56FD\u9645\u5316 (i18next) \u63D2\u4EF6 \u2014 TS-first \u5DE5\u4F5C\u6D41",
|
|
2680
2801
|
setup(context) {
|
|
2681
2802
|
const {
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2803
|
+
defaultLocale = "zh-CN",
|
|
2804
|
+
locales = ["zh-CN", "en-US"],
|
|
2805
|
+
localesDir = "locales",
|
|
2806
|
+
sourceDir = "src/locales/default",
|
|
2807
|
+
defaultNS = ["common"],
|
|
2808
|
+
autoScaffold = true
|
|
2685
2809
|
} = options;
|
|
2686
|
-
const { cwd, logger } = context;
|
|
2687
|
-
if (
|
|
2688
|
-
|
|
2810
|
+
const { cwd, logger, isDev } = context;
|
|
2811
|
+
if (autoScaffold) {
|
|
2812
|
+
scaffoldSourceFiles(cwd, sourceDir, defaultNS, logger);
|
|
2813
|
+
scaffoldResourcesFile(cwd, sourceDir, defaultNS, locales, defaultLocale, logger);
|
|
2814
|
+
scaffoldConvertScript(cwd, sourceDir, localesDir, defaultLocale, logger);
|
|
2815
|
+
scaffoldI18nRc(cwd, localesDir, defaultLocale, locales, logger);
|
|
2816
|
+
scaffoldLocaleJsonDirs(cwd, localesDir, locales, defaultLocale, defaultNS, logger);
|
|
2689
2817
|
}
|
|
2690
2818
|
const hooks = {
|
|
2691
2819
|
modifyRspackConfig(rspackConfig) {
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
test: /tailwind\.css$/,
|
|
2698
|
-
use: [
|
|
2699
|
-
isProd ? rspack3.CssExtractRspackPlugin.loader : "style-loader",
|
|
2700
|
-
"css-loader",
|
|
2701
|
-
{
|
|
2702
|
-
loader: "postcss-loader",
|
|
2703
|
-
options: {
|
|
2704
|
-
postcssOptions: {
|
|
2705
|
-
config: postcssConfigPath
|
|
2706
|
-
}
|
|
2707
|
-
}
|
|
2708
|
-
}
|
|
2709
|
-
]
|
|
2710
|
-
};
|
|
2711
|
-
rules.unshift(tailwindRule);
|
|
2712
|
-
rspackConfig.module = { ...rspackConfig.module, rules };
|
|
2820
|
+
const aliases = rspackConfig.resolve?.alias || {};
|
|
2821
|
+
if (!aliases["@locales"]) {
|
|
2822
|
+
aliases["@locales"] = join8(cwd, localesDir);
|
|
2823
|
+
}
|
|
2824
|
+
rspackConfig.resolve = { ...rspackConfig.resolve, alias: aliases };
|
|
2713
2825
|
return rspackConfig;
|
|
2714
2826
|
},
|
|
2715
|
-
generateFiles(
|
|
2716
|
-
const cssContent = buildTailwindCSS(darkModeSelector, extraCSS);
|
|
2827
|
+
generateFiles(_ctx) {
|
|
2717
2828
|
return [
|
|
2718
2829
|
{
|
|
2719
|
-
path: "
|
|
2720
|
-
content:
|
|
2830
|
+
path: "i18n.ts",
|
|
2831
|
+
content: generateI18nCode({
|
|
2832
|
+
defaultLocale,
|
|
2833
|
+
locales,
|
|
2834
|
+
localesDir,
|
|
2835
|
+
sourceDir,
|
|
2836
|
+
defaultNS,
|
|
2837
|
+
isDev
|
|
2838
|
+
})
|
|
2721
2839
|
}
|
|
2722
2840
|
];
|
|
2723
2841
|
},
|
|
2724
|
-
|
|
2842
|
+
injectBootstrap(_ctx) {
|
|
2725
2843
|
return {
|
|
2726
|
-
imports: [
|
|
2727
|
-
|
|
2728
|
-
]
|
|
2729
|
-
};
|
|
2730
|
-
}
|
|
2731
|
-
};
|
|
2732
|
-
return hooks;
|
|
2733
|
-
}
|
|
2734
|
-
}));
|
|
2735
|
-
function buildTailwindCSS(darkModeSelector, extraCSS) {
|
|
2736
|
-
return `/* \u6B64\u6587\u4EF6\u7531 @4399ywkf/plugin-tailwind \u81EA\u52A8\u751F\u6210 */
|
|
2737
|
-
@import "tailwindcss";
|
|
2738
|
-
@variant dark (${darkModeSelector});
|
|
2739
|
-
${extraCSS ? `
|
|
2740
|
-
${extraCSS}` : ""}
|
|
2741
|
-
`;
|
|
2742
|
-
}
|
|
2743
|
-
function ensurePostcssConfig(cwd, logger) {
|
|
2744
|
-
const configPath = join7(cwd, "postcss.config.js");
|
|
2745
|
-
if (!existsSync7(configPath)) {
|
|
2746
|
-
writeFileSync3(
|
|
2747
|
-
configPath,
|
|
2748
|
-
`module.exports = {
|
|
2749
|
-
plugins: {
|
|
2750
|
-
"@tailwindcss/postcss": {},
|
|
2751
|
-
},
|
|
2752
|
-
};
|
|
2753
|
-
`,
|
|
2754
|
-
"utf-8"
|
|
2755
|
-
);
|
|
2756
|
-
logger.info("\u5DF2\u81EA\u52A8\u751F\u6210 postcss.config.js");
|
|
2757
|
-
}
|
|
2758
|
-
}
|
|
2759
|
-
|
|
2760
|
-
// src/plugin/builtin/i18n.ts
|
|
2761
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
2762
|
-
import { join as join8 } from "path";
|
|
2763
|
-
var i18nPlugin = createPlugin((options = {}) => ({
|
|
2764
|
-
name: "@4399ywkf/plugin-i18n",
|
|
2765
|
-
version: "1.0.0",
|
|
2766
|
-
description: "\u56FD\u9645\u5316 (i18next) \u63D2\u4EF6 \u2014 TS-first \u5DE5\u4F5C\u6D41",
|
|
2767
|
-
setup(context) {
|
|
2768
|
-
const {
|
|
2769
|
-
defaultLocale = "zh-CN",
|
|
2770
|
-
locales = ["zh-CN", "en-US"],
|
|
2771
|
-
localesDir = "locales",
|
|
2772
|
-
sourceDir = "src/locales/default",
|
|
2773
|
-
defaultNS = ["common"],
|
|
2774
|
-
autoScaffold = true
|
|
2775
|
-
} = options;
|
|
2776
|
-
const { cwd, logger, isDev } = context;
|
|
2777
|
-
if (autoScaffold) {
|
|
2778
|
-
scaffoldSourceFiles(cwd, sourceDir, defaultNS, logger);
|
|
2779
|
-
scaffoldResourcesFile(cwd, sourceDir, defaultNS, locales, defaultLocale, logger);
|
|
2780
|
-
scaffoldConvertScript(cwd, sourceDir, localesDir, defaultLocale, logger);
|
|
2781
|
-
scaffoldI18nRc(cwd, localesDir, defaultLocale, locales, logger);
|
|
2782
|
-
scaffoldLocaleJsonDirs(cwd, localesDir, locales, defaultLocale, defaultNS, logger);
|
|
2783
|
-
}
|
|
2784
|
-
const hooks = {
|
|
2785
|
-
modifyRspackConfig(rspackConfig) {
|
|
2786
|
-
const aliases = rspackConfig.resolve?.alias || {};
|
|
2787
|
-
if (!aliases["@locales"]) {
|
|
2788
|
-
aliases["@locales"] = join8(cwd, localesDir);
|
|
2789
|
-
}
|
|
2790
|
-
rspackConfig.resolve = { ...rspackConfig.resolve, alias: aliases };
|
|
2791
|
-
return rspackConfig;
|
|
2792
|
-
},
|
|
2793
|
-
generateFiles(ctx) {
|
|
2794
|
-
return [
|
|
2795
|
-
{
|
|
2796
|
-
path: "i18n.ts",
|
|
2797
|
-
content: generateI18nCode({ defaultLocale, locales, localesDir, sourceDir, defaultNS, isDev })
|
|
2798
|
-
}
|
|
2799
|
-
];
|
|
2800
|
-
},
|
|
2801
|
-
injectBootstrap(ctx) {
|
|
2802
|
-
return {
|
|
2803
|
-
imports: [
|
|
2804
|
-
`import { initI18n } from "./i18n";`
|
|
2805
|
-
],
|
|
2806
|
-
topLevel: [
|
|
2807
|
-
`await initI18n();`
|
|
2808
|
-
]
|
|
2844
|
+
imports: [`import { initI18n } from "./i18n";`],
|
|
2845
|
+
topLevel: [`await initI18n();`]
|
|
2809
2846
|
};
|
|
2810
2847
|
}
|
|
2811
2848
|
};
|
|
@@ -2916,7 +2953,7 @@ function buildDefaultNsFile(ns) {
|
|
|
2916
2953
|
} as const;
|
|
2917
2954
|
`;
|
|
2918
2955
|
}
|
|
2919
|
-
function scaffoldResourcesFile(cwd, sourceDir,
|
|
2956
|
+
function scaffoldResourcesFile(cwd, sourceDir, _namespaces, locales, defaultLocale, logger) {
|
|
2920
2957
|
const parentDir = join8(cwd, sourceDir, "..");
|
|
2921
2958
|
const filePath = join8(parentDir, "resources.ts");
|
|
2922
2959
|
if (existsSync8(filePath)) return;
|
|
@@ -2967,7 +3004,7 @@ function getLocaleLabel(locale) {
|
|
|
2967
3004
|
"ru-RU": "\u0420\u0443\u0441\u0441\u043A\u0438\u0439",
|
|
2968
3005
|
"it-IT": "Italiano",
|
|
2969
3006
|
"vi-VN": "Ti\u1EBFng Vi\u1EC7t",
|
|
2970
|
-
|
|
3007
|
+
ar: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629"
|
|
2971
3008
|
};
|
|
2972
3009
|
return map[locale] || locale;
|
|
2973
3010
|
}
|
|
@@ -3043,98 +3080,152 @@ function scaffoldLocaleJsonDirs(cwd, localesDir, locales, defaultLocale, namespa
|
|
|
3043
3080
|
for (const ns of namespaces) {
|
|
3044
3081
|
const filePath = join8(localeDir, `${ns}.json`);
|
|
3045
3082
|
if (!existsSync8(filePath)) {
|
|
3046
|
-
const placeholder = ns === "common" ? JSON.stringify(
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3083
|
+
const placeholder = ns === "common" ? JSON.stringify(
|
|
3084
|
+
{
|
|
3085
|
+
welcome: "Welcome",
|
|
3086
|
+
loading: "Loading...",
|
|
3087
|
+
confirm: "OK",
|
|
3088
|
+
cancel: "Cancel",
|
|
3089
|
+
save: "Save",
|
|
3090
|
+
delete: "Delete",
|
|
3091
|
+
edit: "Edit",
|
|
3092
|
+
back: "Back"
|
|
3093
|
+
},
|
|
3094
|
+
null,
|
|
3095
|
+
2
|
|
3096
|
+
) : JSON.stringify({ title: ns }, null, 2);
|
|
3097
|
+
writeFileSync4(filePath, `${placeholder}
|
|
3098
|
+
`, "utf-8");
|
|
3057
3099
|
logger.info(`\u5DF2\u751F\u6210\u7FFB\u8BD1\u6587\u4EF6: ${localesDir}/${locale}/${ns}.json`);
|
|
3058
3100
|
}
|
|
3059
3101
|
}
|
|
3060
3102
|
}
|
|
3061
3103
|
}
|
|
3062
3104
|
|
|
3063
|
-
// src/plugin/builtin/
|
|
3064
|
-
import {
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3105
|
+
// src/plugin/builtin/mock.ts
|
|
3106
|
+
import { existsSync as existsSync9, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
3107
|
+
import { join as join9, resolve as resolve3 } from "path";
|
|
3108
|
+
var mockPlugin = createPlugin((options = {}) => ({
|
|
3109
|
+
name: "@4399ywkf/plugin-mock",
|
|
3110
|
+
version: "1.0.0",
|
|
3111
|
+
description: "Mock \u6570\u636E\u63D2\u4EF6",
|
|
3112
|
+
setup(context) {
|
|
3113
|
+
const { mockDir = "mock", enableInProd = false, delay = 0, prefix = "" } = options;
|
|
3114
|
+
const { cwd, isDev, logger } = context;
|
|
3115
|
+
if (!isDev && !enableInProd) {
|
|
3116
|
+
logger.info("\u751F\u4EA7\u73AF\u5883\u5DF2\u7981\u7528 Mock");
|
|
3117
|
+
return {};
|
|
3118
|
+
}
|
|
3119
|
+
const mockPath = resolve3(cwd, mockDir);
|
|
3120
|
+
if (!existsSync9(mockPath)) {
|
|
3121
|
+
logger.warn(`Mock \u76EE\u5F55\u4E0D\u5B58\u5728: ${mockPath}`);
|
|
3122
|
+
return {};
|
|
3123
|
+
}
|
|
3124
|
+
const hooks = {
|
|
3125
|
+
modifyRspackConfig(rspackConfig) {
|
|
3126
|
+
if (isDev && rspackConfig.devServer) {
|
|
3127
|
+
const mockFiles = scanMockFiles(mockPath);
|
|
3128
|
+
logger.info(`\u627E\u5230 ${mockFiles.length} \u4E2A Mock \u6587\u4EF6`);
|
|
3129
|
+
rspackConfig.devServer.setupMiddlewares = (middlewares, _devServer) => {
|
|
3130
|
+
middlewares.unshift({
|
|
3131
|
+
name: "mock-middleware",
|
|
3132
|
+
middleware: createMockMiddleware(mockPath, { delay, prefix, logger })
|
|
3133
|
+
});
|
|
3134
|
+
return middlewares;
|
|
3135
|
+
};
|
|
3136
|
+
}
|
|
3137
|
+
return rspackConfig;
|
|
3138
|
+
},
|
|
3139
|
+
beforeDevServer() {
|
|
3140
|
+
logger.info(`Mock \u5DF2\u542F\u7528\uFF0C\u76EE\u5F55: ${mockPath}`);
|
|
3141
|
+
if (delay > 0) {
|
|
3142
|
+
logger.info(`\u6A21\u62DF\u5EF6\u8FDF: ${delay}ms`);
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
};
|
|
3146
|
+
return hooks;
|
|
3147
|
+
}
|
|
3148
|
+
}));
|
|
3149
|
+
function scanMockFiles(dir) {
|
|
3150
|
+
const files = [];
|
|
3151
|
+
if (!existsSync9(dir)) {
|
|
3152
|
+
return files;
|
|
3153
|
+
}
|
|
3154
|
+
const entries = readdirSync2(dir);
|
|
3155
|
+
for (const entry of entries) {
|
|
3156
|
+
const fullPath = join9(dir, entry);
|
|
3157
|
+
const stat = statSync2(fullPath);
|
|
3158
|
+
if (stat.isFile() && /\.(ts|js|mjs)$/.test(entry)) {
|
|
3159
|
+
files.push(fullPath);
|
|
3160
|
+
} else if (stat.isDirectory()) {
|
|
3161
|
+
files.push(...scanMockFiles(fullPath));
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
return files;
|
|
3165
|
+
}
|
|
3166
|
+
function createMockMiddleware(mockPath, options) {
|
|
3167
|
+
const { delay } = options;
|
|
3168
|
+
scanMockFiles(mockPath);
|
|
3169
|
+
return async (_req, _res, next) => {
|
|
3170
|
+
if (delay > 0) {
|
|
3171
|
+
await new Promise((resolve4) => setTimeout(resolve4, delay));
|
|
3172
|
+
}
|
|
3173
|
+
next();
|
|
3174
|
+
};
|
|
3175
|
+
}
|
|
3176
|
+
|
|
3177
|
+
// src/plugin/builtin/react-query.ts
|
|
3178
|
+
var reactQueryPlugin = createPlugin((options = {}) => ({
|
|
3179
|
+
name: "@4399ywkf/plugin-react-query",
|
|
3180
|
+
version: "1.0.0",
|
|
3181
|
+
description: "React Query + Axios \u8BF7\u6C42\u5C42\u96C6\u6210",
|
|
3069
3182
|
setup(context) {
|
|
3070
3183
|
const {
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
globalReset = true,
|
|
3078
|
-
externalTheme = false
|
|
3184
|
+
staleTime = 5 * 60 * 1e3,
|
|
3185
|
+
gcTime = 10 * 60 * 1e3,
|
|
3186
|
+
retry = 1,
|
|
3187
|
+
devtools = true,
|
|
3188
|
+
baseURL = "",
|
|
3189
|
+
timeout = 15e3
|
|
3079
3190
|
} = options;
|
|
3080
|
-
const { logger } = context;
|
|
3081
|
-
logger.info(`\u4E3B\u9898\u6A21\u5F0F: ${defaultAppearance}, \u4E3B\u8272: ${primaryColor ?? "primary(\u9ED8\u8BA4\u9ED1)"}, \u54CD\u5E94\u5F0F: \u2713`);
|
|
3191
|
+
const { logger, isDev } = context;
|
|
3082
3192
|
const hooks = {
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
const
|
|
3086
|
-
config.resolve = {
|
|
3087
|
-
...config.resolve,
|
|
3088
|
-
alias: {
|
|
3089
|
-
...currentAlias,
|
|
3090
|
-
"@ywkf/theme": themePath
|
|
3091
|
-
}
|
|
3092
|
-
};
|
|
3093
|
-
return config;
|
|
3094
|
-
},
|
|
3095
|
-
generateFiles(ctx) {
|
|
3096
|
-
return [
|
|
3193
|
+
generateFiles(_ctx) {
|
|
3194
|
+
logger.info("React Query \u5DF2\u542F\u7528");
|
|
3195
|
+
const files = [
|
|
3097
3196
|
{
|
|
3098
|
-
path: "
|
|
3099
|
-
content:
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
prefixCls,
|
|
3105
|
-
cssVar,
|
|
3106
|
-
globalReset,
|
|
3107
|
-
externalTheme
|
|
3108
|
-
})
|
|
3197
|
+
path: "query-client.ts",
|
|
3198
|
+
content: buildQueryClientFile({ staleTime, gcTime, retry, devtools, isDev })
|
|
3199
|
+
},
|
|
3200
|
+
{
|
|
3201
|
+
path: "request.ts",
|
|
3202
|
+
content: buildRequestFile({ baseURL, timeout })
|
|
3109
3203
|
}
|
|
3110
3204
|
];
|
|
3205
|
+
return files;
|
|
3111
3206
|
},
|
|
3112
|
-
injectBootstrap(
|
|
3207
|
+
injectBootstrap(_ctx) {
|
|
3113
3208
|
return {
|
|
3114
3209
|
imports: [
|
|
3115
|
-
`import {
|
|
3116
|
-
|
|
3210
|
+
`import { QueryClientProvider } from "@tanstack/react-query";`,
|
|
3211
|
+
`import { queryClient } from "./query-client";`
|
|
3212
|
+
],
|
|
3213
|
+
topLevel: [`// React Query Provider\uFF08\u7531 @4399ywkf/plugin-react-query \u6CE8\u5165\uFF09`]
|
|
3117
3214
|
};
|
|
3118
3215
|
},
|
|
3119
3216
|
modifyBootstrapCode(code) {
|
|
3120
3217
|
const providerEntry = ` {
|
|
3121
|
-
component:
|
|
3122
|
-
props: {},
|
|
3123
|
-
order:
|
|
3218
|
+
component: QueryClientProvider as React.ComponentType<{ children: React.ReactNode }>,
|
|
3219
|
+
props: { client: queryClient },
|
|
3220
|
+
order: 20,
|
|
3124
3221
|
}`;
|
|
3125
3222
|
if (code.includes("providers: []")) {
|
|
3126
|
-
code = code.replace(
|
|
3127
|
-
"providers: []",
|
|
3128
|
-
`providers: [
|
|
3223
|
+
code = code.replace("providers: []", `providers: [
|
|
3129
3224
|
${providerEntry},
|
|
3130
|
-
]`
|
|
3131
|
-
);
|
|
3225
|
+
]`);
|
|
3132
3226
|
} else if (code.includes("providers: [")) {
|
|
3133
|
-
code = code.replace(
|
|
3134
|
-
|
|
3135
|
-
`providers: [
|
|
3136
|
-
${providerEntry},`
|
|
3137
|
-
);
|
|
3227
|
+
code = code.replace("providers: [", `providers: [
|
|
3228
|
+
${providerEntry},`);
|
|
3138
3229
|
}
|
|
3139
3230
|
if (!code.includes("import React")) {
|
|
3140
3231
|
code = code.replace(
|
|
@@ -3149,489 +3240,366 @@ import { bootstrap`
|
|
|
3149
3240
|
return hooks;
|
|
3150
3241
|
}
|
|
3151
3242
|
}));
|
|
3152
|
-
function
|
|
3153
|
-
const {
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
primaryColor,
|
|
3157
|
-
neutralColor,
|
|
3158
|
-
prefixCls,
|
|
3159
|
-
cssVar,
|
|
3160
|
-
globalReset,
|
|
3161
|
-
externalTheme
|
|
3162
|
-
} = opts;
|
|
3163
|
-
const sections = [];
|
|
3164
|
-
sections.push(`// \u6B64\u6587\u4EF6\u7531 @4399ywkf/plugin-theme v3 \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u4FEE\u6539`);
|
|
3165
|
-
sections.push(buildImports({ globalReset, cssVar }));
|
|
3166
|
-
sections.push(TYPES_CODE);
|
|
3167
|
-
sections.push(buildStoreCode({ defaultAppearance, primaryColor, neutralColor }));
|
|
3168
|
-
sections.push(HOOKS_CODE);
|
|
3169
|
-
if (globalReset) sections.push(GLOBAL_RESET_CODE);
|
|
3170
|
-
if (cssVar) sections.push(CSS_VAR_SYNC_CODE);
|
|
3171
|
-
if (darkMode) sections.push(APPEARANCE_SYNC_CODE);
|
|
3172
|
-
if (externalTheme) sections.push(EXTERNAL_THEME_CODE);
|
|
3173
|
-
sections.push(buildWrapperCode({ darkMode, cssVar, globalReset, externalTheme, prefixCls }));
|
|
3174
|
-
return sections.join("\n");
|
|
3175
|
-
}
|
|
3176
|
-
function buildImports(opts) {
|
|
3177
|
-
const reactImports = [
|
|
3178
|
-
"useCallback",
|
|
3179
|
-
"useEffect",
|
|
3180
|
-
"useMemo",
|
|
3181
|
-
...opts.cssVar ? ["useLayoutEffect", "useRef"] : [],
|
|
3182
|
-
"type ReactNode"
|
|
3183
|
-
];
|
|
3184
|
-
const antdStyleImports = [
|
|
3185
|
-
"ThemeProvider as AntdThemeProvider",
|
|
3186
|
-
"type GetAntdTheme",
|
|
3187
|
-
...opts.globalReset ? ["createGlobalStyle", "css"] : []
|
|
3188
|
-
];
|
|
3189
|
-
return `
|
|
3190
|
-
import React, { ${reactImports.join(", ")} } from "react";
|
|
3191
|
-
import { ${antdStyleImports.join(", ")} } from "antd-style";
|
|
3192
|
-
import { createWithEqualityFn } from "zustand/traditional";
|
|
3193
|
-
import { shallow } from "zustand/shallow";
|
|
3194
|
-
import { createThemeConfig, type PrimaryColors, type NeutralColors } from "@4399ywkf/theme-system";`;
|
|
3195
|
-
}
|
|
3196
|
-
var TYPES_CODE = `
|
|
3197
|
-
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Types \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3243
|
+
function buildQueryClientFile(opts) {
|
|
3244
|
+
const { staleTime, gcTime, retry, devtools, isDev } = opts;
|
|
3245
|
+
return `// \u6B64\u6587\u4EF6\u7531 @4399ywkf/plugin-react-query \u81EA\u52A8\u751F\u6210
|
|
3246
|
+
import { QueryClient } from "@tanstack/react-query";
|
|
3198
3247
|
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3248
|
+
/**
|
|
3249
|
+
* \u5168\u5C40 QueryClient \u5B9E\u4F8B
|
|
3250
|
+
*
|
|
3251
|
+
* \u9ED8\u8BA4\u914D\u7F6E\u53EF\u5728 ywkf.config.ts \u7684 reactQueryPlugin \u9009\u9879\u4E2D\u4FEE\u6539\u3002
|
|
3252
|
+
* \u8FD0\u884C\u65F6\u81EA\u5B9A\u4E49\u53EF\u901A\u8FC7 src/app.config.ts \u8986\u76D6\u3002
|
|
3253
|
+
*/
|
|
3254
|
+
export const queryClient = new QueryClient({
|
|
3255
|
+
defaultOptions: {
|
|
3256
|
+
queries: {
|
|
3257
|
+
staleTime: ${staleTime},
|
|
3258
|
+
gcTime: ${gcTime},
|
|
3259
|
+
retry: ${typeof retry === "boolean" ? retry : retry},
|
|
3260
|
+
refetchOnWindowFocus: false,
|
|
3261
|
+
},
|
|
3262
|
+
mutations: {
|
|
3263
|
+
retry: false,
|
|
3264
|
+
},
|
|
3265
|
+
},
|
|
3266
|
+
});
|
|
3206
3267
|
|
|
3207
|
-
export
|
|
3208
|
-
|
|
3209
|
-
setPrimaryColor: (color: PrimaryColors | undefined) => void;
|
|
3210
|
-
setNeutralColor: (color: NeutralColors | undefined) => void;
|
|
3211
|
-
setTheme: (partial: Partial<ThemeState>) => void;
|
|
3268
|
+
export default queryClient;
|
|
3269
|
+
`;
|
|
3212
3270
|
}
|
|
3271
|
+
function buildRequestFile(opts) {
|
|
3272
|
+
const { baseURL, timeout } = opts;
|
|
3273
|
+
return `// \u6B64\u6587\u4EF6\u7531 @4399ywkf/plugin-react-query \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u4FEE\u6539
|
|
3274
|
+
// \u5982\u9700\u5B9A\u5236\u62E6\u622A\u5668\uFF0C\u8BF7\u7F16\u8F91 src/request.ts
|
|
3275
|
+
import axios from "axios";
|
|
3276
|
+
import qs from "qs";
|
|
3277
|
+
import type { AxiosInstance, AxiosRequestConfig, InternalAxiosRequestConfig, AxiosResponse, AxiosError } from "axios";
|
|
3278
|
+
import type { RequestConfig, Result } from "@4399ywkf/core/runtime";
|
|
3213
3279
|
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
export type { PrimaryColors, NeutralColors };`;
|
|
3217
|
-
function buildStoreCode(opts) {
|
|
3218
|
-
const primaryLine = opts.primaryColor ? ` primaryColor: "${opts.primaryColor}" as PrimaryColors,` : ` primaryColor: undefined,`;
|
|
3219
|
-
const neutralLine = opts.neutralColor ? ` neutralColor: "${opts.neutralColor}" as NeutralColors,` : ` neutralColor: undefined,`;
|
|
3220
|
-
return `
|
|
3221
|
-
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Theme Store \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3280
|
+
// ============ \u52A0\u8F7D\u7528\u6237\u914D\u7F6E ============
|
|
3222
3281
|
|
|
3223
|
-
|
|
3224
|
-
appearance: "${opts.defaultAppearance}",
|
|
3225
|
-
${primaryLine}
|
|
3226
|
-
${neutralLine}
|
|
3227
|
-
};
|
|
3282
|
+
let userConfig: RequestConfig = {};
|
|
3228
3283
|
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
setNeutralColor: (color) => set({ neutralColor: color }),
|
|
3235
|
-
setTheme: (partial) => set(partial),
|
|
3236
|
-
}),
|
|
3237
|
-
shallow,
|
|
3238
|
-
);`;
|
|
3284
|
+
try {
|
|
3285
|
+
const mod = require("@/request");
|
|
3286
|
+
userConfig = mod.default || mod;
|
|
3287
|
+
} catch {
|
|
3288
|
+
// src/request.ts \u4E0D\u5B58\u5728\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E
|
|
3239
3289
|
}
|
|
3240
|
-
var HOOKS_CODE = `
|
|
3241
|
-
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Convenience Hooks \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3242
3290
|
|
|
3243
|
-
|
|
3244
|
-
useThemeStore(
|
|
3245
|
-
(s) => ({
|
|
3246
|
-
appearance: s.appearance,
|
|
3247
|
-
primaryColor: s.primaryColor,
|
|
3248
|
-
neutralColor: s.neutralColor,
|
|
3249
|
-
}),
|
|
3250
|
-
shallow,
|
|
3251
|
-
);
|
|
3291
|
+
// ============ \u53C2\u6570\u5E8F\u5217\u5316\uFF08GET \u8BF7\u6C42\u4E13\u7528\uFF09============
|
|
3252
3292
|
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3293
|
+
/**
|
|
3294
|
+
* GET \u8BF7\u6C42\u53C2\u6570\u5E8F\u5217\u5316\u89C4\u5219\uFF1A
|
|
3295
|
+
* - \u6570\u7EC4\uFF1Arepeat \u6A21\u5F0F\uFF08key=1&key=2\uFF09
|
|
3296
|
+
* - \u5BF9\u8C61\uFF1AJSON.stringify \u540E\u4F5C\u4E3A\u5B57\u7B26\u4E32\u4F20\u9012
|
|
3297
|
+
* - null / undefined\uFF1AskipNulls \u8DF3\u8FC7
|
|
3298
|
+
* - \u57FA\u672C\u7C7B\u578B\uFF1A\u539F\u6837\u4F20\u9012
|
|
3299
|
+
*/
|
|
3300
|
+
export function paramsSerializer(params: Record<string, any>): string {
|
|
3301
|
+
const normalized: Record<string, any> = {};
|
|
3257
3302
|
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
--font-settings: "cv01", "tnum", "kern";
|
|
3261
|
-
--font-variations: "opsz" auto, tabular-nums;
|
|
3262
|
-
}
|
|
3303
|
+
Object.keys(params).forEach((key) => {
|
|
3304
|
+
const value = params[key];
|
|
3263
3305
|
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3306
|
+
if (value === null || value === undefined) {
|
|
3307
|
+
normalized[key] = value;
|
|
3308
|
+
} else if (Array.isArray(value)) {
|
|
3309
|
+
normalized[key] = value;
|
|
3310
|
+
} else if (typeof value === "object") {
|
|
3311
|
+
normalized[key] = JSON.stringify(value);
|
|
3312
|
+
} else {
|
|
3313
|
+
normalized[key] = value;
|
|
3314
|
+
}
|
|
3315
|
+
});
|
|
3270
3316
|
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
scrollbar-width: thin;
|
|
3274
|
-
}
|
|
3317
|
+
return qs.stringify(normalized, { arrayFormat: "repeat", skipNulls: true });
|
|
3318
|
+
}
|
|
3275
3319
|
|
|
3276
|
-
|
|
3277
|
-
overscroll-behavior: none;
|
|
3278
|
-
color-scheme: \${theme.isDarkMode ? "dark" : "light"};
|
|
3279
|
-
}
|
|
3320
|
+
// ============ \u521B\u5EFA Axios \u5B9E\u4F8B ============
|
|
3280
3321
|
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3322
|
+
const instance: AxiosInstance = axios.create({
|
|
3323
|
+
baseURL: userConfig.baseURL ?? ("${baseURL}" || ""),
|
|
3324
|
+
timeout: userConfig.timeout ?? ${timeout},
|
|
3325
|
+
withCredentials: userConfig.withCredentials ?? false,
|
|
3326
|
+
headers: {
|
|
3327
|
+
"Content-Type": "application/json",
|
|
3328
|
+
...(userConfig.headers || {}),
|
|
3329
|
+
},
|
|
3330
|
+
});
|
|
3286
3331
|
|
|
3287
|
-
|
|
3288
|
-
overflow: hidden auto;
|
|
3289
|
-
min-height: 100vh;
|
|
3290
|
-
font-family: \${theme.fontFamily};
|
|
3291
|
-
font-size: \${theme.fontSize}px;
|
|
3292
|
-
font-feature-settings: var(--font-settings);
|
|
3293
|
-
font-variation-settings: var(--font-variations);
|
|
3294
|
-
line-height: 1;
|
|
3295
|
-
color: \${theme.colorTextBase};
|
|
3296
|
-
text-size-adjust: none;
|
|
3297
|
-
text-rendering: optimizelegibility;
|
|
3298
|
-
word-wrap: break-word;
|
|
3299
|
-
background-color: \${theme.colorBgLayout};
|
|
3300
|
-
-webkit-font-smoothing: antialiased;
|
|
3301
|
-
-moz-osx-font-smoothing: grayscale;
|
|
3302
|
-
-webkit-overflow-scrolling: touch;
|
|
3303
|
-
-webkit-tap-highlight-color: transparent;
|
|
3304
|
-
}
|
|
3332
|
+
// ============ \u8BF7\u6C42\u62E6\u622A\u5668 ============
|
|
3305
3333
|
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3334
|
+
instance.interceptors.request.use(
|
|
3335
|
+
(config: InternalAxiosRequestConfig) => {
|
|
3336
|
+
// 1. Token \u6CE8\u5165
|
|
3337
|
+
if (userConfig.getToken) {
|
|
3338
|
+
const token = userConfig.getToken();
|
|
3339
|
+
if (token && config.headers) {
|
|
3340
|
+
const prefix = userConfig.tokenPrefix ?? "Bearer";
|
|
3341
|
+
config.headers.Authorization = prefix ? \`\${prefix} \${token}\` : token;
|
|
3342
|
+
}
|
|
3343
|
+
} else {
|
|
3344
|
+
// \u9ED8\u8BA4\uFF1A\u4ECE localStorage \u8BFB\u53D6
|
|
3345
|
+
const token = typeof localStorage !== "undefined"
|
|
3346
|
+
? localStorage.getItem("token")
|
|
3347
|
+
: null;
|
|
3348
|
+
if (token && config.headers) {
|
|
3349
|
+
config.headers.Authorization = \`Bearer \${token}\`;
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3309
3352
|
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
\`);`;
|
|
3315
|
-
var CSS_VAR_SYNC_CODE = `
|
|
3316
|
-
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 CSS Variable Sync \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3353
|
+
// 2. \u7528\u6237\u81EA\u5B9A\u4E49\u8BF7\u6C42\u62E6\u622A
|
|
3354
|
+
if (userConfig.requestInterceptor) {
|
|
3355
|
+
return userConfig.requestInterceptor(config as any) as any;
|
|
3356
|
+
}
|
|
3317
3357
|
|
|
3318
|
-
|
|
3358
|
+
return config;
|
|
3359
|
+
},
|
|
3360
|
+
(error: AxiosError) => Promise.reject(error)
|
|
3361
|
+
);
|
|
3319
3362
|
|
|
3320
|
-
|
|
3321
|
-
useLayoutEffect(() => {
|
|
3322
|
-
const node = ref.current;
|
|
3323
|
-
if (!node) return;
|
|
3363
|
+
// ============ \u54CD\u5E94\u62E6\u622A\u5668 ============
|
|
3324
3364
|
|
|
3325
|
-
|
|
3326
|
-
|
|
3365
|
+
instance.interceptors.response.use(
|
|
3366
|
+
(response: AxiosResponse) => {
|
|
3367
|
+
// \u7528\u6237\u81EA\u5B9A\u4E49\u54CD\u5E94\u62E6\u622A
|
|
3368
|
+
if (userConfig.responseInterceptor) {
|
|
3369
|
+
return userConfig.responseInterceptor(response as any);
|
|
3370
|
+
}
|
|
3327
3371
|
|
|
3328
|
-
|
|
3329
|
-
|
|
3372
|
+
// \u9ED8\u8BA4\uFF1A\u76F4\u63A5\u8FD4\u56DE response.data
|
|
3373
|
+
return response.data;
|
|
3374
|
+
},
|
|
3375
|
+
(error: AxiosError) => {
|
|
3376
|
+
// \u7528\u6237\u81EA\u5B9A\u4E49\u9519\u8BEF\u5904\u7406
|
|
3377
|
+
if (userConfig.errorHandler) {
|
|
3378
|
+
return userConfig.errorHandler(error as any);
|
|
3379
|
+
}
|
|
3330
3380
|
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3381
|
+
// \u9ED8\u8BA4\u9519\u8BEF\u5904\u7406
|
|
3382
|
+
const status = error.response?.status;
|
|
3383
|
+
|
|
3384
|
+
switch (status) {
|
|
3385
|
+
case 401:
|
|
3386
|
+
console.warn("[request] \u672A\u6388\u6743\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55");
|
|
3387
|
+
break;
|
|
3388
|
+
case 403:
|
|
3389
|
+
console.warn("[request] \u65E0\u8BBF\u95EE\u6743\u9650");
|
|
3390
|
+
break;
|
|
3391
|
+
case 500:
|
|
3392
|
+
console.error("[request] \u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF");
|
|
3393
|
+
break;
|
|
3394
|
+
default:
|
|
3395
|
+
if (!error.response) {
|
|
3396
|
+
console.error("[request] \u7F51\u7EDC\u5F02\u5E38\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5");
|
|
3336
3397
|
}
|
|
3337
|
-
|
|
3338
|
-
}
|
|
3398
|
+
}
|
|
3339
3399
|
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3400
|
+
return Promise.reject(error);
|
|
3401
|
+
}
|
|
3402
|
+
);
|
|
3343
3403
|
|
|
3344
|
-
|
|
3404
|
+
// ============ \u8BF7\u6C42\u5C01\u88C5\u7C7B ============
|
|
3345
3405
|
|
|
3346
|
-
|
|
3347
|
-
let el: HTMLElement | null = node;
|
|
3348
|
-
while (el && el !== htmlEl) {
|
|
3349
|
-
observer.observe(el, { attributeFilter: ["class"] });
|
|
3350
|
-
el = el.parentElement;
|
|
3351
|
-
}
|
|
3352
|
-
|
|
3353
|
-
return () => {
|
|
3354
|
-
observer.disconnect();
|
|
3355
|
-
for (const cls of currentClasses) htmlEl.classList.remove(cls);
|
|
3356
|
-
};
|
|
3357
|
-
}, []);
|
|
3358
|
-
}`;
|
|
3359
|
-
var APPEARANCE_SYNC_CODE = `
|
|
3360
|
-
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Appearance Sync \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3361
|
-
|
|
3362
|
-
function useAppearanceSync(appearance: ThemeAppearance) {
|
|
3363
|
-
useEffect(() => {
|
|
3364
|
-
if (appearance !== "auto") {
|
|
3365
|
-
document.documentElement.dataset.theme = appearance;
|
|
3366
|
-
return;
|
|
3367
|
-
}
|
|
3368
|
-
|
|
3369
|
-
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
3370
|
-
document.documentElement.dataset.theme = mq.matches ? "dark" : "light";
|
|
3371
|
-
|
|
3372
|
-
function handleChange(e: MediaQueryListEvent) {
|
|
3373
|
-
document.documentElement.dataset.theme = e.matches ? "dark" : "light";
|
|
3374
|
-
}
|
|
3406
|
+
type ExtraConfig = AxiosRequestConfig & { suppressErrorNotification?: boolean };
|
|
3375
3407
|
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
}, [appearance]);
|
|
3379
|
-
}`;
|
|
3380
|
-
var EXTERNAL_THEME_CODE = `
|
|
3381
|
-
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 External Theme Injection \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3408
|
+
class Request {
|
|
3409
|
+
constructor(private readonly http: AxiosInstance) {}
|
|
3382
3410
|
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
}
|
|
3411
|
+
get<T = any>(url: string, params?: Record<string, any>, config?: ExtraConfig): Promise<Result<T>> {
|
|
3412
|
+
return this.http.get(url, {
|
|
3413
|
+
...config,
|
|
3414
|
+
params,
|
|
3415
|
+
paramsSerializer,
|
|
3416
|
+
});
|
|
3417
|
+
}
|
|
3389
3418
|
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
};
|
|
3419
|
+
post<T = any>(url: string, data?: any, config?: ExtraConfig): Promise<Result<T>> {
|
|
3420
|
+
return this.http.post(url, data, config);
|
|
3421
|
+
}
|
|
3394
3422
|
|
|
3395
|
-
|
|
3396
|
-
return
|
|
3397
|
-
}
|
|
3398
|
-
}`;
|
|
3399
|
-
function buildWrapperCode(opts) {
|
|
3400
|
-
const { darkMode, cssVar, globalReset, externalTheme, prefixCls } = opts;
|
|
3401
|
-
const refLine = cssVar ? "\n const containerRef = useRef<HTMLDivElement>(null);" : "";
|
|
3402
|
-
const cssVarSyncLine = cssVar ? "\n useCssVarSync(containerRef);" : "";
|
|
3403
|
-
const appearanceSyncLine = darkMode ? "\n useAppearanceSync(appearance);" : "";
|
|
3404
|
-
const externalThemeLine = externalTheme ? "\n useExternalTheme();" : "";
|
|
3405
|
-
const childrenSlot = cssVar ? `<div ref={containerRef} style={{ display: "contents" }}>
|
|
3406
|
-
{children}
|
|
3407
|
-
</div>` : "{children}";
|
|
3408
|
-
return `
|
|
3409
|
-
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 ThemeWrapper \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3423
|
+
put<T = any>(url: string, data?: any, config?: ExtraConfig): Promise<Result<T>> {
|
|
3424
|
+
return this.http.put(url, data, config);
|
|
3425
|
+
}
|
|
3410
3426
|
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3427
|
+
delete<T = any>(url: string, params?: Record<string, any>, config?: ExtraConfig): Promise<Result<T>> {
|
|
3428
|
+
return this.http.delete(url, {
|
|
3429
|
+
...config,
|
|
3430
|
+
params,
|
|
3431
|
+
paramsSerializer,
|
|
3432
|
+
});
|
|
3433
|
+
}
|
|
3414
3434
|
|
|
3415
|
-
|
|
3416
|
-
|
|
3435
|
+
patch<T = any>(url: string, data?: any, config?: ExtraConfig): Promise<Result<T>> {
|
|
3436
|
+
return this.http.patch(url, data, config);
|
|
3437
|
+
}
|
|
3417
3438
|
}
|
|
3418
3439
|
|
|
3419
|
-
|
|
3420
|
-
const { appearance, primaryColor, neutralColor } = useThemeStore(
|
|
3421
|
-
(s) => ({ appearance: s.appearance, primaryColor: s.primaryColor, neutralColor: s.neutralColor }),
|
|
3422
|
-
shallow,
|
|
3423
|
-
);${cssVarSyncLine}${appearanceSyncLine}${externalThemeLine}
|
|
3424
|
-
|
|
3425
|
-
const resolvedAppearance = useMemo(() => {
|
|
3426
|
-
if (appearance !== "auto") return appearance;
|
|
3427
|
-
if (typeof window === "undefined") return "light";
|
|
3428
|
-
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
3429
|
-
}, [appearance]);
|
|
3430
|
-
|
|
3431
|
-
const theme = useCallback<GetAntdTheme>(
|
|
3432
|
-
(ap) => createThemeConfig({
|
|
3433
|
-
appearance: ap as "light" | "dark",
|
|
3434
|
-
primaryColor,
|
|
3435
|
-
neutralColor,
|
|
3436
|
-
}),
|
|
3437
|
-
[primaryColor, neutralColor],
|
|
3438
|
-
);
|
|
3439
|
-
|
|
3440
|
-
return (
|
|
3441
|
-
<AntdThemeProvider
|
|
3442
|
-
prefixCls={RUNTIME_PREFIX_CLS}
|
|
3443
|
-
appearance={resolvedAppearance}
|
|
3444
|
-
themeMode={appearance}
|
|
3445
|
-
theme={theme}${cssVar ? "\n customToken={{ cssVar: true }}" : ""}
|
|
3446
|
-
>
|
|
3447
|
-
${globalReset ? "<GlobalReset />" : ""}
|
|
3448
|
-
${childrenSlot}
|
|
3449
|
-
</AntdThemeProvider>
|
|
3450
|
-
);
|
|
3451
|
-
}
|
|
3440
|
+
// ============ \u5BFC\u51FA ============
|
|
3452
3441
|
|
|
3453
|
-
export
|
|
3442
|
+
export const request = new Request(instance);
|
|
3443
|
+
export type { Result };
|
|
3444
|
+
export default request;
|
|
3454
3445
|
`;
|
|
3455
3446
|
}
|
|
3456
3447
|
|
|
3457
|
-
// src/plugin/builtin/
|
|
3458
|
-
import {
|
|
3459
|
-
import {
|
|
3460
|
-
|
|
3461
|
-
|
|
3448
|
+
// src/plugin/builtin/tailwind.ts
|
|
3449
|
+
import { existsSync as existsSync10, writeFileSync as writeFileSync5 } from "fs";
|
|
3450
|
+
import { join as join10 } from "path";
|
|
3451
|
+
import { rspack as rspack5 } from "@rspack/core";
|
|
3452
|
+
var tailwindPlugin = createPlugin((options = {}) => ({
|
|
3453
|
+
name: "@4399ywkf/plugin-tailwind",
|
|
3462
3454
|
version: "1.0.0",
|
|
3463
|
-
description: "
|
|
3455
|
+
description: "Tailwind CSS \u96C6\u6210\u63D2\u4EF6",
|
|
3464
3456
|
setup(context) {
|
|
3465
3457
|
const {
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
prefix = ""
|
|
3458
|
+
darkModeSelector = '&:where([data-theme="dark"], [data-theme="dark"] *)',
|
|
3459
|
+
autoConfig = true,
|
|
3460
|
+
extraCSS = ""
|
|
3470
3461
|
} = options;
|
|
3471
|
-
const { cwd,
|
|
3472
|
-
if (
|
|
3473
|
-
|
|
3474
|
-
return {};
|
|
3475
|
-
}
|
|
3476
|
-
const mockPath = resolve2(cwd, mockDir);
|
|
3477
|
-
if (!existsSync9(mockPath)) {
|
|
3478
|
-
logger.warn(`Mock \u76EE\u5F55\u4E0D\u5B58\u5728: ${mockPath}`);
|
|
3479
|
-
return {};
|
|
3462
|
+
const { cwd, logger } = context;
|
|
3463
|
+
if (autoConfig) {
|
|
3464
|
+
ensurePostcssConfig(cwd, logger);
|
|
3480
3465
|
}
|
|
3481
3466
|
const hooks = {
|
|
3482
3467
|
modifyRspackConfig(rspackConfig) {
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3468
|
+
logger.info("Tailwind CSS \u5DF2\u542F\u7528");
|
|
3469
|
+
const rules = rspackConfig.module?.rules || [];
|
|
3470
|
+
const postcssConfigPath = join10(cwd, "postcss.config.js");
|
|
3471
|
+
const isProd = rspackConfig.mode === "production";
|
|
3472
|
+
const tailwindRule = {
|
|
3473
|
+
test: /tailwind\.css$/,
|
|
3474
|
+
use: [
|
|
3475
|
+
isProd ? rspack5.CssExtractRspackPlugin.loader : "style-loader",
|
|
3476
|
+
"css-loader",
|
|
3477
|
+
{
|
|
3478
|
+
loader: "postcss-loader",
|
|
3479
|
+
options: {
|
|
3480
|
+
postcssOptions: {
|
|
3481
|
+
config: postcssConfigPath
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
]
|
|
3486
|
+
};
|
|
3487
|
+
rules.unshift(tailwindRule);
|
|
3488
|
+
rspackConfig.module = { ...rspackConfig.module, rules };
|
|
3494
3489
|
return rspackConfig;
|
|
3495
3490
|
},
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3491
|
+
generateFiles(_ctx) {
|
|
3492
|
+
const cssContent = buildTailwindCSS(darkModeSelector, extraCSS);
|
|
3493
|
+
return [
|
|
3494
|
+
{
|
|
3495
|
+
path: "tailwind.css",
|
|
3496
|
+
content: cssContent
|
|
3497
|
+
}
|
|
3498
|
+
];
|
|
3499
|
+
},
|
|
3500
|
+
injectEntry(_ctx) {
|
|
3501
|
+
return {
|
|
3502
|
+
imports: [`import "./tailwind.css";`]
|
|
3503
|
+
};
|
|
3501
3504
|
}
|
|
3502
3505
|
};
|
|
3503
3506
|
return hooks;
|
|
3504
3507
|
}
|
|
3505
3508
|
}));
|
|
3506
|
-
function
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
const fullPath = join10(dir, entry);
|
|
3514
|
-
const stat = statSync2(fullPath);
|
|
3515
|
-
if (stat.isFile() && /\.(ts|js|mjs)$/.test(entry)) {
|
|
3516
|
-
files.push(fullPath);
|
|
3517
|
-
} else if (stat.isDirectory()) {
|
|
3518
|
-
files.push(...scanMockFiles(fullPath));
|
|
3519
|
-
}
|
|
3520
|
-
}
|
|
3521
|
-
return files;
|
|
3509
|
+
function buildTailwindCSS(darkModeSelector, extraCSS) {
|
|
3510
|
+
return `/* \u6B64\u6587\u4EF6\u7531 @4399ywkf/plugin-tailwind \u81EA\u52A8\u751F\u6210 */
|
|
3511
|
+
@import "tailwindcss";
|
|
3512
|
+
@variant dark (${darkModeSelector});
|
|
3513
|
+
${extraCSS ? `
|
|
3514
|
+
${extraCSS}` : ""}
|
|
3515
|
+
`;
|
|
3522
3516
|
}
|
|
3523
|
-
function
|
|
3524
|
-
const
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
}
|
|
3517
|
+
function ensurePostcssConfig(cwd, logger) {
|
|
3518
|
+
const configPath = join10(cwd, "postcss.config.js");
|
|
3519
|
+
if (!existsSync10(configPath)) {
|
|
3520
|
+
writeFileSync5(
|
|
3521
|
+
configPath,
|
|
3522
|
+
`module.exports = {
|
|
3523
|
+
plugins: {
|
|
3524
|
+
"@tailwindcss/postcss": {},
|
|
3525
|
+
},
|
|
3526
|
+
};
|
|
3527
|
+
`,
|
|
3528
|
+
"utf-8"
|
|
3529
|
+
);
|
|
3530
|
+
logger.info("\u5DF2\u81EA\u52A8\u751F\u6210 postcss.config.js");
|
|
3531
|
+
}
|
|
3532
3532
|
}
|
|
3533
3533
|
|
|
3534
|
-
// src/plugin/builtin/
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3534
|
+
// src/plugin/builtin/theme.ts
|
|
3535
|
+
import { join as join11 } from "path";
|
|
3536
|
+
var themePlugin = createPlugin((options = {}) => ({
|
|
3537
|
+
name: "@4399ywkf/plugin-theme",
|
|
3538
|
+
version: "3.0.0",
|
|
3539
|
+
description: "Lobe-UI \u98CE\u683C\u54CD\u5E94\u5F0F\u4E3B\u9898\u7CFB\u7EDF\u63D2\u4EF6",
|
|
3539
3540
|
setup(context) {
|
|
3540
3541
|
const {
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
beforeBuild() {
|
|
3550
|
-
if (timing) {
|
|
3551
|
-
buildStartTime = Date.now();
|
|
3552
|
-
logger.info("\u5F00\u59CB\u6784\u5EFA...");
|
|
3553
|
-
}
|
|
3554
|
-
},
|
|
3555
|
-
afterBuild(_context, stats) {
|
|
3556
|
-
if (timing) {
|
|
3557
|
-
const duration = Date.now() - buildStartTime;
|
|
3558
|
-
logger.info(`\u6784\u5EFA\u5B8C\u6210\uFF0C\u8017\u65F6: ${(duration / 1e3).toFixed(2)}s`);
|
|
3559
|
-
}
|
|
3560
|
-
if (!stats.success && stats.errors) {
|
|
3561
|
-
logger.error(`\u6784\u5EFA\u5931\u8D25\uFF0C\u9519\u8BEF\u6570: ${stats.errors.length}`);
|
|
3562
|
-
}
|
|
3563
|
-
},
|
|
3564
|
-
modifyRspackConfig(config) {
|
|
3565
|
-
if (buildAnalysis && isProd) {
|
|
3566
|
-
logger.info("\u6784\u5EFA\u5206\u6790\u5DF2\u542F\u7528");
|
|
3567
|
-
}
|
|
3568
|
-
return config;
|
|
3569
|
-
}
|
|
3570
|
-
};
|
|
3571
|
-
return hooks;
|
|
3572
|
-
}
|
|
3573
|
-
}));
|
|
3574
|
-
|
|
3575
|
-
// src/plugin/builtin/react-query.ts
|
|
3576
|
-
var reactQueryPlugin = createPlugin((options = {}) => ({
|
|
3577
|
-
name: "@4399ywkf/plugin-react-query",
|
|
3578
|
-
version: "1.0.0",
|
|
3579
|
-
description: "React Query + Axios \u8BF7\u6C42\u5C42\u96C6\u6210",
|
|
3580
|
-
setup(context) {
|
|
3581
|
-
const {
|
|
3582
|
-
staleTime = 5 * 60 * 1e3,
|
|
3583
|
-
gcTime = 10 * 60 * 1e3,
|
|
3584
|
-
retry = 1,
|
|
3585
|
-
devtools = true,
|
|
3586
|
-
baseURL = "",
|
|
3587
|
-
timeout = 15e3
|
|
3542
|
+
darkMode = true,
|
|
3543
|
+
defaultAppearance = "light",
|
|
3544
|
+
primaryColor,
|
|
3545
|
+
neutralColor,
|
|
3546
|
+
prefixCls = "ant",
|
|
3547
|
+
cssVar = true,
|
|
3548
|
+
globalReset = true,
|
|
3549
|
+
externalTheme = false
|
|
3588
3550
|
} = options;
|
|
3589
|
-
const { logger
|
|
3551
|
+
const { logger } = context;
|
|
3552
|
+
logger.info(
|
|
3553
|
+
`\u4E3B\u9898\u6A21\u5F0F: ${defaultAppearance}, \u4E3B\u8272: ${primaryColor ?? "primary(\u9ED8\u8BA4\u9ED1)"}, \u54CD\u5E94\u5F0F: \u2713`
|
|
3554
|
+
);
|
|
3590
3555
|
const hooks = {
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
const
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3556
|
+
modifyRspackConfig(config, ctx) {
|
|
3557
|
+
const themePath = join11(ctx.cwd, ".ywkf", "theme.tsx");
|
|
3558
|
+
const currentAlias = config.resolve?.alias ?? {};
|
|
3559
|
+
config.resolve = {
|
|
3560
|
+
...config.resolve,
|
|
3561
|
+
alias: {
|
|
3562
|
+
...currentAlias,
|
|
3563
|
+
"@ywkf/theme": themePath
|
|
3564
|
+
}
|
|
3565
|
+
};
|
|
3566
|
+
return config;
|
|
3567
|
+
},
|
|
3568
|
+
generateFiles(_ctx) {
|
|
3569
|
+
return [
|
|
3598
3570
|
{
|
|
3599
|
-
path: "
|
|
3600
|
-
content:
|
|
3571
|
+
path: "theme.tsx",
|
|
3572
|
+
content: generateThemeProvider({
|
|
3573
|
+
darkMode,
|
|
3574
|
+
defaultAppearance,
|
|
3575
|
+
primaryColor,
|
|
3576
|
+
neutralColor,
|
|
3577
|
+
prefixCls,
|
|
3578
|
+
cssVar,
|
|
3579
|
+
globalReset,
|
|
3580
|
+
externalTheme
|
|
3581
|
+
})
|
|
3601
3582
|
}
|
|
3602
3583
|
];
|
|
3603
|
-
return files;
|
|
3604
3584
|
},
|
|
3605
|
-
injectBootstrap(
|
|
3585
|
+
injectBootstrap(_ctx) {
|
|
3606
3586
|
return {
|
|
3607
|
-
imports: [
|
|
3608
|
-
`import { QueryClientProvider } from "@tanstack/react-query";`,
|
|
3609
|
-
`import { queryClient } from "./query-client";`
|
|
3610
|
-
],
|
|
3611
|
-
topLevel: [
|
|
3612
|
-
`// React Query Provider\uFF08\u7531 @4399ywkf/plugin-react-query \u6CE8\u5165\uFF09`
|
|
3613
|
-
]
|
|
3587
|
+
imports: [`import { ThemeWrapper } from "./theme";`]
|
|
3614
3588
|
};
|
|
3615
3589
|
},
|
|
3616
3590
|
modifyBootstrapCode(code) {
|
|
3617
3591
|
const providerEntry = ` {
|
|
3618
|
-
component:
|
|
3619
|
-
props: {
|
|
3620
|
-
order:
|
|
3592
|
+
component: ThemeWrapper as React.ComponentType<{ children: React.ReactNode }>,
|
|
3593
|
+
props: {},
|
|
3594
|
+
order: 10,
|
|
3621
3595
|
}`;
|
|
3622
3596
|
if (code.includes("providers: []")) {
|
|
3623
|
-
code = code.replace(
|
|
3624
|
-
"providers: []",
|
|
3625
|
-
`providers: [
|
|
3597
|
+
code = code.replace("providers: []", `providers: [
|
|
3626
3598
|
${providerEntry},
|
|
3627
|
-
]`
|
|
3628
|
-
);
|
|
3599
|
+
]`);
|
|
3629
3600
|
} else if (code.includes("providers: [")) {
|
|
3630
|
-
code = code.replace(
|
|
3631
|
-
|
|
3632
|
-
`providers: [
|
|
3633
|
-
${providerEntry},`
|
|
3634
|
-
);
|
|
3601
|
+
code = code.replace("providers: [", `providers: [
|
|
3602
|
+
${providerEntry},`);
|
|
3635
3603
|
}
|
|
3636
3604
|
if (!code.includes("import React")) {
|
|
3637
3605
|
code = code.replace(
|
|
@@ -3646,223 +3614,323 @@ import { bootstrap`
|
|
|
3646
3614
|
return hooks;
|
|
3647
3615
|
}
|
|
3648
3616
|
}));
|
|
3649
|
-
function
|
|
3650
|
-
const {
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
});
|
|
3673
|
-
|
|
3674
|
-
export default queryClient;
|
|
3675
|
-
`;
|
|
3617
|
+
function generateThemeProvider(opts) {
|
|
3618
|
+
const {
|
|
3619
|
+
darkMode,
|
|
3620
|
+
defaultAppearance,
|
|
3621
|
+
primaryColor,
|
|
3622
|
+
neutralColor,
|
|
3623
|
+
prefixCls,
|
|
3624
|
+
cssVar,
|
|
3625
|
+
globalReset,
|
|
3626
|
+
externalTheme
|
|
3627
|
+
} = opts;
|
|
3628
|
+
const sections = [];
|
|
3629
|
+
sections.push(`// \u6B64\u6587\u4EF6\u7531 @4399ywkf/plugin-theme v3 \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u4FEE\u6539`);
|
|
3630
|
+
sections.push(buildImports({ globalReset, cssVar }));
|
|
3631
|
+
sections.push(TYPES_CODE);
|
|
3632
|
+
sections.push(buildStoreCode({ defaultAppearance, primaryColor, neutralColor }));
|
|
3633
|
+
sections.push(HOOKS_CODE);
|
|
3634
|
+
if (globalReset) sections.push(GLOBAL_RESET_CODE);
|
|
3635
|
+
if (cssVar) sections.push(CSS_VAR_SYNC_CODE);
|
|
3636
|
+
if (darkMode) sections.push(APPEARANCE_SYNC_CODE);
|
|
3637
|
+
if (externalTheme) sections.push(EXTERNAL_THEME_CODE);
|
|
3638
|
+
sections.push(buildWrapperCode({ darkMode, cssVar, globalReset, externalTheme, prefixCls }));
|
|
3639
|
+
return sections.join("\n");
|
|
3676
3640
|
}
|
|
3677
|
-
function
|
|
3678
|
-
const
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3641
|
+
function buildImports(opts) {
|
|
3642
|
+
const reactImports = [
|
|
3643
|
+
"useCallback",
|
|
3644
|
+
"useEffect",
|
|
3645
|
+
"useMemo",
|
|
3646
|
+
...opts.cssVar ? ["useLayoutEffect", "useRef"] : [],
|
|
3647
|
+
"type ReactNode"
|
|
3648
|
+
];
|
|
3649
|
+
const antdStyleImports = [
|
|
3650
|
+
"ThemeProvider as AntdThemeProvider",
|
|
3651
|
+
"type GetAntdTheme",
|
|
3652
|
+
...opts.globalReset ? ["createGlobalStyle", "css"] : []
|
|
3653
|
+
];
|
|
3654
|
+
return `
|
|
3655
|
+
import React, { ${reactImports.join(", ")} } from "react";
|
|
3656
|
+
import { ${antdStyleImports.join(", ")} } from "antd-style";
|
|
3657
|
+
import { createWithEqualityFn } from "zustand/traditional";
|
|
3658
|
+
import { shallow } from "zustand/shallow";
|
|
3659
|
+
import { createThemeConfig, type PrimaryColors, type NeutralColors } from "@4399ywkf/theme-system";`;
|
|
3660
|
+
}
|
|
3661
|
+
var TYPES_CODE = `
|
|
3662
|
+
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Types \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3687
3663
|
|
|
3688
|
-
|
|
3664
|
+
export type ThemeAppearance = "light" | "dark" | "auto";
|
|
3689
3665
|
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
// src/request.ts \u4E0D\u5B58\u5728\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E
|
|
3666
|
+
export interface ThemeState {
|
|
3667
|
+
appearance: ThemeAppearance;
|
|
3668
|
+
primaryColor?: PrimaryColors;
|
|
3669
|
+
neutralColor?: NeutralColors;
|
|
3695
3670
|
}
|
|
3696
3671
|
|
|
3697
|
-
|
|
3672
|
+
export interface ThemeActions {
|
|
3673
|
+
setAppearance: (mode: ThemeAppearance) => void;
|
|
3674
|
+
setPrimaryColor: (color: PrimaryColors | undefined) => void;
|
|
3675
|
+
setNeutralColor: (color: NeutralColors | undefined) => void;
|
|
3676
|
+
setTheme: (partial: Partial<ThemeState>) => void;
|
|
3677
|
+
}
|
|
3698
3678
|
|
|
3699
|
-
|
|
3700
|
-
* GET \u8BF7\u6C42\u53C2\u6570\u5E8F\u5217\u5316\u89C4\u5219\uFF1A
|
|
3701
|
-
* - \u6570\u7EC4\uFF1Arepeat \u6A21\u5F0F\uFF08key=1&key=2\uFF09
|
|
3702
|
-
* - \u5BF9\u8C61\uFF1AJSON.stringify \u540E\u4F5C\u4E3A\u5B57\u7B26\u4E32\u4F20\u9012
|
|
3703
|
-
* - null / undefined\uFF1AskipNulls \u8DF3\u8FC7
|
|
3704
|
-
* - \u57FA\u672C\u7C7B\u578B\uFF1A\u539F\u6837\u4F20\u9012
|
|
3705
|
-
*/
|
|
3706
|
-
export function paramsSerializer(params: Record<string, any>): string {
|
|
3707
|
-
const normalized: Record<string, any> = {};
|
|
3679
|
+
export type ThemeStore = ThemeState & ThemeActions;
|
|
3708
3680
|
|
|
3709
|
-
|
|
3710
|
-
|
|
3681
|
+
export type { PrimaryColors, NeutralColors };`;
|
|
3682
|
+
function buildStoreCode(opts) {
|
|
3683
|
+
const primaryLine = opts.primaryColor ? ` primaryColor: "${opts.primaryColor}" as PrimaryColors,` : ` primaryColor: undefined,`;
|
|
3684
|
+
const neutralLine = opts.neutralColor ? ` neutralColor: "${opts.neutralColor}" as NeutralColors,` : ` neutralColor: undefined,`;
|
|
3685
|
+
return `
|
|
3686
|
+
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Theme Store \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3711
3687
|
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
normalized[key] = JSON.stringify(value);
|
|
3718
|
-
} else {
|
|
3719
|
-
normalized[key] = value;
|
|
3720
|
-
}
|
|
3721
|
-
});
|
|
3688
|
+
const DEFAULT_THEME: ThemeState = {
|
|
3689
|
+
appearance: "${opts.defaultAppearance}",
|
|
3690
|
+
${primaryLine}
|
|
3691
|
+
${neutralLine}
|
|
3692
|
+
};
|
|
3722
3693
|
|
|
3723
|
-
|
|
3694
|
+
export const useThemeStore = createWithEqualityFn<ThemeStore>()(
|
|
3695
|
+
(set) => ({
|
|
3696
|
+
...DEFAULT_THEME,
|
|
3697
|
+
setAppearance: (mode) => set({ appearance: mode }),
|
|
3698
|
+
setPrimaryColor: (color) => set({ primaryColor: color }),
|
|
3699
|
+
setNeutralColor: (color) => set({ neutralColor: color }),
|
|
3700
|
+
setTheme: (partial) => set(partial),
|
|
3701
|
+
}),
|
|
3702
|
+
shallow,
|
|
3703
|
+
);`;
|
|
3724
3704
|
}
|
|
3705
|
+
var HOOKS_CODE = `
|
|
3706
|
+
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Convenience Hooks \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3725
3707
|
|
|
3726
|
-
|
|
3708
|
+
export const useTheme = () =>
|
|
3709
|
+
useThemeStore(
|
|
3710
|
+
(s) => ({
|
|
3711
|
+
appearance: s.appearance,
|
|
3712
|
+
primaryColor: s.primaryColor,
|
|
3713
|
+
neutralColor: s.neutralColor,
|
|
3714
|
+
}),
|
|
3715
|
+
shallow,
|
|
3716
|
+
);
|
|
3727
3717
|
|
|
3728
|
-
const
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
headers: {
|
|
3733
|
-
"Content-Type": "application/json",
|
|
3734
|
-
...(userConfig.headers || {}),
|
|
3735
|
-
},
|
|
3736
|
-
});
|
|
3718
|
+
export const useAppearance = () => useThemeStore((s) => s.appearance);
|
|
3719
|
+
export const usePrimaryColor = () => useThemeStore((s) => s.primaryColor);`;
|
|
3720
|
+
var GLOBAL_RESET_CODE = `
|
|
3721
|
+
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Global Style \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3737
3722
|
|
|
3738
|
-
|
|
3723
|
+
const GlobalReset = createGlobalStyle(({ theme }) => css\`
|
|
3724
|
+
:root {
|
|
3725
|
+
--font-settings: "cv01", "tnum", "kern";
|
|
3726
|
+
--font-variations: "opsz" auto, tabular-nums;
|
|
3727
|
+
}
|
|
3739
3728
|
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
const prefix = userConfig.tokenPrefix ?? "Bearer";
|
|
3747
|
-
config.headers.Authorization = prefix ? \`\${prefix} \${token}\` : token;
|
|
3748
|
-
}
|
|
3749
|
-
} else {
|
|
3750
|
-
// \u9ED8\u8BA4\uFF1A\u4ECE localStorage \u8BFB\u53D6
|
|
3751
|
-
const token = typeof localStorage !== "undefined"
|
|
3752
|
-
? localStorage.getItem("token")
|
|
3753
|
-
: null;
|
|
3754
|
-
if (token && config.headers) {
|
|
3755
|
-
config.headers.Authorization = \`Bearer \${token}\`;
|
|
3756
|
-
}
|
|
3757
|
-
}
|
|
3729
|
+
*,
|
|
3730
|
+
*::before,
|
|
3731
|
+
*::after {
|
|
3732
|
+
box-sizing: border-box;
|
|
3733
|
+
vertical-align: baseline;
|
|
3734
|
+
}
|
|
3758
3735
|
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3736
|
+
* {
|
|
3737
|
+
scrollbar-color: \${theme.colorFill} transparent;
|
|
3738
|
+
scrollbar-width: thin;
|
|
3739
|
+
}
|
|
3763
3740
|
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3741
|
+
html {
|
|
3742
|
+
overscroll-behavior: none;
|
|
3743
|
+
color-scheme: \${theme.isDarkMode ? "dark" : "light"};
|
|
3744
|
+
}
|
|
3768
3745
|
|
|
3769
|
-
|
|
3746
|
+
html, body, #root, #app {
|
|
3747
|
+
height: 100%;
|
|
3748
|
+
margin: 0;
|
|
3749
|
+
padding: 0;
|
|
3750
|
+
}
|
|
3770
3751
|
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3752
|
+
body {
|
|
3753
|
+
overflow: hidden auto;
|
|
3754
|
+
min-height: 100vh;
|
|
3755
|
+
font-family: \${theme.fontFamily};
|
|
3756
|
+
font-size: \${theme.fontSize}px;
|
|
3757
|
+
font-feature-settings: var(--font-settings);
|
|
3758
|
+
font-variation-settings: var(--font-variations);
|
|
3759
|
+
line-height: 1;
|
|
3760
|
+
color: \${theme.colorTextBase};
|
|
3761
|
+
text-size-adjust: none;
|
|
3762
|
+
text-rendering: optimizelegibility;
|
|
3763
|
+
word-wrap: break-word;
|
|
3764
|
+
background-color: \${theme.colorBgLayout};
|
|
3765
|
+
-webkit-font-smoothing: antialiased;
|
|
3766
|
+
-moz-osx-font-smoothing: grayscale;
|
|
3767
|
+
-webkit-overflow-scrolling: touch;
|
|
3768
|
+
-webkit-tap-highlight-color: transparent;
|
|
3769
|
+
}
|
|
3777
3770
|
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
}
|
|
3781
|
-
(error: AxiosError) => {
|
|
3782
|
-
// \u7528\u6237\u81EA\u5B9A\u4E49\u9519\u8BEF\u5904\u7406
|
|
3783
|
-
if (userConfig.errorHandler) {
|
|
3784
|
-
return userConfig.errorHandler(error as any);
|
|
3785
|
-
}
|
|
3771
|
+
code {
|
|
3772
|
+
font-family: \${theme.fontFamilyCode} !important;
|
|
3773
|
+
}
|
|
3786
3774
|
|
|
3787
|
-
|
|
3788
|
-
|
|
3775
|
+
::selection {
|
|
3776
|
+
color: #000;
|
|
3777
|
+
-webkit-text-fill-color: unset !important;
|
|
3778
|
+
}
|
|
3779
|
+
\`);`;
|
|
3780
|
+
var CSS_VAR_SYNC_CODE = `
|
|
3781
|
+
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 CSS Variable Sync \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3789
3782
|
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3783
|
+
const CSS_VAR_PREFIX = "css-var-";
|
|
3784
|
+
|
|
3785
|
+
function useCssVarSync(ref: React.RefObject<HTMLDivElement | null>) {
|
|
3786
|
+
useLayoutEffect(() => {
|
|
3787
|
+
const node = ref.current;
|
|
3788
|
+
if (!node) return;
|
|
3789
|
+
|
|
3790
|
+
const htmlEl = document.documentElement;
|
|
3791
|
+
let currentClasses: string[] = [];
|
|
3792
|
+
|
|
3793
|
+
const sync = () => {
|
|
3794
|
+
for (const cls of currentClasses) htmlEl.classList.remove(cls);
|
|
3795
|
+
|
|
3796
|
+
const next: string[] = [];
|
|
3797
|
+
let el: HTMLElement | null = node;
|
|
3798
|
+
while (el && el !== htmlEl) {
|
|
3799
|
+
for (const cls of el.classList) {
|
|
3800
|
+
if (cls.startsWith(CSS_VAR_PREFIX)) next.push(cls);
|
|
3803
3801
|
}
|
|
3802
|
+
el = el.parentElement;
|
|
3803
|
+
}
|
|
3804
|
+
|
|
3805
|
+
for (const cls of next) htmlEl.classList.add(cls);
|
|
3806
|
+
currentClasses = next;
|
|
3807
|
+
};
|
|
3808
|
+
|
|
3809
|
+
sync();
|
|
3810
|
+
|
|
3811
|
+
const observer = new MutationObserver(sync);
|
|
3812
|
+
let el: HTMLElement | null = node;
|
|
3813
|
+
while (el && el !== htmlEl) {
|
|
3814
|
+
observer.observe(el, { attributeFilter: ["class"] });
|
|
3815
|
+
el = el.parentElement;
|
|
3804
3816
|
}
|
|
3805
3817
|
|
|
3806
|
-
return
|
|
3807
|
-
|
|
3808
|
-
);
|
|
3818
|
+
return () => {
|
|
3819
|
+
observer.disconnect();
|
|
3820
|
+
for (const cls of currentClasses) htmlEl.classList.remove(cls);
|
|
3821
|
+
};
|
|
3822
|
+
}, []);
|
|
3823
|
+
}`;
|
|
3824
|
+
var APPEARANCE_SYNC_CODE = `
|
|
3825
|
+
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Appearance Sync \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3809
3826
|
|
|
3810
|
-
|
|
3827
|
+
function useAppearanceSync(appearance: ThemeAppearance) {
|
|
3828
|
+
useEffect(() => {
|
|
3829
|
+
if (appearance !== "auto") {
|
|
3830
|
+
document.documentElement.dataset.theme = appearance;
|
|
3831
|
+
return;
|
|
3832
|
+
}
|
|
3811
3833
|
|
|
3812
|
-
|
|
3834
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
3835
|
+
document.documentElement.dataset.theme = mq.matches ? "dark" : "light";
|
|
3813
3836
|
|
|
3814
|
-
|
|
3815
|
-
|
|
3837
|
+
function handleChange(e: MediaQueryListEvent) {
|
|
3838
|
+
document.documentElement.dataset.theme = e.matches ? "dark" : "light";
|
|
3839
|
+
}
|
|
3816
3840
|
|
|
3817
|
-
|
|
3818
|
-
return
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
}
|
|
3841
|
+
mq.addEventListener("change", handleChange);
|
|
3842
|
+
return () => mq.removeEventListener("change", handleChange);
|
|
3843
|
+
}, [appearance]);
|
|
3844
|
+
}`;
|
|
3845
|
+
var EXTERNAL_THEME_CODE = `
|
|
3846
|
+
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 External Theme Injection \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3824
3847
|
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3848
|
+
function useExternalTheme() {
|
|
3849
|
+
useEffect(() => {
|
|
3850
|
+
const hostTheme = (window as any).__YWKF_THEME__;
|
|
3851
|
+
if (hostTheme && typeof hostTheme === "object") {
|
|
3852
|
+
useThemeStore.getState().setTheme(hostTheme);
|
|
3853
|
+
}
|
|
3828
3854
|
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3855
|
+
const handler = (e: Event) => {
|
|
3856
|
+
const detail = (e as CustomEvent<Partial<ThemeState>>).detail;
|
|
3857
|
+
if (detail) useThemeStore.getState().setTheme(detail);
|
|
3858
|
+
};
|
|
3832
3859
|
|
|
3833
|
-
|
|
3834
|
-
return
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3860
|
+
window.addEventListener("ywkf:theme-change", handler);
|
|
3861
|
+
return () => window.removeEventListener("ywkf:theme-change", handler);
|
|
3862
|
+
}, []);
|
|
3863
|
+
}`;
|
|
3864
|
+
function buildWrapperCode(opts) {
|
|
3865
|
+
const { darkMode, cssVar, globalReset, externalTheme, prefixCls } = opts;
|
|
3866
|
+
const refLine = cssVar ? "\n const containerRef = useRef<HTMLDivElement>(null);" : "";
|
|
3867
|
+
const cssVarSyncLine = cssVar ? "\n useCssVarSync(containerRef);" : "";
|
|
3868
|
+
const appearanceSyncLine = darkMode ? "\n useAppearanceSync(appearance);" : "";
|
|
3869
|
+
const externalThemeLine = externalTheme ? "\n useExternalTheme();" : "";
|
|
3870
|
+
const childrenSlot = cssVar ? `<div ref={containerRef} style={{ display: "contents" }}>
|
|
3871
|
+
{children}
|
|
3872
|
+
</div>` : "{children}";
|
|
3873
|
+
return `
|
|
3874
|
+
// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 ThemeWrapper \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
3840
3875
|
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
}
|
|
3876
|
+
const RUNTIME_PREFIX_CLS = typeof process !== "undefined"
|
|
3877
|
+
&& process.env?.YWKF_PREFIX_CLS
|
|
3878
|
+
|| "${prefixCls}";
|
|
3879
|
+
|
|
3880
|
+
interface ThemeWrapperProps {
|
|
3881
|
+
children: ReactNode;
|
|
3844
3882
|
}
|
|
3845
3883
|
|
|
3846
|
-
|
|
3884
|
+
export function ThemeWrapper({ children }: ThemeWrapperProps) {${refLine}
|
|
3885
|
+
const { appearance, primaryColor, neutralColor } = useThemeStore(
|
|
3886
|
+
(s) => ({ appearance: s.appearance, primaryColor: s.primaryColor, neutralColor: s.neutralColor }),
|
|
3887
|
+
shallow,
|
|
3888
|
+
);${cssVarSyncLine}${appearanceSyncLine}${externalThemeLine}
|
|
3847
3889
|
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
}
|
|
3890
|
+
const resolvedAppearance = useMemo(() => {
|
|
3891
|
+
if (appearance !== "auto") return appearance;
|
|
3892
|
+
if (typeof window === "undefined") return "light";
|
|
3893
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
3894
|
+
}, [appearance]);
|
|
3853
3895
|
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3896
|
+
const theme = useCallback<GetAntdTheme>(
|
|
3897
|
+
(ap) => createThemeConfig({
|
|
3898
|
+
appearance: ap as "light" | "dark",
|
|
3899
|
+
primaryColor,
|
|
3900
|
+
neutralColor,
|
|
3901
|
+
}),
|
|
3902
|
+
[primaryColor, neutralColor],
|
|
3903
|
+
);
|
|
3904
|
+
|
|
3905
|
+
return (
|
|
3906
|
+
<AntdThemeProvider
|
|
3907
|
+
prefixCls={RUNTIME_PREFIX_CLS}
|
|
3908
|
+
appearance={resolvedAppearance}
|
|
3909
|
+
themeMode={appearance}
|
|
3910
|
+
theme={theme}${cssVar ? "\n customToken={{ cssVar: true }}" : ""}
|
|
3911
|
+
>
|
|
3912
|
+
${globalReset ? "<GlobalReset />" : ""}
|
|
3913
|
+
${childrenSlot}
|
|
3914
|
+
</AntdThemeProvider>
|
|
3915
|
+
);
|
|
3916
|
+
}
|
|
3917
|
+
|
|
3918
|
+
export default ThemeWrapper;
|
|
3919
|
+
`;
|
|
3920
|
+
}
|
|
3921
|
+
|
|
3922
|
+
// src/plugin/builtin/zustand.ts
|
|
3923
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
3924
|
+
import { join as join12 } from "path";
|
|
3925
|
+
var zustandPlugin = createPlugin((options = {}) => ({
|
|
3858
3926
|
name: "@4399ywkf/plugin-zustand",
|
|
3859
3927
|
version: "1.0.0",
|
|
3860
3928
|
description: "Zustand \u72B6\u6001\u7BA1\u7406\u96C6\u6210",
|
|
3861
3929
|
setup(context) {
|
|
3862
3930
|
const { scaffold = true, storeDir = "store" } = options;
|
|
3863
3931
|
const { cwd, logger } = context;
|
|
3864
|
-
const storePath =
|
|
3865
|
-
if (scaffold && !
|
|
3932
|
+
const storePath = join12(cwd, storeDir);
|
|
3933
|
+
if (scaffold && !existsSync11(storePath)) {
|
|
3866
3934
|
scaffoldStore(storePath, logger);
|
|
3867
3935
|
}
|
|
3868
3936
|
const hooks = {
|
|
@@ -3875,7 +3943,7 @@ var zustandPlugin = createPlugin((options = {}) => ({
|
|
|
3875
3943
|
rspackConfig.resolve = resolve4;
|
|
3876
3944
|
return rspackConfig;
|
|
3877
3945
|
},
|
|
3878
|
-
generateFiles(
|
|
3946
|
+
generateFiles(_ctx) {
|
|
3879
3947
|
return [
|
|
3880
3948
|
{
|
|
3881
3949
|
path: "store.ts",
|
|
@@ -3890,47 +3958,31 @@ var zustandPlugin = createPlugin((options = {}) => ({
|
|
|
3890
3958
|
function scaffoldStore(storePath, logger) {
|
|
3891
3959
|
const dirs = [
|
|
3892
3960
|
storePath,
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3961
|
+
join12(storePath, "middleware"),
|
|
3962
|
+
join12(storePath, "app"),
|
|
3963
|
+
join12(storePath, "app", "slices"),
|
|
3964
|
+
join12(storePath, "app", "slices", "counter")
|
|
3897
3965
|
];
|
|
3898
3966
|
for (const dir of dirs) {
|
|
3899
|
-
if (!
|
|
3967
|
+
if (!existsSync11(dir)) {
|
|
3900
3968
|
mkdirSync4(dir, { recursive: true });
|
|
3901
3969
|
}
|
|
3902
3970
|
}
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
"utf-8"
|
|
3907
|
-
);
|
|
3908
|
-
writeFileSync5(
|
|
3909
|
-
join11(storePath, "app", "slices", "counter", "initialState.ts"),
|
|
3971
|
+
writeFileSync6(join12(storePath, "middleware", "createDevtools.ts"), TPL_CREATE_DEVTOOLS, "utf-8");
|
|
3972
|
+
writeFileSync6(
|
|
3973
|
+
join12(storePath, "app", "slices", "counter", "initialState.ts"),
|
|
3910
3974
|
TPL_COUNTER_INITIAL_STATE,
|
|
3911
3975
|
"utf-8"
|
|
3912
3976
|
);
|
|
3913
|
-
|
|
3914
|
-
|
|
3977
|
+
writeFileSync6(
|
|
3978
|
+
join12(storePath, "app", "slices", "counter", "actions.ts"),
|
|
3915
3979
|
TPL_COUNTER_ACTIONS,
|
|
3916
3980
|
"utf-8"
|
|
3917
3981
|
);
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
);
|
|
3923
|
-
writeFileSync5(
|
|
3924
|
-
join11(storePath, "app", "store.ts"),
|
|
3925
|
-
TPL_APP_STORE,
|
|
3926
|
-
"utf-8"
|
|
3927
|
-
);
|
|
3928
|
-
writeFileSync5(
|
|
3929
|
-
join11(storePath, "app", "index.tsx"),
|
|
3930
|
-
TPL_APP_INDEX,
|
|
3931
|
-
"utf-8"
|
|
3932
|
-
);
|
|
3933
|
-
writeFileSync5(join11(storePath, "index.ts"), TPL_STORE_INDEX, "utf-8");
|
|
3982
|
+
writeFileSync6(join12(storePath, "app", "initialState.ts"), TPL_APP_INITIAL_STATE, "utf-8");
|
|
3983
|
+
writeFileSync6(join12(storePath, "app", "store.ts"), TPL_APP_STORE, "utf-8");
|
|
3984
|
+
writeFileSync6(join12(storePath, "app", "index.tsx"), TPL_APP_INDEX, "utf-8");
|
|
3985
|
+
writeFileSync6(join12(storePath, "index.ts"), TPL_STORE_INDEX, "utf-8");
|
|
3934
3986
|
logger.info("\u5DF2\u751F\u6210 store/ \u811A\u624B\u67B6\uFF08Agent/Slice \u67B6\u6784\uFF09");
|
|
3935
3987
|
}
|
|
3936
3988
|
var TPL_CREATE_DEVTOOLS = `import type { DevtoolsOptions } from "zustand/middleware";
|
|
@@ -4092,502 +4144,469 @@ export type { StateCreator, StoreApi } from "zustand";
|
|
|
4092
4144
|
`;
|
|
4093
4145
|
}
|
|
4094
4146
|
|
|
4095
|
-
// src/
|
|
4096
|
-
import {
|
|
4097
|
-
import {
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4147
|
+
// src/router/plugin.ts
|
|
4148
|
+
import { existsSync as existsSync12, watch as watch2 } from "fs";
|
|
4149
|
+
import { join as join13 } from "path";
|
|
4150
|
+
var ConventionalRoutePlugin = class {
|
|
4151
|
+
options;
|
|
4152
|
+
isWatching = false;
|
|
4153
|
+
hasGenerated = false;
|
|
4154
|
+
lastGeneratedContent = "";
|
|
4155
|
+
constructor(options) {
|
|
4156
|
+
this.options = options;
|
|
4157
|
+
}
|
|
4158
|
+
apply(compiler) {
|
|
4159
|
+
const pluginName = "ConventionalRoutePlugin";
|
|
4160
|
+
compiler.hooks.beforeCompile.tapAsync(pluginName, (_params, callback) => {
|
|
4161
|
+
if (!this.hasGenerated) {
|
|
4162
|
+
this.generateRoutes();
|
|
4163
|
+
this.hasGenerated = true;
|
|
4164
|
+
}
|
|
4165
|
+
callback();
|
|
4166
|
+
});
|
|
4167
|
+
if (this.options.watch && !this.isWatching) {
|
|
4168
|
+
this.watchPages();
|
|
4116
4169
|
}
|
|
4117
4170
|
}
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4171
|
+
/**
|
|
4172
|
+
* 生成路由文件(带内容比对,避免不必要的重复生成)
|
|
4173
|
+
*/
|
|
4174
|
+
generateRoutes() {
|
|
4175
|
+
try {
|
|
4176
|
+
const generator = new ConventionalRouteGenerator({
|
|
4177
|
+
pagesDir: this.options.pagesDir,
|
|
4178
|
+
outputDir: this.options.outputDir,
|
|
4179
|
+
basename: this.options.basename
|
|
4180
|
+
});
|
|
4181
|
+
const newContent = generator.generateCode();
|
|
4182
|
+
const _outputPath = join13(this.options.outputDir, "routes.tsx");
|
|
4183
|
+
const normalizedNew = this.normalizeContent(newContent);
|
|
4184
|
+
const normalizedOld = this.normalizeContent(this.lastGeneratedContent);
|
|
4185
|
+
if (normalizedNew === normalizedOld) {
|
|
4186
|
+
return;
|
|
4128
4187
|
}
|
|
4129
|
-
|
|
4188
|
+
generator.write();
|
|
4189
|
+
this.lastGeneratedContent = newContent;
|
|
4190
|
+
} catch (error) {
|
|
4191
|
+
console.error("[ywkf] \u751F\u6210\u8DEF\u7531\u5931\u8D25:", error);
|
|
4130
4192
|
}
|
|
4131
4193
|
}
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
const publicEnvPath = resolve3(cwd, env.publicEnvFile ?? "config/env/.env.public");
|
|
4138
|
-
if (existsSync11(publicEnvPath)) {
|
|
4139
|
-
dotenv.config({ path: publicEnvPath });
|
|
4194
|
+
/**
|
|
4195
|
+
* 标准化内容(去掉时间戳等动态部分)
|
|
4196
|
+
*/
|
|
4197
|
+
normalizeContent(content) {
|
|
4198
|
+
return content.replace(/\/\/ Generated at: .+/g, "");
|
|
4140
4199
|
}
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4200
|
+
/**
|
|
4201
|
+
* 监听页面目录变化
|
|
4202
|
+
*/
|
|
4203
|
+
watchPages() {
|
|
4204
|
+
if (!existsSync12(this.options.pagesDir)) {
|
|
4205
|
+
return;
|
|
4147
4206
|
}
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
process.env.APP_PORT = process.env.APP_PORT || String(config.dev.port);
|
|
4157
|
-
}
|
|
4158
|
-
|
|
4159
|
-
// src/cli/port.ts
|
|
4160
|
-
import net from "net";
|
|
4161
|
-
function isPortAvailable(port, host) {
|
|
4162
|
-
return new Promise((resolve4) => {
|
|
4163
|
-
const server = net.createServer();
|
|
4164
|
-
server.once("error", (err) => {
|
|
4165
|
-
if (err.code === "EADDRINUSE") {
|
|
4166
|
-
resolve4(false);
|
|
4167
|
-
} else {
|
|
4168
|
-
resolve4(false);
|
|
4207
|
+
this.isWatching = true;
|
|
4208
|
+
let debounceTimer = null;
|
|
4209
|
+
const watcher = watch2(this.options.pagesDir, { recursive: true }, (_eventType, filename) => {
|
|
4210
|
+
if (!filename?.match(/\.(tsx?|jsx?)$/)) {
|
|
4211
|
+
return;
|
|
4212
|
+
}
|
|
4213
|
+
if (debounceTimer) {
|
|
4214
|
+
clearTimeout(debounceTimer);
|
|
4169
4215
|
}
|
|
4216
|
+
debounceTimer = setTimeout(() => {
|
|
4217
|
+
if (process.env.DEBUG) console.log(`[ywkf] \u68C0\u6D4B\u5230\u9875\u9762\u53D8\u5316: ${filename}`);
|
|
4218
|
+
this.generateRoutes();
|
|
4219
|
+
}, 500);
|
|
4170
4220
|
});
|
|
4171
|
-
|
|
4172
|
-
|
|
4221
|
+
process.on("exit", () => {
|
|
4222
|
+
watcher.close();
|
|
4173
4223
|
});
|
|
4174
|
-
|
|
4175
|
-
|
|
4224
|
+
}
|
|
4225
|
+
};
|
|
4226
|
+
|
|
4227
|
+
// src/runtime/bootstrap.tsx
|
|
4228
|
+
import { createRoot } from "react-dom/client";
|
|
4229
|
+
|
|
4230
|
+
// src/runtime/providers.tsx
|
|
4231
|
+
import { ConfigProvider } from "antd";
|
|
4232
|
+
import zhCN from "antd/locale/zh_CN.js";
|
|
4233
|
+
import { StrictMode, Suspense } from "react";
|
|
4234
|
+
import { RouterProvider } from "react-router";
|
|
4235
|
+
|
|
4236
|
+
// src/runtime/context.tsx
|
|
4237
|
+
import { createContext, useContext } from "react";
|
|
4238
|
+
import { jsx } from "react/jsx-runtime";
|
|
4239
|
+
var defaultContextValue = {
|
|
4240
|
+
appName: "app",
|
|
4241
|
+
basename: "/",
|
|
4242
|
+
isDev: process.env.NODE_ENV === "development",
|
|
4243
|
+
env: {}
|
|
4244
|
+
};
|
|
4245
|
+
var AppContext = createContext(defaultContextValue);
|
|
4246
|
+
function AppContextProvider({ value, children }) {
|
|
4247
|
+
const contextValue = {
|
|
4248
|
+
...defaultContextValue,
|
|
4249
|
+
...value,
|
|
4250
|
+
env: {
|
|
4251
|
+
...defaultContextValue.env,
|
|
4252
|
+
...value.env
|
|
4253
|
+
}
|
|
4254
|
+
};
|
|
4255
|
+
return /* @__PURE__ */ jsx(AppContext.Provider, { value: contextValue, children });
|
|
4176
4256
|
}
|
|
4177
|
-
|
|
4178
|
-
const
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
const available = await isPortAvailable(port, host);
|
|
4182
|
-
if (available) return port;
|
|
4257
|
+
function useApp() {
|
|
4258
|
+
const context = useContext(AppContext);
|
|
4259
|
+
if (!context) {
|
|
4260
|
+
throw new Error("useApp must be used within AppContextProvider");
|
|
4183
4261
|
}
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4262
|
+
return context;
|
|
4263
|
+
}
|
|
4264
|
+
function useAppName() {
|
|
4265
|
+
return useApp().appName;
|
|
4266
|
+
}
|
|
4267
|
+
function useBasename() {
|
|
4268
|
+
return useApp().basename;
|
|
4269
|
+
}
|
|
4270
|
+
function useEnv() {
|
|
4271
|
+
return useApp().env;
|
|
4272
|
+
}
|
|
4273
|
+
function useIsDev() {
|
|
4274
|
+
return useApp().isDev;
|
|
4187
4275
|
}
|
|
4188
4276
|
|
|
4189
|
-
// src/
|
|
4190
|
-
import
|
|
4191
|
-
import
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
var __dirname2 = dirname2(__filename);
|
|
4197
|
-
var require4 = createRequire3(import.meta.url);
|
|
4198
|
-
var _version = null;
|
|
4199
|
-
function getFrameworkVersion() {
|
|
4200
|
-
if (_version) return _version;
|
|
4201
|
-
try {
|
|
4202
|
-
const pkgPath = join12(__dirname2, "../../package.json");
|
|
4203
|
-
const pkg = require4(pkgPath);
|
|
4204
|
-
_version = pkg.version || "0.0.0";
|
|
4205
|
-
} catch {
|
|
4206
|
-
_version = "0.0.0";
|
|
4277
|
+
// src/runtime/error-boundary.tsx
|
|
4278
|
+
import { Component } from "react";
|
|
4279
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
4280
|
+
var ErrorBoundary = class extends Component {
|
|
4281
|
+
constructor(props) {
|
|
4282
|
+
super(props);
|
|
4283
|
+
this.state = { hasError: false, error: null };
|
|
4207
4284
|
}
|
|
4208
|
-
|
|
4209
|
-
}
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4285
|
+
static getDerivedStateFromError(error) {
|
|
4286
|
+
return { hasError: true, error };
|
|
4287
|
+
}
|
|
4288
|
+
componentDidCatch(error, errorInfo) {
|
|
4289
|
+
console.error("[ErrorBoundary] Caught error:", error, errorInfo);
|
|
4290
|
+
this.props.onError?.(error, errorInfo);
|
|
4291
|
+
}
|
|
4292
|
+
reset = () => {
|
|
4293
|
+
this.setState({ hasError: false, error: null });
|
|
4294
|
+
};
|
|
4295
|
+
render() {
|
|
4296
|
+
const { hasError, error } = this.state;
|
|
4297
|
+
const { children, fallback } = this.props;
|
|
4298
|
+
if (hasError && error) {
|
|
4299
|
+
if (typeof fallback === "function") {
|
|
4300
|
+
return fallback(error, this.reset);
|
|
4301
|
+
}
|
|
4302
|
+
if (fallback) {
|
|
4303
|
+
return fallback;
|
|
4217
4304
|
}
|
|
4305
|
+
return /* @__PURE__ */ jsx2(DefaultErrorFallback, { error, onReset: this.reset });
|
|
4218
4306
|
}
|
|
4219
|
-
|
|
4220
|
-
return null;
|
|
4221
|
-
}
|
|
4222
|
-
var BAR_WIDTH = 30;
|
|
4223
|
-
function renderBar(percent) {
|
|
4224
|
-
const filled = Math.round(BAR_WIDTH * percent);
|
|
4225
|
-
const empty = BAR_WIDTH - filled;
|
|
4226
|
-
const bar = chalk.green("\u2501".repeat(filled)) + chalk.gray("\u2501".repeat(empty));
|
|
4227
|
-
return bar;
|
|
4228
|
-
}
|
|
4229
|
-
var DevPrinter = class {
|
|
4230
|
-
constructor(host, port, pluginNames, isBuild = false) {
|
|
4231
|
-
this.host = host;
|
|
4232
|
-
this.port = port;
|
|
4233
|
-
this.pluginNames = pluginNames;
|
|
4234
|
-
this.isBuild = isBuild;
|
|
4235
|
-
}
|
|
4236
|
-
startTime = 0;
|
|
4237
|
-
lastProgressLine = "";
|
|
4238
|
-
firstCompileDone = false;
|
|
4239
|
-
/**
|
|
4240
|
-
* 打印框架 banner
|
|
4241
|
-
*/
|
|
4242
|
-
printBanner() {
|
|
4243
|
-
const version = getFrameworkVersion();
|
|
4244
|
-
console.log();
|
|
4245
|
-
console.log(
|
|
4246
|
-
` ${chalk.bold.cyan("@4399ywkf/core")} ${chalk.green(`Framework v${version}`)}`
|
|
4247
|
-
);
|
|
4248
|
-
console.log();
|
|
4249
|
-
}
|
|
4250
|
-
/**
|
|
4251
|
-
* 打印 "start build started..."
|
|
4252
|
-
*/
|
|
4253
|
-
printBuildStart() {
|
|
4254
|
-
this.startTime = Date.now();
|
|
4255
|
-
this.compileDone = false;
|
|
4256
|
-
const label = chalk.gray("start");
|
|
4257
|
-
console.log(` ${label} build started...`);
|
|
4258
|
-
}
|
|
4259
|
-
/**
|
|
4260
|
-
* 更新编译进度条(原地覆写同一行)
|
|
4261
|
-
*/
|
|
4262
|
-
updateProgress(percent, message) {
|
|
4263
|
-
const pct = Math.min(Math.round(percent * 100), 100);
|
|
4264
|
-
const bar = renderBar(percent);
|
|
4265
|
-
const status = message || "compiling";
|
|
4266
|
-
const line = ` ${chalk.yellow("\u25CF")} client ${bar} ${chalk.bold(`(${pct}%)`)} ${chalk.gray(status)}`;
|
|
4267
|
-
if (process.stdout.isTTY) {
|
|
4268
|
-
if (this.lastProgressLine) {
|
|
4269
|
-
process.stdout.write("\x1B[1A\x1B[2K");
|
|
4270
|
-
}
|
|
4271
|
-
process.stdout.write(line + "\n");
|
|
4272
|
-
} else if (!this.firstCompileDone && pct === 100) {
|
|
4273
|
-
console.log(line);
|
|
4274
|
-
}
|
|
4275
|
-
this.lastProgressLine = line;
|
|
4276
|
-
}
|
|
4277
|
-
/**
|
|
4278
|
-
* 编译完成
|
|
4279
|
-
*/
|
|
4280
|
-
printBuildDone(hasErrors = false) {
|
|
4281
|
-
if (this.firstCompileDone) {
|
|
4282
|
-
if (!hasErrors) {
|
|
4283
|
-
const elapsed2 = ((Date.now() - this.startTime) / 1e3).toFixed(2);
|
|
4284
|
-
console.log(
|
|
4285
|
-
` ${chalk.green("hmr")} update in ${chalk.bold(`${elapsed2} s`)}`
|
|
4286
|
-
);
|
|
4287
|
-
}
|
|
4288
|
-
return;
|
|
4289
|
-
}
|
|
4290
|
-
this.firstCompileDone = true;
|
|
4291
|
-
this.lastProgressLine = "";
|
|
4292
|
-
if (hasErrors) return;
|
|
4293
|
-
const elapsed = ((Date.now() - this.startTime) / 1e3).toFixed(2);
|
|
4294
|
-
const label = chalk.green("ready");
|
|
4295
|
-
console.log(` ${label} built in ${chalk.bold(`${elapsed} s`)}`);
|
|
4296
|
-
console.log();
|
|
4297
|
-
if (this.isBuild) {
|
|
4298
|
-
this.printPluginList();
|
|
4299
|
-
} else {
|
|
4300
|
-
this.printServerInfo();
|
|
4301
|
-
}
|
|
4302
|
-
}
|
|
4303
|
-
/**
|
|
4304
|
-
* 标记新一轮编译开始(HMR)
|
|
4305
|
-
*/
|
|
4306
|
-
markRebuildStart() {
|
|
4307
|
-
this.startTime = Date.now();
|
|
4308
|
-
this.lastProgressLine = "";
|
|
4309
|
-
}
|
|
4310
|
-
/**
|
|
4311
|
-
* 仅打印插件列表(build 模式使用)
|
|
4312
|
-
*/
|
|
4313
|
-
printPluginList() {
|
|
4314
|
-
if (this.pluginNames.length > 0) {
|
|
4315
|
-
console.log(` ${chalk.bold(">")} Plugins:`);
|
|
4316
|
-
for (const name of this.pluginNames) {
|
|
4317
|
-
const shortName = name.replace("@4399ywkf/plugin-", "").replace("@4399ywkf/", "");
|
|
4318
|
-
console.log(` ${chalk.green("\u2713")} ${shortName}`);
|
|
4319
|
-
}
|
|
4320
|
-
console.log();
|
|
4321
|
-
}
|
|
4322
|
-
}
|
|
4323
|
-
/**
|
|
4324
|
-
* 打印服务器信息面板(dev 模式使用)
|
|
4325
|
-
*/
|
|
4326
|
-
printServerInfo() {
|
|
4327
|
-
const localUrl = `http://localhost:${this.port}/`;
|
|
4328
|
-
const networkUrl = getNetworkAddress(this.port);
|
|
4329
|
-
console.log(` ${chalk.bold(">")} Local: ${chalk.cyan(localUrl)}`);
|
|
4330
|
-
if (networkUrl) {
|
|
4331
|
-
console.log(` ${chalk.bold(">")} Network: ${chalk.cyan(networkUrl)}`);
|
|
4332
|
-
}
|
|
4333
|
-
console.log();
|
|
4334
|
-
this.printPluginList();
|
|
4335
|
-
console.log(
|
|
4336
|
-
` ${chalk.bold(">")} press ${chalk.bold("h + enter")} to show shortcuts`
|
|
4337
|
-
);
|
|
4338
|
-
console.log();
|
|
4339
|
-
}
|
|
4340
|
-
/**
|
|
4341
|
-
* 打印快捷键帮助
|
|
4342
|
-
*/
|
|
4343
|
-
printShortcuts() {
|
|
4344
|
-
console.log();
|
|
4345
|
-
console.log(` ${chalk.bold("Shortcuts:")}`);
|
|
4346
|
-
console.log(` ${chalk.bold("o + enter")} open in browser`);
|
|
4347
|
-
console.log(` ${chalk.bold("c + enter")} clear console`);
|
|
4348
|
-
console.log(` ${chalk.bold("q + enter")} quit`);
|
|
4349
|
-
console.log();
|
|
4307
|
+
return children;
|
|
4350
4308
|
}
|
|
4351
4309
|
};
|
|
4352
|
-
function
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4310
|
+
function DefaultErrorFallback({ error, onReset }) {
|
|
4311
|
+
const isDev = process.env.NODE_ENV === "development";
|
|
4312
|
+
return /* @__PURE__ */ jsx2(
|
|
4313
|
+
"div",
|
|
4314
|
+
{
|
|
4315
|
+
style: {
|
|
4316
|
+
padding: 24,
|
|
4317
|
+
display: "flex",
|
|
4318
|
+
flexDirection: "column",
|
|
4319
|
+
alignItems: "center",
|
|
4320
|
+
justifyContent: "center",
|
|
4321
|
+
minHeight: "100vh",
|
|
4322
|
+
backgroundColor: "#f5f5f5"
|
|
4323
|
+
},
|
|
4324
|
+
children: /* @__PURE__ */ jsxs(
|
|
4325
|
+
"div",
|
|
4326
|
+
{
|
|
4327
|
+
style: {
|
|
4328
|
+
maxWidth: 600,
|
|
4329
|
+
padding: 32,
|
|
4330
|
+
backgroundColor: "#fff",
|
|
4331
|
+
borderRadius: 8,
|
|
4332
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.1)"
|
|
4333
|
+
},
|
|
4334
|
+
children: [
|
|
4335
|
+
/* @__PURE__ */ jsx2("h1", { style: { color: "#ff4d4f", marginBottom: 16 }, children: "\u9875\u9762\u51FA\u9519\u4E86" }),
|
|
4336
|
+
/* @__PURE__ */ jsx2("p", { style: { color: "#666", marginBottom: 16 }, children: "\u62B1\u6B49\uFF0C\u9875\u9762\u9047\u5230\u4E86\u4E00\u4E9B\u95EE\u9898\u3002\u8BF7\u5C1D\u8BD5\u5237\u65B0\u9875\u9762\u6216\u8054\u7CFB\u7BA1\u7406\u5458\u3002" }),
|
|
4337
|
+
isDev && /* @__PURE__ */ jsxs(
|
|
4338
|
+
"details",
|
|
4339
|
+
{
|
|
4340
|
+
style: {
|
|
4341
|
+
marginBottom: 16,
|
|
4342
|
+
padding: 12,
|
|
4343
|
+
backgroundColor: "#fff2f0",
|
|
4344
|
+
borderRadius: 4,
|
|
4345
|
+
border: "1px solid #ffccc7"
|
|
4346
|
+
},
|
|
4347
|
+
children: [
|
|
4348
|
+
/* @__PURE__ */ jsx2("summary", { style: { cursor: "pointer", fontWeight: "bold" }, children: "\u9519\u8BEF\u8BE6\u60C5\uFF08\u4EC5\u5F00\u53D1\u73AF\u5883\u53EF\u89C1\uFF09" }),
|
|
4349
|
+
/* @__PURE__ */ jsxs(
|
|
4350
|
+
"pre",
|
|
4351
|
+
{
|
|
4352
|
+
style: {
|
|
4353
|
+
marginTop: 8,
|
|
4354
|
+
padding: 8,
|
|
4355
|
+
backgroundColor: "#fff",
|
|
4356
|
+
borderRadius: 4,
|
|
4357
|
+
overflow: "auto",
|
|
4358
|
+
fontSize: 12
|
|
4359
|
+
},
|
|
4360
|
+
children: [
|
|
4361
|
+
error.message,
|
|
4362
|
+
"\n\n",
|
|
4363
|
+
error.stack
|
|
4364
|
+
]
|
|
4365
|
+
}
|
|
4366
|
+
)
|
|
4367
|
+
]
|
|
4368
|
+
}
|
|
4369
|
+
),
|
|
4370
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8 }, children: [
|
|
4371
|
+
/* @__PURE__ */ jsx2(
|
|
4372
|
+
"button",
|
|
4373
|
+
{
|
|
4374
|
+
onClick: onReset,
|
|
4375
|
+
style: {
|
|
4376
|
+
padding: "8px 16px",
|
|
4377
|
+
backgroundColor: "#1890ff",
|
|
4378
|
+
color: "#fff",
|
|
4379
|
+
border: "none",
|
|
4380
|
+
borderRadius: 4,
|
|
4381
|
+
cursor: "pointer"
|
|
4382
|
+
},
|
|
4383
|
+
children: "\u91CD\u8BD5"
|
|
4384
|
+
}
|
|
4385
|
+
),
|
|
4386
|
+
/* @__PURE__ */ jsx2(
|
|
4387
|
+
"button",
|
|
4388
|
+
{
|
|
4389
|
+
onClick: () => window.location.reload(),
|
|
4390
|
+
style: {
|
|
4391
|
+
padding: "8px 16px",
|
|
4392
|
+
backgroundColor: "#fff",
|
|
4393
|
+
color: "#666",
|
|
4394
|
+
border: "1px solid #d9d9d9",
|
|
4395
|
+
borderRadius: 4,
|
|
4396
|
+
cursor: "pointer"
|
|
4397
|
+
},
|
|
4398
|
+
children: "\u5237\u65B0\u9875\u9762"
|
|
4399
|
+
}
|
|
4400
|
+
)
|
|
4401
|
+
] })
|
|
4402
|
+
]
|
|
4403
|
+
}
|
|
4404
|
+
)
|
|
4386
4405
|
}
|
|
4387
|
-
|
|
4388
|
-
process.stdin.on("data", handler);
|
|
4389
|
-
process.stdin.resume();
|
|
4406
|
+
);
|
|
4390
4407
|
}
|
|
4391
4408
|
|
|
4392
|
-
// src/
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
const host = config.dev.host || "localhost";
|
|
4408
|
-
const preferredPort = config.dev.port || 3e3;
|
|
4409
|
-
const port = await getAvailablePort(preferredPort, host);
|
|
4410
|
-
const pluginNames = pluginManager.getPluginNames();
|
|
4411
|
-
if (port !== preferredPort) {
|
|
4412
|
-
console.log(
|
|
4413
|
-
chalk2.yellow(` Port ${preferredPort} is in use, using ${port} instead.
|
|
4414
|
-
`)
|
|
4415
|
-
);
|
|
4416
|
-
}
|
|
4417
|
-
const printer = new DevPrinter(host, port, pluginNames);
|
|
4418
|
-
printer.printBanner();
|
|
4419
|
-
printer.printBuildStart();
|
|
4420
|
-
printer.updateProgress(0, "preparing");
|
|
4421
|
-
rspackConfig.plugins = rspackConfig.plugins || [];
|
|
4422
|
-
rspackConfig.plugins.push(
|
|
4423
|
-
new rspack4.ProgressPlugin(createProgressHandler(printer))
|
|
4424
|
-
);
|
|
4425
|
-
rspackConfig.stats = "none";
|
|
4426
|
-
rspackConfig.infrastructureLogging = { level: "none" };
|
|
4427
|
-
if (rspackConfig.devServer) {
|
|
4428
|
-
const ds = rspackConfig.devServer;
|
|
4429
|
-
const existingClient = ds.client ?? {};
|
|
4430
|
-
ds.client = {
|
|
4431
|
-
...existingClient,
|
|
4432
|
-
logging: "warn",
|
|
4433
|
-
overlay: false,
|
|
4434
|
-
progress: false
|
|
4435
|
-
};
|
|
4409
|
+
// src/runtime/providers.tsx
|
|
4410
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
4411
|
+
function DefaultLoading() {
|
|
4412
|
+
return /* @__PURE__ */ jsx3(
|
|
4413
|
+
"div",
|
|
4414
|
+
{
|
|
4415
|
+
style: {
|
|
4416
|
+
display: "flex",
|
|
4417
|
+
alignItems: "center",
|
|
4418
|
+
justifyContent: "center",
|
|
4419
|
+
height: "100vh",
|
|
4420
|
+
fontSize: 16,
|
|
4421
|
+
color: "#999"
|
|
4422
|
+
},
|
|
4423
|
+
children: "\u52A0\u8F7D\u4E2D..."
|
|
4436
4424
|
}
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4425
|
+
);
|
|
4426
|
+
}
|
|
4427
|
+
function composeProviders(providers) {
|
|
4428
|
+
const sortedProviders = [...providers].sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
|
|
4429
|
+
return function ComposedProviders({ children }) {
|
|
4430
|
+
return sortedProviders.reduceRight((acc, { component: Provider, props }) => {
|
|
4431
|
+
return /* @__PURE__ */ jsx3(Provider, { ...props, children: acc });
|
|
4432
|
+
}, children);
|
|
4433
|
+
};
|
|
4434
|
+
}
|
|
4435
|
+
function RootProvider({ config, children }) {
|
|
4436
|
+
const {
|
|
4437
|
+
appName = "app",
|
|
4438
|
+
router,
|
|
4439
|
+
basename = "/",
|
|
4440
|
+
strictMode = true,
|
|
4441
|
+
antd = { enabled: true },
|
|
4442
|
+
providers = [],
|
|
4443
|
+
lifecycle
|
|
4444
|
+
} = config;
|
|
4445
|
+
const appContextValue = {
|
|
4446
|
+
appName,
|
|
4447
|
+
basename,
|
|
4448
|
+
isDev: process.env.NODE_ENV === "development",
|
|
4449
|
+
env: typeof process !== "undefined" ? process.env : {}
|
|
4450
|
+
};
|
|
4451
|
+
const allProviders = [
|
|
4452
|
+
// 应用上下文 Provider(最外层)
|
|
4453
|
+
{
|
|
4454
|
+
component: AppContextProvider,
|
|
4455
|
+
props: { value: appContextValue },
|
|
4456
|
+
order: 0
|
|
4457
|
+
},
|
|
4458
|
+
// Ant Design ConfigProvider
|
|
4459
|
+
...antd.enabled !== false ? [
|
|
4460
|
+
{
|
|
4461
|
+
component: ConfigProvider,
|
|
4462
|
+
props: {
|
|
4463
|
+
locale: antd.locale || zhCN,
|
|
4464
|
+
theme: antd.theme,
|
|
4465
|
+
...antd.configProvider
|
|
4466
|
+
},
|
|
4467
|
+
order: 10
|
|
4469
4468
|
}
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
console.error();
|
|
4480
|
-
console.error(chalk2.red(" \u2716 Dev server failed to start"));
|
|
4481
|
-
console.error(error);
|
|
4482
|
-
process.exit(1);
|
|
4469
|
+
] : [],
|
|
4470
|
+
// 用户自定义 Providers
|
|
4471
|
+
...providers.map((p) => ({ ...p, order: p.order ?? 50 }))
|
|
4472
|
+
];
|
|
4473
|
+
const ComposedProviders = composeProviders(allProviders);
|
|
4474
|
+
const content = router ? /* @__PURE__ */ jsx3(Suspense, { fallback: /* @__PURE__ */ jsx3(DefaultLoading, {}), children: /* @__PURE__ */ jsx3(RouterProvider, { router }) }) : children;
|
|
4475
|
+
const app = /* @__PURE__ */ jsx3(ErrorBoundary, { onError: lifecycle?.onError, children: /* @__PURE__ */ jsx3(ComposedProviders, { children: content }) });
|
|
4476
|
+
if (strictMode) {
|
|
4477
|
+
return /* @__PURE__ */ jsx3(StrictMode, { children: app });
|
|
4483
4478
|
}
|
|
4479
|
+
return app;
|
|
4484
4480
|
}
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
|
|
4492
|
-
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
4481
|
+
function createProvider(component, props, order) {
|
|
4482
|
+
return {
|
|
4483
|
+
component,
|
|
4484
|
+
props,
|
|
4485
|
+
order
|
|
4486
|
+
};
|
|
4493
4487
|
}
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
console.log(chalk3.red("\n Compile errors:"));
|
|
4502
|
-
for (const error of info.errors) {
|
|
4503
|
-
console.log(chalk3.red(` ${error.message}`));
|
|
4504
|
-
}
|
|
4505
|
-
return;
|
|
4488
|
+
|
|
4489
|
+
// src/runtime/bootstrap.tsx
|
|
4490
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
4491
|
+
var root = null;
|
|
4492
|
+
async function resolveAppConfig(config) {
|
|
4493
|
+
if (config.router || !config.conventionalRoutes) {
|
|
4494
|
+
return config;
|
|
4506
4495
|
}
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4496
|
+
try {
|
|
4497
|
+
const routesModule = await import("@ywkf/routes");
|
|
4498
|
+
const createRouter = routesModule.createRouter || routesModule.default?.createRouter;
|
|
4499
|
+
if (typeof createRouter === "function") {
|
|
4500
|
+
const router = createRouter(config.basename);
|
|
4501
|
+
console.log("[ywkf] \u5DF2\u81EA\u52A8\u6CE8\u5165\u7EA6\u5B9A\u5F0F\u8DEF\u7531");
|
|
4502
|
+
return { ...config, router };
|
|
4503
|
+
} else {
|
|
4504
|
+
console.warn("[ywkf] @ywkf/routes \u672A\u5BFC\u51FA createRouter \u51FD\u6570");
|
|
4511
4505
|
}
|
|
4506
|
+
} catch (error) {
|
|
4507
|
+
console.error("[ywkf] \u52A0\u8F7D\u7EA6\u5B9A\u5F0F\u8DEF\u7531\u5931\u8D25:", error);
|
|
4508
|
+
console.warn("[ywkf] \u8BF7\u786E\u4FDD\u5DF2\u542F\u7528\u7EA6\u5B9A\u5F0F\u8DEF\u7531\u4E14 src/pages \u76EE\u5F55\u5B58\u5728");
|
|
4512
4509
|
}
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
const
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
` ${chalk3.dim(asset.name.padEnd(50))} ${sizeColor(formatSize(asset.size))}`
|
|
4521
|
-
);
|
|
4510
|
+
return config;
|
|
4511
|
+
}
|
|
4512
|
+
async function bootstrap(config) {
|
|
4513
|
+
const { rootId = "root", lifecycle } = config;
|
|
4514
|
+
const resolvedConfig = await resolveAppConfig(config);
|
|
4515
|
+
if (lifecycle?.onBeforeMount) {
|
|
4516
|
+
await lifecycle.onBeforeMount();
|
|
4522
4517
|
}
|
|
4523
|
-
|
|
4524
|
-
|
|
4518
|
+
const rootElement = document.getElementById(rootId);
|
|
4519
|
+
if (!rootElement) {
|
|
4520
|
+
throw new Error(`\u627E\u4E0D\u5230\u6839\u5143\u7D20 #${rootId}`);
|
|
4525
4521
|
}
|
|
4526
|
-
|
|
4527
|
-
}
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
if (config.plugins && config.plugins.length > 0) {
|
|
4537
|
-
await pluginManager.loadPlugins(config.plugins);
|
|
4538
|
-
}
|
|
4539
|
-
await pluginManager.runBeforeBuild();
|
|
4540
|
-
let rspackConfig = createRspackConfig(config, cwd, { isDev: false });
|
|
4541
|
-
rspackConfig = await pluginManager.applyRspackConfigHooks(rspackConfig);
|
|
4542
|
-
const pluginNames = pluginManager.getPluginNames();
|
|
4543
|
-
const printer = new DevPrinter("localhost", 0, pluginNames, true);
|
|
4544
|
-
printer.printBanner();
|
|
4545
|
-
printer.printBuildStart();
|
|
4546
|
-
printer.updateProgress(0, "preparing");
|
|
4547
|
-
rspackConfig.plugins = rspackConfig.plugins || [];
|
|
4548
|
-
rspackConfig.plugins.push(
|
|
4549
|
-
new rspack5.ProgressPlugin(createProgressHandler(printer))
|
|
4550
|
-
);
|
|
4551
|
-
rspackConfig.stats = "none";
|
|
4552
|
-
rspackConfig.infrastructureLogging = { level: "none" };
|
|
4553
|
-
const compiler = rspack5(rspackConfig);
|
|
4554
|
-
const stats = await new Promise((resolve4, reject) => {
|
|
4555
|
-
compiler.run((err, stats2) => {
|
|
4556
|
-
if (err) {
|
|
4557
|
-
reject(err);
|
|
4558
|
-
return;
|
|
4559
|
-
}
|
|
4560
|
-
if (!stats2) {
|
|
4561
|
-
reject(new Error("Build failed: no stats available"));
|
|
4562
|
-
return;
|
|
4563
|
-
}
|
|
4564
|
-
resolve4(stats2);
|
|
4565
|
-
});
|
|
4566
|
-
});
|
|
4567
|
-
await new Promise((resolve4, reject) => {
|
|
4568
|
-
compiler.close((err) => {
|
|
4569
|
-
if (err) reject(err);
|
|
4570
|
-
else resolve4();
|
|
4571
|
-
});
|
|
4572
|
-
});
|
|
4573
|
-
const hasErrors = stats.hasErrors();
|
|
4574
|
-
const statsInfo = stats.toJson({ errors: true });
|
|
4575
|
-
await pluginManager.runAfterBuild({
|
|
4576
|
-
success: !hasErrors,
|
|
4577
|
-
errors: statsInfo.errors?.map((e) => e.message)
|
|
4522
|
+
root = createRoot(rootElement);
|
|
4523
|
+
root.render(/* @__PURE__ */ jsx4(RootProvider, { config: resolvedConfig }));
|
|
4524
|
+
if (lifecycle?.onMounted) {
|
|
4525
|
+
setTimeout(() => {
|
|
4526
|
+
lifecycle.onMounted?.();
|
|
4527
|
+
}, 0);
|
|
4528
|
+
}
|
|
4529
|
+
if (lifecycle?.onUnmount) {
|
|
4530
|
+
window.addEventListener("beforeunload", () => {
|
|
4531
|
+
lifecycle.onUnmount?.();
|
|
4578
4532
|
});
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4533
|
+
}
|
|
4534
|
+
}
|
|
4535
|
+
function unmount() {
|
|
4536
|
+
if (root) {
|
|
4537
|
+
root.unmount();
|
|
4538
|
+
root = null;
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4541
|
+
function createMicroApp(getConfig) {
|
|
4542
|
+
let microRoot = null;
|
|
4543
|
+
return {
|
|
4544
|
+
/**
|
|
4545
|
+
* 微前端 bootstrap 生命周期
|
|
4546
|
+
*/
|
|
4547
|
+
async bootstrap() {
|
|
4548
|
+
console.log("[MicroApp] bootstrap");
|
|
4549
|
+
},
|
|
4550
|
+
/**
|
|
4551
|
+
* 微前端 mount 生命周期
|
|
4552
|
+
*/
|
|
4553
|
+
async mount(props) {
|
|
4554
|
+
console.log("[MicroApp] mount", props);
|
|
4555
|
+
const config = getConfig(props);
|
|
4556
|
+
const resolvedConfig = await resolveAppConfig(config);
|
|
4557
|
+
const container = props?.masterProps?.container;
|
|
4558
|
+
const rootId = resolvedConfig.rootId || "root";
|
|
4559
|
+
const rootElement = container ? container.querySelector(`#${rootId}`) : document.getElementById(rootId);
|
|
4560
|
+
if (!rootElement) {
|
|
4561
|
+
throw new Error(`[MicroApp] \u627E\u4E0D\u5230\u6839\u5143\u7D20 #${rootId}`);
|
|
4562
|
+
}
|
|
4563
|
+
if (resolvedConfig.lifecycle?.onBeforeMount) {
|
|
4564
|
+
await resolvedConfig.lifecycle.onBeforeMount();
|
|
4565
|
+
}
|
|
4566
|
+
microRoot = createRoot(rootElement);
|
|
4567
|
+
microRoot.render(/* @__PURE__ */ jsx4(RootProvider, { config: resolvedConfig }));
|
|
4568
|
+
if (resolvedConfig.lifecycle?.onMounted) {
|
|
4569
|
+
setTimeout(() => {
|
|
4570
|
+
resolvedConfig.lifecycle?.onMounted?.();
|
|
4571
|
+
}, 0);
|
|
4572
|
+
}
|
|
4573
|
+
},
|
|
4574
|
+
/**
|
|
4575
|
+
* 微前端 unmount 生命周期
|
|
4576
|
+
*/
|
|
4577
|
+
async unmount(props) {
|
|
4578
|
+
console.log("[MicroApp] unmount", props);
|
|
4579
|
+
const config = getConfig(props);
|
|
4580
|
+
if (config.lifecycle?.onUnmount) {
|
|
4581
|
+
config.lifecycle.onUnmount();
|
|
4582
|
+
}
|
|
4583
|
+
if (microRoot) {
|
|
4584
|
+
microRoot.unmount();
|
|
4585
|
+
microRoot = null;
|
|
4586
|
+
}
|
|
4587
|
+
},
|
|
4588
|
+
/**
|
|
4589
|
+
* 微前端 update 生命周期(可选)
|
|
4590
|
+
*/
|
|
4591
|
+
async update(props) {
|
|
4592
|
+
console.log("[MicroApp] update", props);
|
|
4583
4593
|
}
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4594
|
+
};
|
|
4595
|
+
}
|
|
4596
|
+
function isMicroAppEnv() {
|
|
4597
|
+
if (window.__POWERED_BY_QIANKUN__) {
|
|
4598
|
+
return true;
|
|
4599
|
+
}
|
|
4600
|
+
if (window.__GARFISH__) {
|
|
4601
|
+
return true;
|
|
4602
|
+
}
|
|
4603
|
+
return false;
|
|
4604
|
+
}
|
|
4605
|
+
function getMicroAppPublicPath() {
|
|
4606
|
+
if (window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__) {
|
|
4607
|
+
return window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
|
|
4590
4608
|
}
|
|
4609
|
+
return "/";
|
|
4591
4610
|
}
|
|
4592
4611
|
export {
|
|
4593
4612
|
AppContext,
|
|
@@ -4600,6 +4619,7 @@ export {
|
|
|
4600
4619
|
YwkfGenerator,
|
|
4601
4620
|
YwkfGeneratorPlugin,
|
|
4602
4621
|
analyticsPlugin,
|
|
4622
|
+
biomePlugin,
|
|
4603
4623
|
bootstrap,
|
|
4604
4624
|
build,
|
|
4605
4625
|
createBaseConfig,
|
|
@@ -4615,6 +4635,7 @@ export {
|
|
|
4615
4635
|
dev,
|
|
4616
4636
|
garfishPlugin,
|
|
4617
4637
|
generateConventionalRoutes,
|
|
4638
|
+
getDefaultBiomeConfig,
|
|
4618
4639
|
getMicroAppPublicPath,
|
|
4619
4640
|
i18nPlugin,
|
|
4620
4641
|
isMicroAppEnv,
|