webpods
Version:
Append-only log service with OAuth authentication
190 lines • 5.83 kB
JavaScript
/**
* Stream operations domain logic
*/
import { isValidStreamId, isSystemStream } from "../utils.js";
import { createLogger } from "../logger.js";
const logger = createLogger("webpods:domain:streams");
/**
* Map database row to domain type
*/
function mapStreamFromDb(row) {
return {
id: row.id,
pod_id: row.pod_id,
stream_id: row.stream_id,
creator_id: row.creator_id,
access_permission: row.access_permission,
metadata: undefined,
created_at: row.created_at,
updated_at: row.created_at,
};
}
/**
* Get or create a stream
*/
export async function getOrCreateStream(db, podId, streamId, userId, accessPermission) {
// Validate stream ID
if (!isValidStreamId(streamId)) {
return {
success: false,
error: {
code: "INVALID_STREAM_ID",
message: "Invalid stream ID",
},
};
}
const actualStreamId = streamId;
try {
// Try to find existing stream
let stream = await db.oneOrNone(`SELECT * FROM stream
WHERE pod_id = $(podId)
AND stream_id = $(streamId)`, { podId, streamId: actualStreamId });
if (stream) {
return {
success: true,
data: { stream: mapStreamFromDb(stream), created: false },
};
}
// Create new stream
stream = await db.one(`INSERT INTO stream (id, pod_id, stream_id, creator_id, access_permission, created_at)
VALUES (gen_random_uuid(), $(podId), $(streamId), $(userId), $(accessPermission), NOW())
RETURNING *`, {
podId,
streamId: actualStreamId,
userId,
accessPermission: accessPermission || "public",
});
logger.info("Stream created", { podId, streamId: actualStreamId, userId });
return {
success: true,
data: { stream: mapStreamFromDb(stream), created: true },
};
}
catch (error) {
logger.error("Failed to get/create stream", { error, podId, streamId });
return {
success: false,
error: {
code: "DATABASE_ERROR",
message: "Failed to get/create stream",
},
};
}
}
/**
* Get stream by pod and stream ID
*/
export async function getStream(db, podId, streamId) {
try {
const stream = await db.oneOrNone(`SELECT * FROM stream
WHERE pod_id = $(podId)
AND stream_id = $(streamId)`, { podId, streamId });
if (!stream) {
return {
success: false,
error: {
code: "STREAM_NOT_FOUND",
message: "Stream not found",
},
};
}
return { success: true, data: mapStreamFromDb(stream) };
}
catch (error) {
logger.error("Failed to get stream", { error, podId, streamId });
return {
success: false,
error: {
code: "DATABASE_ERROR",
message: "Failed to get stream",
},
};
}
}
/**
* Delete a stream
*/
export async function deleteStream(db, podId, streamId, userId) {
// Prevent deletion of system streams
if (isSystemStream(streamId)) {
return {
success: false,
error: {
code: "FORBIDDEN",
message: "System streams cannot be deleted",
},
};
}
try {
const stream = await db.oneOrNone(`SELECT * FROM stream
WHERE pod_id = $(podId)
AND stream_id = $(streamId)`, { podId, streamId });
if (!stream) {
return {
success: false,
error: {
code: "STREAM_NOT_FOUND",
message: "Stream not found",
},
};
}
// Only creator can delete stream
if (stream.creator_id !== userId) {
return {
success: false,
error: {
code: "FORBIDDEN",
message: "Only stream creator can delete stream",
},
};
}
// Delete stream (cascades to records)
await db.none(`DELETE FROM stream WHERE id = $(streamId)`, {
streamId: stream.id,
});
logger.info("Stream deleted", { podId, streamId, userId });
return { success: true, data: undefined };
}
catch (error) {
logger.error("Failed to delete stream", { error, podId, streamId });
return {
success: false,
error: {
code: "DATABASE_ERROR",
message: "Failed to delete stream",
},
};
}
}
/**
* Update stream permissions
*/
export async function updateStreamPermissions(db, streamId, accessPermission) {
try {
const stream = await db.oneOrNone(`UPDATE stream
SET access_permission = COALESCE($(accessPermission), access_permission)
WHERE id = $(streamId)
RETURNING *`, { streamId, accessPermission });
if (!stream) {
return {
success: false,
error: {
code: "STREAM_NOT_FOUND",
message: "Stream not found",
},
};
}
return { success: true, data: mapStreamFromDb(stream) };
}
catch (error) {
logger.error("Failed to update stream permissions", { error, streamId });
return {
success: false,
error: {
code: "DATABASE_ERROR",
message: "Failed to update stream permissions",
},
};
}
}
//# sourceMappingURL=streams.js.map