chore: Cleanup development comments

This commit is contained in:
FoxxMD
2026-07-28 17:27:23 +00:00
parent d595bf9961
commit 516a8d2178
7 changed files with 0 additions and 98 deletions
@@ -20,11 +20,6 @@ export const clientDefaultsSchema = z.object({
export type ClientDefaults = z.infer<typeof clientDefaultsSchema>;
// `TransformOptions`/`TransformerCommonConfig<T,Y>` (from `../../../../core/Atomic.ts`) are only ever used at
// their default type params (`Record<string, any>`) everywhere in the codebase, but `TransformerCommonConfig`
// stays generic there and `TransformerCommon<T,Y> extends TransformerCommonConfig<T,Y>` - converting the
// exported interface itself would break that extends clause. Reconstructed locally here instead, scoped to
// this file's `transformers` field only.
const transformOptionsSchema = z.object({
failOnFetch: z.boolean().optional(),
throwOnFailure: z.union([
@@ -6,9 +6,6 @@ export const statusTypeSchema = z.union([z.literal("online"), z.literal("idle"),
export type StatusType = z.infer<typeof statusTypeSchema>;
// `z.tuple([z.number(), z.string()])` in the installed zod version infers as `[number?, string?, ...unknown[]]`
// rather than `[number, string]`, which breaks real consumers (e.g. DiscordIPCClient.ts) expecting a strict
// 2-tuple. `z.custom` sidesteps the bug while still checking shape at runtime.
const ipcLocationTupleSchema = z.custom<[number, string]>((val) => Array.isArray(val) && val.length === 2 && typeof val[0] === 'number' && typeof val[1] === 'string');
export const discordDataSchema = z.object({
@@ -46,11 +46,6 @@ export type MatchLoggingOptions = z.infer<typeof matchLoggingOptionsSchema>;
export const commonClientDataSchema = z.looseObject({});
// `z.infer` of an empty object schema (strict or loose) picks up a `never`/`unknown` index signature that a
// plain empty TS interface never had, which breaks the many `interface FooData extends CommonClientData, ...`
// declarations elsewhere (see the same fix applied to `CommonSourceData` in `../source/index.ts`). The
// original `interface CommonClientData {}` is structurally identical to `{}` itself, so the type is declared
// directly rather than derived from the schema for this one empty-shape case.
export type CommonClientData = {};
export const upstreamRefreshOptionsSchema = z.object({
@@ -188,6 +183,4 @@ export const commonClientConfigSchema = z.object({
options: commonClientOptionsSchema.optional(),
});
// `data`'s type is overridden here for the same reason `CommonClientData` is declared directly above rather
// than derived from `commonClientDataSchema`.
export type CommonClientConfig = Omit<z.infer<typeof commonClientConfigSchema>, 'data'> & { data?: CommonClientData };
@@ -8,10 +8,6 @@ export type RetentionPlayType = z.infer<typeof retentionPlayTypeSchema>;
export const retentionPlayTypes: RetentionPlayType[] = ['failed','completed','duped'];
// `Duration` (from `dayjs/plugin/duration.js`) is a class instance with dozens of methods (`asSeconds`,
// `humanize`, `add`, `clone`, etc.), not a plain data shape - reconstructing its full interface as a zod
// object wouldn't provide any real validation value. This checks for a Duration-shaped object via one of its
// signature methods and relies on the imported type for full static typing.
const durationSchema = z.custom<Duration>(
(val) => val !== null && typeof val === 'object' && typeof (val as Duration).asMilliseconds === 'function',
{message: 'Expected a dayjs Duration instance'}
@@ -25,14 +21,6 @@ export const retentionValueSchema = z.union([durationSchema, z.literal(false)]);
export type RetentionValue = z.infer<typeof retentionValueSchema>;
// `RententionGranular<T>`, `RetentionConfigValue<T>`, `RetentionOption<T>`, and `RetentionConfig<T>` were
// previously left as plain generics since zod can't represent a generic object schema the way a TS interface
// can. In practice though each is only ever instantiated with one of three known terms - `DurationValue`,
// `Duration`, and `RetentionValue` - so below builds one concrete schema per term actually valid for each
// family (per each type's original generic constraint) and unifies them with `z.union` into a single
// non-generic replacement. Call sites elsewhere now use the specific per-term type where the term is
// statically known.
export const rententionGranularDurationValueSchema = z.object({
failed: durationValueSchema.optional(),
completed: durationValueSchema.optional(),
@@ -93,8 +81,6 @@ export const COMPACTABLE = {
export const compactableProperties: CompactableProperty[] = [COMPACTABLE.transform, COMPACTABLE.input];
// `RetentionOption<T>`'s original constraint (`T extends RetentionValue`) only ever admits `Duration` and
// `RetentionValue` itself - not `DurationValue` - so there are only two valid terms here.
export const retentionOptionDurationSchema = z.object({
failed: durationSchema,
completed: durationSchema,
@@ -59,12 +59,8 @@ export const scrobbleThresholdsSchema = z.object({
export type ScrobbleThresholds = z.infer<typeof scrobbleThresholdsSchema>;
// `LogLevel` (from `@foxxmd/logging`) is a simple string-literal union, reconstructed directly.
export const logLevelSchema = z.enum(["silent", "fatal", "error", "warn", "info", "log", "verbose", "debug", "trace"]);
// `FileLogOptions` (from `@foxxmd/logging`) extends `FileOptions`, which itself extends `PinoRollOptions` and
// `RollOptions` - two levels deep, but all plain data fields, so it's reconstructed in full here rather than
// stubbed.
export const fileLogOptionsSchema = z.object({
size: z.union([z.number(), z.string()]).optional(),
frequency: z.union([z.literal('daily'), z.literal('hourly'), z.number()]).optional(),
@@ -184,11 +180,6 @@ export type ManualListeningOptions = z.infer<typeof manualListeningOptionsSchema
export const commonSourceDataSchema = z.looseObject({});
// `z.infer` of an empty object schema (strict or loose) picks up a `never`/`unknown` index signature that a
// plain empty TS interface never had, which breaks the many `interface FooData extends CommonSourceData, ...`
// declarations elsewhere (some in the "extends" direction, some in the "assign a plain object" direction).
// The original `interface CommonSourceData {}` is structurally identical to `{}` itself, so the type is
// declared directly rather than derived from the schema for this one empty-shape case.
export type CommonSourceData = {};
export const commonSourceConfigSchema = z.object({
@@ -213,7 +204,4 @@ export const commonSourceConfigSchema = z.object({
options: commonSourceOptionsSchema.optional(),
});
// `data`'s type is overridden here for the same reason `CommonSourceData` is declared directly above rather
// than derived from `commonSourceDataSchema` - the schema-inferred type carries an index signature that the
// original empty `data?: CommonSourceData` field never had.
export type CommonSourceConfig = Omit<z.infer<typeof commonSourceConfigSchema>, 'data'> & { data?: CommonSourceData };
@@ -1,10 +1,6 @@
import * as z from "zod";
import {commonSourceConfigSchema, commonSourceDataSchema, commonSourceOptionsSchema} from "./index.ts";
// `CollectionType`/`MediaType` (from `@jellyfin/sdk`) don't resolve cleanly - the package's typings don't
// line up with its actual exports (see the `@ts-expect-error` this replaced). Represented as `string`/`string[]`
// per instruction rather than chasing the SDK's broken typings.
export const jellyApiDataSchema = z.object({
...commonSourceDataSchema.shape,
/**
-53
View File
@@ -3,16 +3,7 @@ import type {SearchAndReplaceRegExp} from "@foxxmd/regex-buddy-core";
import type { MarkRequired } from "ts-essentials";
import { stripIndents } from "common-tags";
// The following generic types are used elsewhere in the codebase with several different concrete type
// parameters (e.g. `PlayTransformHooks<ExternalMetadataTerm>`, `PlayTransformStage<SearchAndReplaceTerm[]>`,
// `PlayTransformUserStage<ConditionalSearchAndReplaceRegExp[]>`). Zod schemas cannot be generic the way a
// TypeScript interface can, so these are intentionally left as plain types. `PlayTransformOptions` and
// `PlayTransformRules` below are instead built from concrete, hand-resolved zod schemas that represent one
// specific instantiation of this generic machinery.
export type PlayTransformParts<T, Y = StageTyped> = Extract<PlayTransformStage<T>, Y> & Whennable;
//export type PlayTransformUserParts<T> = PlayTransformUserStage<T[]> & { when?: WhenConditionsConfig };
//export type PlayTransformMetaParts<T = ExternalMetadataTerm> = PlayTransformMetadataStage<T> & { when?: WhenConditionsConfig };
export type PlayTransformPartsArray<T, Y = StageTyped> = PlayTransformParts<T, Y>[];
/** Represents the weakly-defined user config. May be an array of parts or one parts object
@@ -94,16 +85,6 @@ export const TRANSFORM_HOOK = {
export type WhenParts<T> = PlayTransformPartsAtomic<T>;
export type WhenConditions<T> = WhenParts<T>[];
// --------------------------------------------------------------------------------------------------------
// Concrete zod schemas
//
// Everything below backs the non-generic types that the generic scaffolding above is built from/into.
// `PlayTransformOptions` (raw user JSON) and `PlayTransformRules` (the strongly-typed runtime result) are
// each a specific instantiation of `PlayTransformHooksConfig<T>` / `PlayTransformHooks<T>`. Rather than try
// to make those interfaces themselves generic in zod, this section hand-resolves the two concrete `T`s that
// matter (the user-facing term shape vs. the normalized rule-term shape) and builds each stage variant once
// per instantiation.
// --------------------------------------------------------------------------------------------------------
// Helper used to construct a concrete `PlayTransformPartsAtomic<T>` schema for a given term schema, since
// `PlayTransformPartsAtomic<T>` itself can't be represented generically in zod.
@@ -140,9 +121,6 @@ export const whennableSchema = z.object({
export type Whennable = z.infer<typeof whennableSchema>;
// `SearchAndReplaceRegExp` (from `@foxxmd/regex-buddy-core`) declares `test?: (obj: SearchAndReplaceRegExp) => boolean`.
// Zod can only structurally confirm this is a function, not validate its signature/behavior, so `z.custom` is
// used as a best-effort check.
export const conditionalSearchAndReplaceRegExpSchema = z.object({
...whennableSchema.shape,
/** The plain string or regex pattern to match */
@@ -158,9 +136,6 @@ export const conditionalSearchAndReplaceRegExpSchema = z.object({
// https://stackoverflow.com/a/77256318
export type ConditionalSearchAndReplaceRegExp = MarkRequired<z.infer<typeof conditionalSearchAndReplaceRegExpSchema>, 'search'>;
// `Exclude<ConditionalSearchAndReplaceRegExp, 'test'>` is a no-op in the original type: `Exclude` only
// removes union members, and `ConditionalSearchAndReplaceRegExp` is an object type, not a union containing
// the literal `'test'`. So this type is identical to `ConditionalSearchAndReplaceRegExp`.
const {
test,
...restConditionalRegSchema
@@ -204,8 +179,6 @@ export const stageTypeUserSchema = z.literal('user').meta({title: 'Stage Type Us
export type StageTypeUser = z.infer<typeof stageTypeUserSchema>;
// `StageTypeMetadata | StageTypeUser | string` collapses to `string` (the literal members are absorbed by
// the wider `string` member), so the schema is just `z.string()`.
export const stageTypeSchema = z.string().meta({title: 'Stage Type'});
export type StageType = z.infer<typeof stageTypeSchema>;
@@ -253,7 +226,6 @@ export const playTransformNativeStageSchema = z.object({
export type PlayTransformNativeStage = z.infer<typeof playTransformNativeStageSchema>;
// `type: any` stage, shared as-is between the Options and Rules pools below (it doesn't depend on the outer T).
//const anyAtomicSchema = buildPartsAtomicSchema(z.any());
// const playTransformGenericStageSchema = z.object({
// ...stageConfigSchema.shape,
@@ -261,8 +233,6 @@ export type PlayTransformNativeStage = z.infer<typeof playTransformNativeStageSc
// type: stageTypeSchema,
// }).meta({title: 'Transform Generic Stage'});
// `PlayTransformOptions` term shape: T = SearchAndReplaceTerm[] | ExternalMetadataTerm
//const optionsPartsTermSchema = z.union([z.array(searchAndReplaceTermSchema), externalMetadataTermSchema]);
const optionsAtomicSchema = buildPartsAtomicSchema(z.array(searchAndReplaceTermSchema));
const playTransformUserStageOptionsSchema = z.object({
@@ -276,8 +246,6 @@ const playTransformUserStageOptionsSchema = z.object({
// ...optionsAtomicSchema.shape,
// }).meta({title: 'Transform User Stage'});
// `PlayTransformRules` term shape: T = ConditionalSearchAndReplaceRegExp[] | ExternalMetadataTerm
//const rulesPartsTermSchema = z.union([z.array(conditionalSearchAndReplaceRegExpSchema), externalMetadataTermSchema]).meta({title: 'Rule Parts Term'});
const rulesAtomicSchema = buildPartsAtomicSchema(z.array(searchAndReplaceTermSchema)).meta({title: 'Rules Atomic'});
const playTransformUserStageRulesSchema = z.object({
@@ -286,20 +254,10 @@ const playTransformUserStageRulesSchema = z.object({
type: z.literal('user'),
}).meta({title: 'User Stage Rules'});
// zod's `discriminatedUnion` requires each branch's discriminant literal(s) to be unique across the whole
// union. `StageTypeMetadata` nominally includes `'native'`, but `'native'`-typed stages are represented by
// the dedicated, stricter `playTransformNativeStageSchema` (no `score` field) instead. This narrows the
// metadata branch to `'spotify' | 'musicbrainz'` only for the purposes of this union - the overall set of
// `type` values covered across the whole union is unchanged.
const metadataStageForUnionSchema = playTransformMetadataStageSchema.extend({
type: z.enum(['musicbrainz']),
}).meta({title: 'Transform External Stage'});
// `PlayTransformParts<T, Y> = Extract<PlayTransformStage<T>, Y> & Whennable` - the `& Whennable` intersection
// is redundant here since every stage schema already includes `when` via `stageConfigSchema`/`untypedStageConfigSchema`.
// Options pool: `Extract<PlayTransformStage<T>, MaybeStageTyped>` doesn't filter anything out, since every
// member of `PlayTransformStage<T>` already structurally satisfies `StageTyped | NotStageTyped`.
const playTransformTypedStageOptionsSchema = z.discriminatedUnion('type', [
metadataStageForUnionSchema,
playTransformNativeStageSchema,
@@ -311,17 +269,11 @@ const playTransformTypedStageOptionsSchema = z.discriminatedUnion('type', [
// untypedPlayTransformUserStageOptionsSchema,
// ]).meta({title: 'Stage'});
// Rules pool: `Extract<PlayTransformStage<T>, StageTyped>` excludes `UntypedPlayTransformUserStage<T>`,
// since it has no `type` field and so isn't assignable to `StageTyped`.
const playTransformTypedStageRulesSchema = z.discriminatedUnion('type', [
metadataStageForUnionSchema,
playTransformNativeStageSchema,
playTransformUserStageRulesSchema,
]);
// const playTransformStageRulesSchema = z.union([
// playTransformTypedStageRulesSchema,
// playTransformGenericStageSchema,
// ]);
const playTransformPartsConfigOptionsSchema = z.union([
z.array(playTransformTypedStageOptionsSchema),
@@ -372,11 +324,6 @@ export const playTransformRulesSchema = z.object({
export type PlayTransformRules = z.infer<typeof playTransformRulesSchema>;
// Converting raw user JSON (`PlayTransformOptions`) into the normalized runtime shape (`PlayTransformRules`)
// requires real business logic - assigning default `type`s to untyped user stages, normalizing the
// single-object-or-array shorthand into arrays, and resolving bare string search/replace shorthand into full
// `ConditionalSearchAndReplaceRegExp` objects. That logic already lives in
// `AbstractComponent.transformPartToStrong` and is out of scope here, so this transform is stubbed only.
export const playTransformOptionsToRulesSchema = playTransformOptionsSchema.transform((val): PlayTransformRules => {
throw new Error('Not implemented: use AbstractComponent.transformPartToStrong for PlayTransformOptions -> PlayTransformRules normalization');
}).meta({title: 'Transform Options to Rules'});