mirror of
https://github.com/FoxxMD/multi-scrobbler.git
synced 2026-09-03 05:10:00 +03:00
refactor(database): Replace relation select type with simpler built type
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { DBQueryConfig, DBQueryConfigWith, ExtractTablesFromSchema, KnownKeysOnly, RelationFieldsFilterInternals, Many, InferSelectModel, ExtractTablesWithRelations } from "drizzle-orm";
|
||||
import { DBQueryConfig, DBQueryConfigWith, ExtractTablesFromSchema, KnownKeysOnly, RelationFieldsFilterInternals, Many, InferSelectModel, ExtractTablesWithRelations, type BuildQueryResult, RelationsFilter } from "drizzle-orm";
|
||||
import { components, playInputs, plays, queueStates, relations } from "./schema/schema.js";
|
||||
import {TSchema, TableName, Schema } from "./schema/schema.js";
|
||||
import { MarkOptional, MarkRequired } from "ts-essentials";
|
||||
|
||||
|
||||
export type ComponentNew = typeof components.$inferInsert;
|
||||
@@ -14,6 +15,7 @@ export type PlayInputSelect = typeof playInputs.$inferSelect;
|
||||
|
||||
export type PlaySelect = typeof plays.$inferSelect;
|
||||
export type PlaySelectRel = ModelWithRelations<typeof plays>;
|
||||
export type PlaySelectWithQueueStates = GenericRelationResult<'plays', 'queueStates'>;
|
||||
export type PlayNew = typeof plays.$inferInsert;
|
||||
|
||||
|
||||
@@ -31,6 +33,9 @@ export type QueryConfig<T extends TableName> = DBQueryConfig<"many", TSchema, TS
|
||||
export type FindMany<T extends TableName> = Pick<KnownKeysOnly<QueryConfig<T>, DBQueryConfig<"many", TSchema, TSchema[T]>>, 'where' | 'orderBy' | 'limit' | 'offset' | 'extras'> & {with?: FindWith<T>}
|
||||
export type FindOne<T extends TableName> = Pick<KnownKeysOnly<QueryConfig<T>, DBQueryConfig<"one", TSchema, TSchema[T]>>, 'where' | 'orderBy' | 'limit' | 'offset' | 'extras'> & {with?: FindWith<T>}
|
||||
export type FindWhere<T extends TableName> = QueryConfig<T>['where'];
|
||||
// https://github.com/drizzle-team/drizzle-orm/issues/5218#issuecomment-4154686086
|
||||
export type WhereClause<T extends keyof typeof relations> = RelationsFilter<typeof relations[T], typeof relations>
|
||||
|
||||
|
||||
export type CompareOp<T> = Pick<RelationFieldsFilterInternals<T>, 'gt' | 'gte' | 'eq' | 'lt' | 'lte' | 'ne'>
|
||||
export type CompareOpKey<T> = keyof CompareOp<T>;
|
||||
@@ -89,4 +94,7 @@ export type ModelWithRelations<TTable extends Schema[keyof Schema]> =
|
||||
|
||||
|
||||
// all relations are are now fully typed and optional
|
||||
//type FullPlay = ModelWithRelations<typeof plays>;
|
||||
//type FullPlay = ModelWithRelations<typeof plays>;
|
||||
|
||||
// https://github.com/drizzle-team/drizzle-orm/issues/695#issuecomment-4389296482
|
||||
type GenericRelationResult<T extends keyof TSchema, K extends keyof TSchema[T]['relations']> = BuildQueryResult<TSchema, TSchema[T], { with: Record<K, true> }>;
|
||||
@@ -1,5 +1,5 @@
|
||||
import assert from "node:assert";
|
||||
import { PlayNew, PlaySelect, PlaySelectRel } from "./drizzleTypes.js";
|
||||
import { PlayNew, PlaySelect, PlaySelectWithQueueStates } from "./drizzleTypes.js";
|
||||
import { PlayInputNew } from "./drizzleTypes.js";
|
||||
import { QueueStateNew } from "./drizzleTypes.js";
|
||||
import { ComponentNew } from "./drizzleTypes.js";
|
||||
@@ -71,7 +71,7 @@ export const hydratePlaySelect = (select: PlaySelect, opts: PlayHydateOptions[]
|
||||
return res;
|
||||
}
|
||||
|
||||
export const playSelectToDeadScrobble = (select: MarkRequired<PlaySelectRel, 'queueStates'>): DeadLetterScrobble<PlayObject> => {
|
||||
export const playSelectToDeadScrobble = (select: PlaySelectWithQueueStates): DeadLetterScrobble<PlayObject> => {
|
||||
const deadQueue = select.queueStates.find(x => x.queueName === CLIENT_DEAD_QUEUE);
|
||||
return {
|
||||
play: select.play,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { loggerNoop } from "../../../MaybeLogger.js";
|
||||
import { ErrorLike, PlayObject, TA_CLOSE, TA_DEFAULT_ACCURACY, TA_EXACT, TemporalAccuracy } from "../../../../../core/Atomic.js";
|
||||
import { generateInputEntity, generatePlayEntity, PlayEntityOpts, hydratePlaySelect, PlayHydateOptions } from "../entityUtils.js";
|
||||
import { playInputs, plays, queueStates, relations } from "../schema/schema.js";
|
||||
import { PlayNew, PlaySelect, PlayInputNew, FindWhere, FindMany, CompareOpKey, QueueStateSelect, PlayInputSelect, PlaySelectRel, FindWith } from "../drizzleTypes.js";;
|
||||
import { PlayNew, PlaySelect, PlayInputNew, FindWhere, FindMany, CompareOpKey, QueueStateSelect, PlayInputSelect, PlaySelectRel, FindWith, PlaySelectWithQueueStates, WhereClause } from "../drizzleTypes.js";;
|
||||
import { MarkOptional, MarkRequired, PathValue } from "ts-essentials";
|
||||
import { genGroupIdStrFromPlay, removeEmptyArrays, removeUndefinedKeys } from "../../../../utils.js";
|
||||
import dayjs, { Dayjs } from "dayjs";
|
||||
@@ -397,7 +397,7 @@ export class DrizzlePlayRepository extends DrizzleBaseRepository<'plays'> {
|
||||
},
|
||||
}).prepare()
|
||||
|
||||
public getQueueNext = async (queueName: string, opts: {order?: 'asc' | 'desc', retries?: number} & ComponentConstrainedRepoOpts = {}): Promise<MarkRequired<PlaySelectRel, 'queueStates'> | undefined> => {
|
||||
public getQueueNext = async (queueName: string, opts: {order?: 'asc' | 'desc', retries?: number} & ComponentConstrainedRepoOpts = {}): Promise<PlaySelectWithQueueStates | undefined> => {
|
||||
const {
|
||||
retries = 0,
|
||||
order = 'asc',
|
||||
@@ -538,7 +538,7 @@ export class DrizzlePlayRepository extends DrizzleBaseRepository<'plays'> {
|
||||
return {data: res.map(x => ({...x, play: hydratePlaySelect(x, hydrate)})), meta: {limit, offset}};
|
||||
}
|
||||
|
||||
public checkExisting = async (play: PlayObject, opts: {queueName?: string, states?: PlaySelect['state'][], taAccuracy?: TemporalAccuracy[]} & ComponentConstrainedRepoOpts = {}): Promise<MarkRequired<PlaySelectRel, 'queueStates'> | undefined> => {
|
||||
public checkExisting = async (play: PlayObject, opts: {queueName?: string, states?: PlaySelect['state'][], taAccuracy?: TemporalAccuracy[]} & ComponentConstrainedRepoOpts = {}): Promise<PlaySelectWithQueueStates | undefined> => {
|
||||
const {
|
||||
queueName,
|
||||
componentId = this.componentId,
|
||||
@@ -689,7 +689,7 @@ export const buildPlayWith = (args: WithPlayRelation[] | undefined): FindWith<'p
|
||||
return qWith;
|
||||
}
|
||||
|
||||
export const buildPlayWhere = (args: PlayWhereOpts): FindWhere<'plays'> => {
|
||||
export const buildPlayWhere = (args: PlayWhereOpts): WhereClause<'plays'> => {
|
||||
// old way
|
||||
// let where: Parameters<(ReturnType<typeof getDb>)['query']['plays']['findMany']>[0]['where'] = {
|
||||
// };
|
||||
|
||||
@@ -73,7 +73,7 @@ import {isErrorLike, serializeError} from 'serialize-error';
|
||||
import { DEFAULT_NEW_PADDING, groupPlaysToTimeRanges } from "../utils/ListenFetchUtils.js";
|
||||
import { spawn, catchAbortError, isAbortError, rethrowAbortError, delay, forever, AbortError, throwIfAborted } from 'abort-controller-x';
|
||||
import { DrizzlePlayRepository, playToRepositoryCreatePlayOpts, QueryPlaysOpts } from "../common/database/drizzle/repositories/PlayRepository.js";
|
||||
import { PlaySelect, PlaySelectRel, QueueStateNew, QueueStateSelect } from "../common/database/drizzle/drizzleTypes.js";
|
||||
import { PlaySelect, PlaySelectWithQueueStates, QueueStateNew, QueueStateSelect } from "../common/database/drizzle/drizzleTypes.js";
|
||||
import { asPlay } from "../../core/PlayMarshalUtils.js";
|
||||
import { DrizzleQueueRepository } from "../common/database/drizzle/repositories/QueueRepository.js";
|
||||
import { SourceType } from "../common/infrastructure/config/source/sources.js";
|
||||
@@ -857,7 +857,7 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
|
||||
}
|
||||
}
|
||||
|
||||
protected processQueueCurrentScrobble = async (currQueuedPlay: MarkRequired<PlaySelectRel, "queueStates">, signal: AbortSignal) => {
|
||||
protected processQueueCurrentScrobble = async (currQueuedPlay: PlaySelectWithQueueStates, signal: AbortSignal) => {
|
||||
signal.throwIfAborted();
|
||||
//const currQueuedPlay = await this.playRepo.getQueueNext(CLIENT_INGRESS_QUEUE);
|
||||
// if (currQueuedPlay === undefined) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { TimeRangeListensFetcher } from "../../common/infrastructure/Atomic.js";
|
||||
import { loggerNoop } from "../../common/MaybeLogger.js";
|
||||
import { DrizzlePlayRepository, RepositoryCreatePlayOpts } from "../../common/database/drizzle/repositories/PlayRepository.js";
|
||||
import { DrizzleQueueRepository } from "../../common/database/drizzle/repositories/QueueRepository.js";
|
||||
import { PlaySelectRel } from "../../common/database/drizzle/drizzleTypes.js";
|
||||
import { PlaySelect } from "../../common/database/drizzle/drizzleTypes.js";
|
||||
import { loggerDebug } from "@foxxmd/logging";
|
||||
|
||||
export class TestScrobbler extends AbstractScrobbleClient {
|
||||
@@ -48,7 +48,7 @@ export class TestScrobbler extends AbstractScrobbleClient {
|
||||
return playObject;
|
||||
}
|
||||
|
||||
addScrobbled = async (plays: PlayObject[]): Promise<PlaySelectRel[]> => {
|
||||
addScrobbled = async (plays: PlayObject[]): Promise<PlaySelect[]> => {
|
||||
const newPlayData: RepositoryCreatePlayOpts[] = plays.map(x => ({play: x, state: 'scrobbled', input: {}}));
|
||||
return await this.playRepoTest.createPlays(newPlayData);
|
||||
}
|
||||
|
||||
+2
-2
@@ -605,10 +605,10 @@ export const CLIENT_DEAD_QUEUE = 'dead';
|
||||
/**
|
||||
* Useful TS type-only utility for testing type equality
|
||||
*
|
||||
* Usage: type EQ = IfEquals<any[], [number][], "same", "different">; // "different"
|
||||
* Usage: type EQ = TypesAreEqual<any[], [number][], "same", "different">; // "different"
|
||||
*
|
||||
* @see https://stackoverflow.com/a/53808212/1469797
|
||||
*/
|
||||
export type IfEquals<T, U, Y=unknown, N=never> =
|
||||
export type TypesAreEqual<T, U, Y=unknown, N=never> =
|
||||
(<G>() => G extends T ? 1 : 2) extends
|
||||
(<G>() => G extends U ? 1 : 2) ? Y : N;
|
||||
Reference in New Issue
Block a user