@4399ywkf/cli 2.0.20 → 2.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +166 -63
- package/dist/templates/app/package.json.tpl +6 -3
- package/dist/templates/app/postcss.config.js +1 -1
- package/dist/templates/app/src/index.css +4 -3
- package/dist/templates/app/src/pages/dashboard/layout.tsx +1 -1
- package/dist/templates/app/src/pages/dashboard/page.tsx +3 -3
- package/dist/templates/app/src/pages/error.tsx +1 -1
- package/dist/templates/app/src/pages/layout.tsx +3 -8
- package/dist/templates/app/src/pages/loading.tsx +3 -1
- package/dist/templates/app/src/pages/page.tsx +1 -2
- package/dist/templates/app/src/pages/user/[id]/page.tsx +3 -4
- package/dist/templates/app/src/pages/user/page.tsx +2 -7
- package/dist/templates/app/store/app/index.tsx +3 -3
- package/dist/templates/app/store/app/initialState.ts +1 -4
- package/dist/templates/app/store/app/slices/counter/actions.ts +1 -1
- package/dist/templates/app/store/app/store.ts +2 -7
- package/dist/templates/app/store/index.ts +1 -1
- package/dist/templates/app/tsconfig.json +2 -10
- package/dist/templates/app/ywkf.config.ts.tpl +4 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var utils = require('@umijs/utils');
|
|
4
|
+
var boxen = require('boxen');
|
|
5
|
+
var figlet = require('figlet');
|
|
4
6
|
var fs = require('fs');
|
|
5
7
|
var path = require('path');
|
|
6
|
-
var figlet = require('figlet');
|
|
7
|
-
var boxen = require('boxen');
|
|
8
8
|
|
|
9
9
|
var ERegistry = /* @__PURE__ */ ((ERegistry2) => {
|
|
10
10
|
ERegistry2["npm"] = "https://registry.npmjs.com/";
|
|
@@ -17,9 +17,7 @@ const cloneGitTemplate = async (opts) => {
|
|
|
17
17
|
const { template, dest, gitUrl = "https://ywgit.gz4399.com/ywkf/" /* git */ } = opts;
|
|
18
18
|
const absoluteDest = path.resolve(dest);
|
|
19
19
|
const tempDir = `${absoluteDest}_temp`;
|
|
20
|
-
utils.logger.info(
|
|
21
|
-
`Init a new project with template ${utils.chalk.blue(template)} from git ...`
|
|
22
|
-
);
|
|
20
|
+
utils.logger.info(`Init a new project with template ${utils.chalk.blue(template)} from git ...`);
|
|
23
21
|
const repoUrl = `${gitUrl}${template}.git`;
|
|
24
22
|
try {
|
|
25
23
|
if (utils.fsExtra.existsSync(absoluteDest)) {
|
|
@@ -46,7 +44,7 @@ const cloneGitTemplate = async (opts) => {
|
|
|
46
44
|
if (utils.fsExtra.existsSync(tempDir)) {
|
|
47
45
|
try {
|
|
48
46
|
utils.fsExtra.removeSync(tempDir);
|
|
49
|
-
} catch (
|
|
47
|
+
} catch (_cleanupError) {
|
|
50
48
|
utils.logger.warn(`Failed to cleanup temporary directory: ${tempDir}`);
|
|
51
49
|
}
|
|
52
50
|
}
|
|
@@ -75,22 +73,20 @@ const DEFAULT_DATA = {
|
|
|
75
73
|
withHusky: false,
|
|
76
74
|
extraNpmrc: "",
|
|
77
75
|
appTemplate: "app" /* app */,
|
|
78
|
-
microRole: "none" /* none
|
|
76
|
+
microRole: "none" /* none */,
|
|
77
|
+
enableBiome: true
|
|
79
78
|
};
|
|
80
|
-
var index = async ({
|
|
81
|
-
cwd,
|
|
82
|
-
args,
|
|
83
|
-
defaultData = DEFAULT_DATA
|
|
84
|
-
}) => {
|
|
79
|
+
var index = async ({ cwd, args, defaultData = DEFAULT_DATA }) => {
|
|
85
80
|
let [name] = args._;
|
|
86
81
|
let npmClient = "pnpm" /* pnpm */;
|
|
87
82
|
let registry = ERegistry.npm;
|
|
88
83
|
let gitTemplate;
|
|
89
84
|
let appTemplate = (defaultData == null ? void 0 : defaultData.appTemplate) || "app" /* app */;
|
|
90
85
|
let microRole = (defaultData == null ? void 0 : defaultData.microRole) || "none" /* none */;
|
|
86
|
+
let enableBiome = (defaultData == null ? void 0 : defaultData.enableBiome) ?? true;
|
|
91
87
|
const { username, email } = await utils.getGitInfo();
|
|
92
88
|
const author = email && username ? `${username} <${email}>` : "";
|
|
93
|
-
|
|
89
|
+
const pluginName = `${name || "demo"}`;
|
|
94
90
|
let target = name ? path.join(cwd, name) : cwd;
|
|
95
91
|
const { isCancel, text, select, intro, outro, confirm, note } = utils.clackPrompts;
|
|
96
92
|
const exitPrompt = () => {
|
|
@@ -105,7 +101,7 @@ var index = async ({
|
|
|
105
101
|
if (!value.length) {
|
|
106
102
|
return "\u8BF7\u8F93\u5165\u9879\u76EE\u540D\u79F0";
|
|
107
103
|
}
|
|
108
|
-
if (value
|
|
104
|
+
if (value !== "." && utils.fsExtra.existsSync(path.join(cwd, value))) {
|
|
109
105
|
return `\u76EE\u5F55 ${value} \u5DF2\u5B58\u5728`;
|
|
110
106
|
}
|
|
111
107
|
}
|
|
@@ -172,6 +168,16 @@ var index = async ({
|
|
|
172
168
|
exitPrompt();
|
|
173
169
|
}
|
|
174
170
|
};
|
|
171
|
+
const selectBiome = async () => {
|
|
172
|
+
const useBiome = await confirm({
|
|
173
|
+
message: "\u662F\u5426\u542F\u7528 Biome \u4EE3\u7801\u89C4\u8303\u68C0\u67E5\uFF1F\uFF08Lint / Format / Import Sorting\uFF09",
|
|
174
|
+
initialValue: true
|
|
175
|
+
});
|
|
176
|
+
if (isCancel(useBiome)) {
|
|
177
|
+
exitPrompt();
|
|
178
|
+
}
|
|
179
|
+
enableBiome = !!useBiome;
|
|
180
|
+
};
|
|
175
181
|
const selectGitInit = async () => {
|
|
176
182
|
const initGitAnswer = await confirm({
|
|
177
183
|
message: "\u662F\u5426\u521D\u59CB\u5316 Git \u4ED3\u5E93\uFF1F",
|
|
@@ -203,9 +209,7 @@ var index = async ({
|
|
|
203
209
|
});
|
|
204
210
|
console.log(utils.chalk.hex("#19BDD2")(banner));
|
|
205
211
|
console.log("");
|
|
206
|
-
console.log(
|
|
207
|
-
utils.chalk.hex("#19BDD2")(" \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501")
|
|
208
|
-
);
|
|
212
|
+
console.log(utils.chalk.hex("#19BDD2")(" \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
209
213
|
console.log("");
|
|
210
214
|
console.log(
|
|
211
215
|
utils.chalk.bold.white(" \u{1F680} \u6B22\u8FCE\u4F7F\u7528 ") + utils.chalk.hex("#19BDD2").bold("\u8FD0\u7EF4\u6280\u672F\u4E2D\u5FC3\u5F00\u53D1\u90E8") + utils.chalk.bold.white(" \u9879\u76EE\u811A\u624B\u67B6\u5DE5\u5177")
|
|
@@ -217,9 +221,7 @@ var index = async ({
|
|
|
217
221
|
console.log("");
|
|
218
222
|
console.log(utils.chalk.yellow(" \u8BA9\u6211\u4EEC\u4E00\u8D77\u521B\u5EFA\u4E00\u4E2A\u65B0\u9879\u76EE\u5427\uFF01"));
|
|
219
223
|
console.log("");
|
|
220
|
-
console.log(
|
|
221
|
-
utils.chalk.hex("#19BDD2")(" \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501")
|
|
222
|
-
);
|
|
224
|
+
console.log(utils.chalk.hex("#19BDD2")(" \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
|
|
223
225
|
console.log("");
|
|
224
226
|
intro(utils.chalk.hex("#19BDD2").bold("\u5F00\u59CB\u521B\u5EFA"));
|
|
225
227
|
await setName();
|
|
@@ -239,6 +241,7 @@ var index = async ({
|
|
|
239
241
|
if (isCancel(registry)) {
|
|
240
242
|
exitPrompt();
|
|
241
243
|
}
|
|
244
|
+
await selectBiome();
|
|
242
245
|
await selectMicroFrontend();
|
|
243
246
|
await selectGitInit();
|
|
244
247
|
outro(utils.chalk.green(`\u2728 \u4E00\u5207\u5C31\u7EEA, \u5F00\u59CB\u521B\u5EFA\u9879\u76EE...`));
|
|
@@ -262,7 +265,7 @@ var index = async ({
|
|
|
262
265
|
});
|
|
263
266
|
break;
|
|
264
267
|
// TODO: init template from git
|
|
265
|
-
case useGitTemplate:
|
|
268
|
+
case useGitTemplate: {
|
|
266
269
|
intro(utils.chalk.bgHex("#19BDD2")(" create-ywkf "));
|
|
267
270
|
await setName();
|
|
268
271
|
if (isCancel(name)) {
|
|
@@ -298,6 +301,7 @@ Git\u6A21\u677F: ${gitTemplate}
|
|
|
298
301
|
dest: target
|
|
299
302
|
});
|
|
300
303
|
break;
|
|
304
|
+
}
|
|
301
305
|
default:
|
|
302
306
|
if (!useDefaultData) {
|
|
303
307
|
await internalTemplatePrompts();
|
|
@@ -339,7 +343,8 @@ Git\u6A21\u677F: ${gitTemplate}
|
|
|
339
343
|
microRole,
|
|
340
344
|
enableMicro: microRole !== "none" /* none */,
|
|
341
345
|
isMasterApp: microRole === "master" /* master */,
|
|
342
|
-
isSubApp: microRole === "sub" /* sub
|
|
346
|
+
isSubApp: microRole === "sub" /* sub */,
|
|
347
|
+
enableBiome
|
|
343
348
|
}
|
|
344
349
|
});
|
|
345
350
|
await generator.run();
|
|
@@ -349,6 +354,10 @@ Git\u6A21\u677F: ${gitTemplate}
|
|
|
349
354
|
if (microRole !== "none" /* none */) {
|
|
350
355
|
await injectMicroFrontendPages(target, microRole);
|
|
351
356
|
}
|
|
357
|
+
await injectVscodeConfig(target, enableBiome);
|
|
358
|
+
if (enableBiome) {
|
|
359
|
+
await injectBiomeConfig(target);
|
|
360
|
+
}
|
|
352
361
|
}
|
|
353
362
|
const context = {
|
|
354
363
|
target,
|
|
@@ -378,9 +387,7 @@ Git\u6A21\u677F: ${gitTemplate}
|
|
|
378
387
|
utils.logger.info(`Skip install deps`);
|
|
379
388
|
if (isPnpm8) {
|
|
380
389
|
utils.logger.warn(
|
|
381
|
-
utils.chalk.yellow(
|
|
382
|
-
`You current using pnpm v8, it will install minimal version of dependencies`
|
|
383
|
-
)
|
|
390
|
+
utils.chalk.yellow(`You current using pnpm v8, it will install minimal version of dependencies`)
|
|
384
391
|
);
|
|
385
392
|
utils.logger.warn(
|
|
386
393
|
utils.chalk.green(
|
|
@@ -391,20 +398,21 @@ Git\u6A21\u677F: ${gitTemplate}
|
|
|
391
398
|
);
|
|
392
399
|
}
|
|
393
400
|
}
|
|
394
|
-
printSuccess({ name, target, npmClient, microRole });
|
|
401
|
+
printSuccess({ name, target, npmClient, microRole, enableBiome });
|
|
395
402
|
};
|
|
396
403
|
function printSuccess(opts) {
|
|
397
|
-
const { name, target, npmClient, microRole } = opts;
|
|
404
|
+
const { name, target, npmClient, microRole, enableBiome } = opts;
|
|
398
405
|
const { outro } = utils.clackPrompts;
|
|
399
406
|
const microLabel = microRole === "master" ? "\u4E3B\u5E94\u7528\uFF08\u57FA\u5EA7\uFF09" : microRole === "sub" ? "\u5B50\u5E94\u7528" : "\u672A\u542F\u7528";
|
|
407
|
+
const biomeLabel = enableBiome ? "\u5DF2\u542F\u7528" : "\u672A\u542F\u7528";
|
|
400
408
|
console.log("");
|
|
401
409
|
console.log(
|
|
402
410
|
boxen(
|
|
403
|
-
utils.chalk.green.bold("\u{1F389} \u9879\u76EE\u521B\u5EFA\u6210\u529F\uFF01\n\n") + utils.chalk.white("\u{1F4E6} \u9879\u76EE\u4FE1\u606F\n") + utils.chalk.gray("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n") + utils.chalk.cyan("\u540D\u79F0: ") + utils.chalk.white(name) + "\n" + utils.chalk.cyan("\u8DEF\u5F84: ") + utils.chalk.white(target) + "\n" + utils.chalk.cyan("\u5305\u7BA1\u7406\u5668: ") + utils.chalk.white(npmClient) + "\n" + utils.chalk.cyan("\u5FAE\u524D\u7AEF: ") + utils.chalk.white(microLabel) + "\n\n" + utils.chalk.white("\u{1F680} \u5FEB\u901F\u5F00\u59CB\n") + utils.chalk.gray("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n") + utils.chalk.white("1. \u8FDB\u5165\u9879\u76EE\u76EE\u5F55\n") + utils.chalk.cyan(` cd ${name}
|
|
411
|
+
utils.chalk.green.bold("\u{1F389} \u9879\u76EE\u521B\u5EFA\u6210\u529F\uFF01\n\n") + utils.chalk.white("\u{1F4E6} \u9879\u76EE\u4FE1\u606F\n") + utils.chalk.gray("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n") + utils.chalk.cyan("\u540D\u79F0: ") + utils.chalk.white(name) + "\n" + utils.chalk.cyan("\u8DEF\u5F84: ") + utils.chalk.white(target) + "\n" + utils.chalk.cyan("\u5305\u7BA1\u7406\u5668: ") + utils.chalk.white(npmClient) + "\n" + utils.chalk.cyan("\u4EE3\u7801\u89C4\u8303: ") + utils.chalk.white(`Biome ${biomeLabel}`) + "\n" + utils.chalk.cyan("\u5FAE\u524D\u7AEF: ") + utils.chalk.white(microLabel) + "\n\n" + utils.chalk.white("\u{1F680} \u5FEB\u901F\u5F00\u59CB\n") + utils.chalk.gray("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n") + utils.chalk.white("1. \u8FDB\u5165\u9879\u76EE\u76EE\u5F55\n") + utils.chalk.cyan(` cd ${name}
|
|
404
412
|
|
|
405
413
|
`) + utils.chalk.white("2. \u542F\u52A8\u5F00\u53D1\u670D\u52A1\u5668\n") + utils.chalk.cyan(` ${npmClient} run dev
|
|
406
414
|
|
|
407
|
-
`) + utils.chalk.white("3. \u6784\u5EFA\u751F\u4EA7\u7248\u672C\n") + utils.chalk.cyan(` ${npmClient} run build`),
|
|
415
|
+
`) + utils.chalk.white("3. \u6784\u5EFA\u751F\u4EA7\u7248\u672C\n") + utils.chalk.cyan(` ${npmClient} run build`) + (enableBiome ? "\n\n" + utils.chalk.white("4. \u4EE3\u7801\u68C0\u67E5 & \u683C\u5F0F\u5316\n") + utils.chalk.cyan(` ${npmClient} run lint:fix`) : ""),
|
|
408
416
|
{
|
|
409
417
|
padding: 1,
|
|
410
418
|
margin: 1,
|
|
@@ -423,10 +431,7 @@ async function detectMonorepoRoot(opts) {
|
|
|
423
431
|
return null;
|
|
424
432
|
}
|
|
425
433
|
const rootDir = path.dirname(rootPkg);
|
|
426
|
-
if (utils.tryPaths([
|
|
427
|
-
path.join(rootDir, "lerna.json"),
|
|
428
|
-
path.join(rootDir, "pnpm-workspace.yaml")
|
|
429
|
-
])) {
|
|
434
|
+
if (utils.tryPaths([path.join(rootDir, "lerna.json"), path.join(rootDir, "pnpm-workspace.yaml")])) {
|
|
430
435
|
return rootDir;
|
|
431
436
|
}
|
|
432
437
|
return null;
|
|
@@ -456,6 +461,125 @@ async function removeHusky(opts) {
|
|
|
456
461
|
await utils.fsExtra.remove(dir);
|
|
457
462
|
}
|
|
458
463
|
}
|
|
464
|
+
async function injectBiomeConfig(target) {
|
|
465
|
+
const biomeConfig = {
|
|
466
|
+
$schema: "https://biomejs.dev/schemas/2.3.2/schema.json",
|
|
467
|
+
vcs: {
|
|
468
|
+
enabled: true,
|
|
469
|
+
defaultBranch: "main",
|
|
470
|
+
clientKind: "git",
|
|
471
|
+
useIgnoreFile: true
|
|
472
|
+
},
|
|
473
|
+
formatter: {
|
|
474
|
+
enabled: true,
|
|
475
|
+
indentStyle: "space"
|
|
476
|
+
},
|
|
477
|
+
css: {
|
|
478
|
+
formatter: {
|
|
479
|
+
quoteStyle: "single"
|
|
480
|
+
}
|
|
481
|
+
},
|
|
482
|
+
javascript: {
|
|
483
|
+
formatter: {
|
|
484
|
+
quoteStyle: "double",
|
|
485
|
+
arrowParentheses: "always",
|
|
486
|
+
jsxQuoteStyle: "double",
|
|
487
|
+
lineWidth: 100
|
|
488
|
+
}
|
|
489
|
+
},
|
|
490
|
+
linter: {
|
|
491
|
+
enabled: true,
|
|
492
|
+
rules: {
|
|
493
|
+
recommended: true,
|
|
494
|
+
style: {
|
|
495
|
+
useNodejsImportProtocol: "off",
|
|
496
|
+
noNonNullAssertion: "off",
|
|
497
|
+
noUnusedTemplateLiteral: "off",
|
|
498
|
+
noUselessElse: "off",
|
|
499
|
+
useNumberNamespace: "off"
|
|
500
|
+
},
|
|
501
|
+
suspicious: {
|
|
502
|
+
noExplicitAny: "off",
|
|
503
|
+
noConfusingVoidType: "off",
|
|
504
|
+
noImplicitAnyLet: "off",
|
|
505
|
+
noAssignInExpressions: "off",
|
|
506
|
+
noPrototypeBuiltins: "off"
|
|
507
|
+
},
|
|
508
|
+
complexity: {
|
|
509
|
+
noForEach: "off",
|
|
510
|
+
noBannedTypes: "off",
|
|
511
|
+
useArrowFunction: "off"
|
|
512
|
+
},
|
|
513
|
+
correctness: {
|
|
514
|
+
useExhaustiveDependencies: "off"
|
|
515
|
+
},
|
|
516
|
+
a11y: {
|
|
517
|
+
useAltText: "off",
|
|
518
|
+
useKeyWithClickEvents: "off",
|
|
519
|
+
useButtonType: "off",
|
|
520
|
+
noSvgWithoutTitle: "off"
|
|
521
|
+
},
|
|
522
|
+
performance: {
|
|
523
|
+
noDelete: "off"
|
|
524
|
+
},
|
|
525
|
+
security: {
|
|
526
|
+
noDangerouslySetInnerHtml: "off"
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
},
|
|
530
|
+
assist: {
|
|
531
|
+
actions: {
|
|
532
|
+
source: {
|
|
533
|
+
organizeImports: "on"
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
},
|
|
537
|
+
files: {
|
|
538
|
+
ignoreUnknown: true,
|
|
539
|
+
includes: [
|
|
540
|
+
"**",
|
|
541
|
+
"!**/.vscode/**/*",
|
|
542
|
+
"!**/node_modules/**/*",
|
|
543
|
+
"!**/dist/**/*",
|
|
544
|
+
"!**/.ywkf/**/*"
|
|
545
|
+
]
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
const filePath = path.join(target, "biome.json");
|
|
549
|
+
await writeFile(filePath, `${JSON.stringify(biomeConfig, null, 2)}
|
|
550
|
+
`);
|
|
551
|
+
}
|
|
552
|
+
async function injectVscodeConfig(target, enableBiome) {
|
|
553
|
+
const vscodeDir = path.join(target, ".vscode");
|
|
554
|
+
await utils.fsExtra.ensureDir(vscodeDir);
|
|
555
|
+
const settings = {
|
|
556
|
+
"editor.formatOnSave": true
|
|
557
|
+
};
|
|
558
|
+
const extensions = {
|
|
559
|
+
recommendations: []
|
|
560
|
+
};
|
|
561
|
+
if (enableBiome) {
|
|
562
|
+
Object.assign(settings, {
|
|
563
|
+
"editor.defaultFormatter": "biomejs.biome",
|
|
564
|
+
"editor.codeActionsOnSave": {
|
|
565
|
+
"quickfix.biome": "explicit",
|
|
566
|
+
"source.organizeImports.biome": "explicit"
|
|
567
|
+
},
|
|
568
|
+
"[javascript]": { "editor.defaultFormatter": "biomejs.biome" },
|
|
569
|
+
"[typescript]": { "editor.defaultFormatter": "biomejs.biome" },
|
|
570
|
+
"[javascriptreact]": { "editor.defaultFormatter": "biomejs.biome" },
|
|
571
|
+
"[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" },
|
|
572
|
+
"[json]": { "editor.defaultFormatter": "biomejs.biome" },
|
|
573
|
+
"[css]": { "editor.defaultFormatter": "biomejs.biome" },
|
|
574
|
+
"biome.lsp.bin": "./node_modules/@biomejs/biome/bin/biome"
|
|
575
|
+
});
|
|
576
|
+
extensions.recommendations.push("biomejs.biome");
|
|
577
|
+
}
|
|
578
|
+
await writeFile(path.join(vscodeDir, "settings.json"), `${JSON.stringify(settings, null, 2)}
|
|
579
|
+
`);
|
|
580
|
+
await writeFile(path.join(vscodeDir, "extensions.json"), `${JSON.stringify(extensions, null, 2)}
|
|
581
|
+
`);
|
|
582
|
+
}
|
|
459
583
|
async function installAndUpdateWithPnpm(cwd) {
|
|
460
584
|
await utils.execa.execa("pnpm", ["up", "-L"], { cwd, stdio: "inherit" });
|
|
461
585
|
}
|
|
@@ -479,37 +603,16 @@ async function writeFile(filePath, content) {
|
|
|
479
603
|
await utils.fsExtra.ensureDir(path.dirname(filePath));
|
|
480
604
|
await utils.fsExtra.writeFile(filePath, content, "utf-8");
|
|
481
605
|
}
|
|
482
|
-
async function injectMasterAppPages(pagesDir,
|
|
483
|
-
await writeFile(
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
);
|
|
487
|
-
await writeFile(
|
|
488
|
-
path.join(pagesDir, "micro/page.tsx"),
|
|
489
|
-
MASTER_MICRO_PAGE
|
|
490
|
-
);
|
|
491
|
-
await writeFile(
|
|
492
|
-
path.join(pagesDir, "micro/layout.tsx"),
|
|
493
|
-
MASTER_MICRO_LAYOUT
|
|
494
|
-
);
|
|
495
|
-
await writeFile(
|
|
496
|
-
path.join(pagesDir, "micro/$.tsx"),
|
|
497
|
-
MASTER_MICRO_CATCHALL
|
|
498
|
-
);
|
|
499
|
-
await writeFile(
|
|
500
|
-
path.join(pagesDir, "page.tsx"),
|
|
501
|
-
MASTER_HOME_PAGE
|
|
502
|
-
);
|
|
606
|
+
async function injectMasterAppPages(pagesDir, _appName) {
|
|
607
|
+
await writeFile(path.join(pagesDir, "layout.tsx"), MASTER_LAYOUT);
|
|
608
|
+
await writeFile(path.join(pagesDir, "micro/page.tsx"), MASTER_MICRO_PAGE);
|
|
609
|
+
await writeFile(path.join(pagesDir, "micro/layout.tsx"), MASTER_MICRO_LAYOUT);
|
|
610
|
+
await writeFile(path.join(pagesDir, "micro/$.tsx"), MASTER_MICRO_CATCHALL);
|
|
611
|
+
await writeFile(path.join(pagesDir, "page.tsx"), MASTER_HOME_PAGE);
|
|
503
612
|
}
|
|
504
|
-
async function injectSubAppPages(pagesDir,
|
|
505
|
-
await writeFile(
|
|
506
|
-
|
|
507
|
-
SUB_LAYOUT
|
|
508
|
-
);
|
|
509
|
-
await writeFile(
|
|
510
|
-
path.join(pagesDir, "page.tsx"),
|
|
511
|
-
SUB_HOME_PAGE
|
|
512
|
-
);
|
|
613
|
+
async function injectSubAppPages(pagesDir, _appName) {
|
|
614
|
+
await writeFile(path.join(pagesDir, "layout.tsx"), SUB_LAYOUT);
|
|
615
|
+
await writeFile(path.join(pagesDir, "page.tsx"), SUB_HOME_PAGE);
|
|
513
616
|
}
|
|
514
617
|
const MASTER_LAYOUT = `import { Outlet, Link, useLocation } from "react-router";
|
|
515
618
|
import { Layout, Menu } from "antd";
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "ywkf dev",
|
|
7
7
|
"build": "ywkf build",
|
|
8
|
-
"build:analyze": "ywkf build --analyze",
|
|
9
|
-
"lint": "biome check"
|
|
8
|
+
"build:analyze": "ywkf build --analyze"{{#enableBiome}},
|
|
9
|
+
"lint": "biome check",
|
|
10
|
+
"lint:fix": "biome check --write"{{/enableBiome}}
|
|
10
11
|
},
|
|
11
12
|
"engines": {
|
|
12
13
|
"node": ">=20.0.0",
|
|
@@ -29,7 +30,9 @@
|
|
|
29
30
|
"zustand": "^5.0.5"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
|
-
|
|
33
|
+
{{#enableBiome}}
|
|
34
|
+
"@biomejs/biome": "^2.3.2",
|
|
35
|
+
{{/enableBiome}}
|
|
33
36
|
"@tailwindcss/postcss": "^4.1.8",
|
|
34
37
|
"@types/node": "^22.9.0",
|
|
35
38
|
"@types/react": "^19.1.6",
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
body {
|
|
9
|
-
font-family:
|
|
10
|
-
"
|
|
9
|
+
font-family:
|
|
10
|
+
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
|
|
11
|
+
Arial, sans-serif;
|
|
11
12
|
-webkit-font-smoothing: antialiased;
|
|
12
13
|
-moz-osx-font-smoothing: grayscale;
|
|
13
14
|
background: #fafafa;
|
|
@@ -20,7 +21,7 @@ a:hover {
|
|
|
20
21
|
|
|
21
22
|
/* Card hover effect */
|
|
22
23
|
a[style*="border-radius: 12px"]:hover {
|
|
23
|
-
border-color: #3b82f6
|
|
24
|
+
border-color: #3b82f6;
|
|
24
25
|
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.1);
|
|
25
26
|
transform: translateY(-2px);
|
|
26
27
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Card, Col, Row, Statistic, Typography } from "antd";
|
|
2
2
|
|
|
3
3
|
const { Paragraph } = Typography;
|
|
4
4
|
|
|
@@ -6,8 +6,8 @@ export default function DashboardPage() {
|
|
|
6
6
|
return (
|
|
7
7
|
<div>
|
|
8
8
|
<Paragraph>
|
|
9
|
-
这是 <code>/dashboard</code> 的默认页面(<code>page.tsx</code>),
|
|
10
|
-
|
|
9
|
+
这是 <code>/dashboard</code> 的默认页面(<code>page.tsx</code>), 与{" "}
|
|
10
|
+
<code>layout.tsx</code> 配合实现嵌套布局。
|
|
11
11
|
</Paragraph>
|
|
12
12
|
<Row gutter={16}>
|
|
13
13
|
<Col span={8}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Link, Outlet, useLocation } from "react-router";
|
|
2
2
|
|
|
3
3
|
const NAV_ITEMS = [
|
|
4
4
|
{ key: "/", label: "首页" },
|
|
@@ -17,10 +17,7 @@ export default function RootLayout() {
|
|
|
17
17
|
</Link>
|
|
18
18
|
<nav style={styles.nav}>
|
|
19
19
|
{NAV_ITEMS.map((item) => {
|
|
20
|
-
const active =
|
|
21
|
-
item.key === "/"
|
|
22
|
-
? pathname === "/"
|
|
23
|
-
: pathname.startsWith(item.key);
|
|
20
|
+
const active = item.key === "/" ? pathname === "/" : pathname.startsWith(item.key);
|
|
24
21
|
return (
|
|
25
22
|
<Link
|
|
26
23
|
key={item.key}
|
|
@@ -41,9 +38,7 @@ export default function RootLayout() {
|
|
|
41
38
|
<Outlet />
|
|
42
39
|
</main>
|
|
43
40
|
|
|
44
|
-
<footer style={styles.footer}>
|
|
45
|
-
YWKF Framework ©{new Date().getFullYear()}
|
|
46
|
-
</footer>
|
|
41
|
+
<footer style={styles.footer}>YWKF Framework ©{new Date().getFullYear()}</footer>
|
|
47
42
|
</div>
|
|
48
43
|
);
|
|
49
44
|
}
|
|
@@ -2,7 +2,9 @@ import { Spin } from "antd";
|
|
|
2
2
|
|
|
3
3
|
export default function RootLoading() {
|
|
4
4
|
return (
|
|
5
|
-
<div
|
|
5
|
+
<div
|
|
6
|
+
style={{ display: "flex", justifyContent: "center", alignItems: "center", height: "60vh" }}
|
|
7
|
+
>
|
|
6
8
|
<Spin size="large" tip="加载中..." />
|
|
7
9
|
</div>
|
|
8
10
|
);
|
|
@@ -36,8 +36,7 @@ export default function WelcomePage() {
|
|
|
36
36
|
<span style={styles.brand}>YWKF Framework</span>
|
|
37
37
|
</h1>
|
|
38
38
|
<p style={styles.hint}>
|
|
39
|
-
开始编辑{
|
|
40
|
-
<code style={styles.code}>src/pages/page.tsx</code>
|
|
39
|
+
开始编辑 <code style={styles.code}>src/pages/page.tsx</code>
|
|
41
40
|
</p>
|
|
42
41
|
</div>
|
|
43
42
|
</div>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Button, Descriptions, Typography } from "antd";
|
|
2
|
+
import { useNavigate, useParams } from "react-router";
|
|
3
3
|
|
|
4
4
|
const { Title } = Typography;
|
|
5
5
|
|
|
@@ -16,8 +16,7 @@ export default function UserDetailPage() {
|
|
|
16
16
|
<code>/user/[id]/page.tsx</code> → <code>/user/:id</code>
|
|
17
17
|
</Descriptions.Item>
|
|
18
18
|
<Descriptions.Item label="说明">
|
|
19
|
-
目录名 <code>[id]</code> 会被解析为动态路由参数,
|
|
20
|
-
使用 <code>useParams()</code> 获取值。
|
|
19
|
+
目录名 <code>[id]</code> 会被解析为动态路由参数, 使用 <code>useParams()</code> 获取值。
|
|
21
20
|
</Descriptions.Item>
|
|
22
21
|
</Descriptions>
|
|
23
22
|
<div style={{ marginTop: 16 }}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Button, Table, Typography } from "antd";
|
|
2
2
|
import { Link } from "react-router";
|
|
3
3
|
|
|
4
4
|
const { Title } = Typography;
|
|
@@ -26,12 +26,7 @@ export default function UserListPage() {
|
|
|
26
26
|
return (
|
|
27
27
|
<div style={{ maxWidth: 720, margin: "0 auto" }}>
|
|
28
28
|
<Title level={2}>用户列表</Title>
|
|
29
|
-
<Table
|
|
30
|
-
dataSource={MOCK_USERS}
|
|
31
|
-
columns={columns}
|
|
32
|
-
rowKey="id"
|
|
33
|
-
pagination={false}
|
|
34
|
-
/>
|
|
29
|
+
<Table dataSource={MOCK_USERS} columns={columns} rowKey="id" pagination={false} />
|
|
35
30
|
<div style={{ marginTop: 16 }}>
|
|
36
31
|
<Button type="link">
|
|
37
32
|
<Link to="/user/42">直接访问 /user/42(动态路由)</Link>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { useAppStore, getAppStoreState } from "./store";
|
|
2
|
-
export type { AppStore } from "./store";
|
|
3
|
-
export { initialState } from "./initialState";
|
|
4
1
|
export type { AppStoreState } from "./initialState";
|
|
2
|
+
export { initialState } from "./initialState";
|
|
3
|
+
export type { AppStore } from "./store";
|
|
4
|
+
export { getAppStoreState, useAppStore } from "./store";
|
|
@@ -15,7 +15,7 @@ export const createCounterSlice: StateCreator<
|
|
|
15
15
|
[["zustand/devtools", never]],
|
|
16
16
|
[],
|
|
17
17
|
CounterAction
|
|
18
|
-
> = (set,
|
|
18
|
+
> = (set, _get) => ({
|
|
19
19
|
increment: () => set((s) => ({ count: s.count + 1 })),
|
|
20
20
|
decrement: () => set((s) => ({ count: s.count - 1 })),
|
|
21
21
|
reset: () => set({ count: 0, error: null }),
|
|
@@ -6,16 +6,11 @@ import type { StateCreator } from "zustand/vanilla";
|
|
|
6
6
|
import { createDevtools } from "../middleware/createDevtools";
|
|
7
7
|
import { type AppStoreState, initialState } from "./initialState";
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
type CounterAction,
|
|
11
|
-
createCounterSlice,
|
|
12
|
-
} from "./slices/counter/actions";
|
|
9
|
+
import { type CounterAction, createCounterSlice } from "./slices/counter/actions";
|
|
13
10
|
|
|
14
11
|
export type AppStore = AppStoreState & CounterAction;
|
|
15
12
|
|
|
16
|
-
const createStore: StateCreator<AppStore, [["zustand/devtools", never]]> = (
|
|
17
|
-
...parameters
|
|
18
|
-
) => ({
|
|
13
|
+
const createStore: StateCreator<AppStore, [["zustand/devtools", never]]> = (...parameters) => ({
|
|
19
14
|
...initialState,
|
|
20
15
|
...createCounterSlice(...parameters),
|
|
21
16
|
});
|
|
@@ -19,14 +19,6 @@
|
|
|
19
19
|
"@ywkf/store": ["./.ywkf/store.ts"]
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
|
-
"include": [
|
|
23
|
-
|
|
24
|
-
"store/**/*",
|
|
25
|
-
".ywkf/**/*",
|
|
26
|
-
"ywkf.config.ts"
|
|
27
|
-
],
|
|
28
|
-
"exclude": [
|
|
29
|
-
"node_modules",
|
|
30
|
-
"dist"
|
|
31
|
-
]
|
|
22
|
+
"include": ["src/**/*", "store/**/*", ".ywkf/**/*", "ywkf.config.ts"],
|
|
23
|
+
"exclude": ["node_modules", "dist"]
|
|
32
24
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineConfig } from "@4399ywkf/core/config";
|
|
2
|
-
import { tailwindPlugin, reactQueryPlugin, zustandPlugin, themePlugin{{#enableMicro}}, garfishPlugin{{/enableMicro}} } from "@4399ywkf/core";
|
|
2
|
+
import { tailwindPlugin, reactQueryPlugin, zustandPlugin, themePlugin{{#enableBiome}}, biomePlugin{{/enableBiome}}{{#enableMicro}}, garfishPlugin{{/enableMicro}} } from "@4399ywkf/core";
|
|
3
3
|
|
|
4
4
|
export default defineConfig({
|
|
5
5
|
appName: process.env.APP_NAME || "{{{ name }}}",
|
|
@@ -58,6 +58,9 @@ export default defineConfig({
|
|
|
58
58
|
}),
|
|
59
59
|
zustandPlugin(),
|
|
60
60
|
tailwindPlugin(),
|
|
61
|
+
{{#enableBiome}}
|
|
62
|
+
biomePlugin(),
|
|
63
|
+
{{/enableBiome}}
|
|
61
64
|
{{#isSubApp}}
|
|
62
65
|
|
|
63
66
|
// 微前端 · 子应用模式
|