refactor(pcd): reorganise entityTests/releases to CRUD pattern

This commit is contained in:
Sam Chau
2026-01-28 01:04:02 +10:30
parent bb64b9ba9a
commit ec5946428d
17 changed files with 154 additions and 154 deletions

View File

@@ -1,58 +0,0 @@
/**
* Create test release operation
*/
import type { PCDCache } from '../../cache.ts';
import { writeOperation, type OperationLayer } from '../../writer.ts';
export interface CreateTestReleaseInput {
entityType: 'movie' | 'series';
entityTmdbId: number;
title: string;
size_bytes: number | null;
languages: string[];
indexers: string[];
flags: string[];
}
export interface CreateTestReleaseOptions {
databaseId: number;
cache: PCDCache;
layer: OperationLayer;
input: CreateTestReleaseInput;
}
/**
* Create a test release by writing an operation to the specified layer
*/
export async function createRelease(options: CreateTestReleaseOptions) {
const { databaseId, cache, layer, input } = options;
const db = cache.kb;
const insertRelease = db
.insertInto('test_releases')
.values({
entity_type: input.entityType,
entity_tmdb_id: input.entityTmdbId,
title: input.title,
size_bytes: input.size_bytes,
languages: JSON.stringify(input.languages),
indexers: JSON.stringify(input.indexers),
flags: JSON.stringify(input.flags)
})
.compile();
const result = await writeOperation({
databaseId,
layer,
description: `create-test-release`,
queries: [insertRelease],
metadata: {
operation: 'create',
entity: 'test_release',
name: input.title.substring(0, 50)
}
});
return result;
}

View File

@@ -1,23 +0,0 @@
/**
* Entity Test queries and mutations
*/
// Export types
export type { CreateTestEntityInput, CreateTestEntitiesOptions } from './create.ts';
export type { CreateTestReleaseInput, CreateTestReleaseOptions } from './createRelease.ts';
export type { CreateTestReleasesInput, CreateTestReleasesOptions } from './createReleases.ts';
export type { UpdateTestReleaseInput, UpdateTestReleaseOptions } from './updateRelease.ts';
export type { DeleteTestReleaseOptions } from './deleteRelease.ts';
// Export query functions
export { list } from './list.ts';
// Export entity mutation functions
export { create } from './create.ts';
export { remove } from './delete.ts';
// Export release mutation functions
export { createRelease } from './createRelease.ts';
export { createReleases } from './createReleases.ts';
export { updateRelease } from './updateRelease.ts';
export { deleteRelease } from './deleteRelease.ts';

View File

