mirror of
https://github.com/iconify/iconify.git
synced 2025-01-12 01:45:41 +00:00
Redo internal API exports to make API functions reusable
This commit is contained in:
parent
fbb836d3c0
commit
a5f8282df2
@ -129,3 +129,7 @@ export type GetAPIConfig = (provider: string) => IconifyAPIConfig | undefined;
|
||||
export const getAPIConfig: GetAPIConfig = (
|
||||
provider: string
|
||||
): IconifyAPIConfig | undefined => configStorage[provider];
|
||||
|
||||
/**
|
||||
* List API providers
|
||||
*/
|
||||
|
@ -1,5 +1,4 @@
|
||||
import type { IconifyAPIInternalStorage } from '.';
|
||||
import { API, getRedundancyCache } from '.';
|
||||
import { API } from '.';
|
||||
import type { IconifyIconName } from '@iconify/utils/lib/icon/name';
|
||||
import type {
|
||||
IconifyIconLoaderAbort,
|
||||
@ -7,8 +6,14 @@ import type {
|
||||
} from '../interfaces/loader';
|
||||
import type { GetAPIConfig, IconifyAPIConfig } from './config';
|
||||
import { getAPIConfig, setAPIConfig } from './config';
|
||||
import type { IconifyAPIModule } from './modules';
|
||||
import { setAPIModule } from './modules';
|
||||
import type {
|
||||
IconifyAPIModule,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
} from './modules';
|
||||
import { setAPIModule, getAPIModule } from './modules';
|
||||
import type { MergeParams, IconifyAPIMergeQueryParams } from './params';
|
||||
import { mergeParams } from './params';
|
||||
|
||||
/**
|
||||
* Iconify API functions
|
||||
@ -44,11 +49,6 @@ export const APIFunctions: IconifyAPIFunctions = {
|
||||
* Important: any changes published in a release must be backwards compatible.
|
||||
*/
|
||||
export interface IconifyAPIInternalFunctions {
|
||||
/**
|
||||
* Get internal API data, used by Icon Finder
|
||||
*/
|
||||
getAPI: (provider: string) => IconifyAPIInternalStorage | undefined;
|
||||
|
||||
/**
|
||||
* Get API config, used by custom modules
|
||||
*/
|
||||
@ -59,15 +59,35 @@ export interface IconifyAPIInternalFunctions {
|
||||
*/
|
||||
setAPIModule: (provider: string, item: IconifyAPIModule) => void;
|
||||
|
||||
/**
|
||||
* Get API module
|
||||
*/
|
||||
getAPIModule: (provider: string) => IconifyAPIModule | undefined;
|
||||
|
||||
/**
|
||||
* Optional setFetch and getFetch (should be imported from ./modules/fetch if fetch is used)
|
||||
*/
|
||||
setFetch?: (item: typeof fetch) => void;
|
||||
getFetch?: () => typeof fetch | null;
|
||||
|
||||
/**
|
||||
* Merge parameters
|
||||
*/
|
||||
mergeParams: MergeParams;
|
||||
}
|
||||
|
||||
export const APIInternalFunctions: IconifyAPIInternalFunctions = {
|
||||
getAPI: getRedundancyCache,
|
||||
getAPIConfig,
|
||||
setAPIModule,
|
||||
getAPIModule,
|
||||
mergeParams,
|
||||
};
|
||||
|
||||
/**
|
||||
* Types needed for internal functions
|
||||
*/
|
||||
export type {
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
};
|
||||
|
@ -38,8 +38,10 @@ function emptyCallback(): void {
|
||||
* [provider][prefix][icon] = time when icon was added to queue
|
||||
*/
|
||||
type PendingIcons = Record<string, number>;
|
||||
const pendingIcons: Record<string, Record<string, PendingIcons>> =
|
||||
Object.create(null);
|
||||
const pendingIcons: Record<
|
||||
string,
|
||||
Record<string, PendingIcons>
|
||||
> = Object.create(null);
|
||||
|
||||
/**
|
||||
* List of icons that are waiting to be loaded.
|
||||
@ -51,16 +53,18 @@ const pendingIcons: Record<string, Record<string, PendingIcons>> =
|
||||
*
|
||||
* [provider][prefix] = array of icon names
|
||||
*/
|
||||
const iconsToLoad: Record<string, Record<string, string[]>> =
|
||||
Object.create(null);
|
||||
const iconsToLoad: Record<string, Record<string, string[]>> = Object.create(
|
||||
null
|
||||
);
|
||||
|
||||
// Flags to merge multiple synchronous icon requests in one asynchronous request
|
||||
const loaderFlags: Record<string, Record<string, boolean>> =
|
||||
Object.create(null);
|
||||
const loaderFlags: Record<string, Record<string, boolean>> = Object.create(
|
||||
null
|
||||
);
|
||||
const queueFlags: Record<string, Record<string, boolean>> = Object.create(null);
|
||||
|
||||
// Redundancy instances cache, sorted by provider
|
||||
export interface IconifyAPIInternalStorage {
|
||||
interface IconifyAPIInternalStorage {
|
||||
config: IconifyAPIConfig;
|
||||
redundancy: Redundancy;
|
||||
}
|
||||
@ -70,7 +74,7 @@ const redundancyCache: Record<string, IconifyAPIInternalStorage> =
|
||||
/**
|
||||
* Get Redundancy instance for provider
|
||||
*/
|
||||
export function getRedundancyCache(
|
||||
function getRedundancyCache(
|
||||
provider: string
|
||||
): IconifyAPIInternalStorage | undefined {
|
||||
if (redundancyCache[provider] === void 0) {
|
||||
@ -293,8 +297,9 @@ const loadIcons: IconifyLoadIcons = (
|
||||
}
|
||||
|
||||
// Get all sources for pending icons
|
||||
const newIcons: Record<string, Record<string, string[]>> =
|
||||
Object.create(null);
|
||||
const newIcons: Record<string, Record<string, string[]>> = Object.create(
|
||||
null
|
||||
);
|
||||
const sources: IconifyIconSource[] = [];
|
||||
let lastProvider: string, lastPrefix: string;
|
||||
|
||||
|
@ -4,19 +4,21 @@ import type { GetAPIConfig } from '../api/config';
|
||||
/**
|
||||
* Params for sendQuery()
|
||||
*/
|
||||
export interface APIIconsQueryParams {
|
||||
export interface IconifyAPIIconsQueryParams {
|
||||
type: 'icons';
|
||||
provider: string;
|
||||
prefix: string;
|
||||
icons: string[];
|
||||
}
|
||||
export interface APICustomQueryParams {
|
||||
export interface IconifyAPICustomQueryParams {
|
||||
type: 'custom';
|
||||
provider: string;
|
||||
uri: string;
|
||||
}
|
||||
|
||||
export type APIQueryParams = APIIconsQueryParams | APICustomQueryParams;
|
||||
export type IconifyAPIQueryParams =
|
||||
| IconifyAPIIconsQueryParams
|
||||
| IconifyAPICustomQueryParams;
|
||||
|
||||
/**
|
||||
* Functions to implement in module
|
||||
@ -25,11 +27,11 @@ export type IconifyAPIPrepareIconsQuery = (
|
||||
provider: string,
|
||||
prefix: string,
|
||||
icons: string[]
|
||||
) => APIIconsQueryParams[];
|
||||
) => IconifyAPIIconsQueryParams[];
|
||||
|
||||
export type IconifyAPISendQuery = (
|
||||
host: string,
|
||||
params: APIQueryParams,
|
||||
params: IconifyAPIQueryParams,
|
||||
status: PendingQueryItem
|
||||
) => void;
|
||||
|
||||
|
@ -1,18 +1,14 @@
|
||||
import type { PendingQueryItem } from '@cyberalien/redundancy';
|
||||
import type {
|
||||
APIQueryParams,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
IconifyAPISendQuery,
|
||||
IconifyAPIModule,
|
||||
GetIconifyAPIModule,
|
||||
APIIconsQueryParams,
|
||||
IconifyAPIIconsQueryParams,
|
||||
} from '../modules';
|
||||
import type { GetAPIConfig } from '../config';
|
||||
|
||||
/**
|
||||
* Endpoint
|
||||
*/
|
||||
const endPoint = '{prefix}.json?icons={icons}';
|
||||
import { mergeParams } from '../params';
|
||||
|
||||
/**
|
||||
* Cache
|
||||
@ -41,7 +37,7 @@ const detectFetch = (): FetchType | null => {
|
||||
try {
|
||||
// Obfuscate require() to avoid cross-fetch being bundled by Webpack
|
||||
const chunk = String.fromCharCode(114) + String.fromCharCode(101);
|
||||
const req = (this as unknown as Record<string, FetchType>)[
|
||||
const req = (global as unknown as Record<string, FetchType>)[
|
||||
chunk + 'qui' + chunk
|
||||
];
|
||||
callback = req('cross-fetch');
|
||||
@ -102,19 +98,17 @@ export const getAPIModule: GetIconifyAPIModule = (
|
||||
});
|
||||
|
||||
// Get available length
|
||||
const url = mergeParams(prefix + '.json', {
|
||||
icons: '',
|
||||
});
|
||||
|
||||
result =
|
||||
config.maxURL -
|
||||
maxHostLength -
|
||||
config.path.length -
|
||||
endPoint
|
||||
.replace('{provider}', provider)
|
||||
.replace('{prefix}', prefix)
|
||||
.replace('{icons}', '').length;
|
||||
config.maxURL - maxHostLength - config.path.length - url.length;
|
||||
}
|
||||
|
||||
// Cache stuff and return result
|
||||
const cacheKey = provider + ':' + prefix;
|
||||
pathCache[cacheKey] = config.path;
|
||||
pathCache[provider] = config.path;
|
||||
maxLengthCache[cacheKey] = result;
|
||||
return result;
|
||||
}
|
||||
@ -126,8 +120,8 @@ export const getAPIModule: GetIconifyAPIModule = (
|
||||
provider: string,
|
||||
prefix: string,
|
||||
icons: string[]
|
||||
): APIIconsQueryParams[] => {
|
||||
const results: APIIconsQueryParams[] = [];
|
||||
): IconifyAPIIconsQueryParams[] => {
|
||||
const results: IconifyAPIIconsQueryParams[] = [];
|
||||
|
||||
// Get maximum icons list length
|
||||
let maxLength = maxLengthCache[prefix];
|
||||
@ -137,7 +131,7 @@ export const getAPIModule: GetIconifyAPIModule = (
|
||||
|
||||
// Split icons
|
||||
const type = 'icons';
|
||||
let item: APIIconsQueryParams = {
|
||||
let item: IconifyAPIIconsQueryParams = {
|
||||
type,
|
||||
provider,
|
||||
prefix,
|
||||
@ -170,7 +164,7 @@ export const getAPIModule: GetIconifyAPIModule = (
|
||||
*/
|
||||
const send: IconifyAPISendQuery = (
|
||||
host: string,
|
||||
params: APIQueryParams,
|
||||
params: IconifyAPIQueryParams,
|
||||
status: PendingQueryItem
|
||||
): void => {
|
||||
const provider = params.provider;
|
||||
@ -182,19 +176,19 @@ export const getAPIModule: GetIconifyAPIModule = (
|
||||
const icons = params.icons;
|
||||
const iconsList = icons.join(',');
|
||||
|
||||
const cacheKey = provider + ':' + prefix;
|
||||
path =
|
||||
pathCache[cacheKey] +
|
||||
endPoint
|
||||
.replace('{provider}', provider)
|
||||
.replace('{prefix}', prefix)
|
||||
.replace('{icons}', iconsList);
|
||||
pathCache[provider] +
|
||||
mergeParams(prefix + '.json', {
|
||||
icons: iconsList,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case 'custom': {
|
||||
const uri = params.uri;
|
||||
path = uri.slice(0, 1) === '/' ? uri.slice(1) : uri;
|
||||
path =
|
||||
pathCache[provider] +
|
||||
(uri.slice(0, 1) === '/' ? uri.slice(1) : uri);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import type { PendingQueryItem } from '@cyberalien/redundancy';
|
||||
import type {
|
||||
APIQueryParams,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
IconifyAPISendQuery,
|
||||
IconifyAPIModule,
|
||||
GetIconifyAPIModule,
|
||||
APIIconsQueryParams,
|
||||
IconifyAPIIconsQueryParams,
|
||||
} from '../modules';
|
||||
import type { GetAPIConfig } from '../config';
|
||||
import { mergeParams } from '../params';
|
||||
|
||||
/**
|
||||
* Global
|
||||
@ -15,11 +17,7 @@ import type { GetAPIConfig } from '../config';
|
||||
type Callback = (data: unknown) => void;
|
||||
type JSONPRoot = Record<string, Callback>;
|
||||
let rootVar: JSONPRoot | null = null;
|
||||
|
||||
/**
|
||||
* Endpoint
|
||||
*/
|
||||
let endPoint = '{prefix}.js?icons={icons}&callback={callback}';
|
||||
let rootVarName: string | null = null;
|
||||
|
||||
/**
|
||||
* Cache: provider:prefix = value
|
||||
@ -75,10 +73,7 @@ function getGlobal(): JSONPRoot {
|
||||
}
|
||||
|
||||
// Change end point
|
||||
endPoint = endPoint.replace(
|
||||
'{callback}',
|
||||
prefix + extraPrefix + '.{cb}'
|
||||
);
|
||||
rootVarName = prefix + extraPrefix + '.{cb}';
|
||||
}
|
||||
|
||||
return rootVar;
|
||||
@ -114,19 +109,13 @@ export const getAPIModule: GetIconifyAPIModule = (
|
||||
// Make sure global is set
|
||||
getGlobal();
|
||||
|
||||
// Extra width: prefix (3) + counter (4) - '{cb}' (4)
|
||||
const extraLength = 3;
|
||||
|
||||
// Get available length
|
||||
const url = mergeParams(prefix + '.js', {
|
||||
icons: '',
|
||||
callback: rootVarName!,
|
||||
});
|
||||
result =
|
||||
config.maxURL -
|
||||
maxHostLength -
|
||||
config.path.length -
|
||||
endPoint
|
||||
.replace('{provider}', provider)
|
||||
.replace('{prefix}', prefix)
|
||||
.replace('{icons}', '').length -
|
||||
extraLength;
|
||||
config.maxURL - maxHostLength - config.path.length - url.length;
|
||||
}
|
||||
|
||||
// Cache stuff and return result
|
||||
@ -143,8 +132,8 @@ export const getAPIModule: GetIconifyAPIModule = (
|
||||
provider: string,
|
||||
prefix: string,
|
||||
icons: string[]
|
||||
): APIIconsQueryParams[] => {
|
||||
const results: APIIconsQueryParams[] = [];
|
||||
): IconifyAPIIconsQueryParams[] => {
|
||||
const results: IconifyAPIIconsQueryParams[] = [];
|
||||
|
||||
// Get maximum icons list length
|
||||
const cacheKey = provider + ':' + prefix;
|
||||
@ -155,7 +144,7 @@ export const getAPIModule: GetIconifyAPIModule = (
|
||||
|
||||
// Split icons
|
||||
const type = 'icons';
|
||||
let item: APIIconsQueryParams = {
|
||||
let item: IconifyAPIIconsQueryParams = {
|
||||
type,
|
||||
provider,
|
||||
prefix,
|
||||
@ -188,7 +177,7 @@ export const getAPIModule: GetIconifyAPIModule = (
|
||||
*/
|
||||
const send: IconifyAPISendQuery = (
|
||||
host: string,
|
||||
params: APIQueryParams,
|
||||
params: IconifyAPIQueryParams,
|
||||
status: PendingQueryItem
|
||||
): void => {
|
||||
if (params.type !== 'icons') {
|
||||
@ -218,13 +207,11 @@ export const getAPIModule: GetIconifyAPIModule = (
|
||||
}
|
||||
const callbackName = cbPrefix + cbCounter;
|
||||
|
||||
const path =
|
||||
pathCache[cacheKey] +
|
||||
endPoint
|
||||
.replace('{provider}', provider)
|
||||
.replace('{prefix}', prefix)
|
||||
.replace('{icons}', iconsList)
|
||||
.replace('{cb}', callbackName);
|
||||
const url = mergeParams(prefix + '.js', {
|
||||
icons: iconsList,
|
||||
callback: rootVarName!.replace('{cb}', callbackName),
|
||||
});
|
||||
const path = pathCache[cacheKey] + url;
|
||||
|
||||
global[callbackName] = (data: unknown): void => {
|
||||
// Remove callback and complete query
|
||||
|
@ -2,8 +2,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import type { PendingQueryItem } from '@cyberalien/redundancy';
|
||||
import type {
|
||||
APIIconsQueryParams,
|
||||
APIQueryParams,
|
||||
IconifyAPIIconsQueryParams,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPIModule,
|
||||
} from '../modules';
|
||||
import type { IconifyJSON } from '@iconify/types';
|
||||
@ -45,16 +45,37 @@ export interface IconifyMockIconsAPI extends IconifyMockAPIBase {
|
||||
response: number | IconifyJSON;
|
||||
}
|
||||
|
||||
export type IconifyMockAPI = IconifyMockIconsAPI;
|
||||
export interface IconifyMockCustomAPI extends IconifyMockAPIBase {
|
||||
type: 'custom';
|
||||
|
||||
// Request parameters
|
||||
uri: string;
|
||||
|
||||
// Response
|
||||
// Number if error should be sent, JSON on success
|
||||
response: number | Record<string, unknown>;
|
||||
}
|
||||
|
||||
export type IconifyMockAPI = IconifyMockIconsAPI | IconifyMockCustomAPI;
|
||||
|
||||
/**
|
||||
* Fake API storage
|
||||
* Fake API storage for icons
|
||||
*
|
||||
* [provider][prefix] = list of entries
|
||||
*/
|
||||
export const storage: Record<
|
||||
export const iconsStorage: Record<
|
||||
string,
|
||||
Record<string, IconifyMockAPI[]>
|
||||
Record<string, IconifyMockIconsAPI[]>
|
||||
> = Object.create(null);
|
||||
|
||||
/**
|
||||
* Fake API storage for custom queries
|
||||
*
|
||||
* [provider][uri] = response
|
||||
*/
|
||||
export const customStorage: Record<
|
||||
string,
|
||||
Record<string, IconifyMockCustomAPI>
|
||||
> = Object.create(null);
|
||||
|
||||
/**
|
||||
@ -62,20 +83,33 @@ export const storage: Record<
|
||||
*/
|
||||
export function mockAPIData(data: IconifyMockAPI): void {
|
||||
const provider = data.provider;
|
||||
if (storage[provider] === void 0) {
|
||||
storage[provider] = Object.create(null);
|
||||
}
|
||||
const providerStorage = storage[provider];
|
||||
switch (data.type) {
|
||||
case 'icons': {
|
||||
if (iconsStorage[provider] === void 0) {
|
||||
iconsStorage[provider] = Object.create(null);
|
||||
}
|
||||
const providerStorage = iconsStorage[provider];
|
||||
|
||||
const prefix = data.prefix;
|
||||
if (providerStorage[prefix] === void 0) {
|
||||
providerStorage[prefix] = [];
|
||||
}
|
||||
const prefix = data.prefix;
|
||||
if (providerStorage[prefix] === void 0) {
|
||||
providerStorage[prefix] = [];
|
||||
}
|
||||
|
||||
storage[provider][prefix].push(data);
|
||||
iconsStorage[provider][prefix].push(data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'custom': {
|
||||
if (customStorage[provider] === void 0) {
|
||||
customStorage[provider] = Object.create(null);
|
||||
}
|
||||
customStorage[provider][data.uri] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface MockAPIIconsQueryParams extends APIIconsQueryParams {
|
||||
interface MockAPIIconsQueryParams extends IconifyAPIIconsQueryParams {
|
||||
index: number;
|
||||
}
|
||||
|
||||
@ -90,12 +124,12 @@ export const mockAPIModule: IconifyAPIModule = {
|
||||
provider: string,
|
||||
prefix: string,
|
||||
icons: string[]
|
||||
): APIIconsQueryParams[] => {
|
||||
): IconifyAPIIconsQueryParams[] => {
|
||||
const type = 'icons';
|
||||
|
||||
if (
|
||||
storage[provider] === void 0 ||
|
||||
storage[provider][prefix] === void 0
|
||||
iconsStorage[provider] === void 0 ||
|
||||
iconsStorage[provider][prefix] === void 0
|
||||
) {
|
||||
// No mock data: bundle all icons in one request that will return 404
|
||||
return [
|
||||
@ -107,7 +141,7 @@ export const mockAPIModule: IconifyAPIModule = {
|
||||
},
|
||||
];
|
||||
}
|
||||
const mockData = storage[provider][prefix];
|
||||
const mockData = iconsStorage[provider][prefix];
|
||||
|
||||
// Find catch all entry with error
|
||||
const catchAllIndex = mockData.findIndex(
|
||||
@ -157,7 +191,7 @@ export const mockAPIModule: IconifyAPIModule = {
|
||||
});
|
||||
|
||||
// Sort results
|
||||
const results: APIIconsQueryParams[] = [];
|
||||
const results: IconifyAPIIconsQueryParams[] = [];
|
||||
if (noMatch.length > 0) {
|
||||
results.push({
|
||||
type,
|
||||
@ -174,7 +208,7 @@ export const mockAPIModule: IconifyAPIModule = {
|
||||
prefix,
|
||||
icons: matches[index],
|
||||
index,
|
||||
} as APIIconsQueryParams);
|
||||
} as IconifyAPIIconsQueryParams);
|
||||
});
|
||||
|
||||
return results;
|
||||
@ -183,27 +217,23 @@ export const mockAPIModule: IconifyAPIModule = {
|
||||
/**
|
||||
* Load icons
|
||||
*/
|
||||
send: (host: string, params: APIQueryParams, status: PendingQueryItem) => {
|
||||
send: (
|
||||
host: string,
|
||||
params: IconifyAPIQueryParams,
|
||||
status: PendingQueryItem
|
||||
) => {
|
||||
const provider = params.provider;
|
||||
let data: IconifyMockAPI;
|
||||
|
||||
switch (params.type) {
|
||||
case 'icons': {
|
||||
const prefix = params.prefix;
|
||||
const index = (params as MockAPIIconsQueryParams).index;
|
||||
data = iconsStorage[provider]?.[params.prefix]?.[index];
|
||||
break;
|
||||
}
|
||||
|
||||
// Get item
|
||||
if (
|
||||
storage[provider] === void 0 ||
|
||||
storage[provider][prefix] === void 0 ||
|
||||
storage[provider][prefix][index] === void 0
|
||||
) {
|
||||
// No entry
|
||||
status.done(void 0, 404);
|
||||
return;
|
||||
}
|
||||
|
||||
data = storage[provider][prefix][index];
|
||||
case 'custom': {
|
||||
data = customStorage[provider]?.[params.uri];
|
||||
break;
|
||||
}
|
||||
|
||||
@ -213,6 +243,11 @@ export const mockAPIModule: IconifyAPIModule = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data === void 0) {
|
||||
status.done(void 0, 404);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get delay
|
||||
const delay = data.delay;
|
||||
let callback: IconifyMockAPIDelayCallback;
|
||||
|
59
packages/core/src/api/params.ts
Normal file
59
packages/core/src/api/params.ts
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* API query parameters
|
||||
*/
|
||||
type APIQueryParamValue = number | string | boolean | undefined;
|
||||
export type IconifyAPIMergeQueryParams = Record<string, APIQueryParamValue>;
|
||||
|
||||
/**
|
||||
* Type for mergeParams()
|
||||
*/
|
||||
export type MergeParams = (
|
||||
base: string,
|
||||
params: IconifyAPIMergeQueryParams
|
||||
) => string;
|
||||
|
||||
/**
|
||||
* Add parameters to query
|
||||
*/
|
||||
export const mergeParams: MergeParams = (
|
||||
base: string,
|
||||
params: IconifyAPIMergeQueryParams
|
||||
): string => {
|
||||
let result = base,
|
||||
hasParams = result.indexOf('?') !== -1;
|
||||
|
||||
/**
|
||||
* Convertion of parameters to string, only allows simple types used by Iconify API
|
||||
*/
|
||||
function paramToString(value: APIQueryParamValue): string {
|
||||
switch (typeof value) {
|
||||
case 'boolean':
|
||||
return value ? 'true' : 'false';
|
||||
|
||||
case 'number':
|
||||
return encodeURIComponent(value);
|
||||
|
||||
case 'string':
|
||||
return encodeURIComponent(value);
|
||||
|
||||
default:
|
||||
throw new Error('Invalid parameter');
|
||||
}
|
||||
}
|
||||
|
||||
Object.keys(params).forEach((key: string) => {
|
||||
let value;
|
||||
|
||||
try {
|
||||
value = paramToString(params[key]);
|
||||
} catch (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
result +=
|
||||
(hasParams ? '&' : '?') + encodeURIComponent(key) + '=' + value;
|
||||
hasParams = true;
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
34
packages/core/tests/30-api/10-merge-params-test.ts
Normal file
34
packages/core/tests/30-api/10-merge-params-test.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { mergeParams } from '../../lib/api/params';
|
||||
|
||||
describe('Testing mergeParams', () => {
|
||||
it('mergeParams()', () => {
|
||||
// Nothing
|
||||
expect(mergeParams('/foo', {})).to.be.equal('/foo');
|
||||
|
||||
// Simple variables
|
||||
expect(
|
||||
mergeParams('/foo', {
|
||||
foo: 1,
|
||||
bar: 'baz',
|
||||
baz: true,
|
||||
})
|
||||
).to.be.equal('/foo?foo=1&bar=baz&baz=true');
|
||||
|
||||
// More parameters to existing query
|
||||
expect(
|
||||
mergeParams('/foo?bar=baz', {
|
||||
foo: false,
|
||||
})
|
||||
).to.be.equal('/foo?bar=baz&foo=false');
|
||||
|
||||
// Escaping characters
|
||||
expect(
|
||||
mergeParams('/foo', {
|
||||
'2&2': '1=1',
|
||||
'3 z': '?3',
|
||||
})
|
||||
).to.be.equal('/foo?2%262=1%3D1&3%20z=%3F3');
|
||||
});
|
||||
});
|
@ -6,7 +6,7 @@ import type { IconifyMockAPI } from '../../lib/api/modules/mock';
|
||||
import {
|
||||
mockAPIModule,
|
||||
mockAPIData,
|
||||
storage,
|
||||
iconsStorage,
|
||||
} from '../../lib/api/modules/mock';
|
||||
|
||||
describe('Testing mock API module prepare function', () => {
|
||||
@ -35,8 +35,8 @@ describe('Testing mock API module prepare function', () => {
|
||||
mockAPIData(item);
|
||||
|
||||
// Make sure item is stored correctly
|
||||
expect(typeof storage[provider]).to.be.equal('object');
|
||||
expect(storage[provider][prefix]).to.be.eql([item]);
|
||||
expect(typeof iconsStorage[provider]).to.be.equal('object');
|
||||
expect(iconsStorage[provider][prefix]).to.be.eql([item]);
|
||||
|
||||
// Find item for icons
|
||||
const result = prepare(provider, prefix, ['foo', 'bar', 'baz']);
|
||||
@ -87,8 +87,8 @@ describe('Testing mock API module prepare function', () => {
|
||||
mockAPIData(item3);
|
||||
|
||||
// Make sure item is stored correctly
|
||||
expect(typeof storage[provider]).to.be.equal('object');
|
||||
expect(storage[provider][prefix]).to.be.eql([item1, item2, item3]);
|
||||
expect(typeof iconsStorage[provider]).to.be.equal('object');
|
||||
expect(iconsStorage[provider][prefix]).to.be.eql([item1, item2, item3]);
|
||||
|
||||
// Find items for icons
|
||||
const result = prepare(provider, prefix, [
|
||||
@ -145,8 +145,8 @@ describe('Testing mock API module prepare function', () => {
|
||||
mockAPIData(item);
|
||||
|
||||
// Make sure item is stored correctly
|
||||
expect(typeof storage[provider]).to.be.equal('object');
|
||||
expect(storage[provider][prefix]).to.be.eql([item]);
|
||||
expect(typeof iconsStorage[provider]).to.be.equal('object');
|
||||
expect(iconsStorage[provider][prefix]).to.be.eql([item]);
|
||||
|
||||
// Find item for icons
|
||||
const result = prepare(provider, prefix, ['foo', 'bar', 'baz']);
|
||||
|
@ -22,18 +22,21 @@ import type { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build';
|
||||
import { coreModules } from '@iconify/core/lib/modules';
|
||||
|
||||
// API
|
||||
import { API, IconifyAPIInternalStorage } from '@iconify/core/lib/api/';
|
||||
import { API } from '@iconify/core/lib/api/';
|
||||
import {
|
||||
IconifyAPIFunctions,
|
||||
IconifyAPIInternalFunctions,
|
||||
APIFunctions,
|
||||
APIInternalFunctions,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
} from '@iconify/core/lib/api/functions';
|
||||
import {
|
||||
setAPIModule,
|
||||
IconifyAPIModule,
|
||||
IconifyAPISendQuery,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
GetIconifyAPIModule,
|
||||
} from '@iconify/core/lib/api/modules';
|
||||
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
|
||||
@ -102,12 +105,14 @@ export {
|
||||
IconifyAPIConfig,
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
IconifyAPIInternalStorage,
|
||||
IconifyAPIModule,
|
||||
GetAPIConfig,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
IconifyAPISendQuery,
|
||||
PartialIconifyAPIConfig,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
};
|
||||
|
||||
// Builder functions
|
||||
|
@ -34,13 +34,16 @@ import {
|
||||
IconifyAPIInternalFunctions,
|
||||
APIFunctions,
|
||||
APIInternalFunctions,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
} from '@iconify/core/lib/api/functions';
|
||||
import { API, IconifyAPIInternalStorage } from '@iconify/core/lib/api/';
|
||||
import { API } from '@iconify/core/lib/api/';
|
||||
import {
|
||||
setAPIModule,
|
||||
IconifyAPIModule,
|
||||
IconifyAPISendQuery,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
GetIconifyAPIModule,
|
||||
} from '@iconify/core/lib/api/modules';
|
||||
import {
|
||||
@ -94,15 +97,19 @@ export {
|
||||
IconifyAPIConfig,
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
IconifyAPIInternalStorage,
|
||||
IconifyAPIModule,
|
||||
GetAPIConfig,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
IconifyAPISendQuery,
|
||||
IconifyBrowserCacheType,
|
||||
PartialIconifyAPIConfig,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
};
|
||||
|
||||
// Cache
|
||||
export { IconifyBrowserCacheType };
|
||||
|
||||
/**
|
||||
* Iconify interface
|
||||
*/
|
||||
|
@ -25,18 +25,21 @@ import { fullIcon } from '@iconify/utils/lib/icon';
|
||||
import { coreModules } from '@iconify/core/lib/modules';
|
||||
|
||||
// API
|
||||
import { API, IconifyAPIInternalStorage } from '@iconify/core/lib/api/';
|
||||
import { API } from '@iconify/core/lib/api/';
|
||||
import {
|
||||
IconifyAPIFunctions,
|
||||
IconifyAPIInternalFunctions,
|
||||
APIFunctions,
|
||||
APIInternalFunctions,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
} from '@iconify/core/lib/api/functions';
|
||||
import {
|
||||
setAPIModule,
|
||||
IconifyAPIModule,
|
||||
IconifyAPISendQuery,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
GetIconifyAPIModule,
|
||||
} from '@iconify/core/lib/api/modules';
|
||||
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
|
||||
@ -108,12 +111,14 @@ export {
|
||||
IconifyAPIConfig,
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
IconifyAPIInternalStorage,
|
||||
IconifyAPIModule,
|
||||
GetAPIConfig,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
IconifyAPISendQuery,
|
||||
PartialIconifyAPIConfig,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
};
|
||||
|
||||
// Builder functions
|
||||
|
@ -24,18 +24,21 @@ import { fullIcon, IconifyIcon } from '@iconify/utils/lib/icon';
|
||||
import { coreModules } from '@iconify/core/lib/modules';
|
||||
|
||||
// API
|
||||
import { API, IconifyAPIInternalStorage } from '@iconify/core/lib/api/';
|
||||
import { API } from '@iconify/core/lib/api/';
|
||||
import {
|
||||
IconifyAPIFunctions,
|
||||
IconifyAPIInternalFunctions,
|
||||
APIFunctions,
|
||||
APIInternalFunctions,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
} from '@iconify/core/lib/api/functions';
|
||||
import {
|
||||
setAPIModule,
|
||||
IconifyAPIModule,
|
||||
IconifyAPISendQuery,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
GetIconifyAPIModule,
|
||||
} from '@iconify/core/lib/api/modules';
|
||||
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
|
||||
@ -105,12 +108,14 @@ export {
|
||||
IconifyAPIConfig,
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
IconifyAPIInternalStorage,
|
||||
IconifyAPIModule,
|
||||
GetAPIConfig,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
IconifyAPISendQuery,
|
||||
PartialIconifyAPIConfig,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
};
|
||||
|
||||
// Builder functions
|
||||
|
@ -28,12 +28,14 @@ export {
|
||||
IconifyAPIConfig,
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
IconifyAPIInternalStorage,
|
||||
IconifyAPIModule,
|
||||
GetAPIConfig,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
IconifyAPISendQuery,
|
||||
PartialIconifyAPIConfig,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
} from './functions';
|
||||
|
||||
// Builder functions
|
||||
|
@ -34,18 +34,21 @@ import { fullIcon, IconifyIcon } from '@iconify/utils/lib/icon';
|
||||
import { coreModules } from '@iconify/core/lib/modules';
|
||||
|
||||
// API
|
||||
import { API, IconifyAPIInternalStorage } from '@iconify/core/lib/api/';
|
||||
import { API } from '@iconify/core/lib/api/';
|
||||
import {
|
||||
IconifyAPIFunctions,
|
||||
IconifyAPIInternalFunctions,
|
||||
APIFunctions,
|
||||
APIInternalFunctions,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
} from '@iconify/core/lib/api/functions';
|
||||
import {
|
||||
setAPIModule,
|
||||
IconifyAPIModule,
|
||||
IconifyAPISendQuery,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
GetIconifyAPIModule,
|
||||
} from '@iconify/core/lib/api/modules';
|
||||
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
|
||||
@ -116,12 +119,14 @@ export {
|
||||
IconifyAPIConfig,
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
IconifyAPIInternalStorage,
|
||||
IconifyAPIModule,
|
||||
GetAPIConfig,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
IconifyAPISendQuery,
|
||||
PartialIconifyAPIConfig,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
};
|
||||
|
||||
// Builder functions
|
||||
|
@ -26,18 +26,21 @@ import { fullIcon, IconifyIcon } from '@iconify/utils/lib/icon';
|
||||
import { coreModules } from '@iconify/core/lib/modules';
|
||||
|
||||
// API
|
||||
import { API, IconifyAPIInternalStorage } from '@iconify/core/lib/api/';
|
||||
import { API } from '@iconify/core/lib/api/';
|
||||
import {
|
||||
IconifyAPIFunctions,
|
||||
IconifyAPIInternalFunctions,
|
||||
APIFunctions,
|
||||
APIInternalFunctions,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
} from '@iconify/core/lib/api/functions';
|
||||
import {
|
||||
setAPIModule,
|
||||
IconifyAPIModule,
|
||||
IconifyAPISendQuery,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
GetIconifyAPIModule,
|
||||
} from '@iconify/core/lib/api/modules';
|
||||
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
|
||||
@ -108,12 +111,14 @@ export {
|
||||
IconifyAPIConfig,
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
IconifyAPIInternalStorage,
|
||||
IconifyAPIModule,
|
||||
GetAPIConfig,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPIPrepareIconsQuery,
|
||||
IconifyAPISendQuery,
|
||||
PartialIconifyAPIConfig,
|
||||
IconifyAPIQueryParams,
|
||||
IconifyAPICustomQueryParams,
|
||||
IconifyAPIMergeQueryParams,
|
||||
};
|
||||
|
||||
// Builder functions
|
||||
|
Loading…
Reference in New Issue
Block a user