Skip to content

Commit 5b33849

Browse files
committed
refactor: make CF loading cleaner
1 parent a7f5005 commit 5b33849

File tree

4 files changed

+45
-79
lines changed

4 files changed

+45
-79
lines changed

src/custom-formats.test.ts

+16-25
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
33
import * as config from "./config";
44
import { calculateCFsToManage, loadCustomFormatDefinitions, loadLocalCfs, mergeCfSources } from "./custom-formats";
55
import { loadTrashCFs } from "./trash-guide";
6-
import { CFProcessing } from "./types/common.types";
6+
import { CFIDToConfigGroup } from "./types/common.types";
77
import { ConfigCustomFormatList } from "./types/config.types";
88
import { TrashCF } from "./types/trashguide.types";
99
import * as util from "./util";
@@ -43,15 +43,15 @@ describe("CustomFormats", () => {
4343
vi.spyOn(config, "getConfig").mockReturnValue({ localCustomFormatsPath: undefined });
4444

4545
const result = await loadLocalCfs();
46-
expect(result).toBeNull();
46+
expect(result.size).toBe(0);
4747
});
4848

4949
it("should return null when configured path doesn't exist", async () => {
5050
vi.spyOn(config, "getConfig").mockReturnValue({ localCustomFormatsPath: "/fake/path" });
5151
vi.spyOn(fs, "existsSync").mockReturnValue(false);
5252

5353
const result = await loadLocalCfs();
54-
expect(result).toBeNull();
54+
expect(result.size).toBe(0);
5555
});
5656

5757
it("should load and process JSON files from configured path", async () => {
@@ -65,22 +65,16 @@ describe("CustomFormats", () => {
6565

6666
const result = await loadLocalCfs();
6767
expect(result).not.toBeNull();
68-
expect(result!.carrIdMapping.size).toBe(1);
69-
expect(result!.carrIdMapping.get(customCF.trash_id)).not.toBeNull();
68+
expect(result.size).toBe(1);
69+
expect(result.get(customCF.trash_id)).not.toBeNull();
7070
});
7171
});
7272