@@ -2,10 +2,10 @@
* Create test entity operation
*/
import type { PCDCache } from '../../cache.ts';
import { writeOperation, type OperationLayer } from '../../writer.ts';
import type { PCDCache } from '$pcd/cache.ts';
import { writeOperation, type OperationLayer } from '$pcd/writer.ts';
export interface CreateTestEntityInput {
interface CreateEntityInput {
type: 'movie' | 'series';
tmdbId: number;
title: string;
@@ -13,18 +13,18 @@ export interface CreateTestEntityInput {
posterPath: string | null;
}
export interface CreateTestEntitiesOptions {
interface CreateEntitiesOptions {
databaseId: number;
cache: PCDCache;
layer: OperationLayer;
inputs: CreateTestEntityInput[];
inputs: CreateEntityInput[];
}
/**
* Create test entities by writing an operation to the specified layer
* Skips entities that already exist (by type + tmdb_id)
*/
export async function create(options: CreateTestEntitiesOptions) {
export async function create(options: CreateEntitiesOptions) {
const { databaseId, cache, layer, inputs } = options;
const db = cache.kb;

View File

@@ -2,10 +2,10 @@
* Delete test entity operation
*/
import type { PCDCache } from '../../cache.ts';
import { writeOperation, type OperationLayer } from '../../writer.ts';
import type { PCDCache } from '$pcd/cache.ts';
import { writeOperation, type OperationLayer } from '$pcd/writer.ts';
export interface DeleteTestEntityOptions {
interface DeleteEntityOptions {
databaseId: number;
cache: PCDCache;
layer: OperationLayer;
@@ -18,7 +18,7 @@ export interface DeleteTestEntityOptions {
* Delete a test entity and its releases by writing an operation to the specified layer
* Uses stable composite key (type, tmdb_id) instead of auto-generated id
*/
export async function remove(options: DeleteTestEntityOptions) {
export async function remove(options: DeleteEntityOptions) {
const { databaseId, cache, layer, entityType, entityTmdbId, entityTitle } = options;
const db = cache.kb;

View File

@@ -0,0 +1,15 @@
/**
* Entity test queries and mutations
*/
// Read
export { list } from './read.ts';
// Create
export { create } from './create.ts';
// Delete
export { remove } from './delete.ts';
// Release operations
export { createRelease, createReleases, updateRelease, deleteRelease } from './releases/index.ts';

View File

@@ -1,13 +1,14 @@
/**
* Entity test list queries
* Entity test read queries
*/
import type { PCDCache } from '../../cache.ts';
import type { PCDCache } from '$pcd/cache.ts';
import type { TestEntity } from '$shared/pcd/display.ts';
/**
* Get all test entities with their releases
*/
export async function list(cache: PCDCache) {
export async function list(cache: PCDCache): Promise<TestEntity[]> {
const db = cache.kb;
// 1. Get all test entities

View File

@@ -1,11 +1,11 @@
/**
* Bulk create test releases operation
* Create test release operations
*/
import type { PCDCache } from '../../cache.ts';
import { writeOperation, type OperationLayer } from '../../writer.ts';
import type { PCDCache } from '$pcd/cache.ts';
import { writeOperation, type OperationLayer } from '$pcd/writer.ts';
export interface CreateTestReleasesInput {
interface CreateReleaseInput {
entityType: 'movie' | 'series';
entityTmdbId: number;
title: string;
@@ -15,18 +15,60 @@ export interface CreateTestReleasesInput {
flags: string[];
}
export interface CreateTestReleasesOptions {
interface CreateReleaseOptions {
databaseId: number;
cache: PCDCache;
layer: OperationLayer;
inputs: CreateTestReleasesInput[];
input: CreateReleaseInput;
}
interface CreateReleasesOptions {
databaseId: number;
cache: PCDCache;
layer: OperationLayer;
inputs: CreateReleaseInput[];
}
/**
* Create a test release by writing an operation to the specified layer
*/
export async function createRelease(options: CreateReleaseOptions) {
const { databaseId, cache, layer, input } = options;
const db = cache.kb;
const insertRelease = db
.insertInto('test_releases')
.values({
entity_type: input.entityType,
entity_tmdb_id: input.entityTmdbId,
title: input.title,
size_bytes: input.size_bytes,
languages: JSON.stringify(input.languages),
indexers: JSON.stringify(input.indexers),
flags: JSON.stringify(input.flags)
})
.compile();
const result = await writeOperation({
databaseId,
layer,
description: `create-test-release`,
queries: [insertRelease],
metadata: {
operation: 'create',
entity: 'test_release',
name: input.title.substring(0, 50)
}
});
return result;
}
/**
* Bulk create test releases by writing operations to the specified layer
* Skips releases that already exist (by title within the same entity)
*/
export async function createReleases(options: CreateTestReleasesOptions) {
export async function createReleases(options: CreateReleasesOptions) {
const { databaseId, cache, layer, inputs } = options;
const db = cache.kb;

View File

@@ -2,10 +2,10 @@
* Delete test release operation
*/
import type { PCDCache } from '../../cache.ts';
import { writeOperation, type OperationLayer } from '../../writer.ts';
import type { PCDCache } from '$pcd/cache.ts';
import { writeOperation, type OperationLayer } from '$pcd/writer.ts';
export interface DeleteTestReleaseOptions {
interface DeleteReleaseOptions {
databaseId: number;
cache: PCDCache;
layer: OperationLayer;
@@ -15,7 +15,7 @@ export interface DeleteTestReleaseOptions {
/**
* Delete a test release by writing an operation to the specified layer
*/
export async function deleteRelease(options: DeleteTestReleaseOptions) {
export async function deleteRelease(options: DeleteReleaseOptions) {
const { databaseId, cache, layer, releaseId } = options;
const db = cache.kb;

View File

@@ -0,0 +1,12 @@
/**
* Test release queries and mutations
*/
// Create
export { createRelease, createReleases } from './create.ts';
// Update
export { updateRelease } from './update.ts';
// Delete
export { deleteRelease } from './delete.ts';

View File

@@ -2,10 +2,10 @@
* Update test release operation
*/
import type { PCDCache } from '../../cache.ts';
import { writeOperation, type OperationLayer } from '../../writer.ts';
import type { PCDCache } from '$pcd/cache.ts';
import { writeOperation, type OperationLayer } from '$pcd/writer.ts';
export interface UpdateTestReleaseInput {
interface UpdateReleaseInput {
id: number;
title: string;
size_bytes: number | null;
@@ -14,17 +14,17 @@ export interface UpdateTestReleaseInput {
flags: string[];
}
export interface UpdateTestReleaseOptions {
interface UpdateReleaseOptions {
databaseId: number;
cache: PCDCache;
layer: OperationLayer;
input: UpdateTestReleaseInput;
input: UpdateReleaseInput;
}
/**
* Update a test release by writing an operation to the specified layer
*/
export async function updateRelease(options: UpdateTestReleaseOptions) {
export async function updateRelease(options: UpdateReleaseOptions) {
const { databaseId, cache, layer, input } = options;
const db = cache.kb;

View File

@@ -88,3 +88,24 @@ export interface QualityDefinitionsConfig {
name: string;
entries: QualityDefinitionEntry[];
}
// ============================================================================
// ENTITY TESTS
// ============================================================================
import type { TestEntitiesRow, TestReleasesRow } from './types.ts';
/** Test release with parsed arrays (JSON strings → string[]) */
export type TestRelease = Omit<
TestReleasesRow,
'entity_type' | 'entity_tmdb_id' | 'languages' | 'indexers' | 'flags' | 'created_at' | 'updated_at'
> & {
languages: string[];
indexers: string[];
flags: string[];
};
/** Test entity with nested releases */
export type TestEntity = Omit<TestEntitiesRow, 'created_at' | 'updated_at'> & {
releases: TestRelease[];
};

View File

@@ -4,7 +4,7 @@ import { pcdManager } from '$pcd/pcd.ts';
import { canWriteToBase } from '$pcd/writer.ts';
import { tmdbSettingsQueries } from '$db/queries/tmdbSettings.ts';
import { arrInstancesQueries } from '$db/queries/arrInstances.ts';
import * as entityTestQueries from '$pcd/queries/entityTests/index.ts';
import * as entityTestQueries from '$pcd/queries/qualityProfiles/entityTests/index.ts';
import * as qualityProfileQueries from '$pcd/queries/qualityProfiles/index.ts';
import { isParserHealthy } from '$lib/server/utils/arr/parser/index.ts';
import { logger } from '$logger/logger.ts';

View File

@@ -17,7 +17,7 @@
import { createDataPageStore } from '$lib/client/stores/dataPage';
import { alertStore } from '$lib/client/alerts/store';
import type { PageData } from './$types';
import type { TestEntity, TestRelease } from './components/types';
import type { TestEntity, TestRelease } from '$shared/pcd/display.ts';
import type { components } from '$api/v1.d.ts';
type EvaluateResponse = components['schemas']['EvaluateResponse'];

View File

@@ -7,11 +7,25 @@
import ReleaseTable from './ReleaseTable.svelte';
import { alertStore } from '$lib/client/alerts/store';
import type { Column } from '$ui/table/types';
import type { TestEntity, TestRelease, ProfileCfScores, CustomFormatInfo } from './types';
import type { TestEntity, TestRelease } from '$shared/pcd/display.ts';
import type { components } from '$api/v1.d.ts';
type ReleaseEvaluation = components['schemas']['ReleaseEvaluation'];
interface CfScore {
radarr: number | null;
sonarr: number | null;
}
interface ProfileCfScores {
profileName: string;
scores: Record<string, CfScore>;
}
interface CustomFormatInfo {
name: string;
}
export let entities: TestEntity[];
export let evaluations: Record<number, ReleaseEvaluation>;
export let loadingEntityIds: Set<number> = new Set();

View File

@@ -22,7 +22,7 @@
import Badge from '$ui/badge/Badge.svelte';
import { createSearchStore } from '$stores/search';
import { alertStore } from '$alerts/store';
import type { TestEntity } from './types';
import type { TestEntity } from '$shared/pcd/display.ts';
export let open = false;
export let entity: TestEntity | null = null;

View File

@@ -19,11 +19,25 @@
import CustomFormatBadge from '$ui/arr/CustomFormatBadge.svelte';
import { alertStore } from '$lib/client/alerts/store';
import type { Column } from '$ui/table/types';
import type { TestRelease, ProfileCfScores, CustomFormatInfo } from './types';
import type { TestRelease } from '$shared/pcd/display.ts';
import type { components } from '$api/v1.d.ts';
type ReleaseEvaluation = components['schemas']['ReleaseEvaluation'];
interface CfScore {
radarr: number | null;
sonarr: number | null;
}
interface ProfileCfScores {
profileName: string;
scores: Record<string, CfScore>;
}
interface CustomFormatInfo {
name: string;
}
export let entityType: 'movie' | 'series';
export let entityTmdbId: number;
export let releases: TestRelease[];

View File

@@ -1,38 +0,0 @@
export interface TestRelease {
id: number;
title: string;
size_bytes: number | null;
languages: string[];
indexers: string[];
flags: string[];
}
export interface TestEntity {
id: number;
type: 'movie' | 'series';
tmdb_id: number;
title: string;
year: number | null;
poster_path: string | null;
releases: TestRelease[];
}
// Note: ParsedInfo, ReleaseEvaluation, and EvaluateResponse types are now
// generated from OpenAPI spec - see $api/v1.d.ts
/** CF score for a specific arr type */
export interface CfScore {
radarr: number | null;
sonarr: number | null;
}
/** Profile CF scores data */
export interface ProfileCfScores {
profileName: string;
scores: Record<string, CfScore>;
}
/** Custom format info */
export interface CustomFormatInfo {
name: string;
}