mirror of
https://github.com/iconify/iconify.git
synced 2025-01-06 07:20:40 +00:00
Reuse storage for API data, clean up build scripts
This commit is contained in:
parent
9f71691fd2
commit
c1c849a61c
@ -1,16 +1,12 @@
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const child_process = require('child_process');
|
||||
|
||||
const coreDir = path.dirname(require.resolve('@iconify/core/package.json'));
|
||||
|
||||
// List of commands to run
|
||||
const commands = [];
|
||||
|
||||
// Parse command line
|
||||
const compile = {
|
||||
core: false,
|
||||
lib: true,
|
||||
rollup: true,
|
||||
api: true,
|
||||
@ -58,22 +54,9 @@ const fileExists = (file) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
if (compile.lib && !fileExists(coreDir + '/lib/cache.mjs')) {
|
||||
compile.core = true;
|
||||
}
|
||||
|
||||
// Compile core before compiling this package
|
||||
if (compile.core) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build'],
|
||||
cwd: coreDir,
|
||||
});
|
||||
}
|
||||
|
||||
// Compile other packages
|
||||
// Compile packages
|
||||
Object.keys(compile).forEach((key) => {
|
||||
if (key !== 'core' && compile[key]) {
|
||||
if (compile[key]) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build:' + key],
|
||||
|
@ -1,17 +1,12 @@
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const child_process = require('child_process');
|
||||
|
||||
const coreDir = path.dirname(require.resolve('@iconify/core/package.json'));
|
||||
|
||||
// List of commands to run
|
||||
const commands = [];
|
||||
|
||||
// Build process
|
||||
const compile = {
|
||||
// Compile @iconify/core
|
||||
core: false,
|
||||
// Compile TypeScript src -> lib
|
||||
lib: true,
|
||||
// Fix types for icon components
|
||||
@ -72,22 +67,9 @@ if (compile.api && !fileExists('./lib/icon.d.ts')) {
|
||||
compile.lib = true;
|
||||
}
|
||||
|
||||
if (compile.lib && !fileExists(coreDir + '/lib/cache.mjs')) {
|
||||
compile.core = true;
|
||||
}
|
||||
|
||||
// Compile core before compiling this package
|
||||
if (compile.core) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build'],
|
||||
cwd: coreDir,
|
||||
});
|
||||
}
|
||||
|
||||
// Compile other packages
|
||||
// Compile packages
|
||||
Object.keys(compile).forEach((key) => {
|
||||
if (key !== 'core' && compile[key]) {
|
||||
if (compile[key]) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build:' + key],
|
||||
|
@ -1,9 +1,6 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const child_process = require('child_process');
|
||||
|
||||
const coreDir = path.dirname(require.resolve('@iconify/core/package.json'));
|
||||
|
||||
// List of commands to run
|
||||
const commands = [];
|
||||
|
||||
@ -13,7 +10,6 @@ const extractor = (name) =>
|
||||
|
||||
// Parse command line
|
||||
const compile = {
|
||||
core: false,
|
||||
tsc: true,
|
||||
bundles: true,
|
||||
api: true,
|
||||
@ -61,28 +57,12 @@ const fileExists = (file) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
if (compile.dist && !fileExists(coreDir + '/lib/modules.mjs')) {
|
||||
compile.core = true;
|
||||
}
|
||||
|
||||
// Compile core before compiling this package
|
||||
if (compile.core) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build'],
|
||||
cwd: coreDir,
|
||||
});
|
||||
}
|
||||
|
||||
// Compile other packages
|
||||
// Compile packages
|
||||
Object.keys(compile).forEach((key) => {
|
||||
if (!compile[key]) {
|
||||
return;
|
||||
}
|
||||
switch (key) {
|
||||
case 'core':
|
||||
break;
|
||||
|
||||
case 'api':
|
||||
apiFiles().forEach((name) => {
|
||||
const cmd = extractor(name).split(' ');
|
||||
|
@ -1,16 +1,12 @@
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const child_process = require('child_process');
|
||||
|
||||
const coreDir = path.dirname(require.resolve('@iconify/core/package.json'));
|
||||
|
||||
// List of commands to run
|
||||
const commands = [];
|
||||
|
||||
// Parse command line
|
||||
const compile = {
|
||||
core: false,
|
||||
lib: true,
|
||||
dist: true,
|
||||
api: true,
|
||||
@ -65,27 +61,14 @@ if (compile.api && !fileExists('./lib/iconify.d.ts')) {
|
||||
compile.lib = true;
|
||||
}
|
||||
|
||||
if (compile.lib && !fileExists(coreDir + '/lib/cache.mjs')) {
|
||||
compile.core = true;
|
||||
}
|
||||
|
||||
// Compile core before compiling this package
|
||||
if (compile.core) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build'],
|
||||
cwd: coreDir,
|
||||
});
|
||||
}
|
||||
|
||||
// Add api2
|
||||
if (compile.api) {
|
||||
compile.api2 = true;
|
||||
}
|
||||
|
||||
// Compile other packages
|
||||
// Compile packages
|
||||
Object.keys(compile).forEach((key) => {
|
||||
if (key !== 'core' && compile[key]) {
|
||||
if (compile[key]) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build:' + key],
|
||||
|
@ -1,16 +1,12 @@
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const child_process = require('child_process');
|
||||
|
||||
const coreDir = path.dirname(require.resolve('@iconify/core/package.json'));
|
||||
|
||||
// List of commands to run
|
||||
const commands = [];
|
||||
|
||||
// Parse command line
|
||||
const compile = {
|
||||
core: false,
|
||||
lib: true,
|
||||
dist: true,
|
||||
api: true,
|
||||
@ -65,22 +61,9 @@ if (compile.api && !fileExists('./lib/IconifyIcon.d.ts')) {
|
||||
compile.lib = true;
|
||||
}
|
||||
|
||||
if (compile.lib && !fileExists(coreDir + '/lib/cache.mjs')) {
|
||||
compile.core = true;
|
||||
}
|
||||
|
||||
// Compile core before compiling this package
|
||||
if (compile.core) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build'],
|
||||
cwd: coreDir,
|
||||
});
|
||||
}
|
||||
|
||||
// Compile other packages
|
||||
// Compile packages
|
||||
Object.keys(compile).forEach((key) => {
|
||||
if (key !== 'core' && compile[key]) {
|
||||
if (compile[key]) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build:' + key],
|
||||
|
@ -1,21 +1,17 @@
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const child_process = require('child_process');
|
||||
|
||||
const coreDir = path.dirname(require.resolve('@iconify/core/package.json'));
|
||||
|
||||
// List of commands to run
|
||||
const commands = [];
|
||||
|
||||
// Parse command line
|
||||
const compile = {
|
||||
core: false,
|
||||
lib: true,
|
||||
dist: true,
|
||||
api: true,
|
||||
};
|
||||
process.argv.slice(2).forEach(cmd => {
|
||||
process.argv.slice(2).forEach((cmd) => {
|
||||
if (cmd.slice(0, 2) !== '--') {
|
||||
return;
|
||||
}
|
||||
@ -39,7 +35,7 @@ process.argv.slice(2).forEach(cmd => {
|
||||
|
||||
case 'only':
|
||||
// disable other modules
|
||||
Object.keys(compile).forEach(key2 => {
|
||||
Object.keys(compile).forEach((key2) => {
|
||||
compile[key2] = key2 === key;
|
||||
});
|
||||
break;
|
||||
@ -48,7 +44,7 @@ process.argv.slice(2).forEach(cmd => {
|
||||
});
|
||||
|
||||
// Check if required modules in same monorepo are available
|
||||
const fileExists = file => {
|
||||
const fileExists = (file) => {
|
||||
try {
|
||||
fs.statSync(file);
|
||||
} catch (e) {
|
||||
@ -65,22 +61,9 @@ if (compile.api && !fileExists('./lib/IconifyIcon.d.ts')) {
|
||||
compile.lib = true;
|
||||
}
|
||||
|
||||
if (compile.lib && !fileExists(coreDir + '/lib/cache.mjs')) {
|
||||
compile.core = true;
|
||||
}
|
||||
|
||||
// Compile core before compiling this package
|
||||
if (compile.core) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build'],
|
||||
cwd: coreDir,
|
||||
});
|
||||
}
|
||||
|
||||
// Compile other packages
|
||||
Object.keys(compile).forEach(key => {
|
||||
if (key !== 'core' && compile[key]) {
|
||||
// Compile packages
|
||||
Object.keys(compile).forEach((key) => {
|
||||
if (compile[key]) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build:' + key],
|
||||
|
@ -1,16 +1,12 @@
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const child_process = require('child_process');
|
||||
|
||||
const coreDir = path.dirname(require.resolve('@iconify/core/package.json'));
|
||||
|
||||
// List of commands to run
|
||||
const commands = [];
|
||||
|
||||
// Parse command line
|
||||
const compile = {
|
||||
core: false,
|
||||
lib: true,
|
||||
dist: true,
|
||||
api: true,
|
||||
@ -65,22 +61,9 @@ if (compile.api && !fileExists('./lib/index.d.ts')) {
|
||||
compile.lib = true;
|
||||
}
|
||||
|
||||
if (compile.lib && !fileExists(coreDir + '/lib/cache.mjs')) {
|
||||
compile.core = true;
|
||||
}
|
||||
|
||||
// Compile core before compiling this package
|
||||
if (compile.core) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build'],
|
||||
cwd: coreDir,
|
||||
});
|
||||
}
|
||||
|
||||
// Compile other packages
|
||||
// Compile packages
|
||||
Object.keys(compile).forEach((key) => {
|
||||
if (key !== 'core' && compile[key]) {
|
||||
if (compile[key]) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build:' + key],
|
||||
|
@ -57,6 +57,10 @@
|
||||
"require": "./lib/api/query.cjs",
|
||||
"import": "./lib/api/query.mjs"
|
||||
},
|
||||
"./lib/api/types": {
|
||||
"require": "./lib/api/types.cjs",
|
||||
"import": "./lib/api/types.mjs"
|
||||
},
|
||||
"./lib/browser-storage/config": {
|
||||
"require": "./lib/browser-storage/config.cjs",
|
||||
"import": "./lib/browser-storage/config.mjs"
|
||||
|
@ -2,59 +2,17 @@ import type {
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
} from './icons';
|
||||
import { getStorage } from '../storage/storage';
|
||||
import type { SortedIcons } from '../icon/sort';
|
||||
import type { IconifyIconSource } from '@iconify/utils/lib/icon/name';
|
||||
|
||||
/**
|
||||
* Storage for callbacks
|
||||
*/
|
||||
interface CallbackItem {
|
||||
// id
|
||||
id: number;
|
||||
|
||||
// Icons
|
||||
icons: SortedIcons;
|
||||
|
||||
// Callback to call on any update
|
||||
callback: IconifyIconLoaderCallback;
|
||||
|
||||
// Callback to call to remove item from queue
|
||||
abort: IconifyIconLoaderAbort;
|
||||
}
|
||||
|
||||
type PrefixCallbackItems = CallbackItem[];
|
||||
type ProviderCallbackItems = Record<string, PrefixCallbackItems>;
|
||||
|
||||
// Records sorted by provider and prefix
|
||||
// This export is only for unit testing, should not be used
|
||||
export const callbacks = Object.create(null) as Record<
|
||||
string,
|
||||
ProviderCallbackItems
|
||||
>;
|
||||
|
||||
// List of provider/prefix combinations that need to be updated
|
||||
type ProviderPendingUpdates = Record<string, boolean>;
|
||||
const pendingUpdates = Object.create(null) as Record<
|
||||
string,
|
||||
ProviderPendingUpdates
|
||||
>;
|
||||
import type { APICallbackItem, IconStorageWithIcons } from './types';
|
||||
|
||||
/**
|
||||
* Remove callback
|
||||
*/
|
||||
function removeCallback(sources: IconifyIconSource[], id: number): void {
|
||||
sources.forEach((source) => {
|
||||
const provider = source.provider;
|
||||
if (callbacks[provider] === void 0) {
|
||||
return;
|
||||
}
|
||||
const providerCallbacks = callbacks[provider];
|
||||
|
||||
const prefix = source.prefix;
|
||||
const items = providerCallbacks[prefix];
|
||||
function removeCallback(storages: IconStorageWithIcons[], id: number): void {
|
||||
storages.forEach((storage) => {
|
||||
const items = storage.loaderCallbacks;
|
||||
if (items) {
|
||||
providerCallbacks[prefix] = items.filter((row) => row.id !== id);
|
||||
storage.loaderCallbacks = items.filter((row) => row.id !== id);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -62,37 +20,26 @@ function removeCallback(sources: IconifyIconSource[], id: number): void {
|
||||
/**
|
||||
* Update all callbacks for provider and prefix
|
||||
*/
|
||||
export function updateCallbacks(provider: string, prefix: string): void {
|
||||
if (pendingUpdates[provider] === void 0) {
|
||||
pendingUpdates[provider] = Object.create(
|
||||
null
|
||||
) as ProviderPendingUpdates;
|
||||
}
|
||||
const providerPendingUpdates = pendingUpdates[provider];
|
||||
|
||||
if (!providerPendingUpdates[prefix]) {
|
||||
providerPendingUpdates[prefix] = true;
|
||||
export function updateCallbacks(storage: IconStorageWithIcons): void {
|
||||
if (!storage.pendingCallbacksFlag) {
|
||||
storage.pendingCallbacksFlag = true;
|
||||
setTimeout(() => {
|
||||
providerPendingUpdates[prefix] = false;
|
||||
|
||||
if (
|
||||
callbacks[provider] === void 0 ||
|
||||
callbacks[provider][prefix] === void 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
storage.pendingCallbacksFlag = false;
|
||||
|
||||
// Get all items
|
||||
const items = callbacks[provider][prefix].slice(0);
|
||||
const items = storage.loaderCallbacks
|
||||
? storage.loaderCallbacks.slice(0)
|
||||
: [];
|
||||
if (!items.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const storage = getStorage(provider, prefix);
|
||||
|
||||
// Check each item for changes
|
||||
let hasPending = false;
|
||||
items.forEach((item: CallbackItem) => {
|
||||
const provider = storage.provider;
|
||||
const prefix = storage.prefix;
|
||||
|
||||
items.forEach((item) => {
|
||||
const icons = item.icons;
|
||||
const oldLength = icons.pending.length;
|
||||
icons.pending = icons.pending.filter((icon) => {
|
||||
@ -129,15 +76,7 @@ export function updateCallbacks(provider: string, prefix: string): void {
|
||||
if (icons.pending.length !== oldLength) {
|
||||
if (!hasPending) {
|
||||
// All icons have been loaded - remove callback from prefix
|
||||
removeCallback(
|
||||
[
|
||||
{
|
||||
provider,
|
||||
prefix,
|
||||
},
|
||||
],
|
||||
item.id
|
||||
);
|
||||
removeCallback([storage], item.id);
|
||||
}
|
||||
item.callback(
|
||||
icons.loaded.slice(0),
|
||||
@ -162,7 +101,7 @@ let idCounter = 0;
|
||||
export function storeCallback(
|
||||
callback: IconifyIconLoaderCallback,
|
||||
icons: SortedIcons,
|
||||
pendingSources: IconifyIconSource[]
|
||||
pendingSources: IconStorageWithIcons[]
|
||||
): IconifyIconLoaderAbort {
|
||||
// Create unique id and abort function
|
||||
const id = idCounter++;
|
||||
@ -174,24 +113,15 @@ export function storeCallback(
|
||||
}
|
||||
|
||||
// Create item and store it for all pending prefixes
|
||||
const item: CallbackItem = {
|
||||
const item: APICallbackItem = {
|
||||
id,
|
||||
icons,
|
||||
callback,
|
||||
abort: abort,
|
||||
};
|
||||
|
||||
pendingSources.forEach((source) => {
|
||||
const provider = source.provider;
|
||||
const prefix = source.prefix;
|
||||
if (callbacks[provider] === void 0) {
|
||||
callbacks[provider] = Object.create(null) as ProviderCallbackItems;
|
||||
}
|
||||
const providerCallbacks = callbacks[provider];
|
||||
if (providerCallbacks[prefix] === void 0) {
|
||||
providerCallbacks[prefix] = [];
|
||||
}
|
||||
providerCallbacks[prefix].push(item);
|
||||
pendingSources.forEach((storage) => {
|
||||
(storage.loaderCallbacks || (storage.loaderCallbacks = [])).push(item);
|
||||
});
|
||||
|
||||
return abort;
|
||||
|
@ -1,9 +1,5 @@
|
||||
import type { IconifyIcon, IconifyJSON } from '@iconify/types';
|
||||
import {
|
||||
IconifyIconName,
|
||||
IconifyIconSource,
|
||||
stringToIcon,
|
||||
} from '@iconify/utils/lib/icon/name';
|
||||
import { IconifyIconName, stringToIcon } from '@iconify/utils/lib/icon/name';
|
||||
import type { SortedIcons } from '../icon/sort';
|
||||
import { sortIcons } from '../icon/sort';
|
||||
import { storeCallback, updateCallbacks } from './callbacks';
|
||||
@ -13,6 +9,7 @@ import { listToIcons } from '../icon/list';
|
||||
import { allowSimpleNames, getIconData } from '../storage/functions';
|
||||
import { sendAPIQuery } from './query';
|
||||
import { storeInBrowserStorage } from '../browser-storage/store';
|
||||
import type { IconStorageWithIcons } from './types';
|
||||
|
||||
// Empty abort callback for loadIcons()
|
||||
function emptyCallback(): void {
|
||||
@ -49,126 +46,46 @@ export type IconifyLoadIcons = (
|
||||
*/
|
||||
export type IsPending = (icon: IconifyIconName) => boolean;
|
||||
|
||||
/**
|
||||
* List of icons that are being loaded.
|
||||
*
|
||||
* Icons are added to this list when they are being checked and
|
||||
* removed from this list when they are added to storage as
|
||||
* either an icon or a missing icon. This way same icon should
|
||||
* never be requested twice.
|
||||
*
|
||||
* [provider][prefix][icon] = time when icon was added to queue
|
||||
*/
|
||||
type PrefixPendingIcons = Record<string, number>;
|
||||
type ProviderPendingIcons = Record<string, PrefixPendingIcons>;
|
||||
|
||||
const pendingIcons = Object.create(null) as Record<
|
||||
string,
|
||||
ProviderPendingIcons
|
||||
>;
|
||||
|
||||
/**
|
||||
* List of icons that are waiting to be loaded.
|
||||
*
|
||||
* List is passed to API module, then cleared.
|
||||
*
|
||||
* This list should not be used for any checks, use pendingIcons to check
|
||||
* if icons is being loaded.
|
||||
*
|
||||
* [provider][prefix] = array of icon names
|
||||
*/
|
||||
type IconsToLoadPrefixItem = string[];
|
||||
type IconsToLoadProviderItem = Record<string, IconsToLoadPrefixItem>;
|
||||
|
||||
const iconsToLoad = Object.create(null) as Record<
|
||||
string,
|
||||
IconsToLoadProviderItem
|
||||
>;
|
||||
|
||||
// Flags to merge multiple synchronous icon requests in one asynchronous request
|
||||
type FlagsItem = Record<string, boolean>;
|
||||
|
||||
const loaderFlags = Object.create(null) as Record<string, FlagsItem>;
|
||||
const queueFlags = Object.create(null) as Record<string, FlagsItem>;
|
||||
|
||||
/**
|
||||
* Function called when new icons have been loaded
|
||||
*/
|
||||
function loadedNewIcons(provider: string, prefix: string): void {
|
||||
function loadedNewIcons(storage: IconStorageWithIcons): void {
|
||||
// Run only once per tick, possibly joining multiple API responses in one call
|
||||
if (loaderFlags[provider] === void 0) {
|
||||
loaderFlags[provider] = Object.create(null) as FlagsItem;
|
||||
}
|
||||
const providerLoaderFlags = loaderFlags[provider];
|
||||
if (!providerLoaderFlags[prefix]) {
|
||||
providerLoaderFlags[prefix] = true;
|
||||
if (!storage.iconsLoaderFlag) {
|
||||
storage.iconsLoaderFlag = true;
|
||||
setTimeout(() => {
|
||||
providerLoaderFlags[prefix] = false;
|
||||
updateCallbacks(provider, prefix);
|
||||
storage.iconsLoaderFlag = false;
|
||||
updateCallbacks(storage);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Storage for errors for loadNewIcons(). Used to avoid spamming log with identical errors.
|
||||
const errorsCache = Object.create(null) as Record<string, number>;
|
||||
|
||||
/**
|
||||
* Load icons
|
||||
*/
|
||||
function loadNewIcons(provider: string, prefix: string, icons: string[]): void {
|
||||
function err(): void {
|
||||
const key = (provider === '' ? '' : '@' + provider + ':') + prefix;
|
||||
const time = Math.floor(Date.now() / 60000); // log once in a minute
|
||||
if (errorsCache[key] < time) {
|
||||
errorsCache[key] = time;
|
||||
console.error(
|
||||
'Unable to retrieve icons for "' +
|
||||
key +
|
||||
'" because API is not configured properly.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Create nested objects if needed
|
||||
if (iconsToLoad[provider] === void 0) {
|
||||
iconsToLoad[provider] = Object.create(null) as IconsToLoadProviderItem;
|
||||
}
|
||||
const providerIconsToLoad = iconsToLoad[provider];
|
||||
|
||||
if (queueFlags[provider] === void 0) {
|
||||
queueFlags[provider] = Object.create(null) as FlagsItem;
|
||||
}
|
||||
const providerQueueFlags = queueFlags[provider];
|
||||
|
||||
if (pendingIcons[provider] === void 0) {
|
||||
pendingIcons[provider] = Object.create(null) as ProviderPendingIcons;
|
||||
}
|
||||
const providerPendingIcons = pendingIcons[provider];
|
||||
|
||||
function loadNewIcons(storage: IconStorageWithIcons, icons: string[]): void {
|
||||
// Add icons to queue
|
||||
if (providerIconsToLoad[prefix] === void 0) {
|
||||
providerIconsToLoad[prefix] = icons;
|
||||
if (!storage.iconsToLoad) {
|
||||
storage.iconsToLoad = icons;
|
||||
} else {
|
||||
providerIconsToLoad[prefix] = providerIconsToLoad[prefix]
|
||||
.concat(icons)
|
||||
.sort();
|
||||
storage.iconsToLoad = storage.iconsToLoad.concat(icons).sort();
|
||||
}
|
||||
|
||||
// Trigger update on next tick, mering multiple synchronous requests into one asynchronous request
|
||||
if (!providerQueueFlags[prefix]) {
|
||||
providerQueueFlags[prefix] = true;
|
||||
if (!storage.iconsQueueFlag) {
|
||||
storage.iconsQueueFlag = true;
|
||||
setTimeout(() => {
|
||||
providerQueueFlags[prefix] = false;
|
||||
storage.iconsQueueFlag = false;
|
||||
const { provider, prefix } = storage;
|
||||
|
||||
// Get icons and delete queue
|
||||
const icons = providerIconsToLoad[prefix];
|
||||
delete providerIconsToLoad[prefix];
|
||||
const icons = storage.iconsToLoad;
|
||||
delete storage.iconsToLoad;
|
||||
|
||||
// Get API module
|
||||
const api = getAPIModule(provider);
|
||||
if (!api) {
|
||||
// No way to load icons!
|
||||
err();
|
||||
let api: ReturnType<typeof getAPIModule>;
|
||||
if (!icons || !(api = getAPIModule(provider))) {
|
||||
// No icons or no way to load icons!
|
||||
return;
|
||||
}
|
||||
|
||||
@ -176,8 +93,6 @@ function loadNewIcons(provider: string, prefix: string, icons: string[]): void {
|
||||
const params = api.prepare(provider, prefix, icons);
|
||||
params.forEach((item) => {
|
||||
sendAPIQuery(provider, item, (data, error) => {
|
||||
const storage = getStorage(provider, prefix);
|
||||
|
||||
// Check for error
|
||||
if (typeof data !== 'object') {
|
||||
if (error !== 404) {
|
||||
@ -201,10 +116,12 @@ function loadNewIcons(provider: string, prefix: string, icons: string[]): void {
|
||||
}
|
||||
|
||||
// Remove added icons from pending list
|
||||
const pending = providerPendingIcons[prefix];
|
||||
parsed.forEach((name) => {
|
||||
delete pending[name];
|
||||
});
|
||||
const pending = storage.pendingIcons;
|
||||
if (pending) {
|
||||
parsed.forEach((name) => {
|
||||
pending.delete(name);
|
||||
});
|
||||
}
|
||||
|
||||
// Cache API response
|
||||
storeInBrowserStorage(
|
||||
@ -217,7 +134,7 @@ function loadNewIcons(provider: string, prefix: string, icons: string[]): void {
|
||||
}
|
||||
|
||||
// Trigger update on next tick
|
||||
loadedNewIcons(provider, prefix);
|
||||
loadedNewIcons(storage);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -228,13 +145,12 @@ function loadNewIcons(provider: string, prefix: string, icons: string[]): void {
|
||||
* Check if icon is being loaded
|
||||
*/
|
||||
export const isPending: IsPending = (icon: IconifyIconName): boolean => {
|
||||
const provider = icon.provider;
|
||||
const prefix = icon.prefix;
|
||||
return (
|
||||
pendingIcons[provider] &&
|
||||
pendingIcons[provider][prefix] &&
|
||||
pendingIcons[provider][prefix][icon.name] !== void 0
|
||||
);
|
||||
const storage = getStorage(
|
||||
icon.provider,
|
||||
icon.prefix
|
||||
) as IconStorageWithIcons;
|
||||
const pending = storage.pendingIcons;
|
||||
return !!(pending && pending.has(icon.name));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -280,59 +196,41 @@ export const loadIcons: IconifyLoadIcons = (
|
||||
string,
|
||||
ProviderNewIconsList
|
||||
>;
|
||||
const sources: IconifyIconSource[] = [];
|
||||
const sources: IconStorageWithIcons[] = [];
|
||||
let lastProvider: string, lastPrefix: string;
|
||||
|
||||
sortedIcons.pending.forEach((icon) => {
|
||||
const provider = icon.provider;
|
||||
const prefix = icon.prefix;
|
||||
const { provider, prefix } = icon;
|
||||
if (prefix === lastPrefix && provider === lastProvider) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastProvider = provider;
|
||||
lastPrefix = prefix;
|
||||
sources.push({
|
||||
provider,
|
||||
prefix,
|
||||
});
|
||||
sources.push(getStorage(provider, prefix));
|
||||
|
||||
if (pendingIcons[provider] === void 0) {
|
||||
pendingIcons[provider] = Object.create(
|
||||
null
|
||||
) as ProviderPendingIcons;
|
||||
}
|
||||
const providerPendingIcons = pendingIcons[provider];
|
||||
if (providerPendingIcons[prefix] === void 0) {
|
||||
providerPendingIcons[prefix] = Object.create(
|
||||
null
|
||||
) as PrefixPendingIcons;
|
||||
}
|
||||
|
||||
if (newIcons[provider] === void 0) {
|
||||
newIcons[provider] = Object.create(null) as ProviderNewIconsList;
|
||||
}
|
||||
const providerNewIcons = newIcons[provider];
|
||||
if (providerNewIcons[prefix] === void 0) {
|
||||
const providerNewIcons =
|
||||
newIcons[provider] ||
|
||||
(newIcons[provider] = Object.create(null) as ProviderNewIconsList);
|
||||
if (!providerNewIcons[prefix]) {
|
||||
providerNewIcons[prefix] = [];
|
||||
}
|
||||
});
|
||||
|
||||
// List of new icons
|
||||
const time = Date.now();
|
||||
|
||||
// Filter pending icons list: find icons that are not being loaded yet
|
||||
// If icon was called before, it must exist in pendingIcons or storage, but because this
|
||||
// function is called right after sortIcons() that checks storage, icon is definitely not in storage.
|
||||
sortedIcons.pending.forEach((icon) => {
|
||||
const provider = icon.provider;
|
||||
const prefix = icon.prefix;
|
||||
const name = icon.name;
|
||||
const { provider, prefix, name } = icon;
|
||||
|
||||
const pendingQueue = pendingIcons[provider][prefix];
|
||||
if (pendingQueue[name] === void 0) {
|
||||
const storage = getStorage(provider, prefix) as IconStorageWithIcons;
|
||||
const pendingQueue =
|
||||
storage.pendingIcons || (storage.pendingIcons = new Set());
|
||||
|
||||
if (!pendingQueue.has(name)) {
|
||||
// New icon - add to pending queue to mark it as being loaded
|
||||
pendingQueue[name] = time;
|
||||
pendingQueue.add(name);
|
||||
// Add it to new icons list to pass it to API module for loading
|
||||
newIcons[provider][prefix].push(name);
|
||||
}
|
||||
@ -340,11 +238,10 @@ export const loadIcons: IconifyLoadIcons = (
|
||||
|
||||
// Load icons on next tick to make sure result is not returned before callback is stored and
|
||||
// to consolidate multiple synchronous loadIcons() calls into one asynchronous API call
|
||||
sources.forEach((source) => {
|
||||
const provider = source.provider;
|
||||
const prefix = source.prefix;
|
||||
sources.forEach((storage) => {
|
||||
const { provider, prefix } = storage;
|
||||
if (newIcons[provider][prefix].length) {
|
||||
loadNewIcons(provider, prefix, newIcons[provider][prefix]);
|
||||
loadNewIcons(storage, newIcons[provider][prefix]);
|
||||
}
|
||||
});
|
||||
|
||||
|
60
packages/core/src/api/types.ts
Normal file
60
packages/core/src/api/types.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import type {
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
} from './icons';
|
||||
import type { SortedIcons } from '../icon/sort';
|
||||
import type { IconStorage } from '../storage/storage';
|
||||
|
||||
/**
|
||||
* Storage for callbacks
|
||||
*/
|
||||
export interface APICallbackItem {
|
||||
// id
|
||||
id: number;
|
||||
|
||||
// Icons
|
||||
icons: SortedIcons;
|
||||
|
||||
// Callback to call on any update
|
||||
callback: IconifyIconLoaderCallback;
|
||||
|
||||
// Callback to call to remove item from queue
|
||||
abort: IconifyIconLoaderAbort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom stuff to storage
|
||||
*/
|
||||
export interface IconStorageWithIcons extends IconStorage {
|
||||
/**
|
||||
* List of icons that are being loaded, added to storage
|
||||
*
|
||||
* Icons are added to this list when they are being checked and
|
||||
* removed from this list when they are added to storage as
|
||||
* either an icon or a missing icon. This way same icon should
|
||||
* never be requested twice.
|
||||
*/
|
||||
pendingIcons?: Set<string>;
|
||||
|
||||
/**
|
||||
* List of icons that are waiting to be loaded.
|
||||
*
|
||||
* List is passed to API module, then cleared.
|
||||
*
|
||||
* This list should not be used for any checks, use pendingIcons to check
|
||||
* if icons is being loaded.
|
||||
*
|
||||
* [provider][prefix] = array of icon names
|
||||
*/
|
||||
iconsToLoad?: string[];
|
||||
|
||||
// Flags to merge multiple synchronous icon requests in one asynchronous request
|
||||
iconsLoaderFlag?: boolean;
|
||||
iconsQueueFlag?: boolean;
|
||||
|
||||
// Loader callbacks
|
||||
loaderCallbacks?: APICallbackItem[];
|
||||
|
||||
// Pending callbacks update
|
||||
pendingCallbacksFlag?: boolean;
|
||||
}
|
@ -2,7 +2,6 @@ import type {
|
||||
BrowserStorageConfig,
|
||||
BrowserStorageCount,
|
||||
BrowserStorageEmptyList,
|
||||
BrowserStorageStatus,
|
||||
} from './types';
|
||||
|
||||
/**
|
||||
@ -32,8 +31,8 @@ export const browserStorageEmptyItems: BrowserStorageEmptyList = {
|
||||
/**
|
||||
* Flag to check if storage has been loaded
|
||||
*/
|
||||
export let browserStorageStatus: BrowserStorageStatus = false;
|
||||
export let browserStorageStatus = false;
|
||||
|
||||
export function setBrowserStorageStatus(status: BrowserStorageStatus) {
|
||||
export function setBrowserStorageStatus(status: boolean) {
|
||||
browserStorageStatus = status;
|
||||
}
|
||||
|
@ -23,10 +23,10 @@ import type { BrowserStorageConfig, BrowserStorageItem } from './types';
|
||||
* Load icons from cache
|
||||
*/
|
||||
export function initBrowserStorage() {
|
||||
if (browserStorageStatus === true) {
|
||||
if (browserStorageStatus) {
|
||||
return;
|
||||
}
|
||||
setBrowserStorageStatus('loading');
|
||||
setBrowserStorageStatus(true);
|
||||
|
||||
// Minimum time
|
||||
const minTime =
|
||||
@ -66,10 +66,12 @@ export function initBrowserStorage() {
|
||||
valid = false;
|
||||
} else {
|
||||
// Add icon set
|
||||
const iconSet = data.data;
|
||||
|
||||
const provider = data.provider;
|
||||
const prefix = data.data.prefix;
|
||||
const prefix = iconSet.prefix;
|
||||
const storage = getStorage(provider, prefix);
|
||||
valid = addIconSet(storage, data.data).length > 0;
|
||||
valid = addIconSet(storage, iconSet).length > 0;
|
||||
}
|
||||
} catch (err) {
|
||||
valid = false;
|
||||
@ -129,9 +131,10 @@ export function initBrowserStorage() {
|
||||
}
|
||||
}
|
||||
|
||||
// Load each storage
|
||||
for (const key in browserStorageConfig) {
|
||||
load(key as keyof BrowserStorageConfig);
|
||||
}
|
||||
|
||||
setBrowserStorageStatus(true);
|
||||
// Check for update
|
||||
}
|
||||
|
@ -18,9 +18,6 @@ export function storeInBrowserStorage(provider: string, data: IconifyJSON) {
|
||||
if (!browserStorageStatus) {
|
||||
initBrowserStorage();
|
||||
}
|
||||
if (browserStorageStatus === 'loading') {
|
||||
return;
|
||||
}
|
||||
|
||||
function store(key: BrowserStorageType): true | undefined {
|
||||
if (!browserStorageConfig[key]) {
|
||||
|
@ -18,6 +18,3 @@ export interface BrowserStorageItem {
|
||||
provider: string;
|
||||
data: IconifyJSON;
|
||||
}
|
||||
|
||||
// Status: not loaded, loading, loaded
|
||||
export type BrowserStorageStatus = false | 'loading' | true;
|
||||
|
@ -1,8 +1,5 @@
|
||||
import {
|
||||
callbacks,
|
||||
updateCallbacks,
|
||||
storeCallback,
|
||||
} from '../../lib/api/callbacks';
|
||||
import { updateCallbacks, storeCallback } from '../../lib/api/callbacks';
|
||||
import type { IconStorageWithIcons } from '../../lib/api/types';
|
||||
import { sortIcons } from '../../lib/icon/sort';
|
||||
import { getStorage, addIconSet } from '../../lib/storage/storage';
|
||||
|
||||
@ -22,7 +19,7 @@ describe('Testing API callbacks', () => {
|
||||
const prefix = nextPrefix();
|
||||
let counter = 0;
|
||||
|
||||
const storage = getStorage(provider, prefix);
|
||||
const storage = getStorage(provider, prefix) as IconStorageWithIcons;
|
||||
const abort = storeCallback(
|
||||
(loaded, missing, pending, unsubscribe) => {
|
||||
expect(unsubscribe).toBe(abort);
|
||||
@ -52,7 +49,7 @@ describe('Testing API callbacks', () => {
|
||||
name: 'icon2',
|
||||
},
|
||||
]);
|
||||
expect(callbacks[provider][prefix].length).toBe(1);
|
||||
expect(storage.loaderCallbacks?.length).toBe(1);
|
||||
|
||||
// Add icon2 and trigger update
|
||||
addIconSet(storage, {
|
||||
@ -64,7 +61,7 @@ describe('Testing API callbacks', () => {
|
||||
},
|
||||
});
|
||||
|
||||
updateCallbacks(provider, prefix);
|
||||
updateCallbacks(storage);
|
||||
return;
|
||||
|
||||
case 2:
|
||||
@ -89,7 +86,7 @@ describe('Testing API callbacks', () => {
|
||||
},
|
||||
]);
|
||||
expect(pending).toEqual([]);
|
||||
expect(callbacks[provider][prefix].length).toBe(0);
|
||||
expect(storage.loaderCallbacks?.length).toBe(0);
|
||||
done();
|
||||
}
|
||||
},
|
||||
@ -110,19 +107,14 @@ describe('Testing API callbacks', () => {
|
||||
name: 'icon3',
|
||||
},
|
||||
]),
|
||||
[
|
||||
{
|
||||
provider,
|
||||
prefix,
|
||||
},
|
||||
]
|
||||
[storage]
|
||||
);
|
||||
|
||||
// Test callbacks
|
||||
expect(callbacks[provider][prefix].length).toBe(1);
|
||||
expect(storage.loaderCallbacks?.length).toBe(1);
|
||||
|
||||
// Test update - should do nothing
|
||||
updateCallbacks(provider, prefix);
|
||||
updateCallbacks(storage);
|
||||
|
||||
// Wait for tick because updateCallbacks will use one
|
||||
setTimeout(() => {
|
||||
@ -139,7 +131,7 @@ describe('Testing API callbacks', () => {
|
||||
},
|
||||
not_found: ['icon3'],
|
||||
});
|
||||
updateCallbacks(provider, prefix);
|
||||
updateCallbacks(storage);
|
||||
});
|
||||
});
|
||||
|
||||
@ -147,7 +139,7 @@ describe('Testing API callbacks', () => {
|
||||
const provider = '';
|
||||
const prefix = nextPrefix();
|
||||
|
||||
const storage = getStorage(provider, prefix);
|
||||
const storage = getStorage(provider, prefix) as IconStorageWithIcons;
|
||||
addIconSet(storage, {
|
||||
prefix,
|
||||
icons: {
|
||||
@ -182,16 +174,11 @@ describe('Testing API callbacks', () => {
|
||||
name: 'icon3',
|
||||
},
|
||||
]),
|
||||
[
|
||||
{
|
||||
provider,
|
||||
prefix,
|
||||
},
|
||||
]
|
||||
[storage]
|
||||
);
|
||||
|
||||
// callbacks should not have been initialised
|
||||
expect(callbacks[prefix]).toBeUndefined();
|
||||
expect(storage.loaderCallbacks).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Cancel callback', (done) => {
|
||||
@ -199,7 +186,7 @@ describe('Testing API callbacks', () => {
|
||||
const prefix = nextPrefix();
|
||||
let counter = 0;
|
||||
|
||||
const storage = getStorage(provider, prefix);
|
||||
const storage = getStorage(provider, prefix) as IconStorageWithIcons;
|
||||
const abort = storeCallback(
|
||||
(loaded, missing, pending, unsubscribe) => {
|
||||
expect(unsubscribe).toBe(abort);
|
||||
@ -229,7 +216,7 @@ describe('Testing API callbacks', () => {
|
||||
name: 'icon2',
|
||||
},
|
||||
]);
|
||||
expect(callbacks[provider][prefix].length).toBe(1);
|
||||
expect(storage.loaderCallbacks?.length).toBe(1);
|
||||
|
||||
// Add icon2 and trigger update
|
||||
addIconSet(storage, {
|
||||
@ -241,11 +228,11 @@ describe('Testing API callbacks', () => {
|
||||
},
|
||||
});
|
||||
|
||||
updateCallbacks(provider, prefix);
|
||||
updateCallbacks(storage);
|
||||
|
||||
// Unsubscribe and set timer to call done()
|
||||
unsubscribe();
|
||||
expect(callbacks[provider][prefix].length).toBe(0);
|
||||
expect(storage.loaderCallbacks?.length).toBe(0);
|
||||
setTimeout(done);
|
||||
},
|
||||
sortIcons([
|
||||
@ -265,19 +252,14 @@ describe('Testing API callbacks', () => {
|
||||
name: 'icon3',
|
||||
},
|
||||
]),
|
||||
[
|
||||
{
|
||||
provider,
|
||||
prefix,
|
||||
},
|
||||
]
|
||||
[storage]
|
||||
);
|
||||
|
||||
// Test callbacks
|
||||
expect(callbacks[provider][prefix].length).toBe(1);
|
||||
expect(storage.loaderCallbacks?.length).toBe(1);
|
||||
|
||||
// Test update - should do nothing
|
||||
updateCallbacks(provider, prefix);
|
||||
updateCallbacks(storage);
|
||||
|
||||
// Wait for tick because updateCallbacks will use one
|
||||
setTimeout(() => {
|
||||
@ -294,7 +276,7 @@ describe('Testing API callbacks', () => {
|
||||
},
|
||||
not_found: ['icon3'],
|
||||
});
|
||||
updateCallbacks(provider, prefix);
|
||||
updateCallbacks(storage);
|
||||
});
|
||||
});
|
||||
|
||||
@ -304,8 +286,8 @@ describe('Testing API callbacks', () => {
|
||||
const prefix2 = nextPrefix();
|
||||
let counter = 0;
|
||||
|
||||
const storage1 = getStorage(provider, prefix1);
|
||||
const storage2 = getStorage(provider, prefix2);
|
||||
const storage1 = getStorage(provider, prefix1) as IconStorageWithIcons;
|
||||
const storage2 = getStorage(provider, prefix2) as IconStorageWithIcons;
|
||||
|
||||
const abort = storeCallback(
|
||||
(loaded, missing, pending, unsubscribe) => {
|
||||
@ -336,8 +318,8 @@ describe('Testing API callbacks', () => {
|
||||
name: 'icon2',
|
||||
},
|
||||
]);
|
||||
expect(callbacks[provider][prefix1].length).toBe(0);
|
||||
expect(callbacks[provider][prefix2].length).toBe(1);
|
||||
expect(storage1.loaderCallbacks?.length).toBe(0);
|
||||
expect(storage2.loaderCallbacks?.length).toBe(1);
|
||||
|
||||
// Add icon2 and trigger update
|
||||
addIconSet(storage2, {
|
||||
@ -349,13 +331,13 @@ describe('Testing API callbacks', () => {
|
||||
},
|
||||
});
|
||||
|
||||
updateCallbacks(provider, prefix2);
|
||||
updateCallbacks(storage2);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Second run - icon2 should be loaded
|
||||
expect(callbacks[provider][prefix1].length).toBe(0);
|
||||
expect(callbacks[provider][prefix2].length).toBe(0);
|
||||
expect(storage1.loaderCallbacks?.length).toBe(0);
|
||||
expect(storage2.loaderCallbacks?.length).toBe(0);
|
||||
done();
|
||||
break;
|
||||
|
||||
@ -380,18 +362,15 @@ describe('Testing API callbacks', () => {
|
||||
name: 'icon3',
|
||||
},
|
||||
]),
|
||||
[
|
||||
{ provider, prefix: prefix1 },
|
||||
{ provider, prefix: prefix2 },
|
||||
]
|
||||
[storage1, storage2]
|
||||
);
|
||||
|
||||
// Test callbacks
|
||||
expect(callbacks[provider][prefix1].length).toBe(1);
|
||||
expect(callbacks[provider][prefix2].length).toBe(1);
|
||||
expect(storage1.loaderCallbacks?.length).toBe(1);
|
||||
expect(storage2.loaderCallbacks?.length).toBe(1);
|
||||
|
||||
// Test update - should do nothing
|
||||
updateCallbacks(provider, prefix1);
|
||||
updateCallbacks(storage1);
|
||||
|
||||
// Wait for tick because updateCallbacks will use one
|
||||
setTimeout(() => {
|
||||
@ -408,7 +387,7 @@ describe('Testing API callbacks', () => {
|
||||
},
|
||||
not_found: ['icon3'],
|
||||
});
|
||||
updateCallbacks(provider, prefix1);
|
||||
updateCallbacks(storage1);
|
||||
});
|
||||
});
|
||||
|
||||
@ -419,8 +398,8 @@ describe('Testing API callbacks', () => {
|
||||
const prefix2 = nextPrefix();
|
||||
let counter = 0;
|
||||
|
||||
const storage1 = getStorage(provider1, prefix1);
|
||||
const storage2 = getStorage(provider2, prefix2);
|
||||
const storage1 = getStorage(provider1, prefix1) as IconStorageWithIcons;
|
||||
const storage2 = getStorage(provider2, prefix2) as IconStorageWithIcons;
|
||||
|
||||
const abort = storeCallback(
|
||||
(loaded, missing, pending, unsubscribe) => {
|
||||
@ -451,12 +430,8 @@ describe('Testing API callbacks', () => {
|
||||
name: 'icon2',
|
||||
},
|
||||
]);
|
||||
expect(callbacks[provider1][prefix1].length).toBe(0);
|
||||
expect(callbacks[provider2][prefix2].length).toBe(1);
|
||||
|
||||
// Make sure providers/prefixes aren't mixed
|
||||
expect(callbacks[provider1][prefix2]).toBeUndefined();
|
||||
expect(callbacks[provider2][prefix1]).toBeUndefined();
|
||||
expect(storage1.loaderCallbacks?.length).toBe(0);
|
||||
expect(storage2.loaderCallbacks?.length).toBe(1);
|
||||
|
||||
// Add icon2 and trigger update
|
||||
addIconSet(storage2, {
|
||||
@ -468,17 +443,13 @@ describe('Testing API callbacks', () => {
|
||||
},
|
||||
});
|
||||
|
||||
updateCallbacks(provider2, prefix2);
|
||||
updateCallbacks(storage2);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Second run - icon2 should be loaded
|
||||
expect(callbacks[provider1][prefix1].length).toBe(0);
|
||||
expect(callbacks[provider2][prefix2].length).toBe(0);
|
||||
|
||||
// Make sure providers/prefixes aren't mixed
|
||||
expect(callbacks[provider1][prefix2]).toBeUndefined();
|
||||
expect(callbacks[provider2][prefix1]).toBeUndefined();
|
||||
expect(storage1.loaderCallbacks?.length).toBe(0);
|
||||
expect(storage2.loaderCallbacks?.length).toBe(0);
|
||||
|
||||
done();
|
||||
break;
|
||||
@ -504,21 +475,15 @@ describe('Testing API callbacks', () => {
|
||||
name: 'icon3',
|
||||
},
|
||||
]),
|
||||
[
|
||||
{ provider: provider1, prefix: prefix1 },
|
||||
{ provider: provider2, prefix: prefix2 },
|
||||
]
|
||||
[storage1, storage2]
|
||||
);
|
||||
|
||||
// Test callbacks
|
||||
expect(callbacks[provider1][prefix1].length).toBe(1);
|
||||
expect(callbacks[provider2][prefix2].length).toBe(1);
|
||||
|
||||
expect(callbacks[provider1][prefix2]).toBeUndefined();
|
||||
expect(callbacks[provider2][prefix1]).toBeUndefined();
|
||||
expect(storage1.loaderCallbacks?.length).toBe(1);
|
||||
expect(storage2.loaderCallbacks?.length).toBe(1);
|
||||
|
||||
// Test update - should do nothing
|
||||
updateCallbacks(provider1, prefix1);
|
||||
updateCallbacks(storage1);
|
||||
|
||||
// Wait for tick because updateCallbacks will use one
|
||||
setTimeout(() => {
|
||||
@ -535,7 +500,7 @@ describe('Testing API callbacks', () => {
|
||||
},
|
||||
not_found: ['icon3'],
|
||||
});
|
||||
updateCallbacks(provider1, prefix1);
|
||||
updateCallbacks(storage1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user