7373
describe("mergeCfSources", () => {
7474
it("should merge multiple CF sources correctly", () => {
75-
const source1: CFProcessing = {
76-
carrIdMapping: new Map([["id1", { carrConfig: { configarr_id: "id1", name: "CF1" }, requestConfig: {} }]]),
77-
cfNameToCarrConfig: new Map([["CF1", { configarr_id: "id1", name: "CF1" }]]),
78-
};
75+
const source1: CFIDToConfigGroup = new Map([["id1", { carrConfig: { configarr_id: "id1", name: "CF1" }, requestConfig: {} }]]);
7976

80-
const source2: CFProcessing = {
81-
carrIdMapping: new Map([["id2", { carrConfig: { configarr_id: "id2", name: "CF2" }, requestConfig: {} }]]),
82-
cfNameToCarrConfig: new Map([["CF2", { configarr_id: "id2", name: "CF2" }]]),
83-
};
77+
const source2: CFIDToConfigGroup = new Map([["id2", { carrConfig: { configarr_id: "id2", name: "CF2" }, requestConfig: {} }]]);
8478

8579
const result = mergeCfSources(new Set(["id1", "id2"]), [source1, source2, null]);
8680

@@ -112,10 +106,9 @@ describe("CustomFormats", () => {
112106

113107
describe("loadCustomFormatDefinitions", () => {
114108
it("should load and merge (trash CFDs", async () => {
115-
const mockTrashCFs: CFProcessing = {
116-
carrIdMapping: new Map([["trash1", { carrConfig: { configarr_id: "trash1", name: "trash1" }, requestConfig: {} }]]),
117-
cfNameToCarrConfig: new Map(),
118-
};
109+
const mockTrashCFs: CFIDToConfigGroup = new Map([
110+
["trash1", { carrConfig: { configarr_id: "trash1", name: "trash1" }, requestConfig: {} }],
111+
]);
119112

120113
vi.mock("./trash-guide");
121114
vi.mocked(loadTrashCFs).mockResolvedValue(mockTrashCFs);
@@ -128,10 +121,9 @@ describe("CustomFormats", () => {
128121
});
129122

130123
it("should load and merge (additional CFDs)", async () => {
131-
const mockTrashCFs: CFProcessing = {
132-
carrIdMapping: new Map([["trash1", { carrConfig: { configarr_id: "trash1", name: "trash1" }, requestConfig: {} }]]),
133-
cfNameToCarrConfig: new Map(),
134-
};
124+
const mockTrashCFs: CFIDToConfigGroup = new Map([
125+
["trash1", { carrConfig: { configarr_id: "trash1", name: "trash1" }, requestConfig: {} }],
126+
]);
135127

136128
vi.mock("./trash-guide");
137129
vi.mocked(loadTrashCFs).mockResolvedValue(mockTrashCFs);
@@ -144,10 +136,9 @@ describe("CustomFormats", () => {
144136
});
145137

146138
it("should ignore not managed CFs", async () => {
147-
const mockTrashCFs: CFProcessing = {
148-
carrIdMapping: new Map([["trash1", { carrConfig: { configarr_id: "trash1", name: "trash1" }, requestConfig: {} }]]),
149-
cfNameToCarrConfig: new Map(),
150-
};
139+
const mockTrashCFs: CFIDToConfigGroup = new Map([
140+
["trash1", { carrConfig: { configarr_id: "trash1", name: "trash1" }, requestConfig: {} }],
141+
]);
151142

152143
vi.mock("./trash-guide");
153144
vi.mocked(loadTrashCFs).mockResolvedValue(mockTrashCFs);

src/custom-formats.ts

+17-32
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { getConfig } from "./config";
66
import { getEnvs } from "./env";
77
import { logger } from "./logger";
88
import { loadTrashCFs } from "./trash-guide";
9-
import { ArrType, CFProcessing, ConfigarrCF } from "./types/common.types";
9+
import { ArrType, CFIDToConfigGroup, CFProcessing, ConfigarrCF } from "./types/common.types";
1010
import { ConfigCustomFormatList, CustomFormatDefinitions } from "./types/config.types";
1111
import { TrashCF } from "./types/trashguide.types";
1212
import { compareCustomFormats, loadJsonFile, mapImportCfToRequestCf, toCarrCF } from "./util";
@@ -116,24 +116,23 @@ export const manageCf = async (
116116
return { createCFs, updatedCFs, validCFs, errorCFs };
117117
};
118118

119-
export const loadLocalCfs = async (): Promise<CFProcessing | null> => {
119+
export const loadLocalCfs = async (): Promise<CFIDToConfigGroup> => {
120120
const config = getConfig();
121+
const carrIdToObject = new Map<string, { carrConfig: ConfigarrCF; requestConfig: MergedCustomFormatResource }>();
121122

122123
if (config.localCustomFormatsPath == null) {
123124
logger.debug(`No local custom formats specified. Skipping.`);
124-
return null;
125+
return carrIdToObject;
125126
}
126127

127128
const cfPath = path.resolve(config.localCustomFormatsPath);
128129

129130
if (!fs.existsSync(cfPath)) {
130131
logger.info(`Provided local custom formats path '${config.localCustomFormatsPath}' does not exist.`);
131-
return null;
132+
return carrIdToObject;
132133
}
133134

134135
const files = fs.readdirSync(`${cfPath}`).filter((fn) => fn.endsWith("json"));
135-
const carrIdToObject = new Map<string, { carrConfig: ConfigarrCF; requestConfig: MergedCustomFormatResource }>();
136-
const cfNameToCarrObject = new Map<string, ConfigarrCF>();
137136

138137
for (const file of files) {
139138
const name = `${cfPath}/${file}`;
@@ -145,19 +144,12 @@ export const loadLocalCfs = async (): Promise<CFProcessing | null> => {
145144
carrConfig: cfD,
146145
requestConfig: mapImportCfToRequestCf(cfD),
147146
});
148-
149-
if (cfD.name) {
150-
cfNameToCarrObject.set(cfD.name, cfD);
151-
}
152147
}
153148

154-
return {
155-
carrIdMapping: carrIdToObject,
156-
cfNameToCarrConfig: cfNameToCarrObject,
157-
};
149+
return carrIdToObject;
158150
};
159151

160-
export const loadCFFromConfig = (): CFProcessing | null => {
152+
export const loadCFFromConfig = (): CFIDToConfigGroup | null => {
161153
const defs = getConfig().customFormatDefinitions;
162154

163155
if (defs == null) {
@@ -168,41 +160,34 @@ export const loadCFFromConfig = (): CFProcessing | null => {
168160
return mapCustomFormatDefinitions(defs);
169161
};
170162

171-
export const mapCustomFormatDefinitions = (customFormatDefinitions: CustomFormatDefinitions): CFProcessing | null => {
163+
export const mapCustomFormatDefinitions = (customFormatDefinitions: CustomFormatDefinitions): CFIDToConfigGroup | null => {
172164
if (customFormatDefinitions == null) {
173165
return null;
174166
}
175167

176168
const carrIdToObject = new Map<string, { carrConfig: ConfigarrCF; requestConfig: MergedCustomFormatResource }>();
177-
const cfNameToCarrObject = new Map<string, ConfigarrCF>();
178169

179170
for (const def of customFormatDefinitions) {
180171
const cfD = toCarrCF(def);
181172

173+
if (carrIdToObject.has(cfD.configarr_id)) {
174+
logger.warn(`Duplicate ConfigCF ID found: '${cfD.configarr_id}'. Overwriting with name '${cfD.name}'`);
175+
}
176+
182177
carrIdToObject.set(cfD.configarr_id, {
183178
carrConfig: cfD,
184179
requestConfig: mapImportCfToRequestCf(cfD),
185180
});
186-
187-
if (cfD.name) {
188-
cfNameToCarrObject.set(cfD.name, cfD);
189-
}
190181
}
191182

192-
return {
193-
carrIdMapping: carrIdToObject,
194-
cfNameToCarrConfig: cfNameToCarrObject,
195-
};
183+
return carrIdToObject;
196184
};
197185

198186
export const loadCustomFormatDefinitions = async (idsToMange: Set<string>, arrType: ArrType, additionalCFDs: CustomFormatDefinitions) => {
199-
// TODO: the object CFProcessing is only needed as result from this method. All other should only work with ID -> object
200187
const trashCFs = await loadTrashCFs(arrType);
201188
const localFileCFs = await loadLocalCfs();
202189

203-
logger.debug(
204-
`Total loaded CF definitions: ${trashCFs.carrIdMapping.size} TrashCFs, ${localFileCFs?.carrIdMapping.size == null ? 0 : localFileCFs?.carrIdMapping.size} LocalCFs, ${additionalCFDs.length} ConfigCFs`,
205-
);
190+
logger.debug(`Total loaded CF definitions: ${trashCFs.size} TrashCFs, ${localFileCFs.size} LocalCFs, ${additionalCFDs.length} ConfigCFs`);
206191

207192
return mergeCfSources(idsToMange, [trashCFs, localFileCFs, mapCustomFormatDefinitions(additionalCFDs)]);
208193
};
@@ -219,15 +204,15 @@ export const calculateCFsToManage = (yaml: ConfigCustomFormatList) => {
219204
return cfTrashToManage;
220205
};
221206

222-
export const mergeCfSources = (idsToManage: Set<string>, listOfCfs: (CFProcessing | null)[]): CFProcessing => {
207+
export const mergeCfSources = (idsToManage: Set<string>, listOfCfs: (CFIDToConfigGroup | null)[]): CFProcessing => {
223208
return listOfCfs.reduce<CFProcessing>(
224209
(p, c) => {
225-
if (!c) {
210+
if (c == null) {
226211
return p;
227212
}
228213

229214
for (const test of idsToManage) {
230-
const value = c.carrIdMapping.get(test);
215+
const value = c.get(test);
231216
const cfName = value?.carrConfig.name!;
232217

233218
if (value) {

src/trash-guide.ts

+4-15
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import path from "node:path";
33
import { MergedCustomFormatResource } from "./__generated__/mergedTypes";
44
import { getConfig } from "./config";
55
import { logger } from "./logger";
6-
import { ArrType, CFProcessing, ConfigarrCF, QualityDefintionsRadarr, QualityDefintionsSonarr } from "./types/common.types";
6+
import { ArrType, CFIDToConfigGroup, ConfigarrCF, QualityDefintionsRadarr, QualityDefintionsSonarr } from "./types/common.types";
77
import { ConfigCustomFormat, ConfigQualityProfile, ConfigQualityProfileItem } from "./types/config.types";
88
import { TrashCF, TrashQP, TrashQualityDefintion } from "./types/trashguide.types";
99
import { cloneGitRepo, loadJsonFile, mapImportCfToRequestCf, notEmpty, toCarrCF, trashRepoPaths } from "./util";
@@ -22,14 +22,11 @@ export const cloneTrashRepo = async () => {
2222
logger.info(`TRaSH-Guides repo: ref[${cloneResult.ref}], hash[${cloneResult.hash}], path[${cloneResult.localPath}]`);
2323
};
2424

25-
export const loadTrashCFs = async (arrType: ArrType): Promise<CFProcessing> => {
25+
export const loadTrashCFs = async (arrType: ArrType): Promise<CFIDToConfigGroup> => {
2626
if (arrType !== "RADARR" && arrType !== "SONARR") {
2727
logger.debug(`Unsupported arrType: ${arrType}. Skipping TrashCFs.`);
2828

29-
return {
30-
carrIdMapping: new Map(),
31-
cfNameToCarrConfig: new Map(),
32-
};
29+
return new Map();
3330
}
3431

3532
const trashRepoPath = "./repos/trash-guides";
@@ -41,7 +38,6 @@ export const loadTrashCFs = async (arrType: ArrType): Promise<CFProcessing> => {
4138
const trashSonarrCfPath = `${trashSonarrPath}/cf`;
4239

4340
const carrIdToObject = new Map<string, { carrConfig: ConfigarrCF; requestConfig: MergedCustomFormatResource }>();
44-
const cfNameToCarrObject = new Map<string, ConfigarrCF>();
4541

4642
let pathForFiles: string;
4743

@@ -64,18 +60,11 @@ export const loadTrashCFs = async (arrType: ArrType): Promise<CFProcessing> => {
6460
carrConfig: carrConfig,
6561
requestConfig: mapImportCfToRequestCf(carrConfig),
6662
});
67-
68-
if (carrConfig.name) {
69-
cfNameToCarrObject.set(carrConfig.name, carrConfig);
70-
}
7163
}
7264

7365
logger.debug(`Trash CFs: ${carrIdToObject.size}`);
7466

75-
return {
76-
carrIdMapping: carrIdToObject,
77-
cfNameToCarrConfig: cfNameToCarrObject,
78-
};
67+
return carrIdToObject;
7968
};
8069

8170
export const loadQualityDefinitionFromTrash = async (

src/types/common.types.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,15 @@ export type ConfigarrCFMeta = {
5151

5252
export type ConfigarrCF = ConfigarrCFMeta & ImportCF;
5353

54+
type CFConfigGroup = {
55+
carrConfig: ConfigarrCF;
56+
requestConfig: MergedCustomFormatResource;
57+
};
58+
59+
export type CFIDToConfigGroup = Map<string, CFConfigGroup>;
60+
5461
export type CFProcessing = {
55-
carrIdMapping: Map<
56-
string,
57-
{
58-
carrConfig: ConfigarrCF;
59-
requestConfig: MergedCustomFormatResource;
60-
}
61-
>;
62+
carrIdMapping: CFIDToConfigGroup;
6263
cfNameToCarrConfig: Map<string, ConfigarrCF>;
6364
};
6465

0 commit comments

Comments
 (0)