mirror of https://github.com/iconify/api.git
feat: auto-update data, not fully tested yet
This commit is contained in:
parent
3ae315a7b2
commit
f8ed72e24b
|
|
@ -31,6 +31,17 @@ export const appConfig: AppConfig = {
|
|||
|
||||
// Log stuff
|
||||
log: true,
|
||||
|
||||
// Enable update
|
||||
allowUpdate: true,
|
||||
|
||||
// Required parameter to include in `/update` query to trigger update
|
||||
// Value must match environment variable `APP_UPDATE_SECRET`
|
||||
updateRequiredParam: 'secret',
|
||||
|
||||
// Update check throttling
|
||||
// Delay to wait between successful update request and actual update
|
||||
updateThrottle: 60,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -84,3 +84,26 @@ export function updateIconSets(): number {
|
|||
prefixes = Array.from(newPrefixes);
|
||||
return prefixes.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger update
|
||||
*/
|
||||
export function triggerIconSetsUpdate() {
|
||||
if (!importers) {
|
||||
return;
|
||||
}
|
||||
console.log('Checking for updates...');
|
||||
|
||||
(async () => {
|
||||
let updated = false;
|
||||
for (let i = 0; i < importers?.length; i++) {
|
||||
updated = (await importers[i].checkForUpdate()) || updated;
|
||||
}
|
||||
return updated;
|
||||
})()
|
||||
.then((updated) => {
|
||||
console.log(updated ? 'Update complete' : 'Nothing to update');
|
||||
updateIconSets();
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { iconNameRoutePartialRegEx, iconNameRouteRegEx, splitIconName } from '..
|
|||
import { generateIconsDataResponse } from './responses/icons';
|
||||
import { generateLastModifiedResponse } from './responses/modified';
|
||||
import { generateSVGResponse } from './responses/svg';
|
||||
import { generateUpdateResponse } from './responses/update';
|
||||
import { initVersionResponse, versionResponse } from './responses/version';
|
||||
|
||||
/**
|
||||
|
|
@ -105,6 +106,14 @@ export async function startHTTPServer() {
|
|||
});
|
||||
});
|
||||
|
||||
// Update icon sets
|
||||
server.get('/update', (req, res) => {
|
||||
generateUpdateResponse(req.query, res);
|
||||
});
|
||||
server.post('/update', (req, res) => {
|
||||
generateUpdateResponse(req.query, res);
|
||||
});
|
||||
|
||||
// Options
|
||||
server.options('/*', (req, res) => {
|
||||
res.send(200);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
import type { FastifyReply, FastifyRequest } from 'fastify';
|
||||
import { appConfig } from '../../config/app';
|
||||
import { triggerIconSetsUpdate } from '../../data/icon-sets';
|
||||
import { runWhenLoaded } from '../../data/loading';
|
||||
|
||||
let pendingUpdate = false;
|
||||
let lastError = 0;
|
||||
|
||||
const envKey = 'APP_UPDATE_SECRET';
|
||||
|
||||
function logError(msg: string) {
|
||||
const time = Date.now();
|
||||
|
||||
// Do not log error too often
|
||||
if (time > lastError + 3600000) {
|
||||
lastError = time;
|
||||
console.error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function checkKey(query: Record<string, string>): boolean {
|
||||
if (appConfig.updateRequiredParam) {
|
||||
const expectedValue = process.env[envKey];
|
||||
if (!expectedValue) {
|
||||
// Missing env variable
|
||||
logError(`Cannot process update request: missing env variable "${envKey}"`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const value = query[appConfig.updateRequiredParam];
|
||||
if (value !== expectedValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
return true;
|
||||
}
|
||||
|
||||
// No param
|
||||
logError(
|
||||
'Auto-update can be triggered by anyone. Set `updateRequiredParam` config or UPDATE_REQUIRED_PARAM env variable to require secret to trigger update'
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate icons data
|
||||
*/
|
||||
export function generateUpdateResponse(query: FastifyRequest['query'], res: FastifyReply) {
|
||||
if (appConfig.allowUpdate && checkKey((query || {}) as Record<string, string>) && !pendingUpdate) {
|
||||
pendingUpdate = true;
|
||||
runWhenLoaded(() => {
|
||||
const delay = appConfig.updateThrottle;
|
||||
console.log('Will check for update in', delay, 'seconds...');
|
||||
setTimeout(() => {
|
||||
triggerIconSetsUpdate();
|
||||
pendingUpdate = false;
|
||||
}, delay * 1000);
|
||||
});
|
||||
}
|
||||
|
||||
// Fake 404
|
||||
res.send(404);
|
||||
}
|
||||
|
|
@ -23,4 +23,13 @@ export interface AppConfig {
|
|||
|
||||
// Logging
|
||||
log: boolean;
|
||||
|
||||
// Allow update
|
||||
allowUpdate: boolean;
|
||||
|
||||
// Update key
|
||||
updateRequiredParam: string;
|
||||
|
||||
// Update check throttling
|
||||
updateThrottle: number;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue