@mindbase/cli 1.0.4 → 1.0.8

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.
@@ -1,936 +0,0 @@
1
- // ../../node_modules/tsup/assets/esm_shims.js
2
- import path from "path";
3
- import { fileURLToPath } from "url";
4
- var getFilename = () => fileURLToPath(import.meta.url);
5
- var getDirname = () => path.dirname(getFilename());
6
- var __dirname = /* @__PURE__ */ getDirname();
7
-
8
- // src/utils/Logger.ts
9
- var LOG_LEVELS = {
10
- debug: 0,
11
- info: 1,
12
- warn: 2,
13
- error: 3,
14
- silent: 4
15
- };
16
- var currentLogLevel = "info";
17
- var COLORS = {
18
- debug: "\x1B[36m",
19
- info: "\x1B[32m",
20
- warn: "\x1B[33m",
21
- error: "\x1B[31m",
22
- silent: "\x1B[0m",
23
- reset: "\x1B[0m"
24
- };
25
- function formatTimestamp() {
26
- const now = /* @__PURE__ */ new Date();
27
- const year = now.getFullYear();
28
- const month = String(now.getMonth() + 1).padStart(2, "0");
29
- const day = String(now.getDate()).padStart(2, "0");
30
- const hours = String(now.getHours()).padStart(2, "0");
31
- const minutes = String(now.getMinutes()).padStart(2, "0");
32
- const seconds = String(now.getSeconds()).padStart(2, "0");
33
- return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
34
- }
35
- function getVisualWidth(str) {
36
- let width = 0;
37
- const segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
38
- for (const { segment } of segmenter.segment(str)) {
39
- const charCode = segment.charCodeAt(0);
40
- if (charCode <= 255) {
41
- width += 1;
42
- continue;
43
- }
44
- const isCJK = charCode >= 19968 && charCode <= 40959 || // CJK Unified Ideographs
45
- charCode >= 12288 && charCode <= 12351 || // CJK Symbols and Punctuation
46
- charCode >= 65280 && charCode <= 65519;
47
- const isMultiByte = segment.length > 1;
48
- if (isCJK || isMultiByte) {
49
- width += 2;
50
- } else {
51
- width += 1;
52
- }
53
- }
54
- return width;
55
- }
56
- function truncateToWidth(str, maxWidth) {
57
- const segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
58
- const segments = Array.from(segmenter.segment(str)).map((s) => s.segment);
59
- if (getVisualWidth(str) <= maxWidth) return str;
60
- let currentWidth = 3;
61
- let result = "";
62
- for (let i = segments.length - 1; i >= 0; i--) {
63
- const segment = segments[i];
64
- const segmentWidth = getVisualWidth(segment);
65
- if (currentWidth + segmentWidth > maxWidth) break;
66
- result = segment + result;
67
- currentWidth += segmentWidth;
68
- }
69
- return "..." + result;
70
- }
71
- function formatMessage(level, message) {
72
- const timestamp = formatTimestamp();
73
- const terminalWidth = process.stdout.columns || 80;
74
- const timeStr = ` ${timestamp}`;
75
- const timeWidth = getVisualWidth(timeStr);
76
- const maxMessageWidth = terminalWidth - timeWidth - 2;
77
- let displayMessage = message;
78
- const messageWidth = getVisualWidth(displayMessage);
79
- if (messageWidth > maxMessageWidth) {
80
- displayMessage = truncateToWidth(displayMessage, maxMessageWidth);
81
- }
82
- const currentMsgWidth = getVisualWidth(displayMessage);
83
- const paddingCount = Math.max(0, terminalWidth - currentMsgWidth - timeWidth);
84
- const padding = " ".repeat(paddingCount);
85
- return `${COLORS[level]}${displayMessage}${padding}${timeStr}${COLORS.reset}`;
86
- }
87
- var startupTime = Date.now();
88
- function padTag(tag, targetWidth = 8) {
89
- const currentWidth = getVisualWidth(tag);
90
- const padding = Math.max(0, targetWidth - currentWidth);
91
- if (padding === 0) return tag;
92
- const chars = [...tag];
93
- const gapCount = chars.length + 1;
94
- const baseSpaces = Math.floor(padding / gapCount);
95
- const extraSpaces = padding % gapCount;
96
- let result = "";
97
- for (let i = 0; i < chars.length; i++) {
98
- const spaces = baseSpaces + (i < extraSpaces ? 1 : 0);
99
- result += " ".repeat(spaces) + chars[i];
100
- }
101
- result += " ".repeat(baseSpaces + (chars.length < extraSpaces ? 1 : 0));
102
- return result;
103
- }
104
- function startupMessage(message, tag) {
105
- const diff = Date.now() - startupTime;
106
- const timeStr = diff.toString().padStart(6, "0");
107
- const tagStr = tag ? `\u3010${padTag(tag)}\u3011` : "";
108
- return `${COLORS["warn"]}[${timeStr}] ${tagStr}${message}${COLORS["reset"]}`;
109
- }
110
- function shouldLog(level) {
111
- return LOG_LEVELS[level] >= LOG_LEVELS[currentLogLevel];
112
- }
113
- function formatArgs(args) {
114
- return args.map((arg) => {
115
- if (arg instanceof Error) {
116
- return arg.message;
117
- }
118
- if (typeof arg === "object") {
119
- return JSON.stringify(arg, null, 2);
120
- }
121
- return String(arg);
122
- }).join(" ");
123
- }
124
- var logger = {
125
- debug(...args) {
126
- if (shouldLog("debug")) {
127
- console.log(formatMessage("debug", formatArgs(args)));
128
- }
129
- },
130
- info(...args) {
131
- if (shouldLog("info")) {
132
- console.log(formatMessage("info", formatArgs(args)));
133
- }
134
- },
135
- warn(...args) {
136
- if (shouldLog("warn")) {
137
- console.warn(formatMessage("warn", formatArgs(args)));
138
- }
139
- },
140
- error(...args) {
141
- if (shouldLog("error")) {
142
- console.error(formatMessage("error", formatArgs(args)));
143
- const errorArg = args.find((arg) => arg instanceof Error);
144
- if (errorArg) {
145
- console.error(errorArg);
146
- }
147
- }
148
- },
149
- startup(tagOrMessage, ...args) {
150
- if (args.length > 0) {
151
- console.log(startupMessage(formatArgs(args), tagOrMessage));
152
- } else {
153
- console.log(startupMessage(tagOrMessage));
154
- }
155
- },
156
- setLevel(level) {
157
- currentLogLevel = level;
158
- },
159
- getLevel() {
160
- return currentLogLevel;
161
- }
162
- };
163
- var Logger_default = logger;
164
-
165
- // src/utils/prompts.ts
166
- var BACKEND_MODULES = [
167
- { name: "auth", required: true, description: "\u8BA4\u8BC1\u6743\u9650", package: "@mindbase/express-auth" },
168
- { name: "kv", description: "\u952E\u503C\u5B58\u50A8", package: "@mindbase/express-kv" },
169
- { name: "admin", dependencies: ["auth"], description: "\u7528\u6237\u7BA1\u7406", package: "@mindbase/express-admin" },
170
- { name: "storage", dependencies: ["auth", "kv"], description: "\u6587\u4EF6\u5B58\u50A8", package: "@mindbase/express-storage" },
171
- { name: "explorer", description: "\u6587\u4EF6\u7BA1\u7406", package: "@mindbase/express-explorer" },
172
- { name: "knowledge", dependencies: ["auth"], description: "\u77E5\u8BC6\u5E93", package: "@mindbase/express-knowledge" },
173
- { name: "commandRunner", description: "\u547D\u4EE4\u7BA1\u7406", package: "@mindbase/express-command-runner" }
174
- ];
175
- var FRONTEND_APP_TYPES = [
176
- {
177
- name: "admin-app",
178
- description: "\u7BA1\u7406\u540E\u53F0 - \u5B8C\u6574\u7684\u7BA1\u7406\u754C\u9762",
179
- package: "@mindbase/vue3-admin-app",
180
- available: true,
181
- dependencies: ["@mindbase/vue3-auth", "@mindbase/vue3-kv", "@mindbase/vue3-client"]
182
- }
183
- ];
184
- function resolveDependencies(selectedModules) {
185
- const result = /* @__PURE__ */ new Map();
186
- function addModule(name) {
187
- if (result.has(name)) return;
188
- const module = BACKEND_MODULES.find((m) => m.name === name);
189
- if (!module) return;
190
- if (module.dependencies) {
191
- for (const dep of module.dependencies) {
192
- addModule(dep);
193
- }
194
- }
195
- result.set(module.name, module);
196
- }
197
- for (const name of selectedModules) {
198
- addModule(name);
199
- }
200
- return Array.from(result.values());
201
- }
202
- function getFrontendPackage(appType) {
203
- const app = FRONTEND_APP_TYPES.find((a) => a.name === appType);
204
- return app?.package;
205
- }
206
- function getAvailableFrontendApps() {
207
- return FRONTEND_APP_TYPES.filter((app) => app.available);
208
- }
209
- var KNOWN_PACKAGE_DEPS = {
210
- "@mindbase/vue3-auth": ["@mindbase/vue3-kit", "@mindbase/vue3-client"],
211
- "@mindbase/vue3-kv": ["@mindbase/vue3-kit", "@mindbase/vue3-client"],
212
- "@mindbase/vue3-storage": ["@mindbase/vue3-kit", "@mindbase/vue3-client", "spark-md5"],
213
- "@mindbase/vue3-command": ["@mindbase/vue3-kit", "@mindbase/vue3-client"],
214
- "@mindbase/vue3-explorer": ["@mindbase/vue3-kit", "@mindbase/vue3-client"]
215
- };
216
- function resolveFrontendDependencies(appType) {
217
- const packages = /* @__PURE__ */ new Set();
218
- function addPackage(packageName) {
219
- if (packages.has(packageName)) return;
220
- packages.add(packageName);
221
- const app2 = FRONTEND_APP_TYPES.find((a) => a.package === packageName);
222
- if (app2?.dependencies) {
223
- for (const dep of app2.dependencies) {
224
- addPackage(dep);
225
- }
226
- }
227
- if (KNOWN_PACKAGE_DEPS[packageName]) {
228
- for (const dep of KNOWN_PACKAGE_DEPS[packageName]) {
229
- addPackage(dep);
230
- }
231
- }
232
- }
233
- const app = FRONTEND_APP_TYPES.find((a) => a.name === appType);
234
- if (app) {
235
- addPackage(app.package);
236
- }
237
- return Array.from(packages);
238
- }
239
-
240
- // src/utils/BackendInitializer.ts
241
- import fs from "fs";
242
- import path2 from "path";
243
- import prompts from "prompts";
244
- async function collectBackendConfig(cwd) {
245
- const folderName = path2.basename(cwd);
246
- const response = await prompts([
247
- {
248
- type: "text",
249
- name: "name",
250
- message: "\u9879\u76EE\u540D\u79F0",
251
- initial: folderName,
252
- validate: (value) => value.length > 0 || "\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A"
253
- },
254
- {
255
- type: "text",
256
- name: "description",
257
- message: "\u9879\u76EE\u63CF\u8FF0",
258
- initial: "MindBase \u9A71\u52A8\u7684\u5E94\u7528\u9879\u76EE"
259
- },
260
- {
261
- type: "text",
262
- name: "author",
263
- message: "\u4F5C\u8005",
264
- initial: ""
265
- },
266
- {
267
- type: "text",
268
- name: "port",
269
- message: "\u670D\u52A1\u7AEF\u53E3",
270
- initial: "3000",
271
- validate: (value) => {
272
- const val = typeof value === "number" ? value : parseInt(value, 10);
273
- if (isNaN(val) || val < 1 || val > 65535) {
274
- return "\u7AEF\u53E3\u53F7\u5FC5\u987B\u4E3A\u5728 1-65535 \u4E4B\u95F4\u7684\u6570\u5B57";
275
- }
276
- return true;
277
- }
278
- },
279
- {
280
- type: "text",
281
- name: "dbPath",
282
- message: "\u6570\u636E\u5E93\u8DEF\u5F84 (\u5EFA\u8BAE: ./data/app.db)",
283
- initial: "./data/app.db"
284
- },
285
- {
286
- type: "text",
287
- name: "staticPath",
288
- message: "\u9759\u6001\u76EE\u5F55\u8DEF\u5F84 (\u7559\u7A7A\u5219\u4E0D\u521B\u5EFA\uFF0C\u4F8B\u5982: public)",
289
- initial: "public"
290
- },
291
- {
292
- type: "text",
293
- name: "apiPrefix",
294
- message: "API \u524D\u7F00 (\u7559\u7A7A\u5219\u65E0\u524D\u7F00\uFF0C\u4F8B\u5982: /api)",
295
- initial: "/api"
296
- },
297
- {
298
- type: "confirm",
299
- name: "userAgent",
300
- message: "\u542F\u7528 User-Agent \u89E3\u6790\u4E2D\u95F4\u4EF6?",
301
- initial: true
302
- },
303
- {
304
- type: "confirm",
305
- name: "ip",
306
- message: "\u542F\u7528 IP \u89E3\u6790\u4E2D\u95F4\u4EF6?",
307
- initial: true
308
- },
309
- {
310
- type: "confirm",
311
- name: "cors",
312
- message: "\u542F\u7528 CORS \u8DE8\u57DF\u4E2D\u95F4\u4EF6?",
313
- initial: true
314
- },
315
- {
316
- type: "select",
317
- name: "logLevel",
318
- message: "\u65E5\u5FD7\u7EA7\u522B",
319
- choices: [
320
- { title: "debug\uFF08\u663E\u793A\u6240\u6709\uFF09", value: "debug" },
321
- { title: "info\uFF08\u9ED8\u8BA4\uFF09", value: "info" },
322
- { title: "warn\uFF08\u8B66\u544A\uFF09", value: "warn" },
323
- { title: "error\uFF08\u4EC5\u9519\u8BEF\uFF09", value: "error" },
324
- { title: "silent\uFF08\u9759\u9ED8\uFF09", value: "silent" }
325
- ],
326
- initial: 1
327
- },
328
- {
329
- type: "multiselect",
330
- name: "modules",
331
- message: "\u9009\u62E9\u8981\u5305\u542B\u7684\u6A21\u5757",
332
- choices: BACKEND_MODULES.map((m) => ({
333
- title: `${m.name} (${m.description})${m.required ? " - \u5FC5\u9009" : ""}`,
334
- value: m.name,
335
- selected: m.required
336
- }))
337
- }
338
- ]);
339
- if (Object.keys(response).length < 12) {
340
- throw new Error("\u7528\u6237\u53D6\u6D88\u4E86\u521D\u59CB\u5316\u6D41\u7A0B");
341
- }
342
- const selectedModules = response.modules;
343
- const allModules = resolveDependencies(selectedModules);
344
- Logger_default.info(`\u5DF2\u9009\u62E9\u7684\u6A21\u5757: ${allModules.map((item) => item.name).join(", ")}`);
345
- return { ...response, modules: allModules };
346
- }
347
- function setupBackendPackageJson(cwd, config) {
348
- const pkgPath = path2.join(cwd, "package.json");
349
- let pkg = {};
350
- if (fs.existsSync(pkgPath)) {
351
- pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
352
- Logger_default.info("\u2713 \u68C0\u6D4B\u5230\u5DF2\u5B58\u5728\u7684 package.json\uFF0C\u6B63\u5728\u66F4\u65B0\u914D\u7F6E...");
353
- } else {
354
- pkg = {
355
- name: config.name,
356
- version: "1.0.0",
357
- description: config.description,
358
- author: config.author,
359
- scripts: {},
360
- dependencies: {
361
- "art-template": "^4.13.4",
362
- "better-sqlite3": "^11.10.0",
363
- "cookie-parser": "^1.4.7",
364
- cron: "^3.1.9",
365
- dayjs: "^1.11.13",
366
- "drizzle-orm": "^0.44.7",
367
- "drizzle-zod": "^0.5.0",
368
- express: "^5.2.1",
369
- "express-art-template": "^1.0.1",
370
- "fs-extra": "^11.2.0",
371
- glob: "^10.0.0",
372
- "ipip-ipdb": "^0.6.0",
373
- "mime-types": "^2.1.35",
374
- multer: "^1.4.5-lts.1",
375
- radash: "12.1.1",
376
- "ts-morph": "^27.0.0",
377
- "ua-parser-js": "^2.0.0",
378
- uuid: "^10.0.0",
379
- xss: "^1.0.14",
380
- zod: "^3.24.0"
381
- },
382
- devDependencies: {
383
- "@types/express": "^5.0.6",
384
- "@types/node": "^20.0.0",
385
- tsx: "^4.19.2",
386
- typescript: "^5.1.3",
387
- "tsconfig-paths": "^4.2.0",
388
- "drizzle-kit": "^0.31.7",
389
- "@types/better-sqlite3": "^7.6.11",
390
- "@types/fs-extra": "^11.0.4",
391
- "@types/multer": "^1.4.11",
392
- "@types/prompts": "^2.4.9",
393
- "@types/uuid": "^10.0.0"
394
- }
395
- };
396
- Logger_default.info("\u2713 \u6B63\u5728\u751F\u6210 package.json...");
397
- }
398
- pkg.scripts = pkg.scripts || {};
399
- pkg.scripts["dev"] = "tsx --watch --tsconfig-paths ./src/app.ts";
400
- pkg.scripts["start"] = "tsx --tsconfig-paths ./src/app.ts";
401
- pkg.scripts["prepare"] = "tsx prepare.js";
402
- pkg.scripts["init-admin"] = "mindbase-auth init-admin";
403
- pkg.scripts["db:generate"] = "drizzle-kit generate";
404
- pkg.scripts["db:migrate"] = "drizzle-kit migrate";
405
- pkg.scripts["init"] = "npm run prepare && npm run db:generate && npm run db:migrate && npm run init-admin";
406
- pkg.scripts["db:push"] = "drizzle-kit push";
407
- pkg.scripts["db:studio"] = "drizzle-kit studio";
408
- pkg.dependencies["@mindbase/express-common"] = "^1.0.0";
409
- for (const module of config.modules) {
410
- const packageName = module.package;
411
- if (packageName) {
412
- pkg.dependencies[packageName] = "^1.0.0";
413
- }
414
- }
415
- pkg.dependencies["express"] = "^5.2.1";
416
- pkg.dependencies["cross-env"] = "^7.0.3";
417
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
418
- Logger_default.info("\u2713 package.json \u5DF2\u5C31\u7EEA");
419
- }
420
- function setupAppConfig(cwd, config) {
421
- const configDir = path2.join(cwd, "src/config");
422
- const configFilePath = path2.join(configDir, "index.ts");
423
- const configContent = `import { MindBaseAppOptions } from "@mindbase/express-common";
424
-
425
- const config: MindBaseAppOptions = {
426
- port: ${config.port},
427
- logging: true,
428
- logLevel: "${config.logLevel}",
429
- database: {
430
- path: "${config.dbPath}",
431
- },
432
- staticPath: ${config.staticPath ? `"${config.staticPath}"` : "undefined"},
433
- apiPrefix: ${config.apiPrefix ? `"${config.apiPrefix}"` : "undefined"},
434
- userAgent: ${config.userAgent},
435
- ip: ${config.ip},
436
- cors: ${config.cors},
437
- };
438
-
439
- export default config;
440
- `;
441
- if (!fs.existsSync(configDir)) fs.mkdirSync(configDir, { recursive: true });
442
- fs.writeFileSync(configFilePath, configContent);
443
- Logger_default.info("\u2713 src/config/index.ts \u5DF2\u5C31\u7EEA");
444
- if (config.staticPath) {
445
- const staticDir = path2.join(cwd, config.staticPath);
446
- if (!fs.existsSync(staticDir)) {
447
- fs.mkdirSync(staticDir, { recursive: true });
448
- Logger_default.info(`\u2713 \u9759\u6001\u76EE\u5F55\u5DF2\u521B\u5EFA: ${config.staticPath}`);
449
- }
450
- }
451
- }
452
- function setupDrizzleConfig(cwd, config) {
453
- const drizzleConfigPath = path2.join(cwd, "drizzle.config.ts");
454
- const drizzleConfigContent = `import { defineConfig } from "drizzle-kit";
455
- import fs from "fs";
456
-
457
- // \u52A8\u6001\u8BFB\u53D6\u7531 db:sync \u811A\u672C\u751F\u6210\u7684 schema \u8DEF\u5F84\u6E05\u5355
458
- const schemaJson = "./.drizzle-schemas.json";
459
- const schemas = fs.existsSync(schemaJson)
460
- ? JSON.parse(fs.readFileSync(schemaJson, "utf-8"))
461
- : ["./src/**/*.schema.ts"];
462
-
463
- export default defineConfig({
464
- schema: schemas,
465
- out: "./drizzle",
466
- dialect: "sqlite",
467
- dbCredentials: {
468
- url: "${config.dbPath}",
469
- },
470
- });
471
- `;
472
- fs.writeFileSync(drizzleConfigPath, drizzleConfigContent);
473
- Logger_default.info("\u2713 drizzle.config.ts \u5DF2\u5C31\u7EEA");
474
- }
475
- function setupTsConfig(cwd) {
476
- const tsconfigPath = path2.join(cwd, "tsconfig.json");
477
- if (!fs.existsSync(tsconfigPath)) {
478
- const tsconfigContent = {
479
- compilerOptions: {
480
- target: "ESNext",
481
- module: "CommonJS",
482
- moduleResolution: "node",
483
- baseUrl: ".",
484
- paths: {
485
- "#/*": ["src/*"]
486
- },
487
- strict: true,
488
- esModuleInterop: true,
489
- skipLibCheck: true,
490
- forceConsistentCasingInFileNames: true,
491
- experimentalDecorators: true,
492
- emitDecoratorMetadata: true,
493
- outDir: "dist"
494
- },
495
- include: ["src/**/*"],
496
- exclude: ["node_modules"]
497
- };
498
- fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfigContent, null, 2));
499
- Logger_default.info("\u2713 tsconfig.json \u5DF2\u5C31\u7EEA");
500
- }
501
- }
502
- function setupAppEntry(cwd, config) {
503
- const appPath = path2.join(cwd, "src/app.ts");
504
- if (!fs.existsSync(appPath)) {
505
- const appContent = `import { createApp } from "@mindbase/express-common";
506
- ${config.modules.map((module) => "import " + module.name + ' from "' + module.package + '";').join("\n")}
507
- import config from "./config";
508
-
509
- async function bootstrap() {
510
- const app = await createApp(config);
511
-
512
- // \u5728\u6B64\u5904\u4F7F\u7528\u63D2\u4EF6\u6216\u4E2D\u95F4\u4EF6
513
- ${config.modules.map(({ name }) => " app.use(" + name + ")").join("\n")}
514
-
515
- await app.startup();
516
- }
517
-
518
- bootstrap();
519
- `;
520
- if (!fs.existsSync(path2.join(cwd, "src"))) fs.mkdirSync(path2.join(cwd, "src"));
521
- fs.writeFileSync(appPath, appContent);
522
- Logger_default.info("\u2713 src/app.ts \u5DF2\u5C31\u7EEA");
523
- }
524
- }
525
- function copyAssets(cwd) {
526
- const ipdbPath = path2.join(cwd, "ipipfree.ipdb");
527
- const sourceIpdb = path2.join(__dirname, "..", "assets", "ipipfree.ipdb");
528
- if (fs.existsSync(sourceIpdb)) {
529
- if (!fs.existsSync(ipdbPath)) {
530
- fs.copyFileSync(sourceIpdb, ipdbPath);
531
- Logger_default.info("\u2713 ipipfree.ipdb \u5DF2\u5C31\u7EEA");
532
- } else {
533
- Logger_default.info("- ipipfree.ipdb \u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u62F7\u8D1D");
534
- }
535
- } else {
536
- Logger_default.warn(`! \u672A\u80FD\u627E\u5230 ipipfree.ipdb \u6E90\u6587\u4EF6: ${sourceIpdb}`);
537
- }
538
- }
539
- function setupPrepareScript(cwd) {
540
- const preparePath = path2.join(cwd, "prepare.js");
541
- if (!fs.existsSync(preparePath)) {
542
- const prepareContent = `import { prepare } from '@mindbase/express-common';
543
- prepare();`;
544
- fs.writeFileSync(preparePath, prepareContent);
545
- Logger_default.info("\u2713 prepare.js \u5DF2\u5C31\u7EEA");
546
- }
547
- }
548
-
549
- // src/utils/FrontendInitializer.ts
550
- import fs2 from "fs";
551
- import path3 from "path";
552
- import prompts2 from "prompts";
553
- async function collectFrontendConfig(cwd) {
554
- const folderName = path3.basename(cwd);
555
- const availableApps = getAvailableFrontendApps();
556
- const response = await prompts2([
557
- {
558
- type: "text",
559
- name: "name",
560
- message: "\u9879\u76EE\u540D\u79F0",
561
- initial: folderName,
562
- validate: (value) => value.length > 0 || "\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A"
563
- },
564
- {
565
- type: "text",
566
- name: "description",
567
- message: "\u9879\u76EE\u63CF\u8FF0",
568
- initial: "MindBase \u524D\u7AEF\u5E94\u7528"
569
- },
570
- {
571
- type: "text",
572
- name: "author",
573
- message: "\u4F5C\u8005",
574
- initial: ""
575
- },
576
- {
577
- type: "text",
578
- name: "port",
579
- message: "\u5F00\u53D1\u670D\u52A1\u5668\u7AEF\u53E3",
580
- initial: "5173",
581
- validate: (value) => {
582
- const val = typeof value === "number" ? value : parseInt(value, 10);
583
- if (isNaN(val) || val < 1 || val > 65535) {
584
- return "\u7AEF\u53E3\u53F7\u5FC5\u987B\u4E3A\u5728 1-65535 \u4E4B\u95F4\u7684\u6570\u5B57";
585
- }
586
- return true;
587
- }
588
- },
589
- {
590
- type: "text",
591
- name: "proxyTarget",
592
- message: "API \u4EE3\u7406\u76EE\u6807\u5730\u5740",
593
- initial: "http://localhost:3000"
594
- },
595
- {
596
- type: "text",
597
- name: "proxyPath",
598
- message: "API \u4EE3\u7406\u8DEF\u5F84 (\u7559\u7A7A\u5219\u4E0D\u4EE3\u7406)",
599
- initial: "/api"
600
- },
601
- {
602
- type: "select",
603
- name: "appType",
604
- message: "\u9009\u62E9\u5E94\u7528\u5F62\u6001",
605
- choices: availableApps.map((app) => ({
606
- title: app.description,
607
- value: app.name
608
- })),
609
- initial: 0
610
- }
611
- ]);
612
- if (Object.keys(response).length < 7) {
613
- throw new Error("\u7528\u6237\u53D6\u6D88\u4E86\u521D\u59CB\u5316\u6D41\u7A0B");
614
- }
615
- Logger_default.info(`\u5DF2\u9009\u62E9\u5E94\u7528\u5F62\u6001: ${response.appType}`);
616
- return response;
617
- }
618
- function setupFrontendPackageJson(cwd, config) {
619
- const pkgPath = path3.join(cwd, "package.json");
620
- let pkg = {};
621
- if (fs2.existsSync(pkgPath)) {
622
- pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
623
- Logger_default.info("\u2713 \u68C0\u6D4B\u5230\u5DF2\u5B58\u5728\u7684 package.json\uFF0C\u6B63\u5728\u66F4\u65B0\u914D\u7F6E...");
624
- } else {
625
- pkg = {
626
- name: config.name,
627
- version: "1.0.0",
628
- description: config.description,
629
- author: config.author,
630
- private: true,
631
- type: "module",
632
- dependencies: {
633
- axios: "^1.7.0",
634
- "crypto-js": "^4.2.0",
635
- dayjs: "^1.11.19",
636
- "element-plus": "^2.9.0",
637
- "element-plus/icons-vue": "^2.9.0",
638
- "lodash-es": "^4.17.21",
639
- pinia: "^2.2.0",
640
- "spark-md5": "^3.0.2",
641
- vue: "^3.5.0",
642
- "vue-router": "^4.5.0"
643
- },
644
- devDependencies: {
645
- "@vitejs/plugin-vue": "^5.2.0",
646
- typescript: "^5.6.0",
647
- vite: "^6.0.0",
648
- "vue-tsc": "^2.2.0"
649
- }
650
- };
651
- Logger_default.info("\u2713 \u6B63\u5728\u751F\u6210 package.json...");
652
- }
653
- pkg.scripts = pkg.scripts || {};
654
- pkg.scripts["start"] = "npm run dev";
655
- pkg.scripts["dev"] = `vite --port ${config.port}`;
656
- pkg.scripts["build"] = "vue-tsc -b && vite build";
657
- pkg.scripts["preview"] = "vite preview";
658
- const allPackages = resolveFrontendDependencies(config.appType);
659
- for (const packageName of allPackages) {
660
- pkg.dependencies = pkg.dependencies || {};
661
- pkg.dependencies[packageName] = "^1.0.0";
662
- }
663
- pkg.devDependencies = pkg.devDependencies || {};
664
- pkg.devDependencies["vue-tsc"] = "^2.2.0";
665
- fs2.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
666
- Logger_default.info("\u2713 package.json \u5DF2\u5C31\u7EEA");
667
- }
668
- function setupViteConfig(cwd, config) {
669
- const viteConfigPath = path3.join(cwd, "vite.config.ts");
670
- const proxyConfig = config.proxyPath ? `{
671
- '${config.proxyPath}': {
672
- target: '${config.proxyTarget}',
673
- changeOrigin: true,
674
- },
675
- }` : "undefined";
676
- const viteConfigContent = `import { defineConfig } from "vite";
677
- import vue from "@vitejs/plugin-vue";
678
- import path from "path";
679
-
680
- export default defineConfig({
681
- plugins: [vue()],
682
- resolve: {
683
- alias: {
684
- "@": path.resolve(__dirname, "./src"),
685
- },
686
- },
687
- server: {
688
- port: ${config.port},
689
- proxy: ${proxyConfig},
690
- },
691
- });
692
- `;
693
- fs2.writeFileSync(viteConfigPath, viteConfigContent);
694
- Logger_default.info("\u2713 vite.config.ts \u5DF2\u5C31\u7EEA");
695
- }
696
- function setupFrontendTsConfig(cwd) {
697
- const tsconfigPath = path3.join(cwd, "tsconfig.json");
698
- if (!fs2.existsSync(tsconfigPath)) {
699
- const tsconfigContent = {
700
- compilerOptions: {
701
- target: "ES2022",
702
- module: "ESNext",
703
- moduleResolution: "bundler",
704
- strict: true,
705
- esModuleInterop: true,
706
- skipLibCheck: true,
707
- forceConsistentCasingInFileNames: true,
708
- resolveJsonModule: true,
709
- isolatedModules: true,
710
- noEmit: true,
711
- lib: ["ES2022", "DOM", "DOM.Iterable"],
712
- types: ["vite/client"]
713
- },
714
- include: ["src/**/*.ts", "src/**/*.vue", "vite.config.ts"]
715
- };
716
- fs2.writeFileSync(tsconfigPath, JSON.stringify(tsconfigContent, null, 2));
717
- Logger_default.info("\u2713 tsconfig.json \u5DF2\u5C31\u7EEA");
718
- }
719
- }
720
- function setupIndexHtml(cwd, config) {
721
- const htmlPath = path3.join(cwd, "index.html");
722
- const htmlContent = `<!DOCTYPE html>
723
- <html lang="zh-CN">
724
- <head>
725
- <meta charset="UTF-8" />
726
- <link rel="icon" type="image/svg+xml" href="/favicon.ico" />
727
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
728
- <title>${config.name}</title>
729
- </head>
730
- <body>
731
- <div id="app"></div>
732
- <script type="module" src="/src/main.ts"></script>
733
- </body>
734
- </html>
735
- `;
736
- fs2.writeFileSync(htmlPath, htmlContent);
737
- Logger_default.info("\u2713 index.html \u5DF2\u5C31\u7EEA");
738
- }
739
- function setupAppFiles(cwd, config) {
740
- const srcDir = path3.join(cwd, "src");
741
- if (!fs2.existsSync(srcDir)) fs2.mkdirSync(srcDir, { recursive: true });
742
- const mainContent = `import {
743
- createMindBaseApp,
744
- createGlobComponentMap,
745
- } from "${getFrontendPackage(config.appType)}";
746
-
747
- const { app, pinia } = createMindBaseApp({
748
- router: {},
749
- componentMap: createGlobComponentMap(import.meta.glob("./views/**/*.vue"), "./views/"),
750
- });
751
-
752
- app.mount("#app");
753
- `;
754
- fs2.writeFileSync(path3.join(srcDir, "main.ts"), mainContent);
755
- Logger_default.info("\u2713 src/main.ts \u5DF2\u5C31\u7EEA");
756
- const appContent = `<template>
757
- <router-view />
758
- </template>
759
-
760
- <script setup lang="ts">
761
- // \u6839\u7EC4\u4EF6
762
- </script>
763
-
764
- <style>
765
- html,
766
- body,
767
- #app {
768
- margin: 0;
769
- padding: 0;
770
- width: 100%;
771
- height: 100%;
772
- }
773
- </style>
774
- `;
775
- fs2.writeFileSync(path3.join(srcDir, "App.vue"), appContent);
776
- Logger_default.info("\u2713 src/App.vue \u5DF2\u5C31\u7EEA");
777
- const viewsDir = path3.join(srcDir, "views");
778
- if (!fs2.existsSync(viewsDir)) fs2.mkdirSync(viewsDir);
779
- const exampleView = `<template>
780
- <div class="home">
781
- <h1>\u6B22\u8FCE\u4F7F\u7528 ${config.name}</h1>
782
- </div>
783
- </template>
784
-
785
- <script setup lang="ts">
786
- // \u9875\u9762\u903B\u8F91
787
- </script>
788
-
789
- <style scoped>
790
- .home {
791
- padding: 20px;
792
- }
793
- </style>
794
- `;
795
- fs2.writeFileSync(path3.join(viewsDir, "index.vue"), exampleView);
796
- Logger_default.info("\u2713 src/views/index.vue \u5DF2\u5C31\u7EEA");
797
- }
798
- function setupPublicDir(cwd) {
799
- const publicDir = path3.join(cwd, "public");
800
- if (!fs2.existsSync(publicDir)) {
801
- fs2.mkdirSync(publicDir, { recursive: true });
802
- Logger_default.info("\u2713 public \u76EE\u5F55\u5DF2\u521B\u5EFA");
803
- }
804
- }
805
- function copyAdminAssets(cwd, config) {
806
- if (config.appType !== "admin-app") {
807
- return;
808
- }
809
- const sourceDir = path3.join(__dirname, "../assets/iconfont");
810
- if (!fs2.existsSync(sourceDir)) {
811
- Logger_default.warn("\u5B57\u4F53\u6E90\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u590D\u5236");
812
- return;
813
- }
814
- const targetDir = path3.join(cwd, "public/assets/mb-iconfont");
815
- if (!fs2.existsSync(targetDir)) {
816
- fs2.mkdirSync(targetDir, { recursive: true });
817
- }
818
- const fonts = ["iconfont.woff2", "iconfont.woff", "iconfont.ttf"];
819
- let copiedCount = 0;
820
- fonts.forEach((font) => {
821
- const sourcePath = path3.join(sourceDir, font);
822
- const targetPath = path3.join(targetDir, font);
823
- if (fs2.existsSync(sourcePath)) {
824
- fs2.copyFileSync(sourcePath, targetPath);
825
- copiedCount++;
826
- }
827
- });
828
- if (copiedCount > 0) {
829
- Logger_default.info(`\u2713 \u5DF2\u590D\u5236 ${copiedCount} \u4E2A\u5B57\u4F53\u6587\u4EF6\u5230 public/assets/mb-iconfont/`);
830
- }
831
- }
832
-
833
- // src/commands/init/backend.ts
834
- async function initBackend() {
835
- const cwd = process.cwd();
836
- Logger_default.info(`
837
- \u{1F680} \u6B63\u5728\u521D\u59CB\u5316 MindBase \u540E\u7AEF\u9879\u76EE: ${cwd}
838
- `);
839
- try {
840
- const config = await collectBackendConfig(cwd);
841
- setupBackendPackageJson(cwd, config);
842
- setupAppConfig(cwd, config);
843
- setupDrizzleConfig(cwd, config);
844
- setupTsConfig(cwd);
845
- setupAppEntry(cwd, config);
846
- copyAssets(cwd);
847
- setupPrepareScript(cwd);
848
- Logger_default.info("\n\u2728 \u540E\u7AEF\u9879\u76EE\u521D\u59CB\u5316\u6210\u529F\uFF01\u5EFA\u8BAE\u8FD0\u884C: npm install\n");
849
- } catch (err) {
850
- throw err;
851
- }
852
- }
853
-
854
- // src/commands/init/frontend.ts
855
- async function initFrontend() {
856
- const cwd = process.cwd();
857
- Logger_default.info(`
858
- \u{1F680} \u6B63\u5728\u521D\u59CB\u5316 MindBase \u524D\u7AEF\u9879\u76EE: ${cwd}
859
- `);
860
- try {
861
- const config = await collectFrontendConfig(cwd);
862
- setupFrontendPackageJson(cwd, config);
863
- setupViteConfig(cwd, config);
864
- setupFrontendTsConfig(cwd);
865
- setupIndexHtml(cwd, config);
866
- setupAppFiles(cwd, config);
867
- setupPublicDir(cwd);
868
- copyAdminAssets(cwd, config);
869
- Logger_default.info("\n\u2728 \u524D\u7AEF\u9879\u76EE\u521D\u59CB\u5316\u6210\u529F\uFF01\u5EFA\u8BAE\u8FD0\u884C: npm install\n");
870
- } catch (err) {
871
- throw err;
872
- }
873
- }
874
-
875
- // src/commands/init/index.ts
876
- async function init(type) {
877
- switch (type) {
878
- case "backend":
879
- await initBackend();
880
- break;
881
- case "frontend":
882
- await initFrontend();
883
- break;
884
- case "admin":
885
- await initAdmin();
886
- break;
887
- default:
888
- console.log(`
889
- \u7528\u6CD5: mindbase init <type>
890
-
891
- \u7C7B\u578B:
892
- backend \u521D\u59CB\u5316\u540E\u7AEF\u9879\u76EE
893
- frontend \u521D\u59CB\u5316\u524D\u7AEF\u9879\u76EE
894
- admin \u5FEB\u6377\uFF1A\u521D\u59CB\u5316\u5B8C\u6574\u7BA1\u7406\u540E\u53F0\uFF08\u524D\u540E\u7AEF\u4E00\u4F53\uFF09
895
- `);
896
- break;
897
- }
898
- }
899
- async function initAdmin() {
900
- console.log("\n\u{1F3AF} \u6B63\u5728\u521D\u59CB\u5316\u5B8C\u6574\u7BA1\u7406\u540E\u53F0...\n");
901
- console.log("\u7B2C\u4E00\u6B65\uFF1A\u521D\u59CB\u5316\u540E\u7AEF");
902
- await initBackend();
903
- console.log("\n\u7B2C\u4E8C\u6B65\uFF1A\u521D\u59CB\u5316\u524D\u7AEF");
904
- await initFrontend();
905
- console.log("\n\u2728 \u5B8C\u6574\u7BA1\u7406\u540E\u53F0\u521D\u59CB\u5316\u6210\u529F\uFF01");
906
- console.log("\n\u540E\u7EED\u6B65\u9AA4\uFF1A");
907
- console.log(" 1. cd backend && npm install && npm run dev");
908
- console.log(" 2. cd frontend && npm install && npm run dev");
909
- console.log(" 3. \u524D\u7AEF\u4F1A\u81EA\u52A8\u4EE3\u7406 API \u5230\u540E\u7AEF http://localhost:3000\n");
910
- }
911
-
912
- export {
913
- logger,
914
- BACKEND_MODULES,
915
- FRONTEND_APP_TYPES,
916
- resolveDependencies,
917
- getFrontendPackage,
918
- getAvailableFrontendApps,
919
- collectBackendConfig,
920
- setupBackendPackageJson,
921
- setupAppConfig,
922
- setupDrizzleConfig,
923
- setupTsConfig,
924
- setupAppEntry,
925
- copyAssets,
926
- setupPrepareScript,
927
- collectFrontendConfig,
928
- setupFrontendPackageJson,
929
- setupViteConfig,
930
- setupFrontendTsConfig,
931
- setupIndexHtml,
932
- setupAppFiles,
933
- setupPublicDir,
934
- init
935
- };
936
- //# sourceMappingURL=chunk-U3UDAQCW.js.map