feat: support last-modified query

This commit is contained in:
Vjacheslav Trushkin 2022-10-14 19:29:09 +03:00
parent 23294ae691
commit 1001f79dff
4 changed files with 118 additions and 0 deletions

View File

@ -0,0 +1,55 @@
interface MatchPrefixesParams {
// One prefix
prefix?: string;
// Comma separated prefixes
prefixes?: string;
}
/**
* Filter prefixes
*
* returnEmpty = true -> if no filter params set, returns empty array
* returnEmpty = false -> if no filter params set, returns all filters
*/
export function filterPrefixes(prefixes: string[], params: MatchPrefixesParams, returnEmpty: boolean): string[] {
const exactMatch = params.prefix;
if (exactMatch) {
// Exact match
return prefixes.indexOf(exactMatch) === -1 ? [] : [exactMatch];
}
const partialMatch = params.prefixes;
if (partialMatch) {
// Split matches by partial and full
const exact: Set<string> = new Set();
const partial: string[] = [];
partialMatch.split(',').forEach((prefix) => {
if (prefix.slice(-1) === '-') {
// Partial prefix: 'mdi-'
partial.push(prefix);
} else {
// Exact match
exact.add(prefix);
}
});
// Filter prefixes
return prefixes.filter((prefix) => {
if (exact.has(prefix)) {
return true;
}
for (let i = 0; i < partial.length; i++) {
const match = partial[i];
if (prefix.slice(0, match.length) === match) {
return true;
}
}
return false;
});
}
// No filters
return returnEmpty ? [] : prefixes;
}

View File

@ -3,6 +3,7 @@ import { appConfig } from '../config/app';
import { runWhenLoaded } from '../data/loading';
import { iconNameRoutePartialRegEx, iconNameRouteRegEx, splitIconName } from '../misc/name';
import { generateIconsDataResponse } from './responses/icons';
import { generateLastModifiedResponse } from './responses/modified';
import { generateSVGResponse } from './responses/svg';
import { initVersionResponse, versionResponse } from './responses/version';
@ -97,6 +98,13 @@ export async function startHTTPServer() {
});
});
// Last modification time
server.get('/last-modified', (req, res) => {
runWhenLoaded(() => {
generateLastModifiedResponse(req.query, res);
});
});
// Options
server.options('/*', (req, res) => {
res.send(200);

View File

@ -0,0 +1,47 @@
import type { FastifyReply, FastifyRequest } from 'fastify';
import { getPrefixes, iconSets } from '../../data/icon-sets';
import type { LastModifiedAPIResponse } from '../../types/server/modified';
import { checkJSONPQuery, sendJSONResponse } from '../helpers/json';
import { filterPrefixes } from '../helpers/prefixes';
/**
* Generate icons data
*/
export function generateLastModifiedResponse(query: FastifyRequest['query'], res: FastifyReply) {
const q = (query || {}) as Record<string, string>;
const wrap = checkJSONPQuery(q);
if (!wrap) {
// Invalid JSONP callback
res.send(400);
return;
}
// Filter prefixes
const prefixes = filterPrefixes(getPrefixes(), q, false);
// Generate result
const lastModified = Object.create(null) as Record<string, number>;
const response: LastModifiedAPIResponse = {
lastModified,
};
let found = false;
for (let i = 0; i < prefixes.length; i++) {
const prefix = prefixes[i];
const item = iconSets[prefix];
if (item) {
const value = item.item.common.lastModified;
if (value) {
found = true;
lastModified[prefix] = value;
}
}
}
if (!found) {
// No matches
res.send(404);
return;
}
sendJSONResponse(response, q, wrap, res);
}

View File

@ -0,0 +1,8 @@
/**
* Response for `/last-modified` query
*
* Key is prefix, value is last modification time number
*/
export interface LastModifiedAPIResponse {
lastModified: Record<string, number>;
}