From 153ad33b8d889de7bea12fdd7b94fe444cc982f1 Mon Sep 17 00:00:00 2001 From: Pas <74743263+Pasithea0@users.noreply.github.com> Date: Tue, 15 Jul 2025 17:02:05 -0600 Subject: [PATCH] improve cli error system --- src/dev-cli/index.ts | 3 ++- src/providers/get.ts | 54 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/dev-cli/index.ts b/src/dev-cli/index.ts index dd62873..6aa68e7 100644 --- a/src/dev-cli/index.ts +++ b/src/dev-cli/index.ts @@ -83,7 +83,8 @@ async function runQuestions() { name: 'source', message: 'Select a source', choices: sources.map((source) => ({ - message: `[${source.type.toLocaleUpperCase()}] ${source.name} ${joinMediaTypes(source.mediaTypes)}`.trim(), + message: + `[${source.type.toLocaleUpperCase()}] [${source.rank}] ${source.name} ${joinMediaTypes(source.mediaTypes)}`.trim(), name: source.id, })), }, diff --git a/src/providers/get.ts b/src/providers/get.ts index 900bbd1..4a25b96 100644 --- a/src/providers/get.ts +++ b/src/providers/get.ts @@ -1,24 +1,64 @@ import { FeatureMap, flagsAllowedInFeatures } from '@/entrypoint/utils/targets'; import { Embed, Sourcerer } from '@/providers/base'; -import { hasDuplicates } from '@/utils/predicates'; export interface ProviderList { sources: Sourcerer[]; embeds: Embed[]; } +function findDuplicates(items: T[], keyFn: (item: T) => string | number): { key: string | number; items: T[] }[] { + const groups = new Map(); + + for (const item of items) { + const key = keyFn(item); + if (!groups.has(key)) { + groups.set(key, []); + } + groups.get(key)!.push(item); + } + + return Array.from(groups.entries()) + .filter(([_, groupItems]) => groupItems.length > 1) + .map(([key, groupItems]) => ({ key, items: groupItems })); +} + +function formatDuplicateError( + type: string, + duplicates: { key: string | number; items: any[] }[], + keyName: string, +): string { + const duplicateList = duplicates + .map(({ key, items }) => { + const itemNames = items.map((item) => item.name || item.id).join(', '); + return ` ${keyName} ${key}: ${itemNames}`; + }) + .join('\n'); + + return `${type} have duplicate ${keyName}s:\n${duplicateList}`; +} + export function getProviders(features: FeatureMap, list: ProviderList): ProviderList { const sources = list.sources.filter((v) => !v?.disabled); const embeds = list.embeds.filter((v) => !v?.disabled); const combined = [...sources, ...embeds]; - const anyDuplicateId = hasDuplicates(combined.map((v) => v.id)); - const anyDuplicateSourceRank = hasDuplicates(sources.map((v) => v.rank)); - const anyDuplicateEmbedRank = hasDuplicates(embeds.map((v) => v.rank)); + // Check for duplicate IDs + const duplicateIds = findDuplicates(combined, (v) => v.id); + if (duplicateIds.length > 0) { + throw new Error(formatDuplicateError('Sources/embeds', duplicateIds, 'ID')); + } - if (anyDuplicateId) throw new Error('Duplicate id found in sources/embeds'); - if (anyDuplicateSourceRank) throw new Error('Duplicate rank found in sources'); - if (anyDuplicateEmbedRank) throw new Error('Duplicate rank found in embeds'); + // Check for duplicate source ranks + const duplicateSourceRanks = findDuplicates(sources, (v) => v.rank); + if (duplicateSourceRanks.length > 0) { + throw new Error(formatDuplicateError('Sources', duplicateSourceRanks, 'rank')); + } + + // Check for duplicate embed ranks + const duplicateEmbedRanks = findDuplicates(embeds, (v) => v.rank); + if (duplicateEmbedRanks.length > 0) { + throw new Error(formatDuplicateError('Embeds', duplicateEmbedRanks, 'rank')); + } return { sources: sources.filter((s) => flagsAllowedInFeatures(features, s.flags)),