Add activity publish endpoint with fanout to notifications
cgen-aea33da03626496a99135dadf96346ad
This commit is contained in:
parent
bc056f211a
commit
1d756ebd62
1 changed files with 62 additions and 0 deletions
|
|
@ -896,6 +896,68 @@ export function createServer() {
|
|||
}
|
||||
});
|
||||
|
||||
// Activity bus: publish event and fanout notifications
|
||||
app.post("/api/activity/publish", async (req, res) => {
|
||||
const {
|
||||
actor_id,
|
||||
verb,
|
||||
object_type,
|
||||
object_id,
|
||||
target_user_ids,
|
||||
target_team_id,
|
||||
target_project_id,
|
||||
metadata,
|
||||
} = (req.body || {}) as any;
|
||||
if (!actor_id || !verb || !object_type) {
|
||||
return res.status(400).json({ error: "actor_id, verb, object_type required" });
|
||||
}
|
||||
try {
|
||||
const { data: eventRow, error: evErr } = await adminSupabase
|
||||
.from("activity_events")
|
||||
.insert({ actor_id, verb, object_type, object_id: object_id || null, target_id: target_team_id || target_project_id || null, metadata: metadata || null } as any)
|
||||
.select()
|
||||
.single();
|
||||
if (evErr) return res.status(500).json({ error: evErr.message });
|
||||
|
||||
const notify = async (userId: string, title: string, message?: string) => {
|
||||
await adminSupabase.from("notifications").insert({ user_id: userId, type: "info", title, message: message || null });
|
||||
};
|
||||
|
||||
// Notify explicit targets
|
||||
if (Array.isArray(target_user_ids) && target_user_ids.length) {
|
||||
for (const uid of target_user_ids) {
|
||||
await notify(uid, `${verb} · ${object_type}`, (metadata && metadata.summary) || null);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify team members if provided
|
||||
if (target_team_id) {
|
||||
const { data: members } = await adminSupabase
|
||||
.from("team_memberships")
|
||||
.select("user_id")
|
||||
.eq("team_id", target_team_id);
|
||||
for (const m of (members || [])) {
|
||||
await notify((m as any).user_id, `${verb} · ${object_type}`, (metadata && metadata.summary) || null);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify project members if provided
|
||||
if (target_project_id) {
|
||||
const { data: members } = await adminSupabase
|
||||
.from("project_members")
|
||||
.select("user_id")
|
||||
.eq("project_id", target_project_id);
|
||||
for (const m of (members || [])) {
|
||||
await notify((m as any).user_id, `${verb} · ${object_type}`, (metadata && metadata.summary) || null);
|
||||
}
|
||||
}
|
||||
|
||||
return res.json({ ok: true, event: eventRow });
|
||||
} catch (e: any) {
|
||||
return res.status(500).json({ error: e?.message || String(e) });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/rewards/apply", async (req, res) => {
|
||||
const { user_id, action, amount } = (req.body || {}) as {
|
||||
user_id?: string;
|
||||
|
|
|
|||
Loading…
Reference in a new issue