diff --git a/src/importer/index.ts b/src/importer/index.ts index a2bf4be..44d265c 100644 --- a/src/importer/index.ts +++ b/src/importer/index.ts @@ -1,6 +1,7 @@ import { Config, ImportOptions, Thing } from "@types"; import { adapters } from "../adapters"; import { DummyOpenHAB, OpenHAB } from "../openhab"; +import { partitionBy } from "../utils/list"; const createFilter = (filter?: string) => { @@ -11,13 +12,8 @@ const createFilter = (filter?: string) => { return new Function("$", `const v = ${filter}; if(typeof v !== 'boolean') throw new Error("Filter should be of boolean type"); return v;`) as ((_: Thing) => true); }; -export const importThings = async (config: Config, options: ImportOptions) => { - const OH = options.dryRun ? DummyOpenHAB : OpenHAB; - const openhab = new OH(config.openHAB); - - const sources = options.sources ?? Object.keys(config.sources); - - const things = (await Promise.all(sources.map(source => { +const discoverThingsFromSources = async (sources: string[], config: Config, options: ImportOptions): Promise => { + const promises = sources.map(source => { const { type, config: cfg } = config.sources[source]; const constructor = adapters[type as keyof (typeof adapters)]; @@ -27,22 +23,30 @@ export const importThings = async (config: Config, options: ImportOptions) => { } return new constructor(source, cfg).loadThings(); - }))).flat(); + }); - const existingThings = await openhab.getThings(); - const existingThingsUIDs = existingThings.map(t => t.UID); - - const filter = createFilter(options.where); - - const thingsToImport = things - .filter(t => !existingThingsUIDs.includes(t.UID)) - .filter(filter); - - if (options.force) { - await openhab.deleteThings(...thingsToImport.map(t => t.UID)); - } - - await openhab.createThings(...thingsToImport); - - return thingsToImport; + const responses = await Promise.all(promises); + return responses.flat().filter(createFilter(options.where)); +} + +export const importThings = async (config: Config, options: ImportOptions) => { + const OH = options.dryRun ? DummyOpenHAB : OpenHAB; + const openhab = new OH(config.openHAB); + + const sources = options.sources ?? Object.keys(config.sources); + const allThingsToImport = await discoverThingsFromSources(sources, config, options); + + const allThingsInOH = await openhab.getThings(); + const existingThingsUIDs = allThingsInOH.map(t => t.UID); + + const [existing, missing] = partitionBy(allThingsToImport, t => existingThingsUIDs.includes(t.UID)); + + if (options.force) { + await openhab.deleteThings(...existing.map(t => t.UID)); + await openhab.createThings(...allThingsToImport); + return allThingsToImport; + } + + await openhab.createThings(...missing); + return missing; } diff --git a/src/utils/list.ts b/src/utils/list.ts new file mode 100644 index 0000000..0ca3419 --- /dev/null +++ b/src/utils/list.ts @@ -0,0 +1,3 @@ +export const partitionBy = (list: T[], condition: (item: T) => boolean): [T[], T[]] => { + return [list.filter(e => condition(e)), list.filter(e => !condition(e))]; +} \ No newline at end of file