Hair Keeper v1.0.0:一个高度集成、深度定制、约定优于配置的全栈Web应用模板,旨在保持灵活性的同时提供一套基于成熟架构的开发底座,自带身份认证、权限控制、丰富前端组件、文件上传、后台任务、智能体开发等丰富功能,提供AI开发辅助,免于纠结功能如何实现,可快速上手专注于业务逻辑

This commit is contained in:
2025-11-13 15:24:54 +08:00
commit 42be39b343
249 changed files with 38843 additions and 0 deletions

1102
prisma/init_data/院系.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,223 @@
-- CreateTable
CREATE TABLE "user" (
"id" TEXT NOT NULL,
"name" TEXT,
"status" TEXT,
"dept_code" TEXT,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL,
"password" TEXT NOT NULL,
"is_super_admin" BOOLEAN NOT NULL DEFAULT false,
"last_login_at" TIMESTAMPTZ,
CONSTRAINT "user_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "dept" (
"code" TEXT NOT NULL,
"name" TEXT NOT NULL DEFAULT '',
"full_name" TEXT NOT NULL DEFAULT '',
CONSTRAINT "dept_pkey" PRIMARY KEY ("code")
);
-- CreateTable
CREATE TABLE "role" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
CONSTRAINT "role_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "permission" (
"id" SERIAL NOT NULL,
"name" TEXT NOT NULL,
CONSTRAINT "permission_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "selection_log" (
"id" SERIAL NOT NULL,
"userId" TEXT NOT NULL,
"context" TEXT NOT NULL,
"option_id" TEXT NOT NULL,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "selection_log_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "dev_file_type" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT NOT NULL,
"order" INTEGER NOT NULL,
CONSTRAINT "dev_file_type_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "dev_pkg_type" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"description" TEXT NOT NULL,
"order" INTEGER NOT NULL,
CONSTRAINT "dev_pkg_type_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "dev_analyzed_file" (
"id" SERIAL NOT NULL,
"path" TEXT NOT NULL,
"fileName" TEXT NOT NULL,
"commit_id" TEXT NOT NULL DEFAULT '',
"content" TEXT,
"file_type_id" TEXT NOT NULL,
"summary" TEXT NOT NULL,
"description" TEXT NOT NULL,
"exportedMembers" JSONB,
"tags" TEXT[],
"lastAnalyzedAt" TIMESTAMPTZ NOT NULL,
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "dev_analyzed_file_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "dev_analyzed_pkg" (
"name" TEXT NOT NULL,
"version" TEXT NOT NULL,
"modifiedAt" TIMESTAMP(3) NOT NULL,
"description" TEXT NOT NULL,
"homepage" TEXT,
"repository_url" TEXT,
"pkg_type_id" TEXT NOT NULL,
"projectRoleSummary" TEXT NOT NULL,
"primaryUsagePattern" TEXT NOT NULL,
"relatedFiles" TEXT[],
"relatedFileCount" INTEGER NOT NULL,
"last_analyzed_at" TIMESTAMPTZ NOT NULL,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "dev_analyzed_pkg_pkey" PRIMARY KEY ("name")
);
-- CreateTable
CREATE TABLE "dev_file_dependency" (
"id" SERIAL NOT NULL,
"source_file_id" INTEGER NOT NULL,
"target_file_path" TEXT NOT NULL,
"usage_description" TEXT,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "dev_file_dependency_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "dev_file_pkg_dependency" (
"id" SERIAL NOT NULL,
"source_file_id" INTEGER NOT NULL,
"package_name" TEXT NOT NULL,
"usage_description" TEXT,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "dev_file_pkg_dependency_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "dev_analyzed_folder" (
"path" TEXT NOT NULL,
"name" TEXT NOT NULL,
"summary" TEXT NOT NULL,
"description" TEXT NOT NULL,
"last_analyzed_at" TIMESTAMPTZ NOT NULL,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "dev_analyzed_folder_pkey" PRIMARY KEY ("path")
);
-- CreateTable
CREATE TABLE "_RoleToUser" (
"A" INTEGER NOT NULL,
"B" TEXT NOT NULL,
CONSTRAINT "_RoleToUser_AB_pkey" PRIMARY KEY ("A","B")
);
-- CreateTable
CREATE TABLE "_PermissionToRole" (
"A" INTEGER NOT NULL,
"B" INTEGER NOT NULL,
CONSTRAINT "_PermissionToRole_AB_pkey" PRIMARY KEY ("A","B")
);
-- CreateIndex
CREATE UNIQUE INDEX "role_name_key" ON "role"("name");
-- CreateIndex
CREATE UNIQUE INDEX "permission_name_key" ON "permission"("name");
-- CreateIndex
CREATE INDEX "selection_log_userId_context_idx" ON "selection_log"("userId", "context");
-- CreateIndex
CREATE INDEX "selection_log_context_option_id_idx" ON "selection_log"("context", "option_id");
-- CreateIndex
CREATE UNIQUE INDEX "dev_analyzed_file_path_commit_id_key" ON "dev_analyzed_file"("path", "commit_id");
-- CreateIndex
CREATE INDEX "dev_analyzed_pkg_pkg_type_id_idx" ON "dev_analyzed_pkg"("pkg_type_id");
-- CreateIndex
CREATE INDEX "dev_file_dependency_target_file_path_idx" ON "dev_file_dependency"("target_file_path");
-- CreateIndex
CREATE UNIQUE INDEX "dev_file_dependency_source_file_id_target_file_path_key" ON "dev_file_dependency"("source_file_id", "target_file_path");
-- CreateIndex
CREATE INDEX "dev_file_pkg_dependency_package_name_idx" ON "dev_file_pkg_dependency"("package_name");
-- CreateIndex
CREATE UNIQUE INDEX "dev_file_pkg_dependency_source_file_id_package_name_key" ON "dev_file_pkg_dependency"("source_file_id", "package_name");
-- CreateIndex
CREATE INDEX "_RoleToUser_B_index" ON "_RoleToUser"("B");
-- CreateIndex
CREATE INDEX "_PermissionToRole_B_index" ON "_PermissionToRole"("B");
-- AddForeignKey
ALTER TABLE "user" ADD CONSTRAINT "user_dept_code_fkey" FOREIGN KEY ("dept_code") REFERENCES "dept"("code") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "selection_log" ADD CONSTRAINT "selection_log_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "dev_analyzed_file" ADD CONSTRAINT "dev_analyzed_file_file_type_id_fkey" FOREIGN KEY ("file_type_id") REFERENCES "dev_file_type"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "dev_analyzed_pkg" ADD CONSTRAINT "dev_analyzed_pkg_pkg_type_id_fkey" FOREIGN KEY ("pkg_type_id") REFERENCES "dev_pkg_type"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "dev_file_dependency" ADD CONSTRAINT "dev_file_dependency_source_file_id_fkey" FOREIGN KEY ("source_file_id") REFERENCES "dev_analyzed_file"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "dev_file_pkg_dependency" ADD CONSTRAINT "dev_file_pkg_dependency_source_file_id_fkey" FOREIGN KEY ("source_file_id") REFERENCES "dev_analyzed_file"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_RoleToUser" ADD CONSTRAINT "_RoleToUser_A_fkey" FOREIGN KEY ("A") REFERENCES "role"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_RoleToUser" ADD CONSTRAINT "_RoleToUser_B_fkey" FOREIGN KEY ("B") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_PermissionToRole" ADD CONSTRAINT "_PermissionToRole_A_fkey" FOREIGN KEY ("A") REFERENCES "permission"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_PermissionToRole" ADD CONSTRAINT "_PermissionToRole_B_fkey" FOREIGN KEY ("B") REFERENCES "role"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -0,0 +1,9 @@
-- CreateTable
CREATE TABLE "kv_config" (
"key" TEXT NOT NULL,
"value" TEXT NOT NULL,
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ NOT NULL,
CONSTRAINT "kv_config_pkey" PRIMARY KEY ("key")
);

