feat: 完成 B 群組 — 資料層與核心領域模型
- 導入 Prisma 7.9.1 + SQLite(better-sqlite3 driver adapter),prisma.config.ts 管理連線設定 - 完整資料模型:User/Work/Character/CharacterAlias/EpisodicMemory/SemanticMemory/ ProceduralRule/EmotionState/Relationship/SentimentLedgerEntry - packages/db:Prisma Client 存取層(ESM,因 Prisma 7 產出的 generated client 僅支援 ESM) - apps/api 隨之改為 ESM 以相容 packages/db - packages/shared:新增角色/記憶/情緒/關係共用型別,api 與 web 皆從此匯入 - prisma/seed.ts:建立測試使用者與元氣型測試角色,含完整關係帳本與記憶種子資料 - apps/api:新增 GET /characters - scripts/smoke/B.mjs:驗證資料表齊全、API 讀出種子角色、關係與記憶可寫入讀出 - 保留 Prisma 官方隨 CLI 附的 agent skill 文件(.agents/skills 等),供後續群組查閱 npm run restart && npm run smoke -- B 皆通過(B-V),A 群組冒煙測試無回歸。
This commit is contained in:
@@ -3,15 +3,19 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "心音後端服務(NestJS)",
|
||||
"type": "module",
|
||||
"main": "dist/main.js",
|
||||
"scripts": {
|
||||
"build": "tsc -b",
|
||||
"start": "node dist/main.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@kokorone/db": "*",
|
||||
"@kokorone/shared": "*",
|
||||
"@nestjs/common": "^11.1.29",
|
||||
"@nestjs/core": "^11.1.29",
|
||||
"@nestjs/platform-express": "^11.1.29",
|
||||
"dotenv": "^17.4.2",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.2"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { HealthController } from "./health/health.controller.js";
|
||||
import { CharactersModule } from "./characters/characters.module.js";
|
||||
|
||||
@Module({
|
||||
imports: [CharactersModule],
|
||||
controllers: [HealthController],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Controller, Get } from "@nestjs/common";
|
||||
import { CharactersService } from "./characters.service.js";
|
||||
|
||||
@Controller("characters")
|
||||
export class CharactersController {
|
||||
constructor(private readonly charactersService: CharactersService) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.charactersService.findAll();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { PrismaModule } from "../prisma/prisma.module.js";
|
||||
import { CharactersController } from "./characters.controller.js";
|
||||
import { CharactersService } from "./characters.service.js";
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule],
|
||||
controllers: [CharactersController],
|
||||
providers: [CharactersService],
|
||||
})
|
||||
export class CharactersModule {}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import type { Character } from "@kokorone/shared";
|
||||
import { PrismaService } from "../prisma/prisma.service.js";
|
||||
|
||||
@Injectable()
|
||||
export class CharactersService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async findAll(): Promise<Character[]> {
|
||||
const rows = await this.prisma.client.character.findMany({
|
||||
include: { aliases: true },
|
||||
orderBy: { createdAt: "asc" },
|
||||
});
|
||||
|
||||
return rows.map((row) => ({
|
||||
id: row.id,
|
||||
workId: row.workId,
|
||||
source: row.source,
|
||||
buildStatus: row.buildStatus,
|
||||
basicInfo: row.basicInfo,
|
||||
backgroundStory: row.backgroundStory,
|
||||
personalityArchetype: row.personalityArchetype,
|
||||
likesDislikes: row.likesDislikes,
|
||||
goalsObsessions: row.goalsObsessions,
|
||||
speechStyle: row.speechStyle,
|
||||
initialRelationValue: row.initialRelationValue,
|
||||
createdAt: row.createdAt.toISOString(),
|
||||
updatedAt: row.updatedAt.toISOString(),
|
||||
aliases: row.aliases.map((alias) => ({
|
||||
id: alias.id,
|
||||
formalName: alias.formalName,
|
||||
nickname: alias.nickname,
|
||||
calledByOthers: alias.calledByOthers,
|
||||
})),
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import "dotenv/config";
|
||||
import "reflect-metadata";
|
||||
import { NestFactory } from "@nestjs/core";
|
||||
import { log } from "@kokorone/shared";
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { PrismaService } from "./prisma.service.js";
|
||||
|
||||
@Module({
|
||||
providers: [PrismaService],
|
||||
exports: [PrismaService],
|
||||
})
|
||||
export class PrismaModule {}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Injectable, OnModuleDestroy } from "@nestjs/common";
|
||||
import { createPrismaClient } from "@kokorone/db";
|
||||
|
||||
@Injectable()
|
||||
export class PrismaService implements OnModuleDestroy {
|
||||
readonly client = createPrismaClient();
|
||||
|
||||
onModuleDestroy() {
|
||||
return this.client.$disconnect();
|
||||
}
|
||||
}
|
||||
@@ -7,5 +7,5 @@
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "../../packages/shared" }]
|
||||
"references": [{ "path": "../../packages/shared" }, { "path": "../../packages/db" }]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
export type {
|
||||
Character,
|
||||
CharacterAlias,
|
||||
CharacterSource,
|
||||
CharacterBuildStatus,
|
||||
EpisodicMemory,
|
||||
SemanticMemory,
|
||||
ProceduralRule,
|
||||
EmotionTag,
|
||||
MemorySource,
|
||||
EmotionState,
|
||||
Relationship,
|
||||
RelationshipStage,
|
||||
SentimentLedgerEntry,
|
||||
} from "@kokorone/shared";
|
||||
@@ -9,6 +9,7 @@
|
||||
"lint": "eslint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@kokorone/shared": "*",
|
||||
"next": "16.3.0",
|
||||
"react": "19.2.8",
|
||||
"react-dom": "19.2.8"
|
||||
|
||||
Reference in New Issue
Block a user