feat: How to create a session

This commit is contained in:
Wanjohi
2025-11-04 00:09:31 +03:00
parent 6947230a1d
commit 86959f93d9
4 changed files with 104 additions and 27 deletions

Binary file not shown.

View File

@@ -1,5 +1,7 @@
import { z } from "zod/v4"; import { z } from "zod/v4";
import { fn } from "../utils/fn.js"; import { fn } from "../utils/fn.js";
import { Identifier } from "../id.js";
import { and, eq, isNull } from "drizzle-orm";
import { sessionTable } from "./session.sql.js"; import { sessionTable } from "./session.sql.js";
import { import {
MachinePresetName, MachinePresetName,
@@ -12,6 +14,8 @@ import {
type Session as SessionInterface, type Session as SessionInterface,
type Config as SessionConfig, type Config as SessionConfig,
} from "./types.js"; } from "./types.js";
import { Actor } from "../actor.js";
import { Database } from "../drizzle/index.js";
// Re-export all types and schemas from types.ts // Re-export all types and schemas from types.ts
export { export {
@@ -49,9 +53,43 @@ export namespace Session {
run: (ctx: any) => Promise<any>; run: (ctx: any) => Promise<any>;
}; };
export const list = fn(z.void(), () => { export const create = fn(Info.partial({ id: true }), (input) =>
// Placeholder implementation Database.transaction(async (tx) => {
}); const id = Identifier.descending("session", input.id); // Placeholder for Identifier.ascending
await tx
.insert(sessionTable)
.values({
id,
ownerID: Actor.userID(),
...input,
})
.onConflictDoUpdate({
target: sessionTable.id,
set: {
timeDeleted: null,
},
});
return id;
}),
);
export const list = fn(z.void(), () =>
Database.use((tx) =>
tx
.select()
.from(sessionTable)
.where(
and(
eq(sessionTable.ownerID, Actor.userID()),
isNull(sessionTable.timeDeleted),
),
)
.limit(100)
.then((rows) => rows.map(serialize)),
),
);
export function serialize( export function serialize(
input: typeof sessionTable.$inferSelect, input: typeof sessionTable.$inferSelect,

View File

@@ -1,4 +1,4 @@
import { id, timestamps } from "../drizzle/types.js"; import { id, timestamps, ulid } from "../drizzle/types.js";
import { import {
pgTable, pgTable,
varchar, varchar,
@@ -20,11 +20,17 @@ import {
AudioRateControl, AudioRateControl,
VideoBitDepth, VideoBitDepth,
} from "./types.js"; } from "./types.js";
import { userTable } from "../user/user.sql.js";
export const sessionTable = pgTable("sessions", { export const sessionTable = pgTable("sessions", {
...id, ...id,
...timestamps, ...timestamps,
description: text("description"), description: text("description"),
ownerID: ulid("owner_id")
.references(() => userTable.id, {
onDelete: "cascade",
})
.notNull(),
retry: jsonb("retry").$type<RetryOptions>(), retry: jsonb("retry").$type<RetryOptions>(),
queue: jsonb("queue").$type<Queue>(), queue: jsonb("queue").$type<Queue>(),
machine: varchar("machine", { length: 200 }).$type<MachinePresetName>(), machine: varchar("machine", { length: 200 }).$type<MachinePresetName>(),

View File

@@ -2,33 +2,66 @@ import { Hono } from "hono";
import { notPublic } from "../utils/auth.js"; import { notPublic } from "../utils/auth.js";
import { ErrorResponses } from "../utils/error.js"; import { ErrorResponses } from "../utils/error.js";
import { Session } from "@nestri/core/session/index"; import { Session } from "@nestri/core/session/index";
import { describeRoute, resolver } from "hono-openapi"; import { describeRoute, resolver, validator } from "hono-openapi";
export namespace SessionRoute { export namespace SessionRoute {
export const route = new Hono().use(notPublic).get( export const route = new Hono()
"/", .use(notPublic)
describeRoute({ .get(
tags: ["Session"], "/",
operationId: "session.list", describeRoute({
summary: "List all active sessions", tags: ["Session"],
description: "List all the current user's active sessions", operationId: "session.list",
responses: { summary: "List all sessions",
200: { description: "List all the current user's sessions",
description: "List of sessions", responses: {
content: { 200: {
"application/json": { description: "List of sessions",
schema: resolver(Session.Info.array()), content: {
"application/json": {
schema: resolver(Session.Info.array()),
},
}, },
}, },
401: ErrorResponses[401],
403: ErrorResponses[403],
429: ErrorResponses[429],
}, },
401: ErrorResponses[401], }),
403: ErrorResponses[403], async (c) => {
429: ErrorResponses[429], const sessions = await Session.list();
return c.json(sessions);
}, },
}), )
async (c) => { .post(
const sessions = await Session.list(); "/",
return c.json(sessions); describeRoute({
}, tags: ["Session"],
); operationId: "session.create",
summary: "Create a new session",
description: "Create a new session for the current user",
responses: {
201: {
description: "The created session",
content: {
"application/json": {
schema: resolver(Session.Info),
},
},
},
400: ErrorResponses[400],
401: ErrorResponses[401],
403: ErrorResponses[403],
429: ErrorResponses[429],
},
}),
validator("json", Session.Info.omit({ id: true })),
async (c) => {
const sessionData = c.req.valid("json");
const id = await Session.create(sessionData);
return c.json({ ...sessionData, id }, 201);
},
);
} }