mirror of https://github.com/iconify/api.git
126 lines
3.3 KiB
TypeScript
126 lines
3.3 KiB
TypeScript
import type { BaseDownloader } from '../../downloaders/base';
|
|
import { maybeAwait } from '../../misc/async';
|
|
import type {
|
|
BaseCollectionsImporter,
|
|
CreateIconSetImporter,
|
|
CreateIconSetImporterResult,
|
|
} from '../../types/importers/collections';
|
|
import type { ImportedData } from '../../types/importers/common';
|
|
|
|
/**
|
|
* Base collections list importer
|
|
*/
|
|
export function createBaseCollectionsListImporter<Downloader extends BaseDownloader<ImportedData>>(
|
|
instance: Downloader,
|
|
createIconSetImporter: CreateIconSetImporter
|
|
): Downloader & BaseCollectionsImporter {
|
|
const obj = instance as Downloader & BaseCollectionsImporter;
|
|
|
|
// Importers
|
|
const importers: Record<string, CreateIconSetImporterResult> = Object.create(null);
|
|
|
|
// Import status
|
|
let importing = false;
|
|
|
|
// Import each icon set
|
|
const importIconSets = async (prefixes: string[]): Promise<ImportedData> => {
|
|
importing = true;
|
|
|
|
// Reuse old data
|
|
const data: ImportedData = obj.data || {
|
|
prefixes,
|
|
iconSets: Object.create(null),
|
|
};
|
|
const iconSets = data.iconSets;
|
|
|
|
// Parse each prefix
|
|
for (let i = 0; i < prefixes.length; i++) {
|
|
const prefix = prefixes[i];
|
|
|
|
let importer = importers[prefix];
|
|
if (!importer) {
|
|
// New item
|
|
importer = importers[prefix] = await maybeAwait(createIconSetImporter(prefix));
|
|
importer._dataUpdated = async (iconSetData) => {
|
|
data.iconSets[prefix] = iconSetData;
|
|
if (!importing) {
|
|
// Call _dataUpdated() if icon set was updated outside of importIconSets()
|
|
obj._dataUpdated?.(data);
|
|
}
|
|
};
|
|
await importer.init();
|
|
|
|
// Data should have been updated in init()
|
|
continue;
|
|
}
|
|
|
|
// Item already exists: check for update
|
|
await importer.checkForUpdate();
|
|
}
|
|
|
|
// Change status
|
|
importing = false;
|
|
|
|
return {
|
|
prefixes,
|
|
iconSets,
|
|
};
|
|
};
|
|
|
|
// Import from directory
|
|
obj._loadDataFromDirectory = async (path: string) => {
|
|
if (!obj._loadCollectionsListFromDirectory) {
|
|
throw new Error('Importer does not implement _loadCollectionsListFromDirectory()');
|
|
}
|
|
const prefixes = await obj._loadCollectionsListFromDirectory(path);
|
|
if (prefixes) {
|
|
return await importIconSets(prefixes);
|
|
}
|
|
};
|
|
|
|
// Custom import
|
|
obj._loadData = async () => {
|
|
if (!obj._loadCollectionsList) {
|
|
throw new Error('Importer does not implement _loadCollectionsList()');
|
|
}
|
|
const prefixes = await obj._loadCollectionsList();
|
|
if (prefixes) {
|
|
return await importIconSets(prefixes);
|
|
}
|
|
};
|
|
|
|
// Check for update
|
|
const checkCollectionsForUpdate = obj.checkForUpdate.bind(obj);
|
|
const checkIconSetForUpdate = async (prefix: string): Promise<boolean> => {
|
|
const importer = importers[prefix];
|
|
if (importer) {
|
|
return await importer.checkForUpdate();
|
|
}
|
|
console.error(`Cannot check "${prefix}" for update: no such icon set`);
|
|
return false;
|
|
};
|
|
|
|
// Check everything for update
|
|
obj.checkForUpdate = async (): Promise<boolean> => {
|
|
let result = await checkCollectionsForUpdate();
|
|
const prefixes = obj.data?.prefixes.slice(0) || [];
|
|
for (let i = 0; i < prefixes.length; i++) {
|
|
const importer = importers[prefixes[i]];
|
|
if (importer) {
|
|
result = (await importer.checkForUpdate()) || result;
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
// Set instance properties
|
|
const baseData: BaseCollectionsImporter = {
|
|
type: 'collections',
|
|
checkCollectionsForUpdate,
|
|
checkIconSetForUpdate,
|
|
};
|
|
Object.assign(obj, baseData);
|
|
|
|
return obj;
|
|
}
|