@mindbase/cli 1.0.8 → 1.0.12
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/bin/mindbase.d.ts +1 -0
- package/dist/bin/mindbase.js +40 -0
- package/dist/bin/mindbase.js.map +1 -0
- package/dist/chunk-J42QLX7S.js +938 -0
- package/dist/chunk-J42QLX7S.js.map +1 -0
- package/dist/index.d.ts +139 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/package.json +7 -5
- package/src/bin/mindbase.ts +0 -39
- package/src/commands/init/backend.ts +0 -34
- package/src/commands/init/frontend.ts +0 -34
- package/src/commands/init/index.ts +0 -50
- package/src/commands/sdk-docs.ts +0 -138
- package/src/index.ts +0 -33
- package/src/utils/BackendInitializer.ts +0 -377
- package/src/utils/FrontendInitializer.ts +0 -370
- package/src/utils/Logger.ts +0 -219
- package/src/utils/prompts.ts +0 -140
- package/tsconfig.json +0 -15
package/src/index.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// 导出工具函数供外部使用
|
|
2
|
-
export { logger as default, type LogLevel } from "./utils/Logger";
|
|
3
|
-
export {
|
|
4
|
-
BACKEND_MODULES,
|
|
5
|
-
FRONTEND_APP_TYPES,
|
|
6
|
-
resolveDependencies,
|
|
7
|
-
getFrontendPackage,
|
|
8
|
-
getAvailableFrontendApps,
|
|
9
|
-
} from "./utils/prompts";
|
|
10
|
-
export {
|
|
11
|
-
type BackendConfig,
|
|
12
|
-
collectBackendConfig,
|
|
13
|
-
setupBackendPackageJson,
|
|
14
|
-
setupAppConfig,
|
|
15
|
-
setupDrizzleConfig,
|
|
16
|
-
setupTsConfig,
|
|
17
|
-
setupAppEntry,
|
|
18
|
-
copyAssets,
|
|
19
|
-
setupPrepareScript,
|
|
20
|
-
} from "./utils/BackendInitializer";
|
|
21
|
-
export {
|
|
22
|
-
type FrontendConfig,
|
|
23
|
-
collectFrontendConfig,
|
|
24
|
-
setupFrontendPackageJson,
|
|
25
|
-
setupViteConfig,
|
|
26
|
-
setupFrontendTsConfig,
|
|
27
|
-
setupIndexHtml,
|
|
28
|
-
setupAppFiles,
|
|
29
|
-
setupPublicDir,
|
|
30
|
-
} from "./utils/FrontendInitializer";
|
|
31
|
-
|
|
32
|
-
// 导出命令
|
|
33
|
-
export { init } from "./commands/init";
|
|
@@ -1,377 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import prompts from "prompts";
|
|
4
|
-
import logger from "./Logger";
|
|
5
|
-
import { BACKEND_MODULES, resolveDependencies, type BackendModule } from "./prompts";
|
|
6
|
-
|
|
7
|
-
export interface BackendConfig {
|
|
8
|
-
name: string;
|
|
9
|
-
description: string;
|
|
10
|
-
author: string;
|
|
11
|
-
port: number;
|
|
12
|
-
dbPath: string;
|
|
13
|
-
staticPath: string;
|
|
14
|
-
apiPrefix: string;
|
|
15
|
-
userAgent: boolean;
|
|
16
|
-
ip: boolean;
|
|
17
|
-
cors: boolean;
|
|
18
|
-
logLevel: "debug" | "info" | "warn" | "error" | "silent";
|
|
19
|
-
modules: BackendModule[];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* 收集后端项目初始化配置
|
|
24
|
-
*/
|
|
25
|
-
export async function collectBackendConfig(cwd: string): Promise<BackendConfig> {
|
|
26
|
-
const folderName = path.basename(cwd);
|
|
27
|
-
|
|
28
|
-
const response = await prompts([
|
|
29
|
-
{
|
|
30
|
-
type: "text",
|
|
31
|
-
name: "name",
|
|
32
|
-
message: "项目名称",
|
|
33
|
-
initial: folderName,
|
|
34
|
-
validate: (value: string) => value.length > 0 || "项目名称不能为空",
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
type: "text",
|
|
38
|
-
name: "description",
|
|
39
|
-
message: "项目描述",
|
|
40
|
-
initial: "MindBase 驱动的应用项目",
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
type: "text",
|
|
44
|
-
name: "author",
|
|
45
|
-
message: "作者",
|
|
46
|
-
initial: "",
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
type: "text",
|
|
50
|
-
name: "port",
|
|
51
|
-
message: "服务端口",
|
|
52
|
-
initial: "3000",
|
|
53
|
-
validate: (value: string) => {
|
|
54
|
-
const val = typeof value === "number" ? value : parseInt(value, 10);
|
|
55
|
-
if (isNaN(val) || val < 1 || val > 65535) {
|
|
56
|
-
return "端口号必须为在 1-65535 之间的数字";
|
|
57
|
-
}
|
|
58
|
-
return true;
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
type: "text",
|
|
63
|
-
name: "dbPath",
|
|
64
|
-
message: "数据库路径 (建议: ./data/app.db)",
|
|
65
|
-
initial: "./data/app.db",
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
type: "text",
|
|
69
|
-
name: "staticPath",
|
|
70
|
-
message: "静态目录路径 (留空则不创建,例如: public)",
|
|
71
|
-
initial: "public",
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
type: "text",
|
|
75
|
-
name: "apiPrefix",
|
|
76
|
-
message: "API 前缀 (留空则无前缀,例如: /api)",
|
|
77
|
-
initial: "/api",
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
type: "confirm",
|
|
81
|
-
name: "userAgent",
|
|
82
|
-
message: "启用 User-Agent 解析中间件?",
|
|
83
|
-
initial: true,
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
type: "confirm",
|
|
87
|
-
name: "ip",
|
|
88
|
-
message: "启用 IP 解析中间件?",
|
|
89
|
-
initial: true,
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
type: "confirm",
|
|
93
|
-
name: "cors",
|
|
94
|
-
message: "启用 CORS 跨域中间件?",
|
|
95
|
-
initial: true,
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
type: "select",
|
|
99
|
-
name: "logLevel",
|
|
100
|
-
message: "日志级别",
|
|
101
|
-
choices: [
|
|
102
|
-
{ title: "debug(显示所有)", value: "debug" },
|
|
103
|
-
{ title: "info(默认)", value: "info" },
|
|
104
|
-
{ title: "warn(警告)", value: "warn" },
|
|
105
|
-
{ title: "error(仅错误)", value: "error" },
|
|
106
|
-
{ title: "silent(静默)", value: "silent" },
|
|
107
|
-
],
|
|
108
|
-
initial: 1,
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
type: "multiselect",
|
|
112
|
-
name: "modules",
|
|
113
|
-
message: "选择要包含的模块",
|
|
114
|
-
choices: BACKEND_MODULES.map((m) => ({
|
|
115
|
-
title: `${m.name} (${m.description})${m.required ? " - 必选" : ""}`,
|
|
116
|
-
value: m.name,
|
|
117
|
-
selected: m.required,
|
|
118
|
-
})),
|
|
119
|
-
},
|
|
120
|
-
]);
|
|
121
|
-
|
|
122
|
-
if (Object.keys(response).length < 12) {
|
|
123
|
-
throw new Error("用户取消了初始化流程");
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// 解析模块依赖
|
|
127
|
-
const selectedModules = response.modules as string[];
|
|
128
|
-
const allModules = resolveDependencies(selectedModules);
|
|
129
|
-
|
|
130
|
-
logger.info(`已选择的模块: ${allModules.map((item) => item.name).join(", ")}`);
|
|
131
|
-
|
|
132
|
-
return { ...response, modules: allModules } as BackendConfig;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* 初始化 package.json
|
|
137
|
-
*/
|
|
138
|
-
export function setupBackendPackageJson(cwd: string, config: BackendConfig) {
|
|
139
|
-
const pkgPath = path.join(cwd, "package.json");
|
|
140
|
-
let pkg: any = {};
|
|
141
|
-
|
|
142
|
-
if (fs.existsSync(pkgPath)) {
|
|
143
|
-
pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
144
|
-
logger.info("✓ 检测到已存在的 package.json,正在更新配置...");
|
|
145
|
-
} else {
|
|
146
|
-
pkg = {
|
|
147
|
-
name: config.name,
|
|
148
|
-
version: "1.0.0",
|
|
149
|
-
description: config.description,
|
|
150
|
-
author: config.author,
|
|
151
|
-
type: "module",
|
|
152
|
-
private: true,
|
|
153
|
-
scripts: {},
|
|
154
|
-
dependencies: {
|
|
155
|
-
"art-template": "^4.13.4",
|
|
156
|
-
"better-sqlite3": "^11.10.0",
|
|
157
|
-
"cookie-parser": "^1.4.7",
|
|
158
|
-
cron: "^3.1.9",
|
|
159
|
-
dayjs: "^1.11.13",
|
|
160
|
-
"drizzle-orm": "^0.44.7",
|
|
161
|
-
"drizzle-zod": "^0.5.0",
|
|
162
|
-
express: "^5.2.1",
|
|
163
|
-
"express-art-template": "^1.0.1",
|
|
164
|
-
"fs-extra": "^11.2.0",
|
|
165
|
-
glob: "^10.0.0",
|
|
166
|
-
"ipip-ipdb": "^0.6.0",
|
|
167
|
-
"mime-types": "^2.1.35",
|
|
168
|
-
multer: "^1.4.5-lts.1",
|
|
169
|
-
radash: "12.1.1",
|
|
170
|
-
"ts-morph": "^27.0.0",
|
|
171
|
-
"ua-parser-js": "^2.0.0",
|
|
172
|
-
uuid: "^10.0.0",
|
|
173
|
-
xss: "^1.0.14",
|
|
174
|
-
zod: "^3.24.0",
|
|
175
|
-
},
|
|
176
|
-
devDependencies: {
|
|
177
|
-
"@types/express": "^5.0.6",
|
|
178
|
-
"@types/node": "^20.0.0",
|
|
179
|
-
tsx: "^4.19.2",
|
|
180
|
-
typescript: "^5.1.3",
|
|
181
|
-
"tsconfig-paths": "^4.2.0",
|
|
182
|
-
"drizzle-kit": "^0.31.7",
|
|
183
|
-
"@types/better-sqlite3": "^7.6.11",
|
|
184
|
-
"@types/fs-extra": "^11.0.4",
|
|
185
|
-
"@types/multer": "^1.4.11",
|
|
186
|
-
"@types/prompts": "^2.4.9",
|
|
187
|
-
"@types/uuid": "^10.0.0",
|
|
188
|
-
},
|
|
189
|
-
};
|
|
190
|
-
logger.info("✓ 正在生成 package.json...");
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// 注入标准脚本
|
|
194
|
-
pkg.scripts = pkg.scripts || {};
|
|
195
|
-
pkg.scripts["dev"] = "tsx --watch --tsconfig-paths ./src/app.ts";
|
|
196
|
-
pkg.scripts["start"] = "tsx --tsconfig-paths ./src/app.ts";
|
|
197
|
-
pkg.scripts["prepare"] = "tsx prepare.js";
|
|
198
|
-
pkg.scripts["init-admin"] = "mindbase-auth init-admin";
|
|
199
|
-
pkg.scripts["db:generate"] = "drizzle-kit generate";
|
|
200
|
-
pkg.scripts["db:migrate"] = "drizzle-kit migrate";
|
|
201
|
-
pkg.scripts["init"] = "npm run prepare && npm run db:generate && npm run db:migrate && npm run init-admin";
|
|
202
|
-
pkg.scripts["db:push"] = "drizzle-kit push";
|
|
203
|
-
pkg.scripts["db:studio"] = "drizzle-kit studio";
|
|
204
|
-
|
|
205
|
-
// 添加依赖
|
|
206
|
-
pkg.dependencies["@mindbase/express-common"] = "^1.0.0";
|
|
207
|
-
|
|
208
|
-
// 根据模块选择添加依赖
|
|
209
|
-
for (const module of config.modules) {
|
|
210
|
-
const packageName = module.package;
|
|
211
|
-
if (packageName) {
|
|
212
|
-
pkg.dependencies[packageName] = "^1.0.0";
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// 添加 express 和其他必要依赖
|
|
217
|
-
pkg.dependencies["express"] = "^5.2.1";
|
|
218
|
-
pkg.dependencies["cross-env"] = "^7.0.3";
|
|
219
|
-
|
|
220
|
-
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
221
|
-
logger.info("✓ package.json 已就绪");
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* 初始化应用配置 src/config/index.ts
|
|
226
|
-
*/
|
|
227
|
-
export function setupAppConfig(cwd: string, config: BackendConfig) {
|
|
228
|
-
const configDir = path.join(cwd, "src/config");
|
|
229
|
-
const configFilePath = path.join(configDir, "index.ts");
|
|
230
|
-
const configContent = `import { MindBaseAppOptions } from "@mindbase/express-common";
|
|
231
|
-
|
|
232
|
-
const config: MindBaseAppOptions = {
|
|
233
|
-
port: ${config.port},
|
|
234
|
-
logging: true,
|
|
235
|
-
logLevel: "${config.logLevel}",
|
|
236
|
-
database: {
|
|
237
|
-
path: "${config.dbPath}",
|
|
238
|
-
},
|
|
239
|
-
staticPath: ${config.staticPath ? `"${config.staticPath}"` : "undefined"},
|
|
240
|
-
apiPrefix: ${config.apiPrefix ? `"${config.apiPrefix}"` : "undefined"},
|
|
241
|
-
userAgent: ${config.userAgent},
|
|
242
|
-
ip: ${config.ip},
|
|
243
|
-
cors: ${config.cors},
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
export default config;
|
|
247
|
-
`;
|
|
248
|
-
if (!fs.existsSync(configDir)) fs.mkdirSync(configDir, { recursive: true });
|
|
249
|
-
fs.writeFileSync(configFilePath, configContent);
|
|
250
|
-
logger.info("✓ src/config/index.ts 已就绪");
|
|
251
|
-
|
|
252
|
-
// 同步创建静态目录
|
|
253
|
-
if (config.staticPath) {
|
|
254
|
-
const staticDir = path.join(cwd, config.staticPath);
|
|
255
|
-
if (!fs.existsSync(staticDir)) {
|
|
256
|
-
fs.mkdirSync(staticDir, { recursive: true });
|
|
257
|
-
logger.info(`✓ 静态目录已创建: ${config.staticPath}`);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* 初始化 Drizzle 配置 drizzle.config.ts
|
|
264
|
-
*/
|
|
265
|
-
export function setupDrizzleConfig(cwd: string, config: BackendConfig) {
|
|
266
|
-
const drizzleConfigPath = path.join(cwd, "drizzle.config.ts");
|
|
267
|
-
const drizzleConfigContent = `import { defineConfig } from "drizzle-kit";
|
|
268
|
-
import fs from "fs";
|
|
269
|
-
|
|
270
|
-
// 动态读取由 db:sync 脚本生成的 schema 路径清单
|
|
271
|
-
const schemaJson = "./.drizzle-schemas.json";
|
|
272
|
-
const schemas = fs.existsSync(schemaJson)
|
|
273
|
-
? JSON.parse(fs.readFileSync(schemaJson, "utf-8"))
|
|
274
|
-
: ["./src/**/*.schema.ts"];
|
|
275
|
-
|
|
276
|
-
export default defineConfig({
|
|
277
|
-
schema: schemas,
|
|
278
|
-
out: "./drizzle",
|
|
279
|
-
dialect: "sqlite",
|
|
280
|
-
dbCredentials: {
|
|
281
|
-
url: "${config.dbPath}",
|
|
282
|
-
},
|
|
283
|
-
});
|
|
284
|
-
`;
|
|
285
|
-
fs.writeFileSync(drizzleConfigPath, drizzleConfigContent);
|
|
286
|
-
logger.info("✓ drizzle.config.ts 已就绪");
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* 初始化 TypeScript 配置 tsconfig.json
|
|
291
|
-
*/
|
|
292
|
-
export function setupTsConfig(cwd: string) {
|
|
293
|
-
const tsconfigPath = path.join(cwd, "tsconfig.json");
|
|
294
|
-
if (!fs.existsSync(tsconfigPath)) {
|
|
295
|
-
const tsconfigContent = {
|
|
296
|
-
compilerOptions: {
|
|
297
|
-
target: "ESNext",
|
|
298
|
-
module: "CommonJS",
|
|
299
|
-
moduleResolution: "node",
|
|
300
|
-
baseUrl: ".",
|
|
301
|
-
paths: {
|
|
302
|
-
"#/*": ["src/*"],
|
|
303
|
-
},
|
|
304
|
-
strict: true,
|
|
305
|
-
esModuleInterop: true,
|
|
306
|
-
skipLibCheck: true,
|
|
307
|
-
forceConsistentCasingInFileNames: true,
|
|
308
|
-
experimentalDecorators: true,
|
|
309
|
-
emitDecoratorMetadata: true,
|
|
310
|
-
outDir: "dist",
|
|
311
|
-
},
|
|
312
|
-
include: ["src/**/*"],
|
|
313
|
-
exclude: ["node_modules"],
|
|
314
|
-
};
|
|
315
|
-
fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfigContent, null, 2));
|
|
316
|
-
logger.info("✓ tsconfig.json 已就绪");
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* 初始化应用入口 src/app.ts
|
|
322
|
-
*/
|
|
323
|
-
export function setupAppEntry(cwd: string, config: BackendConfig) {
|
|
324
|
-
const appPath = path.join(cwd, "src/app.ts");
|
|
325
|
-
if (!fs.existsSync(appPath)) {
|
|
326
|
-
const appContent = `import { createApp } from "@mindbase/express-common";
|
|
327
|
-
${config.modules.map((module) => "import " + module.name + ' from "' + module.package + '";').join("\n")}
|
|
328
|
-
import config from "./config";
|
|
329
|
-
|
|
330
|
-
async function bootstrap() {
|
|
331
|
-
const app = await createApp(config);
|
|
332
|
-
|
|
333
|
-
// 在此处使用插件或中间件
|
|
334
|
-
${config.modules.map(({ name }) => " app.use(" + name + ")").join("\n")}
|
|
335
|
-
|
|
336
|
-
await app.startup();
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
bootstrap();
|
|
340
|
-
`;
|
|
341
|
-
if (!fs.existsSync(path.join(cwd, "src"))) fs.mkdirSync(path.join(cwd, "src"));
|
|
342
|
-
fs.writeFileSync(appPath, appContent);
|
|
343
|
-
logger.info("✓ src/app.ts 已就绪");
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* 拷贝静态资源
|
|
349
|
-
*/
|
|
350
|
-
export function copyAssets(cwd: string) {
|
|
351
|
-
const ipdbPath = path.join(cwd, "ipipfree.ipdb");
|
|
352
|
-
const sourceIpdb = path.join(__dirname, "..", "assets", "ipipfree.ipdb");
|
|
353
|
-
|
|
354
|
-
if (fs.existsSync(sourceIpdb)) {
|
|
355
|
-
if (!fs.existsSync(ipdbPath)) {
|
|
356
|
-
fs.copyFileSync(sourceIpdb, ipdbPath);
|
|
357
|
-
logger.info("✓ ipipfree.ipdb 已就绪");
|
|
358
|
-
} else {
|
|
359
|
-
logger.info("- ipipfree.ipdb 已存在,跳过拷贝");
|
|
360
|
-
}
|
|
361
|
-
} else {
|
|
362
|
-
logger.warn(`! 未能找到 ipipfree.ipdb 源文件: ${sourceIpdb}`);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* 生成 prepare.js 环境准备脚本
|
|
368
|
-
*/
|
|
369
|
-
export function setupPrepareScript(cwd: string) {
|
|
370
|
-
const preparePath = path.join(cwd, "prepare.js");
|
|
371
|
-
if (!fs.existsSync(preparePath)) {
|
|
372
|
-
const prepareContent = `import { prepare } from '@mindbase/express-common';
|
|
373
|
-
prepare();`;
|
|
374
|
-
fs.writeFileSync(preparePath, prepareContent);
|
|
375
|
-
logger.info("✓ prepare.js 已就绪");
|
|
376
|
-
}
|
|
377
|
-
}
|