DevOS v1 + Phase 2: unified resource model, infra ops, website deployment, AI chat ops

- Monorepo: NestJS API (Fastify) + React web (antd/ProComponents) + shared packages
- PostgreSQL/Prisma (unified resources, relations graph, audit, events, jobs)
- Auth/RBAC/workspace isolation, credential vault (AES-256-GCM)
- Servers/SSH, Docker discovery & lifecycle, Job Center
- Websites & deployments (git provider credential clone, env, health verification)
- Domains/DNS (Cloudflare adapter), certificates (TLS probe), monitoring
- Automation (cron/event/webhook HMAC + notifications), AI Gateway, MCP (29 tools)
- AI chat window (LLM function-calling + rules fallback, SSE streaming, approvals)
- Notes: Vditor WYSIWYG markdown editor, non-blocking autosave
- Tests: 35 unit/security tests; UI audit clean (desktop+mobile, deep links)
This commit is contained in:
phptits
2026-09-10 06:35:55 +00:00
commit 0d6cd37579
209 changed files with 22783 additions and 0 deletions
@@ -0,0 +1,42 @@
/**
* # 事件查询控制器
*/
import { Controller, Get, Query } from "@nestjs/common";
import { z } from "zod";
import { ZodValidationPipe } from "../../common/pipes/zod-validation.pipe";
import { CurrentWorkspace } from "../../common/decorators";
import { PrismaService } from "../../prisma/prisma.service";
import type { RequestWorkspace } from "../../common/decorators";
const ListQuerySchema = z.object({
page: z.coerce.number().int().min(1).default(1),
pageSize: z.coerce.number().int().min(1).max(100).default(20),
eventType: z.string().optional(),
});
@Controller("events")
export class EventController {
constructor(private readonly prisma: PrismaService) {}
/** # 分页查询当前工作区领域事件 */
@Get()
async list(
@CurrentWorkspace() workspace: RequestWorkspace,
@Query(new ZodValidationPipe(ListQuerySchema)) query: z.infer<typeof ListQuerySchema>,
) {
const where = {
workspaceId: workspace.id,
...(query.eventType ? { eventType: query.eventType } : {}),
};
const [total, items] = await this.prisma.$transaction([
this.prisma.eventRecord.count({ where }),
this.prisma.eventRecord.findMany({
where,
orderBy: { createdAt: "desc" },
skip: (query.page - 1) * query.pageSize,
take: query.pageSize,
}),
]);
return { items, total, page: query.page, pageSize: query.pageSize };
}
}