2
0
mirror of https://github.com/iconify/iconify.git synced 2025-01-07 15:44:05 +00:00

Complete restructure of browser storage

This commit is contained in:
Vjacheslav Trushkin 2022-06-28 22:37:23 +03:00
parent 7980cce929
commit 0e0b6b66ef
13 changed files with 117 additions and 130 deletions

View File

@ -54,9 +54,7 @@ import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
import { sendAPIQuery } from '@iconify/core/lib/api/query'; import { sendAPIQuery } from '@iconify/core/lib/api/query';
// Cache // Cache
import { cache } from '@iconify/core/lib/cache'; import { initBrowserStorage } from '@iconify/core/lib/browser-storage';
import { storeCache } from '@iconify/core/lib/browser-storage';
import { loadBrowserStorageCache } from '@iconify/core/lib/browser-storage/load';
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions'; import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
import type { import type {
IconifyBrowserCacheType, IconifyBrowserCacheType,
@ -144,8 +142,7 @@ setAPIModule('', fetchAPIModule);
*/ */
if (typeof document !== 'undefined' && typeof window !== 'undefined') { if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache // Set cache and load existing cache
cache.store = storeCache; initBrowserStorage();
loadBrowserStorageCache();
interface WindowWithIconifyStuff { interface WindowWithIconifyStuff {
IconifyPreload?: IconifyJSON[] | IconifyJSON; IconifyPreload?: IconifyJSON[] | IconifyJSON;

View File

@ -58,9 +58,7 @@ import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
import { sendAPIQuery } from '@iconify/core/lib/api/query'; import { sendAPIQuery } from '@iconify/core/lib/api/query';
// Cache // Cache
import { cache } from '@iconify/core/lib/cache'; import { initBrowserStorage } from '@iconify/core/lib/browser-storage';
import { storeCache } from '@iconify/core/lib/browser-storage';
import { loadBrowserStorageCache } from '@iconify/core/lib/browser-storage/load';
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions'; import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
import type { import type {
IconifyBrowserCacheType, IconifyBrowserCacheType,
@ -153,8 +151,7 @@ setAPIModule('', fetchAPIModule);
*/ */
if (typeof document !== 'undefined' && typeof window !== 'undefined') { if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache // Set cache and load existing cache
cache.store = storeCache; initBrowserStorage();
loadBrowserStorageCache();
interface WindowWithIconifyStuff { interface WindowWithIconifyStuff {
IconifyPreload?: IconifyJSON[] | IconifyJSON; IconifyPreload?: IconifyJSON[] | IconifyJSON;

View File

@ -57,9 +57,7 @@ import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
import { sendAPIQuery } from '@iconify/core/lib/api/query'; import { sendAPIQuery } from '@iconify/core/lib/api/query';
// Cache // Cache
import { cache } from '@iconify/core/lib/cache'; import { initBrowserStorage } from '@iconify/core/lib/browser-storage';
import { storeCache } from '@iconify/core/lib/browser-storage';
import { loadBrowserStorageCache } from '@iconify/core/lib/browser-storage/load';
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions'; import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
import type { import type {
IconifyBrowserCacheType, IconifyBrowserCacheType,
@ -150,8 +148,7 @@ setAPIModule('', fetchAPIModule);
*/ */
if (typeof document !== 'undefined' && typeof window !== 'undefined') { if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache // Set cache and load existing cache
cache.store = storeCache; initBrowserStorage();
loadBrowserStorageCache();
interface WindowWithIconifyStuff { interface WindowWithIconifyStuff {
IconifyPreload?: IconifyJSON[] | IconifyJSON; IconifyPreload?: IconifyJSON[] | IconifyJSON;

View File

@ -17,9 +17,7 @@ import { replaceIDs } from '@iconify/utils/lib/svg/id';
import { calculateSize } from '@iconify/utils/lib/svg/size'; import { calculateSize } from '@iconify/utils/lib/svg/size';
// Cache // Cache
import { storeCache } from '@iconify/core/lib/browser-storage'; import { initBrowserStorage } from '@iconify/core/lib/browser-storage';
import { loadBrowserStorageCache } from '@iconify/core/lib/browser-storage/load';
import { cache } from '@iconify/core/lib/cache';
import type { import type {
IconifyBrowserCacheFunctions, IconifyBrowserCacheFunctions,
IconifyBrowserCacheType, IconifyBrowserCacheType,
@ -150,8 +148,7 @@ setAPIModule('', fetchAPIModule);
*/ */
if (typeof document !== 'undefined' && typeof window !== 'undefined') { if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache // Set cache and load existing cache
cache.store = storeCache; initBrowserStorage();
loadBrowserStorageCache();
interface WindowWithIconifyStuff { interface WindowWithIconifyStuff {
IconifyProviders?: Record<string, PartialIconifyAPIConfig>; IconifyProviders?: Record<string, PartialIconifyAPIConfig>;

View File

@ -67,9 +67,7 @@ import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
import { sendAPIQuery } from '@iconify/core/lib/api/query'; import { sendAPIQuery } from '@iconify/core/lib/api/query';
// Cache // Cache
import { cache } from '@iconify/core/lib/cache'; import { initBrowserStorage } from '@iconify/core/lib/browser-storage';
import { storeCache } from '@iconify/core/lib/browser-storage';
import { loadBrowserStorageCache } from '@iconify/core/lib/browser-storage/load';
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions'; import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
import type { import type {
IconifyBrowserCacheType, IconifyBrowserCacheType,
@ -161,8 +159,7 @@ setAPIModule('', fetchAPIModule);
*/ */
if (typeof document !== 'undefined' && typeof window !== 'undefined') { if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache // Set cache and load existing cache
cache.store = storeCache; initBrowserStorage();
loadBrowserStorageCache();
interface WindowWithIconifyStuff { interface WindowWithIconifyStuff {
IconifyPreload?: IconifyJSON[] | IconifyJSON; IconifyPreload?: IconifyJSON[] | IconifyJSON;

View File

@ -60,9 +60,7 @@ import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
import { sendAPIQuery } from '@iconify/core/lib/api/query'; import { sendAPIQuery } from '@iconify/core/lib/api/query';
// Cache // Cache
import { cache } from '@iconify/core/lib/cache'; import { initBrowserStorage } from '@iconify/core/lib/browser-storage';
import { storeCache } from '@iconify/core/lib/browser-storage';
import { loadBrowserStorageCache } from '@iconify/core/lib/browser-storage/load';
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions'; import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
import type { import type {
IconifyBrowserCacheType, IconifyBrowserCacheType,
@ -152,8 +150,7 @@ setAPIModule('', fetchAPIModule);
*/ */
if (typeof document !== 'undefined' && typeof window !== 'undefined') { if (typeof document !== 'undefined' && typeof window !== 'undefined') {
// Set cache and load existing cache // Set cache and load existing cache
cache.store = storeCache; initBrowserStorage();
loadBrowserStorageCache();
interface WindowWithIconifyStuff { interface WindowWithIconifyStuff {
IconifyPreload?: IconifyJSON[] | IconifyJSON; IconifyPreload?: IconifyJSON[] | IconifyJSON;

View File

@ -37,9 +37,7 @@ import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
import { sendAPIQuery } from '@iconify/core/lib/api/query'; import { sendAPIQuery } from '@iconify/core/lib/api/query';
// Cache // Cache
import { cache } from '@iconify/core/lib/cache'; import { initBrowserStorage } from '@iconify/core/lib/browser-storage';
import { storeCache } from '@iconify/core/lib/browser-storage';
import { loadBrowserStorageCache } from '@iconify/core/lib/browser-storage/load';
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions'; import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
import type { import type {
IconifyBrowserCacheType, IconifyBrowserCacheType,
@ -85,8 +83,7 @@ export function exportFunctions(): IconifyExportedFunctions {
} }
if (_window) { if (_window) {
// Set cache and load existing cache // Set cache and load existing cache
cache.store = storeCache; initBrowserStorage();
loadBrowserStorageCache();
// Load icons from global "IconifyPreload" // Load icons from global "IconifyPreload"
if (_window.IconifyPreload !== void 0) { if (_window.IconifyPreload !== void 0) {

View File

@ -93,6 +93,10 @@
"require": "./lib/browser-storage/mock.cjs", "require": "./lib/browser-storage/mock.cjs",
"import": "./lib/browser-storage/mock.mjs" "import": "./lib/browser-storage/mock.mjs"
}, },
"./lib/browser-storage/store": {
"require": "./lib/browser-storage/store.cjs",
"import": "./lib/browser-storage/store.mjs"
},
"./lib/browser-storage/types": { "./lib/browser-storage/types": {
"require": "./lib/browser-storage/types.cjs", "require": "./lib/browser-storage/types.cjs",
"import": "./lib/browser-storage/types.mjs" "import": "./lib/browser-storage/types.mjs"

View File

@ -1,78 +1,11 @@
import type { IconifyJSON } from '@iconify/types'; import { cache } from '../cache';
import type { CacheIcons } from '../cache';
import { browserCachePrefix, browserStorageHour } from './config';
import { setBrowserStorageItemsCount } from './count';
import {
browserStorageConfig,
browserStorageEmptyItems,
browserStorageItemsCount,
browserStorageLoaded,
} from './data';
import { getBrowserStorage } from './global';
import { loadBrowserStorageCache } from './load'; import { loadBrowserStorageCache } from './load';
import type { BrowserStorageConfig, BrowserStorageItem } from './types'; import { storeInBrowserStorage } from './store';
/** /**
* Function to cache icons * Init browser storage
*/ */
export const storeCache: CacheIcons = ( export function initBrowserStorage() {
provider: string, cache.store = storeInBrowserStorage;
data: IconifyJSON loadBrowserStorageCache();
): void => { }
if (!browserStorageLoaded) {
loadBrowserStorageCache();
}
function store(key: keyof BrowserStorageConfig): boolean {
if (!browserStorageConfig[key]) {
return false;
}
const func = getBrowserStorage(key);
if (!func) {
return false;
}
// Get item index
let index = browserStorageEmptyItems[key].shift();
if (index === void 0) {
// Create new index
index = browserStorageItemsCount[key];
if (!setBrowserStorageItemsCount(func, key, index + 1)) {
return false;
}
}
// Create and save item
try {
const item: BrowserStorageItem = {
cached: Math.floor(Date.now() / browserStorageHour),
provider,
data,
};
func.setItem(
browserCachePrefix + index.toString(),
JSON.stringify(item)
);
} catch (err) {
return false;
}
return true;
}
// Do not store empty sets
if (!Object.keys(data.icons).length) {
return;
}
// Remove not_found (clone object to keep old object intact)
if (data.not_found) {
data = Object.assign({}, data);
delete data.not_found;
}
// Attempt to store at localStorage first, then at sessionStorage
if (!store('local')) {
store('session');
}
};

View File

@ -1,4 +1,3 @@
import type { LoadIconsCache } from '../cache';
import { addIconSet, getStorage } from '../storage/storage'; import { addIconSet, getStorage } from '../storage/storage';
import { import {
browserCachePrefix, browserCachePrefix,
@ -52,7 +51,7 @@ function initBrowserStorage(
/** /**
* Load icons from cache * Load icons from cache
*/ */
export const loadBrowserStorageCache: LoadIconsCache = (): void => { export function loadBrowserStorageCache() {
if (browserStorageLoaded) { if (browserStorageLoaded) {
return; return;
} }
@ -149,4 +148,4 @@ export const loadBrowserStorageCache: LoadIconsCache = (): void => {
for (const key in browserStorageConfig) { for (const key in browserStorageConfig) {
load(key as keyof BrowserStorageConfig); load(key as keyof BrowserStorageConfig);
} }
}; }

View File

@ -0,0 +1,78 @@
import type { IconifyJSON } from '@iconify/types';
import type { CacheIcons } from '../cache';
import { browserCachePrefix, browserStorageHour } from './config';
import { setBrowserStorageItemsCount } from './count';
import {
browserStorageConfig,
browserStorageEmptyItems,
browserStorageItemsCount,
browserStorageLoaded,
} from './data';
import { getBrowserStorage } from './global';
import { loadBrowserStorageCache } from './load';
import type { BrowserStorageConfig, BrowserStorageItem } from './types';
/**
* Function to cache icons
*/
export const storeInBrowserStorage: CacheIcons = (
provider: string,
data: IconifyJSON
): void => {
if (!browserStorageLoaded) {
loadBrowserStorageCache();
}
function store(key: keyof BrowserStorageConfig): boolean {
if (!browserStorageConfig[key]) {
return false;
}
const func = getBrowserStorage(key);
if (!func) {
return false;
}
// Get item index
let index = browserStorageEmptyItems[key].shift();
if (index === void 0) {
// Create new index
index = browserStorageItemsCount[key];
if (!setBrowserStorageItemsCount(func, key, index + 1)) {
return false;
}
}
// Create and save item
try {
const item: BrowserStorageItem = {
cached: Math.floor(Date.now() / browserStorageHour),
provider,
data,
};
func.setItem(
browserCachePrefix + index.toString(),
JSON.stringify(item)
);
} catch (err) {
return false;
}
return true;
}
// Do not store empty sets
if (!Object.keys(data.icons).length) {
return;
}
// Remove not_found (clone object to keep old object intact)
if (data.not_found) {
data = Object.assign({}, data);
delete data.not_found;
}
// Attempt to store at localStorage first, then at sessionStorage
if (!store('local')) {
store('session');
}
};

View File

@ -5,17 +5,11 @@ import type { IconifyJSON } from '@iconify/types';
*/ */
export type CacheIcons = (provider: string, data: IconifyJSON) => void; export type CacheIcons = (provider: string, data: IconifyJSON) => void;
/**
* Function to load icons from cache
*/
export type LoadIconsCache = () => void;
/** /**
* Module * Module
*/ */
interface CacheModule { interface CacheModule {
store?: CacheIcons; store?: CacheIcons;
load?: LoadIconsCache;
} }
export const cache: CacheModule = {}; export const cache: CacheModule = {};

View File

@ -1,6 +1,6 @@
import type { IconifyJSON } from '@iconify/types'; import type { IconifyJSON } from '@iconify/types';
import type { BrowserStorageItem } from '../../lib/browser-storage/types'; import type { BrowserStorageItem } from '../../lib/browser-storage/types';
import { storeCache } from '../../lib/browser-storage'; import { storeInBrowserStorage } from '../../lib/browser-storage/store';
import { loadBrowserStorageCache } from '../../lib/browser-storage/load'; import { loadBrowserStorageCache } from '../../lib/browser-storage/load';
import { import {
browserStorageItemsCount, browserStorageItemsCount,
@ -50,7 +50,7 @@ describe('Testing saving to localStorage', () => {
expect(iconExists(icons, 'foo')).toBe(false); expect(iconExists(icons, 'foo')).toBe(false);
// Save item // Save item
storeCache(provider, icon); storeInBrowserStorage(provider, icon);
// Storing in cache should not add item to storage // Storing in cache should not add item to storage
expect(iconExists(icons, 'foo')).toBe(false); expect(iconExists(icons, 'foo')).toBe(false);
@ -116,8 +116,8 @@ describe('Testing saving to localStorage', () => {
}); });
// Save items // Save items
storeCache(provider, icon0); storeInBrowserStorage(provider, icon0);
storeCache(provider, icon1); storeInBrowserStorage(provider, icon1);
// Check data that should have been updated because storeCache() // Check data that should have been updated because storeCache()
// should call load function before first execution // should call load function before first execution
@ -205,7 +205,7 @@ describe('Testing saving to localStorage', () => {
}); });
// Save items // Save items
storeCache(provider, icon0); storeInBrowserStorage(provider, icon0);
// Check data // Check data
expect(browserStorageItemsCount).toEqual({ expect(browserStorageItemsCount).toEqual({
@ -316,7 +316,7 @@ describe('Testing saving to localStorage', () => {
}); });
// Add item 5 // Add item 5
storeCache(provider, icons[5]); storeInBrowserStorage(provider, icons[5]);
expect(browserStorageItemsCount).toEqual({ expect(browserStorageItemsCount).toEqual({
local: 0, local: 0,
session: 9, session: 9,
@ -331,7 +331,7 @@ describe('Testing saving to localStorage', () => {
const list = [4, 2, 1]; const list = [4, 2, 1];
list.slice(0).forEach((index) => { list.slice(0).forEach((index) => {
expect(list.shift()).toBe(index); expect(list.shift()).toBe(index);
storeCache(provider, icons[index]); storeInBrowserStorage(provider, icons[index]);
expect(browserStorageItemsCount).toEqual({ expect(browserStorageItemsCount).toEqual({
local: 0, local: 0,
session: 9, session: 9,
@ -344,7 +344,7 @@ describe('Testing saving to localStorage', () => {
}); });
// Add item 10 // Add item 10
storeCache(provider, icons[10]); storeInBrowserStorage(provider, icons[10]);
expect(browserStorageItemsCount).toEqual({ expect(browserStorageItemsCount).toEqual({
local: 0, local: 0,
session: 10, session: 10,
@ -356,7 +356,7 @@ describe('Testing saving to localStorage', () => {
expect(cache.getItem(browserCacheCountKey)).toBe('10'); expect(cache.getItem(browserCacheCountKey)).toBe('10');
// Add item 11 // Add item 11
storeCache(provider, icons[11]); storeInBrowserStorage(provider, icons[11]);
expect(browserStorageItemsCount).toEqual({ expect(browserStorageItemsCount).toEqual({
local: 0, local: 0,
session: 11, session: 11,
@ -430,7 +430,7 @@ describe('Testing saving to localStorage', () => {
}; };
// Save item // Save item
storeCache(provider, icon); storeInBrowserStorage(provider, icon);
// Storing in cache should not add item to storage // Storing in cache should not add item to storage
expect(iconExists(icons, 'foo')).toBe(false); expect(iconExists(icons, 'foo')).toBe(false);
@ -555,7 +555,7 @@ describe('Testing saving to localStorage', () => {
provider, provider,
data: icon, data: icon,
}; };
storeCache(provider, icon); storeInBrowserStorage(provider, icon);
// Check data // Check data
expect(browserStorageItemsCount).toEqual({ expect(browserStorageItemsCount).toEqual({
@ -673,7 +673,7 @@ describe('Testing saving to localStorage', () => {
provider, provider,
data: icon, data: icon,
}; };
storeCache(provider, icon); storeInBrowserStorage(provider, icon);
// Check data // Check data
expect(browserStorageItemsCount).toEqual({ expect(browserStorageItemsCount).toEqual({