MicProtocol / apps /api /dist /chat /internal-realtime.controller.js
Benaah's picture
Upload folder using huggingface_hub
303c85f verified
Raw History Blame Contribute Delete
11.1 kB
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var InternalRealtimeController_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.InternalRealtimeController = void 0;
const common_1 = require("@nestjs/common");
const prisma_service_1 = require("../prisma/prisma.service");
const chat_service_1 = require("./chat.service");
const internal_token_guard_1 = require("../auth/internal-token.guard");
let InternalRealtimeController = InternalRealtimeController_1 = class InternalRealtimeController {
prisma;
chat;
logger = new common_1.Logger(InternalRealtimeController_1.name);
constructor(prisma, chat) {
this.prisma = prisma;
this.chat = chat;
}
async getState(conversationId, workspaceId) {
return this.statePayload(conversationId, workspaceId);
}
async postState(conversationId, workspaceId) {
return this.statePayload(conversationId, workspaceId);
}
async postEvent(conversationId, body) {
const event = body.event;
const evType = String(event?.["eventType"] ?? event?.["type"] ?? "message");
if (evType === "typing")
return { ok: true, skipped: "typing" };
if (evType === "read")
return { ok: true, skipped: "read" };
if (evType === "presence")
return { ok: true, skipped: "presence" };
const seq = Number(event?.["seq"] ?? 0);
const exists = await this.prisma.conversationMessage.findUnique({
where: { conversationId_seq: { conversationId, seq } },
select: { id: true },
});
if (exists)
return { ok: true, skipped: "duplicate" };
const created = await this.prisma.conversationMessage.create({
data: {
conversationId,
userId: event?.["userId"] ?? null,
body: event?.["body"] ?? null,
eventType: evType,
metadata: (event?.["meta"] ?? event?.["metadata"] ?? {}),
seq,
},
});
await this.prisma.conversation.update({
where: { id: conversationId },
data: { lastMessageAt: created.createdAt },
}).catch(() => undefined);
return { ok: true, id: created.id };
}
async recent(conversationId, limitParam) {
const limit = this.parseLimit(limitParam);
const messages = await this.fetchRecent(conversationId, limit);
return { messages, nextCursor: null };
}
async recentPost(conversationId, body) {
const limit = this.parseLimit(body?.limit === undefined ? undefined : String(body.limit));
const messages = await this.fetchRecent(conversationId, limit);
return { messages, nextCursor: null };
}
async getMembers(conversationId) {
const members = (await this.membersPayload(conversationId));
return { members };
}
async addMember(conversationId, body) {
if (!body?.userId)
throw new common_1.BadRequestException("userId required");
const role = body.role ?? "member";
return this.chat.ensureMember(conversationId, body.userId, role);
}
async userConversations(userId) {
const memberships = await this.prisma.conversationMember.findMany({
where: { userId },
select: {
conversation: {
select: { id: true, title: true, lastMessageAt: true },
},
},
orderBy: { joinedAt: "desc" },
take: 100,
});
return {
conversations: memberships.map((m) => m.conversation),
};
}
async getUser(userId) {
const user = await this.prisma.user.findUnique({
where: { id: userId },
select: { id: true, name: true, email: true, image: true },
});
if (!user)
return { user: null };
return { user };
}
async statePayload(conversationId, workspaceId) {
if (!workspaceId) {
throw new common_1.BadRequestException("workspaceId is required");
}
const conv = await this.prisma.conversation.findUnique({
where: { id: conversationId },
include: {
members: true,
messages: {
orderBy: { seq: "desc" },
take: 200,
},
},
});
if (!conv || conv.workspaceId !== workspaceId) {
throw new common_1.UnauthorizedException("conversation unavailable");
}
const recent = conv.messages
.slice()
.reverse()
.map((m) => ({
id: m.id,
userId: m.userId,
conversationId: m.conversationId,
body: m.body,
eventType: m.eventType,
metadata: m.metadata,
seq: m.seq,
at: m.createdAt.toISOString(),
}));
const members = {};
for (const m of conv.members) {
members[m.userId] = {
role: m.role,
lastReadSeq: m.lastReadSeq,
};
}
return { members, recent, sequence: conv.messages[0]?.seq ?? 0 };
}
async fetchRecent(conversationId, limit) {
const rows = await this.prisma.conversationMessage.findMany({
where: { conversationId },
orderBy: { seq: "desc" },
take: limit,
});
return rows
.slice()
.reverse()
.map((m) => ({
id: m.id,
userId: m.userId,
conversationId: m.conversationId,
body: m.body,
eventType: m.eventType,
metadata: m.metadata,
seq: m.seq,
at: m.createdAt.toISOString(),
}));
}
async membersPayload(conversationId) {
const conv = await this.prisma.conversation.findUnique({
where: { id: conversationId },
select: { members: true },
});
const members = {};
for (const m of conv?.members ?? []) {
members[m.userId] = { role: m.role, lastReadSeq: m.lastReadSeq };
}
return members;
}
parseLimit(raw) {
if (raw === undefined || raw === "")
return 50;
const n = Number(raw);
if (!Number.isFinite(n)) {
throw new common_1.BadRequestException("limit must be a number");
}
return Math.min(Math.max(Math.trunc(n), 1), 200);
}
};
exports.InternalRealtimeController = InternalRealtimeController;
__decorate([
(0, common_1.Get)("conversations/:conversationId/state"),
__param(0, (0, common_1.Param)("conversationId")),
__param(1, (0, common_1.Query)("workspaceId")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, String]),
__metadata("design:returntype", Promise)
], InternalRealtimeController.prototype, "getState", null);
__decorate([
(0, common_1.Post)("conversations/:conversationId/state"),
__param(0, (0, common_1.Param)("conversationId")),
__param(1, (0, common_1.Query)("workspaceId")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, String]),
__metadata("design:returntype", Promise)
], InternalRealtimeController.prototype, "postState", null);
__decorate([
(0, common_1.Post)("conversations/:conversationId/events"),
__param(0, (0, common_1.Param)("conversationId")),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", Promise)
], InternalRealtimeController.prototype, "postEvent", null);
__decorate([
(0, common_1.Get)("conversations/:conversationId/recent"),
__param(0, (0, common_1.Param)("conversationId")),
__param(1, (0, common_1.Query)("limit")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, String]),
__metadata("design:returntype", Promise)
], InternalRealtimeController.prototype, "recent", null);
__decorate([
(0, common_1.Post)("conversations/:conversationId/recent"),
__param(0, (0, common_1.Param)("conversationId")),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", Promise)
], InternalRealtimeController.prototype, "recentPost", null);
__decorate([
(0, common_1.Get)("conversations/:conversationId/members"),
__param(0, (0, common_1.Param)("conversationId")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Promise)
], InternalRealtimeController.prototype, "getMembers", null);
__decorate([
(0, common_1.Post)("conversations/:conversationId/members"),
__param(0, (0, common_1.Param)("conversationId")),
__param(1, (0, common_1.Body)()),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, Object]),
__metadata("design:returntype", Promise)
], InternalRealtimeController.prototype, "addMember", null);
__decorate([
(0, common_1.Get)("users/:userId/conversations"),
__param(0, (0, common_1.Param)("userId")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Promise)
], InternalRealtimeController.prototype, "userConversations", null);
__decorate([
(0, common_1.Get)("users/:userId"),
__param(0, (0, common_1.Param)("userId")),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Promise)
], InternalRealtimeController.prototype, "getUser", null);
exports.InternalRealtimeController = InternalRealtimeController = InternalRealtimeController_1 = __decorate([
(0, common_1.Controller)("internal/realtime"),
(0, common_1.UseGuards)(internal_token_guard_1.InternalTokenGuard),
__metadata("design:paramtypes", [prisma_service_1.PrismaService,
chat_service_1.ChatService])
], InternalRealtimeController);
//# sourceMappingURL=internal-realtime.controller.js.map