feat: support deprecated API v1 list-icons queries

This commit is contained in:
Vjacheslav Trushkin 2022-10-15 22:41:48 +03:00
parent b137290974
commit d9134cac49
4 changed files with 217 additions and 1 deletions

View File

@ -2,6 +2,7 @@ import fastify, { FastifyReply } from 'fastify';
import { appConfig } from '../config/app';
import { runWhenLoaded } from '../data/loading';
import { iconNameRoutePartialRegEx, iconNameRouteRegEx, splitIconName } from '../misc/name';
import { generateAPIv1IconsListResponse } from './responses/collection-v1';
import { generateAPIv2CollectionResponse } from './responses/collection-v2';
import { generateCollectionsListResponse } from './responses/collections';
import { generateIconsDataResponse } from './responses/icons';
@ -122,6 +123,18 @@ export async function startHTTPServer() {
});
});
// Icons list, API v1
server.get('/list-icons', (req, res) => {
runWhenLoaded(() => {
generateAPIv1IconsListResponse(req.query, res, false);
});
});
server.get('/list-icons-categorized', (req, res) => {
runWhenLoaded(() => {
generateAPIv1IconsListResponse(req.query, res, true);
});
});
// Update icon sets
server.get('/update', (req, res) => {
generateUpdateResponse(req.query, res);

View File

@ -0,0 +1,132 @@
import type { FastifyReply, FastifyRequest } from 'fastify';
import { getPrefixes, iconSets } from '../../data/icon-sets';
import type { StoredIconSet } from '../../types/icon-set/storage';
import type {
APIv1ListIconsBaseResponse,
APIv1ListIconsCategorisedResponse,
APIv1ListIconsResponse,
} from '../../types/server/v1';
import { checkJSONPQuery, sendJSONResponse } from '../helpers/json';
import { filterPrefixesByPrefix } from '../helpers/prefixes';
/**
* Send API v2 response
*
* This response ignores the following parameters:
* - `aliases` -> always enabled
* - `hidden` -> always enabled
*
* Those parameters are always requested anyway, so does not make sense to re-create data in case they are disabled
*/
export function generateAPIv1IconsListResponse(
query: FastifyRequest['query'],
res: FastifyReply,
categorised: boolean
) {
const q = (query || {}) as Record<string, string>;
const wrap = checkJSONPQuery(q);
if (!wrap) {
// Invalid JSONP callback
res.send(400);
return;
}
function parse(prefix: string, iconSet: StoredIconSet): APIv1ListIconsResponse | APIv1ListIconsCategorisedResponse {
const v2Cache = iconSet.apiV2IconsCache;
const rendered = v2Cache.rendered;
// Generate common data
const base: APIv1ListIconsBaseResponse = {
prefix,
total: rendered.total,
};
if (rendered.title) {
base.title = rendered.title;
}
if (q.info && rendered.info) {
base.info = rendered.info;
}
if (q.aliases && rendered.aliases) {
base.aliases = rendered.aliases;
}
if (q.chars && v2Cache.chars) {
base.chars = v2Cache.chars;
}
// Add icons
if (categorised) {
const result = base as APIv1ListIconsCategorisedResponse;
if (rendered.categories) {
result.categories = rendered.categories;
}
if (rendered.uncategorized) {
result.uncategorized = rendered.uncategorized;
}
return result;
}
const result = base as APIv1ListIconsResponse;
result.icons = Array.from(iconSet.icons.visible);
return result;
}
if (q.prefix) {
const prefix = q.prefix;
const iconSet = iconSets[prefix]?.item;
if (!iconSet) {
res.send(404);
return;
}
sendJSONResponse(parse(prefix, iconSet), q, wrap, res);
return;
}
if (q.prefixes) {
const prefixes = filterPrefixesByPrefix(
getPrefixes(),
{
prefixes: q.prefixes,
},
false
);
// Retrieve all items
interface Item {
prefix: string;
iconSet: StoredIconSet;
}
const items: Item[] = [];
for (let i = 0; i < prefixes.length; i++) {
const prefix = prefixes[i];
const iconSet = iconSets[prefix]?.item;
if (iconSet) {
items.push({
prefix,
iconSet,
});
if (items.length > 10) {
break;
}
}
}
if (!items.length) {
// Empty list
res.send(404);
return;
}
// Get all items
const result = Object.create(null) as Record<string, ReturnType<typeof parse>>;
for (let i = 0; i < items.length; i++) {
const item = items[i];
result[item.prefix] = parse(item.prefix, item.iconSet);
}
sendJSONResponse(result, q, wrap, res);
return;
}
// Invalid
res.send(400);
}

View File

@ -1,5 +1,4 @@
import type { FastifyReply, FastifyRequest } from 'fastify';
import { generateIconSetIconsTree } from '../../data/icon-set/lists/icons';
import { iconSets } from '../../data/icon-sets';
import type { APIv2CollectionResponse } from '../../types/server/v2';
import { checkJSONPQuery, sendJSONResponse } from '../helpers/json';

72
src/types/server/v1.ts Normal file
View File

@ -0,0 +1,72 @@
import type { IconifyInfo, IconifyJSON } from '@iconify/types';
/**
* /list-icons
* /list-icons-categorized
*
* Do not use, supported only for legacy software that should no longer be used
*/
export interface APIv1ListIconsParams {
// Icon set prefix
prefix: string;
// Include info in response
info?: boolean;
// Include aliases in response
aliases?: boolean;
// Include characters in response
chars?: boolean;
}
export interface APIv1ListIconsBaseResponse {
// Icon set prefix
prefix: string;
// Number of icons (duplicate of info?.total)
total: number;
// Icon set title, if available (duplicate of info?.name)
title?: string;
// Icon set info
info?: IconifyInfo;
// List of aliases, key = alias, value = parent icon
aliases?: Record<string, string>;
// Characters, key = character, value = icon name
chars?: Record<string, string>;
}
export interface APIv1ListIconsResponse extends APIv1ListIconsBaseResponse {
// Icons
icons: string[];
}
export interface APIv1ListIconsCategorisedResponse extends APIv1ListIconsBaseResponse {
// Icons, sorted by category
categories?: Record<string, string[]>;
// Icons, sorted by category
uncategorized?: string[];
// Themes
themes?: IconifyJSON['themes'];
}
/**
* Same as above, but with `prefixes` parameter set
*
* Result is object, where prefix is key, value is icons list
*/
export interface APIv1ListIconsPrefixedParams extends Omit<APIv1ListIconsParams, 'prefix'> {
// Comma separated list of prefix matches: 'mdi,mdi-'
// If value ends with '-', it is treated as partial prefix
prefixes: string;
}
export type APIv1ListIconsPrefixedResponse = Record<string, APIv1ListIconsResponse>;
export type APIv1ListIconsCategorisedPrefixedResponse = Record<string, APIv1ListIconsCategorisedResponse>;