Release 0.5.8
This commit is contained in:
1 parent
22ae3a68d6
commit
2851c7d936
33 files changed
+1263
-272
No files matched your search
+76
-10
@@ -1,5 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import type Database from 'better-sqlite3';
|
||||
import { createPiece } from './content.js';
|
||||
import { getDatabase } from './database.js';
|
||||
import { detectVideoProvider, type PresentationMode } from './presentation.js';
|
||||
|
||||
@@ -42,6 +43,7 @@ export type PieceUsage = {
|
||||
status: UsageStatus;
|
||||
durationSeconds: number;
|
||||
title: string;
|
||||
outputTitle: string;
|
||||
intro: string;
|
||||
research: string;
|
||||
moderation: string;
|
||||
@@ -129,6 +131,7 @@ export type PieceUsageInput = {
|
||||
|
||||
export type PieceUsageUpdate = {
|
||||
title: string;
|
||||
outputTitle: string;
|
||||
intro: string;
|
||||
research: string;
|
||||
moderation: string;
|
||||
@@ -185,6 +188,7 @@ type UsageRow = {
|
||||
status: UsageStatus;
|
||||
duration_seconds: number;
|
||||
title_snapshot: string;
|
||||
output_title_snapshot: string;
|
||||
intro_snapshot: string;
|
||||
research_snapshot: string;
|
||||
moderation_snapshot: string;
|
||||
@@ -376,6 +380,7 @@ function usageFromRow(row: UsageRow): PieceUsage {
|
||||
status: row.status,
|
||||
durationSeconds: row.duration_seconds,
|
||||
title: row.title_snapshot,
|
||||
outputTitle: row.output_title_snapshot,
|
||||
intro: row.intro_snapshot,
|
||||
research: row.research_snapshot,
|
||||
moderation: row.moderation_snapshot,
|
||||
@@ -478,7 +483,7 @@ export function getShow(id: string): Show | null {
|
||||
const usageRows = database
|
||||
.prepare(
|
||||
`SELECT u.id, u.show_section_id, u.original_piece_id, u.position, u.status,
|
||||
u.duration_seconds, u.title_snapshot, u.intro_snapshot, u.research_snapshot,
|
||||
u.duration_seconds, u.title_snapshot, u.output_title_snapshot, u.intro_snapshot, u.research_snapshot,
|
||||
u.moderation_snapshot, u.transition_snapshot, u.presentation_snapshot,
|
||||
u.presentation_mode_snapshot, u.presentation_source_label_snapshot,
|
||||
u.presentation_source_url_snapshot, u.presentation_source_timecode_snapshot,
|
||||
@@ -805,7 +810,7 @@ export function addPieceUsage(
|
||||
sectionBelongsToShow(database, showId, sectionId, input.sectionId === null);
|
||||
const piece = database
|
||||
.prepare(
|
||||
`SELECT p.title, p.duration_seconds, p.intro, p.research_text, p.moderation_notes,
|
||||
`SELECT p.title, p.output_title, p.duration_seconds, p.intro, p.research_text, p.moderation_notes,
|
||||
p.transition_text, p.presentation_text, p.status, p.presentation_mode,
|
||||
COALESCE(ps.label, '') AS presentation_source_label,
|
||||
COALESCE(ps.url, '') AS presentation_source_url,
|
||||
@@ -818,6 +823,7 @@ export function addPieceUsage(
|
||||
.get(input.pieceId) as
|
||||
| {
|
||||
title: string;
|
||||
output_title: string;
|
||||
duration_seconds: number;
|
||||
intro: string;
|
||||
research_text: string;
|
||||
@@ -849,14 +855,14 @@ export function addPieceUsage(
|
||||
database
|
||||
.prepare(
|
||||
`INSERT INTO piece_usages (id, show_section_id, original_piece_id, position, status,
|
||||
duration_seconds, title_snapshot, intro_snapshot, research_snapshot,
|
||||
duration_seconds, title_snapshot, output_title_snapshot, intro_snapshot, research_snapshot,
|
||||
moderation_snapshot, transition_snapshot, presentation_snapshot,
|
||||
presentation_mode_snapshot, presentation_source_label_snapshot,
|
||||
presentation_source_url_snapshot, presentation_source_timecode_snapshot,
|
||||
presentation_title_meta_snapshot, presentation_description_snapshot,
|
||||
presentation_image_url_snapshot, presentation_site_name_snapshot,
|
||||
presentation_provider_snapshot, presentation_provider_id_snapshot, own_notes, is_reserve)
|
||||
VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '', ?)`
|
||||
VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '', ?)`
|
||||
)
|
||||
.run(
|
||||
id,
|
||||
@@ -865,6 +871,7 @@ export function addPieceUsage(
|
||||
ids.length,
|
||||
piece.duration_seconds,
|
||||
piece.title,
|
||||
piece.output_title,
|
||||
piece.intro,
|
||||
piece.research_text,
|
||||
piece.moderation_notes,
|
||||
@@ -888,6 +895,60 @@ export function addPieceUsage(
|
||||
})();
|
||||
}
|
||||
|
||||
export function createAndAddPieceUsage(
|
||||
showId: string,
|
||||
expectedRevision: number,
|
||||
commandId: string,
|
||||
input: Omit<PieceUsageInput, 'pieceId'> & { title: string; templateId: string }
|
||||
) {
|
||||
if (!commandId || commandId.length > 200) throw new Error('INVALID_COMMAND');
|
||||
const title = cleanText(input.title, 200, 'title', true);
|
||||
const database = getDatabase();
|
||||
return database.transaction(() => {
|
||||
const duplicate = database
|
||||
.prepare(
|
||||
`SELECT piece_id, usage_id, result_revision FROM planning_commands
|
||||
WHERE show_id = ? AND command_id = ?`
|
||||
)
|
||||
.get(showId, commandId) as
|
||||
{ piece_id: string; usage_id: string; result_revision: number } | undefined;
|
||||
if (duplicate) {
|
||||
return {
|
||||
pieceId: duplicate.piece_id,
|
||||
usageId: duplicate.usage_id,
|
||||
revision: duplicate.result_revision,
|
||||
duplicate: true
|
||||
};
|
||||
}
|
||||
|
||||
const pieceId = createPiece(input.templateId || 'blank');
|
||||
database
|
||||
.prepare(
|
||||
`UPDATE pieces SET title = ?, status = 'ready', revision = revision + 1,
|
||||
updated_at_utc = ? WHERE id = ?`
|
||||
)
|
||||
.run(title, new Date().toISOString(), pieceId);
|
||||
const usage = addPieceUsage(showId, expectedRevision, {
|
||||
pieceId,
|
||||
sectionId: input.sectionId,
|
||||
position: input.position
|
||||
});
|
||||
database
|
||||
.prepare(
|
||||
`INSERT INTO planning_commands
|
||||
(show_id, command_id, piece_id, usage_id, result_revision, created_at_utc)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`
|
||||
)
|
||||
.run(showId, commandId, pieceId, usage.id, usage.revision, new Date().toISOString());
|
||||
return {
|
||||
pieceId,
|
||||
usageId: usage.id,
|
||||
revision: usage.revision,
|
||||
duplicate: false
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
export function duplicatePieceUsage(
|
||||
showId: string,
|
||||
usageId: string,
|
||||
@@ -899,7 +960,7 @@ export function duplicatePieceUsage(
|
||||
const sourceSection = usageSection(database, showId, usageId);
|
||||
const source = database
|
||||
.prepare(
|
||||
`SELECT original_piece_id, status, duration_seconds, title_snapshot, intro_snapshot,
|
||||
`SELECT original_piece_id, status, duration_seconds, title_snapshot, output_title_snapshot, intro_snapshot,
|
||||
research_snapshot, moderation_snapshot, transition_snapshot, presentation_snapshot,
|
||||
presentation_mode_snapshot, presentation_source_label_snapshot,
|
||||
presentation_source_url_snapshot, presentation_source_timecode_snapshot,
|
||||
@@ -922,14 +983,14 @@ export function duplicatePieceUsage(
|
||||
database
|
||||
.prepare(
|
||||
`INSERT INTO piece_usages (id, show_section_id, original_piece_id, position, status,
|
||||
duration_seconds, title_snapshot, intro_snapshot, research_snapshot,
|
||||
duration_seconds, title_snapshot, output_title_snapshot, intro_snapshot, research_snapshot,
|
||||
moderation_snapshot, transition_snapshot, presentation_snapshot,
|
||||
presentation_mode_snapshot, presentation_source_label_snapshot,
|
||||
presentation_source_url_snapshot, presentation_source_timecode_snapshot,
|
||||
presentation_title_meta_snapshot, presentation_description_snapshot,
|
||||
presentation_image_url_snapshot, presentation_site_name_snapshot,
|
||||
presentation_provider_snapshot, presentation_provider_id_snapshot, own_notes, is_reserve)
|
||||
VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
VALUES (?, ?, ?, ?, 'open', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
)
|
||||
.run(
|
||||
id,
|
||||
@@ -938,6 +999,7 @@ export function duplicatePieceUsage(
|
||||
ids.length,
|
||||
source.duration_seconds,
|
||||
source.title_snapshot,
|
||||
source.output_title_snapshot,
|
||||
source.intro_snapshot,
|
||||
source.research_snapshot,
|
||||
source.moderation_snapshot,
|
||||
@@ -973,7 +1035,7 @@ export function refreshPieceUsageFromOriginal(
|
||||
usageSection(database, showId, usageId);
|
||||
const source = database
|
||||
.prepare(
|
||||
`SELECT p.title, p.duration_seconds, p.intro, p.research_text,
|
||||
`SELECT p.title, p.output_title, p.duration_seconds, p.intro, p.research_text,
|
||||
p.moderation_notes, p.transition_text, p.presentation_text, p.presentation_mode,
|
||||
COALESCE(ps.label, '') AS presentation_source_label,
|
||||
COALESCE(ps.url, '') AS presentation_source_url,
|
||||
@@ -988,6 +1050,7 @@ export function refreshPieceUsageFromOriginal(
|
||||
.get(usageId) as
|
||||
| {
|
||||
title: string;
|
||||
output_title: string;
|
||||
duration_seconds: number;
|
||||
intro: string;
|
||||
research_text: string;
|
||||
@@ -1009,7 +1072,7 @@ export function refreshPieceUsageFromOriginal(
|
||||
if (!source) throw new Error('ORIGINAL_NOT_FOUND');
|
||||
database
|
||||
.prepare(
|
||||
`UPDATE piece_usages SET title_snapshot = ?, duration_seconds = ?, intro_snapshot = ?,
|
||||
`UPDATE piece_usages SET title_snapshot = ?, output_title_snapshot = ?, duration_seconds = ?, intro_snapshot = ?,
|
||||
research_snapshot = ?, moderation_snapshot = ?, transition_snapshot = ?,
|
||||
presentation_snapshot = ?, presentation_mode_snapshot = ?,
|
||||
presentation_source_label_snapshot = ?, presentation_source_url_snapshot = ?,
|
||||
@@ -1020,6 +1083,7 @@ export function refreshPieceUsageFromOriginal(
|
||||
)
|
||||
.run(
|
||||
source.title,
|
||||
source.output_title,
|
||||
source.duration_seconds,
|
||||
source.intro,
|
||||
source.research_text,
|
||||
@@ -1049,6 +1113,7 @@ export function updatePieceUsage(
|
||||
input: PieceUsageUpdate
|
||||
): MutationResult {
|
||||
const title = cleanText(input.title, 200, 'title', true);
|
||||
const outputTitle = cleanText(input.outputTitle, 300, 'output_title');
|
||||
const duration = validDuration(input.durationSeconds)!;
|
||||
const values = {
|
||||
intro: cleanText(input.intro, 50_000, 'intro'),
|
||||
@@ -1074,7 +1139,7 @@ export function updatePieceUsage(
|
||||
usageSection(database, showId, usageId);
|
||||
database
|
||||
.prepare(
|
||||
`UPDATE piece_usages SET title_snapshot = ?, intro_snapshot = ?, research_snapshot = ?,
|
||||
`UPDATE piece_usages SET title_snapshot = ?, output_title_snapshot = ?, intro_snapshot = ?, research_snapshot = ?,
|
||||
moderation_snapshot = ?, transition_snapshot = ?, presentation_snapshot = ?,
|
||||
presentation_mode_snapshot = ?, presentation_source_label_snapshot = ?,
|
||||
presentation_source_url_snapshot = ?, presentation_source_timecode_snapshot = ?,
|
||||
@@ -1085,6 +1150,7 @@ export function updatePieceUsage(
|
||||
)
|
||||
.run(
|
||||
title,
|
||||
outputTitle,
|
||||
values.intro,
|
||||
values.research,
|
||||
values.moderation,
|
||||
|
||||
Reference in new issue
Block a user