View File

@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "postgresql"

243
prisma/schema.prisma Normal file
View File

@@ -0,0 +1,243 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// 用户表
model User {
id String @id
name String?
status String? // 在校/减离/NULL
deptCode String? @map("dept_code") // 所属院系代码(外键)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz
password String
isSuperAdmin Boolean @default(false) @map("is_super_admin")
lastLoginAt DateTime? @map("last_login_at") @db.Timestamptz
// 关联
dept Dept? @relation(fields: [deptCode], references: [code])
roles Role[] // 多对多关联角色
selectionLogs SelectionLog[] // 选择日志
@@map("user")
}
// 院系表
model Dept {
code String @id
name String @default("")
fullName String @default("") @map("full_name")
// 关联
users User[]
@@map("dept")
}
// 角色表
model Role {
id Int @id @default(autoincrement())
name String @unique
users User[] // 多对多关联用户
permissions Permission[] // 多对多关联权限
@@map("role")
}
// 权限表
model Permission {
id Int @id @default(autoincrement())
name String @unique
roles Role[] // 多对多关联角色
@@map("permission")
}
// 选择日志表
model SelectionLog {
id Int @id @default(autoincrement())
userId String // 关联到用户
user User @relation(fields: [userId], references: [id])
// 用于标识是哪个的选项,用.进行分隔,例如"user.filter.dept"
context String
// 关键字段:被选中的选项的值
optionId String @map("option_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
// 建立索引,提升查询性能
@@index([userId, context])
@@index([context, optionId])
@@map("selection_log")
}
// KV配置表 - 用于存储各种键值对配置
model KVConfig {
key String @id // 配置键
value String @db.Text // 配置值
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz
@@map("kv_config")
}
/*********************************************** 仅在开发阶段可用的数据表放在这下面 ***********************************************/
model DevFileType {
id String @id // 文件类型ID如 "COMPONENT_UI"
name String // 文件类型名称,如 "UI组件"
description String // 文件类型描述
order Int // 用来进行排序方便展示
// 关联
files DevAnalyzedFile[]
@@map("dev_file_type")
}
// 依赖包类型表
model DevPkgType {
id String @id // 依赖包类型ID如 "CORE_FRAMEWORK"
name String // 分类名称,如 "核心框架 (Core Framework)"
description String @db.Text // 职责描述
order Int // 用来进行排序方便展示
packages DevAnalyzedPkg[]
@@map("dev_pkg_type")
}
// 分析得到的项目文件信息
model DevAnalyzedFile {
id Int @id @default(autoincrement())
path String // 文件相对路径,如 "src/app/api/trpc/[trpc]/route.ts"
fileName String // 文件名,如 "route.ts"
commitId String @default("") @map("commit_id") // Git commit ID (前7位修改过的文件后面加*)
content String? @db.Text // 文件内容不超过100K的非二进制文件
fileTypeId String @map("file_type_id") // 文件类型ID外键
summary String // 主要功能一句话总结 (LLM生成)
description String // 详细功能描述 (LLM生成)
// 关键代码信息
exportedMembers Json? // 导出的函数、组件、类型、对象、列表、其他 { name, type }[]
// 元数据
tags String[] // 标签 (用于快速筛选和分类)
lastAnalyzedAt DateTime @updatedAt @db.Timestamptz
createdAt DateTime @default(now()) @db.Timestamptz // 创建时间
// 关联
fileType DevFileType @relation(fields: [fileTypeId], references: [id])
dependencies DevFileDependency[] // 该文件依赖的其他文件
pkgDependencies DevFilePkgDependency[] // 该文件依赖的包
// path 和 commitId 构成唯一键
@@unique([path, commitId], name: "uidx_path_commit")
@@map("dev_analyzed_file")
}
// 分析得到的依赖包信息
model DevAnalyzedPkg {
name String @id // 包名,如 '@tanstack/react-table'
// -- 静态信息通过读取node_modules中包的package.json获取内置包则为node的信息
version String // 版本号,如 '8.17.3'
modifiedAt DateTime // 该版本的发布时间,通过命令获取 npm view @tanstack/react-table "time[8.17.3]"
description String @db.Text // 从 package.json 中获取的官方描述
homepage String? // 包的主页URL
repositoryUrl String? @map("repository_url") // 包的仓库URL例如git+https://github.com/shadcn/ui.git
// -- 调用AI获取
pkgTypeId String @map("pkg_type_id") // 依赖包类型ID (外键)
projectRoleSummary String @db.Text // AI总结的该包的核心功能
primaryUsagePattern String @db.Text // AI总结的主要使用模式分成多点描述
// -- 统计获得
relatedFiles String[] // path[] 本次分析中,认为和该库有关联的文件(统计一定引用层数)
relatedFileCount Int // 该包在项目中被多少个文件直接或引用
// --- 时间戳 ---
lastAnalyzedAt DateTime @updatedAt @map("last_analyzed_at") @db.Timestamptz
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
// --- 关联 ---
pkgType DevPkgType @relation(fields: [pkgTypeId], references: [id])
@@index([pkgTypeId])
@@map("dev_analyzed_pkg")
}
// 文件依赖关系表
model DevFileDependency {
id Int @id @default(autoincrement())
sourceFileId Int @map("source_file_id") // 源文件ID依赖方
targetFilePath String @map("target_file_path") // 目标文件路径(被依赖方)
// AI生成的依赖用途描述
usageDescription String? @map("usage_description") @db.Text // 描述该依赖在源文件中的用途
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
// 关联
sourceFile DevAnalyzedFile @relation(fields: [sourceFileId], references: [id], onDelete: Cascade)
// 确保同一个源文件不会重复依赖同一个目标文件
@@unique([sourceFileId, targetFilePath], name: "uidx_source_target")
@@index([targetFilePath]) // 加速按目标文件路径查询
@@map("dev_file_dependency")
}
// 包依赖关系表
model DevFilePkgDependency {
id Int @id @default(autoincrement())
sourceFileId Int @map("source_file_id") // 源文件ID依赖方
packageName String @map("package_name") // 包名(如 'react' 或 '@tanstack/react-table'
// AI生成的依赖用途描述
usageDescription String? @map("usage_description") @db.Text // 描述该包在源文件中的用途和使用的功能
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
// 关联
sourceFile DevAnalyzedFile @relation(fields: [sourceFileId], references: [id], onDelete: Cascade)
// 确保同一个源文件不会重复依赖同一个包
@@unique([sourceFileId, packageName], name: "uidx_source_package")
@@index([packageName]) // 加速按包名查询
@@map("dev_file_pkg_dependency")
}
// 分析得到的项目文件夹信息
model DevAnalyzedFolder {
path String @id // 文件夹相对路径,如 "src/app/api"
name String // 文件夹名,如 "api"
summary String // 主要功能一句话总结 (LLM生成)
description String @db.Text // 详细功能描述 (LLM生成)
// 元数据
lastAnalyzedAt DateTime @updatedAt @map("last_analyzed_at") @db.Timestamptz
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
@@map("dev_analyzed_folder")
}

180
prisma/seed.ts Normal file
View File

@@ -0,0 +1,180 @@
import { PrismaClient } from '@prisma/client'
import bcrypt from 'bcryptjs'
import { Permissions, ALL_PERMISSIONS } from '../src/constants/permissions'
import fs from 'fs'
import path from 'path'
const prisma = new PrismaClient()
// 解析 JSON 文件并导入院系数据
async function importDepartments() {
const jsonPath = path.join(__dirname, 'init_data', '院系.json')
const jsonContent = fs.readFileSync(jsonPath, 'utf-8')
const departments = JSON.parse(jsonContent)
console.log(`开始导入 ${departments.length} 个院系...`)
await Promise.all(
departments.map((dept: any) => {
return prisma.dept.upsert({
where: { code: dept.id },
update: {
name: dept.name,
fullName: dept.full_name,
},
create: {
code: dept.id,
name: dept.name,
fullName: dept.full_name,
},
})
})
)
console.log('院系数据导入完成')
}
async function main() {
console.log('开始数据库初始化...')
// 插入权限
for (const permName of ALL_PERMISSIONS) {
await prisma.permission.upsert({
where: { name: permName },
update: {},
create: { name: permName },
})
}
// 角色与权限映射
const rolePermissionsMap: Record<string, string[]> = {
系统管理员: ALL_PERMISSIONS,
}
// 插入角色
for (const [roleName, perms] of Object.entries(rolePermissionsMap)) {
await prisma.role.upsert({
where: { name: roleName },
update: {},
create: {
name: roleName,
permissions: {
connect: perms.map((name) => ({ name })),
},
},
})
}
await importDepartments()
// 创建测试用户
const usersToCreate = [
{ id: 'user1', name: '用户甲', status: '在校', deptCode: '00001', roleNames: [] },
{ id: 'sys_admin', name: '系统管理员', status: '在校', deptCode: '00001', roleNames: ['系统管理员'] },
{ id: 'super_admin', password: process.env.SUPER_ADMIN_PASSWORD, name: '超级管理员', status: '在校', deptCode: '00001', roleNames: [], isSuperAdmin: true },
{ id: 'unknown', name: '未知用户', status: '在校', deptCode: '00001', roleNames: [] },
]
for (const u of usersToCreate) {
const password = await bcrypt.hash(u.password ?? '123456', 12)
await prisma.user.upsert({
where: { id: u.id },
update: {
name: u.name,
status: u.status,
deptCode: u.deptCode,
password,
isSuperAdmin: u.isSuperAdmin ?? false,
roles: {
set: u.roleNames.map((name) => ({ name })),
},
},
create: {
id: u.id,
name: u.name,
status: u.status,
deptCode: u.deptCode,
password,
isSuperAdmin: u.isSuperAdmin ?? false,
roles: {
connect: u.roleNames.map((name) => ({ name })),
},
},
})
}
// 插入文件类型(仅开发环境)
const fileTypes = [
{ id: 'COMPONENT_UI', name: 'UI组件', description: '使用"use client"不涉及复杂数据获取专注于UI和交互通用性强' },
{ id: 'COMPONENT_FEATURE', name: '业务组件', description: '使用"use client"不涉及复杂数据获取专注于UI和交互与业务关联性强' },
{ id: 'COMPONENT_PAGE', name: '页面组件', description: 'src/app下的page.tsx文件是页面的主入口' },
{ id: 'COMPONENT_LAYOUT', name: '布局组件', description: '不对应某个特定页面的前端组件,例如定义页面布局的文件' },
{ id: 'COMPONENT_REF', name: '组件关联文件', description: '前端组件相关的其他文件例如定义表格列属性的columns.tsx文件' },
{ id: 'API_TRPC', name: 'tRPC API', description: '基于tRPC的API' },
{ id: 'API_NEXT', name: 'NextJS原生API', description: '直接基于NextJS框架构建的API' },
{ id: 'BACKGROUND_JOB', name: '后台任务', description: '执行后台任务的文件(worker/queue)' },
{ id: 'HOOK', name: 'React Hook', description: '文件名以use开头导出自定义React Hook' },
{ id: 'UTIL', name: '工具函数', description: '提供纯函数、常量等通用工具' },
{ id: 'SCHEMA', name: '数据模式', description: '定义数据长什么样的文件,通常用于保证前后端数据的一致性,对数据进行校验' },
{ id: 'STYLES', name: '样式文件', description: '全局或局部样式文件' },
{ id: 'ASSET', name: '资源文件', description: '图片(包括svg)、视频、音频、文本等' },
{ id: 'TYPE_DEFINITION', name: '类型定义', description: '主要用于导出TypeScript类型和常量' },
{ id: 'GENERATE', name: '自动生成', description: '自动生成的文件' },
{ id: 'SCRIPT', name: '脚本文件', description: '独立于项目单独运行的文件例如prisma/seed.ts' },
{ id: 'FRAMEWORK', name: '框架配置', description: '各种前端库约定俗成的配置文件例如schema.prisma' },
{ id: 'CONFIG', name: '项目配置', description: '项目级别的配置文件通常位于项目根目录下例如package.json' },
{ id: 'OTHER', name: '其他', description: '无法归入以上分类的文件' },
]
for (let index = 0; index < fileTypes.length; index++) {
const fileType = fileTypes[index]
await prisma.devFileType.upsert({
where: { id: fileType.id },
update: {
name: fileType.name,
description: fileType.description,
order: (index + 1) * 10,
},
create: {...fileType, order: (index + 1) * 10},
})
}
console.log('文件类型数据初始化完成')
// 插入依赖包类型(仅开发环境)
const pkgTypes = [
{ id: 'CORE_FRAMEWORK', name: '核心框架', description: '构成应用程序骨架的基础技术决定了项目的基本结构和运行方式例如next、react、react-dom、vue、angular、svelte、remix、solid-js、nuxt、gatsby。' },
{ id: 'UI_INTERACTION', name: 'UI & 交互', description: '负责构建用户界面、处理用户交互和视觉呈现的所有库例如radix-ui/react-xxx、shadcn/ui、@dnd-kit/core、@tanstack/react-table、react-hook-form、lucide-react、framer-motion、antd、mui、chakra-ui、bootstrap、tailwindcss、emotion、styled-components、react-select、react-datepicker、react-toastify、react-icons。' },
{ id: 'API_DATA_COMMS', name: 'API & 数据通信', description: '负责前后端数据交换、API定义和请求例如@trpc/server、@trpc/client、@tanstack/react-query、axios、graphql-request、apollo-client、ws。' },
{ id: 'DATA_LAYER', name: '数据层', description: '负责与数据库、缓存、对象存储等进行交互,例如@prisma/client、ioredis、minio、mongoose、typeorm、sequelize、knex、redis、mongodb、pg、mysql、sqlite3、firebase、supabase。' },
{ id: 'BACKGROUND_JOBS', name: '后台任务', description: '用于处理异步、长时间运行或计划任务例如bullmq、agenda、node-cron、bree、bull、kue、bee-queue、sqs-consumer、rabbitmq、bull-board、bull-arena。' },
{ id: 'SECURITY_AUTH', name: '安全 & 认证', description: '负责用户身份验证、授权和数据加密例如next-auth、bcryptjs、jsonwebtoken、passport、oauth2orize、casl、argon2、express-session、helmet、csrf、@auth0/auth0-react。' },
{ id: 'AI_LLM', name: 'AI & 大模型', description: '专门用于与大型语言模型或其他AI服务进行交互例如ai、@ai-sdk/openai、@ai-sdk/anthropic、openai、@huggingface/inference、langchain、replicate、cohere-ai、stability-sdk、transformers、vertex-ai。' },
{ id: 'UTILITIES', name: '通用工具', description: '提供特定功能的辅助函数库如日期处理、状态管理、验证等例如zod、date-fns、nanoid、lodash、ramda、moment、uuid、joi、yup、clsx、tailwind-merge、deepmerge、numeral、dayjs、chalk、debug、dotenv。' },
{ id: 'NODEJS_CORE', name: 'Node.js核心', description: 'Node.js运行时内置的模块用于底层操作如文件系统、路径处理等例如fs、path、child_process、util、module、os、http、crypto、events、stream、process、net、url、assert。' },
]
for (let index = 0; index < pkgTypes.length; index++) {
const pkgType = pkgTypes[index]
await prisma.devPkgType.upsert({
where: { id: pkgType.id },
update: {
name: pkgType.name,
description: pkgType.description,
order: (index + 1) * 10,
},
create: {...pkgType, order: (index + 1) * 10},
})
}
console.log('依赖包类型数据初始化完成')
console.log('数据库初始化完成')
}
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})