forked from farhoodlabs/paperclip
Add API server with routes, services, and middleware
Express server with CRUD routes for agents, goals, issues, projects, and activity log. Includes validation middleware, structured error handling, request logging, and health check endpoint with tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import { eq, and, desc } from "drizzle-orm";
|
||||
import type { Db } from "@paperclip/db";
|
||||
import { activityLog } from "@paperclip/db";
|
||||
|
||||
export interface ActivityFilters {
|
||||
agentId?: string;
|
||||
entityType?: string;
|
||||
entityId?: string;
|
||||
}
|
||||
|
||||
export function activityService(db: Db) {
|
||||
return {
|
||||
list: (filters?: ActivityFilters) => {
|
||||
const conditions = [];
|
||||
|
||||
if (filters?.agentId) {
|
||||
conditions.push(eq(activityLog.agentId, filters.agentId));
|
||||
}
|
||||
if (filters?.entityType) {
|
||||
conditions.push(eq(activityLog.entityType, filters.entityType));
|
||||
}
|
||||
if (filters?.entityId) {
|
||||
conditions.push(eq(activityLog.entityId, filters.entityId));
|
||||
}
|
||||
|
||||
const query = db.select().from(activityLog);
|
||||
|
||||
if (conditions.length > 0) {
|
||||
return query.where(and(...conditions)).orderBy(desc(activityLog.createdAt));
|
||||
}
|
||||
|
||||
return query.orderBy(desc(activityLog.createdAt));
|
||||
},
|
||||
|
||||
create: (data: typeof activityLog.$inferInsert) =>
|
||||
db
|
||||
.insert(activityLog)
|
||||
.values(data)
|
||||
.returning()
|
||||
.then((rows) => rows[0]),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { Db } from "@paperclip/db";
|
||||
import { agents } from "@paperclip/db";
|
||||
|
||||
export function agentService(db: Db) {
|
||||
return {
|
||||
list: () => db.select().from(agents),
|
||||
|
||||
getById: (id: string) =>
|
||||
db
|
||||
.select()
|
||||
.from(agents)
|
||||
.where(eq(agents.id, id))
|
||||
.then((rows) => rows[0] ?? null),
|
||||
|
||||
create: (data: typeof agents.$inferInsert) =>
|
||||
db
|
||||
.insert(agents)
|
||||
.values(data)
|
||||
.returning()
|
||||
.then((rows) => rows[0]),
|
||||
|
||||
update: (id: string, data: Partial<typeof agents.$inferInsert>) =>
|
||||
db
|
||||
.update(agents)
|
||||
.set({ ...data, updatedAt: new Date() })
|
||||
.where(eq(agents.id, id))
|
||||
.returning()
|
||||
.then((rows) => rows[0] ?? null),
|
||||
|
||||
remove: (id: string) =>
|
||||
db
|
||||
.delete(agents)
|
||||
.where(eq(agents.id, id))
|
||||
.returning()
|
||||
.then((rows) => rows[0] ?? null),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { Db } from "@paperclip/db";
|
||||
import { goals } from "@paperclip/db";
|
||||
|
||||
export function goalService(db: Db) {
|
||||
return {
|
||||
list: () => db.select().from(goals),
|
||||
|
||||
getById: (id: string) =>
|
||||
db
|
||||
.select()
|
||||
.from(goals)
|
||||
.where(eq(goals.id, id))
|
||||
.then((rows) => rows[0] ?? null),
|
||||
|
||||
create: (data: typeof goals.$inferInsert) =>
|
||||
db
|
||||
.insert(goals)
|
||||
.values(data)
|
||||
.returning()
|
||||
.then((rows) => rows[0]),
|
||||
|
||||
update: (id: string, data: Partial<typeof goals.$inferInsert>) =>
|
||||
db
|
||||
.update(goals)
|
||||
.set({ ...data, updatedAt: new Date() })
|
||||
.where(eq(goals.id, id))
|
||||
.returning()
|
||||
.then((rows) => rows[0] ?? null),
|
||||
|
||||
remove: (id: string) =>
|
||||
db
|
||||
.delete(goals)
|
||||
.where(eq(goals.id, id))
|
||||
.returning()
|
||||
.then((rows) => rows[0] ?? null),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export { agentService } from "./agents.js";
|
||||
export { projectService } from "./projects.js";
|
||||
export { issueService } from "./issues.js";
|
||||
export { goalService } from "./goals.js";
|
||||
export { activityService, type ActivityFilters } from "./activity.js";
|
||||
@@ -0,0 +1,38 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { Db } from "@paperclip/db";
|
||||
import { issues } from "@paperclip/db";
|
||||
|
||||
export function issueService(db: Db) {
|
||||
return {
|
||||
list: () => db.select().from(issues),
|
||||
|
||||
getById: (id: string) =>
|
||||
db
|
||||
.select()
|
||||
.from(issues)
|
||||
.where(eq(issues.id, id))
|
||||
.then((rows) => rows[0] ?? null),
|
||||
|
||||
create: (data: typeof issues.$inferInsert) =>
|
||||
db
|
||||
.insert(issues)
|
||||
.values(data)
|
||||
.returning()
|
||||
.then((rows) => rows[0]),
|
||||
|
||||
update: (id: string, data: Partial<typeof issues.$inferInsert>) =>
|
||||
db
|
||||
.update(issues)
|
||||
.set({ ...data, updatedAt: new Date() })
|
||||
.where(eq(issues.id, id))
|
||||
.returning()
|
||||
.then((rows) => rows[0] ?? null),
|
||||
|
||||
remove: (id: string) =>
|
||||
db
|
||||
.delete(issues)
|
||||
.where(eq(issues.id, id))
|
||||
.returning()
|
||||
.then((rows) => rows[0] ?? null),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { Db } from "@paperclip/db";
|
||||
import { projects } from "@paperclip/db";
|
||||
|
||||
export function projectService(db: Db) {
|
||||
return {
|
||||
list: () => db.select().from(projects),
|
||||
|
||||
getById: (id: string) =>
|
||||
db
|
||||
.select()
|
||||
.from(projects)
|
||||
.where(eq(projects.id, id))
|
||||
.then((rows) => rows[0] ?? null),
|
||||
|
||||
create: (data: typeof projects.$inferInsert) =>
|
||||
db
|
||||
.insert(projects)
|
||||
.values(data)
|
||||
.returning()
|
||||
.then((rows) => rows[0]),
|
||||
|
||||
update: (id: string, data: Partial<typeof projects.$inferInsert>) =>
|
||||
db
|
||||
.update(projects)
|
||||
.set({ ...data, updatedAt: new Date() })
|
||||
.where(eq(projects.id, id))
|
||||
.returning()
|
||||
.then((rows) => rows[0] ?? null),
|
||||
|
||||
remove: (id: string) =>
|
||||
db
|
||||
.delete(projects)
|
||||
.where(eq(projects.id, id))
|
||||
.returning()
|
||||
.then((rows) => rows[0] ?? null),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user