mirror of
https://github.com/Dictionarry-Hub/profilarr.git
synced 2026-02-01 07:10:47 +01:00
refactor(pcd): reorganize delayProfiles to CRUD pattern
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
|
||||
import type { PCDCache } from '../../cache.ts';
|
||||
import { writeOperation, type OperationLayer } from '../../writer.ts';
|
||||
import type { PreferredProtocol } from './types.ts';
|
||||
import type { PreferredProtocol } from '$shared/pcd/display.ts';
|
||||
|
||||
export interface CreateDelayProfileInput {
|
||||
interface CreateDelayProfileInput {
|
||||
name: string;
|
||||
preferredProtocol: PreferredProtocol;
|
||||
usenetDelay: number;
|
||||
@@ -16,7 +16,7 @@ export interface CreateDelayProfileInput {
|
||||
minimumCfScore: number;
|
||||
}
|
||||
|
||||
export interface CreateDelayProfileOptions {
|
||||
interface CreateDelayProfileOptions {
|
||||
databaseId: number;
|
||||
cache: PCDCache;
|
||||
layer: OperationLayer;
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
|
||||
import type { PCDCache } from '../../cache.ts';
|
||||
import { writeOperation, type OperationLayer } from '../../writer.ts';
|
||||
import type { DelayProfileTableRow } from './types.ts';
|
||||
import type { DelayProfilesRow } from '$shared/pcd/display.ts';
|
||||
|
||||
export interface DeleteDelayProfileOptions {
|
||||
interface DeleteDelayProfileOptions {
|
||||
databaseId: number;
|
||||
cache: PCDCache;
|
||||
layer: OperationLayer;
|
||||
/** The current profile data (for value guards) */
|
||||
current: DelayProfileTableRow;
|
||||
current: DelayProfilesRow;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* Get a single delay profile by ID
|
||||
*/
|
||||
|
||||
import type { PCDCache } from '../../cache.ts';
|
||||
import type { DelayProfileTableRow, PreferredProtocol } from './types.ts';
|
||||
|
||||
/**
|
||||
* Get a single delay profile by ID with all data
|
||||
*/
|
||||
export async function get(cache: PCDCache, id: number): Promise<DelayProfileTableRow | null> {
|
||||
const db = cache.kb;
|
||||
|
||||
const profile = await db
|
||||
.selectFrom('delay_profiles')
|
||||
.select([
|
||||
'id',
|
||||
'name',
|
||||
'preferred_protocol',
|
||||
'usenet_delay',
|
||||
'torrent_delay',
|
||||
'bypass_if_highest_quality',
|
||||
'bypass_if_above_custom_format_score',
|
||||
'minimum_custom_format_score',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
])
|
||||
.where('id', '=', id)
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!profile) return null;
|
||||
|
||||
return {
|
||||
id: profile.id,
|
||||
name: profile.name,
|
||||
preferred_protocol: profile.preferred_protocol as PreferredProtocol,
|
||||
usenet_delay: profile.usenet_delay,
|
||||
torrent_delay: profile.torrent_delay,
|
||||
bypass_if_highest_quality: profile.bypass_if_highest_quality === 1,
|
||||
bypass_if_above_custom_format_score: profile.bypass_if_above_custom_format_score === 1,
|
||||
minimum_custom_format_score: profile.minimum_custom_format_score,
|
||||
created_at: profile.created_at,
|
||||
updated_at: profile.updated_at
|
||||
};
|
||||
}
|
||||
@@ -1,17 +1,15 @@
|
||||
/**
|
||||
* Delay Profile queries and mutations
|
||||
* Delay Profile CRUD operations
|
||||
*/
|
||||
|
||||
// Export all types
|
||||
export type { DelayProfileTableRow, PreferredProtocol } from './types.ts';
|
||||
export type { CreateDelayProfileInput } from './create.ts';
|
||||
export type { UpdateDelayProfileInput } from './update.ts';
|
||||
// Read
|
||||
export { list, get } from './read.ts';
|
||||
|
||||
// Export query functions
|
||||
export { list } from './list.ts';
|
||||
export { get } from './get.ts';
|
||||
|
||||
// Export mutation functions
|
||||
// Create
|
||||
export { create } from './create.ts';
|
||||
|
||||
// Update
|
||||
export { update } from './update.ts';
|
||||
|
||||
// Delete
|
||||
export { remove } from './delete.ts';
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/**
|
||||
* Delay profile list queries
|
||||
*/
|
||||
|
||||
import type { PCDCache } from '../../cache.ts';
|
||||
import type { DelayProfileTableRow, PreferredProtocol } from './types.ts';
|
||||
|
||||
/**
|
||||
* Get delay profiles with full data for table/card views
|
||||
*/
|
||||
export async function list(cache: PCDCache): Promise<DelayProfileTableRow[]> {
|
||||
const db = cache.kb;
|
||||
|
||||
const profiles = await db
|
||||
.selectFrom('delay_profiles')
|
||||
.select([
|
||||
'id',
|
||||
'name',
|
||||
'preferred_protocol',
|
||||
'usenet_delay',
|
||||
'torrent_delay',
|
||||
'bypass_if_highest_quality',
|
||||
'bypass_if_above_custom_format_score',
|
||||
'minimum_custom_format_score',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
])
|
||||
.orderBy('name')
|
||||
.execute();
|
||||
|
||||
return profiles.map((profile) => ({
|
||||
id: profile.id,
|
||||
name: profile.name,
|
||||
preferred_protocol: profile.preferred_protocol as PreferredProtocol,
|
||||
usenet_delay: profile.usenet_delay,
|
||||
torrent_delay: profile.torrent_delay,
|
||||
bypass_if_highest_quality: profile.bypass_if_highest_quality === 1,
|
||||
bypass_if_above_custom_format_score: profile.bypass_if_above_custom_format_score === 1,
|
||||
minimum_custom_format_score: profile.minimum_custom_format_score,
|
||||
created_at: profile.created_at,
|
||||
updated_at: profile.updated_at
|
||||
}));
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
/**
|
||||
* Delay Profile mutations - re-exports for cleaner imports
|
||||
*/
|
||||
|
||||
export { create, type CreateDelayProfileInput, type CreateDelayProfileOptions } from './create.ts';
|
||||
export { update, type UpdateDelayProfileInput, type UpdateDelayProfileOptions } from './update.ts';
|
||||
export { remove, type DeleteDelayProfileOptions } from './delete.ts';
|
||||
94
src/lib/server/pcd/queries/delayProfiles/read.ts
Normal file
94
src/lib/server/pcd/queries/delayProfiles/read.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Delay profile read operations
|
||||
*/
|
||||
|
||||
/**
|
||||
* Delay profile read operations
|
||||
*/
|
||||
|
||||
import type { PCDCache } from '../../cache.ts';
|
||||
import type { DelayProfilesRow, PreferredProtocol } from '$shared/pcd/display.ts';
|
||||
|
||||
/**
|
||||
* Convert a database row to DelayProfilesRow with boolean conversion.
|
||||
* SQLite returns 0/1 for booleans, we convert to true/false.
|
||||
*/
|
||||
function toDelayProfile(row: {
|
||||
id: number;
|
||||
name: string;
|
||||
preferred_protocol: string;
|
||||
usenet_delay: number | null;
|
||||
torrent_delay: number | null;
|
||||
bypass_if_highest_quality: number;
|
||||
bypass_if_above_custom_format_score: number;
|
||||
minimum_custom_format_score: number | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}): DelayProfilesRow {
|
||||
return {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
preferred_protocol: row.preferred_protocol as PreferredProtocol,
|
||||
usenet_delay: row.usenet_delay,
|
||||
torrent_delay: row.torrent_delay,
|
||||
bypass_if_highest_quality: row.bypass_if_highest_quality === 1,
|
||||
bypass_if_above_custom_format_score: row.bypass_if_above_custom_format_score === 1,
|
||||
minimum_custom_format_score: row.minimum_custom_format_score,
|
||||
created_at: row.created_at,
|
||||
updated_at: row.updated_at
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all delay profiles ordered by name
|
||||
*/
|
||||
export async function list(cache: PCDCache): Promise<DelayProfilesRow[]> {
|
||||
const db = cache.kb;
|
||||
|
||||
const profiles = await db
|
||||
.selectFrom('delay_profiles')
|
||||
.select([
|
||||
'id',
|
||||
'name',
|
||||
'preferred_protocol',
|
||||
'usenet_delay',
|
||||
'torrent_delay',
|
||||
'bypass_if_highest_quality',
|
||||
'bypass_if_above_custom_format_score',
|
||||
'minimum_custom_format_score',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
])
|
||||
.orderBy('name')
|
||||
.execute();
|
||||
|
||||
return profiles.map(toDelayProfile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single delay profile by ID
|
||||
*/
|
||||
export async function get(cache: PCDCache, id: number): Promise<DelayProfilesRow | null> {
|
||||
const db = cache.kb;
|
||||
|
||||
const profile = await db
|
||||
.selectFrom('delay_profiles')
|
||||
.select([
|
||||
'id',
|
||||
'name',
|
||||
'preferred_protocol',
|
||||
'usenet_delay',
|
||||
'torrent_delay',
|
||||
'bypass_if_highest_quality',
|
||||
'bypass_if_above_custom_format_score',
|
||||
'minimum_custom_format_score',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
])
|
||||
.where('id', '=', id)
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!profile) return null;
|
||||
|
||||
return toDelayProfile(profile);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Delay Profile query-specific types
|
||||
*/
|
||||
|
||||
/** Preferred protocol options */
|
||||
export type PreferredProtocol = 'prefer_usenet' | 'prefer_torrent' | 'only_usenet' | 'only_torrent';
|
||||
|
||||
/** Delay profile data for table/card views */
|
||||
export interface DelayProfileTableRow {
|
||||
id: number;
|
||||
name: string;
|
||||
preferred_protocol: PreferredProtocol;
|
||||
usenet_delay: number | null;
|
||||
torrent_delay: number | null;
|
||||
bypass_if_highest_quality: boolean;
|
||||
bypass_if_above_custom_format_score: boolean;
|
||||
minimum_custom_format_score: number | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
import type { PCDCache } from '../../cache.ts';
|
||||
import { writeOperation, type OperationLayer } from '../../writer.ts';
|
||||
import type { PreferredProtocol, DelayProfileTableRow } from './types.ts';
|
||||
import type { DelayProfilesRow, PreferredProtocol } from '$shared/pcd/display.ts';
|
||||
import { logger } from '$logger/logger.ts';
|
||||
|
||||
export interface UpdateDelayProfileInput {
|
||||
interface UpdateDelayProfileInput {
|
||||
name: string;
|
||||
preferredProtocol: PreferredProtocol;
|
||||
usenetDelay: number;
|
||||
@@ -17,12 +17,12 @@ export interface UpdateDelayProfileInput {
|
||||
minimumCfScore: number;
|
||||
}
|
||||
|
||||
export interface UpdateDelayProfileOptions {
|
||||
interface UpdateDelayProfileOptions {
|
||||
databaseId: number;
|
||||
cache: PCDCache;
|
||||
layer: OperationLayer;
|
||||
/** The current profile data (for value guards) */
|
||||
current: DelayProfileTableRow;
|
||||
current: DelayProfilesRow;
|
||||
/** The new values */
|
||||
input: UpdateDelayProfileInput;
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
import { BaseSyncer, type SyncResult } from '../base.ts';
|
||||
import { arrSyncQueries } from '$db/queries/arrSync.ts';
|
||||
import { getCache } from '$pcd/cache.ts';
|
||||
import { get as getDelayProfile } from '$pcd/queries/delayProfiles/get.ts';
|
||||
import type { DelayProfileTableRow } from '$pcd/queries/delayProfiles/types.ts';
|
||||
import { get as getDelayProfile } from '$pcd/queries/delayProfiles/index.ts';
|
||||
import type { DelayProfilesRow } from '$shared/pcd/display.ts';
|
||||
import type { ArrDelayProfile } from '$arr/types.ts';
|
||||
import { logger } from '$logger/logger.ts';
|
||||
|
||||
@@ -66,7 +66,7 @@ export class DelayProfileSyncer extends BaseSyncer {
|
||||
return { success: true, itemsSynced: 1 };
|
||||
}
|
||||
|
||||
private transform(profile: DelayProfileTableRow): ArrDelayProfile {
|
||||
private transform(profile: DelayProfilesRow): ArrDelayProfile {
|
||||
let enableUsenet = true;
|
||||
let enableTorrent = true;
|
||||
let preferredProtocol = 'usenet';
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/**
|
||||
* PCD Display Types
|
||||
*
|
||||
* Types for query results that include JOINed data.
|
||||
* These extend the generated Row types with related entities.
|
||||
* Types for query results that include JOINed data or need semantic naming.
|
||||
* Simple aliases to generated Row types are provided for cleaner API.
|
||||
*/
|
||||
|
||||
import type { RegularExpressionsRow } from './types.ts';
|
||||
import type { DelayProfilesRow } from './types.ts';
|
||||
|
||||
// ============================================================================
|
||||
// COMMON
|
||||
@@ -25,3 +26,14 @@ export interface Tag {
|
||||
export type RegularExpressionWithTags = RegularExpressionsRow & {
|
||||
tags: Tag[];
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// DELAY PROFILES
|
||||
// ============================================================================
|
||||
// No JOINs needed - the generated Row type is already semantic (booleans, unions).
|
||||
// Re-exported here for consistent import pattern across all entities.
|
||||
|
||||
export type { DelayProfilesRow } from './types.ts';
|
||||
|
||||
/** Preferred protocol options - extracted for use in mutations */
|
||||
export type PreferredProtocol = DelayProfilesRow['preferred_protocol'];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { DelayProfileTableRow } from '$pcd/queries/delayProfiles/types.ts';
|
||||
import type { DelayProfilesRow } from '$shared/pcd/display.ts';
|
||||
import IconCheckbox from '$ui/form/IconCheckbox.svelte';
|
||||
import SyncFooter from './SyncFooter.svelte';
|
||||
import { Check } from 'lucide-svelte';
|
||||
@@ -8,7 +8,7 @@
|
||||
interface DatabaseWithProfiles {
|
||||
id: number;
|
||||
name: string;
|
||||
delayProfiles: DelayProfileTableRow[];
|
||||
delayProfiles: DelayProfilesRow[];
|
||||
}
|
||||
|
||||
export let databases: DatabaseWithProfiles[];
|
||||
|
||||
@@ -4,7 +4,7 @@ import { pcdManager } from '$pcd/pcd.ts';
|
||||
import { canWriteToBase } from '$pcd/writer.ts';
|
||||
import * as delayProfileQueries from '$pcd/queries/delayProfiles/index.ts';
|
||||
import type { OperationLayer } from '$pcd/writer.ts';
|
||||
import type { PreferredProtocol } from '$pcd/queries/delayProfiles/index.ts';
|
||||
import type { PreferredProtocol } from '$shared/pcd/display.ts';
|
||||
import { logger } from '$logger/logger.ts';
|
||||
|
||||
export const load: ServerLoad = async ({ params }) => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import SaveTargetModal from '$ui/modal/SaveTargetModal.svelte';
|
||||
import { alertStore } from '$alerts/store';
|
||||
import { Check, Save, Trash2, Loader2 } from 'lucide-svelte';
|
||||
import type { PreferredProtocol } from '$pcd/queries/delayProfiles';
|
||||
import type { PreferredProtocol } from '$shared/pcd/display.ts';
|
||||
import { current, isDirty, initEdit, initCreate, update } from '$lib/client/stores/dirty';
|
||||
|
||||
// Form data shape
|
||||
|
||||
@@ -4,7 +4,7 @@ import { pcdManager } from '$pcd/pcd.ts';
|
||||
import { canWriteToBase } from '$pcd/writer.ts';
|
||||
import * as delayProfileQueries from '$pcd/queries/delayProfiles/index.ts';
|
||||
import type { OperationLayer } from '$pcd/writer.ts';
|
||||
import type { PreferredProtocol } from '$pcd/queries/delayProfiles/index.ts';
|
||||
import type { PreferredProtocol } from '$shared/pcd/display.ts';
|
||||
import { logger } from '$logger/logger.ts';
|
||||
|
||||
export const load: ServerLoad = ({ params }) => {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import type { DelayProfileTableRow } from '$pcd/queries/delayProfiles';
|
||||
import type { DelayProfilesRow } from '$shared/pcd/display.ts';
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { Clock, Zap, Shield } from 'lucide-svelte';
|
||||
|
||||
export let profiles: DelayProfileTableRow[];
|
||||
export let profiles: DelayProfilesRow[];
|
||||
|
||||
function handleCardClick(profile: DelayProfileTableRow) {
|
||||
function handleCardClick(profile: DelayProfilesRow) {
|
||||
const databaseId = $page.params.databaseId;
|
||||
goto(`/delay-profiles/${databaseId}/${profile.id}`);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
import Table from '$ui/table/Table.svelte';
|
||||
import type { Column } from '$ui/table/types';
|
||||
import type { DelayProfileTableRow } from '$pcd/queries/delayProfiles';
|
||||
import type { DelayProfilesRow } from '$shared/pcd/display.ts';
|
||||
import { Tag, Clock, Zap, Shield, Calendar } from 'lucide-svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { parseUTC } from '$shared/dates';
|
||||
|
||||
export let profiles: DelayProfileTableRow[];
|
||||
export let profiles: DelayProfilesRow[];
|
||||
|
||||
function formatDate(dateString: string): string {
|
||||
const date = parseUTC(dateString);
|
||||
@@ -21,7 +21,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
function handleRowClick(row: DelayProfileTableRow) {
|
||||
function handleRowClick(row: DelayProfilesRow) {
|
||||
const databaseId = $page.params.databaseId;
|
||||
goto(`/delay-profiles/${databaseId}/${row.id}`);
|
||||
}
|
||||
@@ -50,14 +50,14 @@
|
||||
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
|
||||
}
|
||||
|
||||
const columns: Column<DelayProfileTableRow>[] = [
|
||||
const columns: Column<DelayProfilesRow>[] = [
|
||||
{
|
||||
key: 'name',
|
||||
header: 'Name',
|
||||
headerIcon: Tag,
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
cell: (row: DelayProfileTableRow) => ({
|
||||
cell: (row: DelayProfilesRow) => ({
|
||||
html: `<div class="font-medium">${row.name}</div>`
|
||||
})
|
||||
},
|
||||
@@ -67,7 +67,7 @@
|
||||
headerIcon: Zap,
|
||||
align: 'left',
|
||||
width: 'w-44',
|
||||
cell: (row: DelayProfileTableRow) => ({
|
||||
cell: (row: DelayProfilesRow) => ({
|
||||
html: `<span class="font-mono text-xs bg-neutral-100 dark:bg-neutral-800 px-2 py-0.5 rounded">${formatProtocol(row.preferred_protocol)}</span>`
|
||||
})
|
||||
},
|
||||
@@ -77,7 +77,7 @@
|
||||
headerIcon: Clock,
|
||||
align: 'left',
|
||||
width: 'w-48',
|
||||
cell: (row: DelayProfileTableRow) => ({
|
||||
cell: (row: DelayProfilesRow) => ({
|
||||
html: `
|
||||
<div class="text-xs space-y-0.5">
|
||||
${row.usenet_delay !== null ? `<div>Usenet: <span class="font-mono text-[10px] bg-neutral-100 dark:bg-neutral-800 px-1 rounded">${formatDelay(row.usenet_delay)}</span></div>` : ''}
|
||||
@@ -92,7 +92,7 @@
|
||||
headerIcon: Shield,
|
||||
align: 'left',
|
||||
width: 'w-56',
|
||||
cell: (row: DelayProfileTableRow) => {
|
||||
cell: (row: DelayProfilesRow) => {
|
||||
const bypasses: string[] = [];
|
||||
if (row.bypass_if_highest_quality) {
|
||||
bypasses.push('Highest Quality');
|
||||
@@ -121,7 +121,7 @@
|
||||
align: 'left',
|
||||
width: 'w-44',
|
||||
sortable: true,
|
||||
cell: (row: DelayProfileTableRow) => ({
|
||||
cell: (row: DelayProfilesRow) => ({
|
||||
html: `<span class="text-xs text-neutral-500 dark:text-neutral-400">${formatDate(row.updated_at)}</span>`
|
||||
})
|
||||
},
|
||||
@@ -132,7 +132,7 @@
|
||||
align: 'left',
|
||||
width: 'w-44',
|
||||
sortable: true,
|
||||
cell: (row: DelayProfileTableRow) => ({
|
||||
cell: (row: DelayProfilesRow) => ({
|
||||
html: `<span class="text-xs text-neutral-500 dark:text-neutral-400">${formatDate(row.created_at)}</span>`
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user