forked from ppfun/pixelplanet
don't require server restart on client changes,
by watching the asset files and reloading if changed
This commit is contained in:
parent
058290aa16
commit
8d41c6533d
|
@ -4,6 +4,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import assetWatcher from './core/fsWatcher';
|
||||||
import canvases from './core/canvases';
|
import canvases from './core/canvases';
|
||||||
import ttag from './core/ttag';
|
import ttag from './core/ttag';
|
||||||
|
|
||||||
|
@ -58,16 +59,21 @@ function getCanvases(t) {
|
||||||
return localizedCanvases;
|
return localizedCanvases;
|
||||||
}
|
}
|
||||||
|
|
||||||
const lCanvases = {};
|
function translateCanvases() {
|
||||||
(() => {
|
const parsedCanvases = {};
|
||||||
const langs = Object.keys(ttag);
|
const langs = Object.keys(ttag);
|
||||||
langs.forEach((lang) => {
|
langs.forEach((lang) => {
|
||||||
lCanvases[lang] = getCanvases(ttag[lang].t);
|
parsedCanvases[lang] = getCanvases(ttag[lang].t);
|
||||||
});
|
});
|
||||||
})();
|
return parsedCanvases;
|
||||||
|
|
||||||
export function getLocalizedCanvases(lang = 'en') {
|
|
||||||
return lCanvases[lang] || lCanvases.en;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default lCanvases;
|
let lCanvases = translateCanvases();
|
||||||
|
// reload on asset change
|
||||||
|
assetWatcher.onChange(() => {
|
||||||
|
lCanvases = translateCanvases();
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function getLocalizedCanvases(lang = 'en') {
|
||||||
|
return lCanvases[lang] || lCanvases.en;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
|
/*
|
||||||
|
* Provide css and js asset files for client
|
||||||
|
*/
|
||||||
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
const ASSET_DIR = '/assets';
|
import assetWatcher from './fsWatcher';
|
||||||
|
import { ASSET_DIR } from './config';
|
||||||
|
|
||||||
const assetDir = path.join(__dirname, 'public', ASSET_DIR);
|
const assetDir = path.join(__dirname, 'public', ASSET_DIR);
|
||||||
/*
|
/*
|
||||||
* {
|
* {
|
||||||
|
@ -78,8 +84,11 @@ function checkAssets() {
|
||||||
return parsedAssets;
|
return parsedAssets;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line prefer-const
|
|
||||||
assets = checkAssets();
|
assets = checkAssets();
|
||||||
|
// reload on asset change
|
||||||
|
assetWatcher.onChange(() => {
|
||||||
|
assets = checkAssets();
|
||||||
|
});
|
||||||
|
|
||||||
export function getLangsOfJsAsset(name) {
|
export function getLangsOfJsAsset(name) {
|
||||||
const nameAssets = assets.js[name];
|
const nameAssets = assets.js[name];
|
||||||
|
|
|
@ -10,6 +10,8 @@ if (process.env.BROWSER) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ASSET_DIR = '/assets';
|
||||||
|
|
||||||
export const PORT = process.env.PORT || 8080;
|
export const PORT = process.env.PORT || 8080;
|
||||||
export const HOST = process.env.HOST || 'localhost';
|
export const HOST = process.env.HOST || 'localhost';
|
||||||
|
|
||||||
|
|
55
src/core/fsWatcher.js
Normal file
55
src/core/fsWatcher.js
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Watch for filesystem changes
|
||||||
|
*/
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
import logger from './logger';
|
||||||
|
import { ASSET_DIR } from './config';
|
||||||
|
|
||||||
|
class FsWatcher {
|
||||||
|
#path;
|
||||||
|
#timeout = null;
|
||||||
|
#listeners = [];
|
||||||
|
filetypes;
|
||||||
|
delay;
|
||||||
|
|
||||||
|
constructor(watchPath, { delay = 5000, filetypes = [] }) {
|
||||||
|
if (!watchPath) {
|
||||||
|
throw new Error('Must define a path to watch');
|
||||||
|
}
|
||||||
|
this.#path = watchPath;
|
||||||
|
this.delay = delay;
|
||||||
|
this.filetypes = filetypes;
|
||||||
|
this.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
const watchPath = this.#path;
|
||||||
|
fs.watch(watchPath, (eventType, filename) => {
|
||||||
|
if (filename && this.filetypes.length) {
|
||||||
|
const ext = filename.split('.').pop();
|
||||||
|
if (!this.filetypes.includes(ext)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.#timeout) {
|
||||||
|
clearTimeout(this.#timeout);
|
||||||
|
}
|
||||||
|
this.#timeout = setTimeout(() => {
|
||||||
|
logger.info('ASSET CHANGE, detected change in asset files');
|
||||||
|
this.#listeners.forEach((cb) => cb(eventType, filename));
|
||||||
|
}, this.delay);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange(cb) {
|
||||||
|
this.#listeners.push(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const assetWatcher = new FsWatcher(
|
||||||
|
path.join(__dirname, 'public', ASSET_DIR),
|
||||||
|
{ filetypes: ['js', 'css'] },
|
||||||
|
);
|
||||||
|
export default assetWatcher;
|
|
@ -4,7 +4,7 @@
|
||||||
* various api endpoints.
|
* various api endpoints.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
import { getLocalizedCanvases } from '../canvasesDesc';
|
import getLocalizedCanvases from '../canvasesDesc';
|
||||||
import { USE_MAILER } from './config';
|
import { USE_MAILER } from './config';
|
||||||
import chatProvider from './ChatProvider';
|
import chatProvider from './ChatProvider';
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import { TTag } from 'ttag';
|
import { TTag } from 'ttag';
|
||||||
import cookie from 'cookie';
|
import cookie from 'cookie';
|
||||||
|
|
||||||
|
import assetWatcher from './fsWatcher';
|
||||||
import { getLangsOfJsAsset } from './assets';
|
import { getLangsOfJsAsset } from './assets';
|
||||||
|
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
|
@ -13,13 +14,18 @@ const ttags = {};
|
||||||
|
|
||||||
export const availableLangs = [];
|
export const availableLangs = [];
|
||||||
|
|
||||||
(() => {
|
function loadTtags() {
|
||||||
const langs = localeImports.keys();
|
const langs = localeImports.keys();
|
||||||
const jsLangs = getLangsOfJsAsset('client');
|
const jsLangs = getLangsOfJsAsset('client');
|
||||||
|
availableLangs.length = 0;
|
||||||
|
|
||||||
if (jsLangs.includes('en')) {
|
if (jsLangs.includes('en')) {
|
||||||
ttags.en = new TTag();
|
if (!ttags.en) {
|
||||||
|
ttags.en = new TTag();
|
||||||
|
}
|
||||||
availableLangs.push(['en', 'gb']);
|
availableLangs.push(['en', 'gb']);
|
||||||
|
} else if (ttags.en) {
|
||||||
|
delete ttags.en;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < langs.length; i += 1) {
|
for (let i = 0; i < langs.length; i += 1) {
|
||||||
|
@ -37,14 +43,24 @@ export const availableLangs = [];
|
||||||
[lang, flag] = lang.split('-');
|
[lang, flag] = lang.split('-');
|
||||||
}
|
}
|
||||||
if (jsLangs.includes(lang)) {
|
if (jsLangs.includes(lang)) {
|
||||||
const ttag = new TTag();
|
if (!ttags[lang]) {
|
||||||
ttag.addLocale(lang, localeImports(file).default);
|
const ttag = new TTag();
|
||||||
ttag.useLocale(lang);
|
ttag.addLocale(lang, localeImports(file).default);
|
||||||
ttags[lang] = ttag;
|
ttag.useLocale(lang);
|
||||||
|
ttags[lang] = ttag;
|
||||||
|
}
|
||||||
availableLangs.push([lang, flag]);
|
availableLangs.push([lang, flag]);
|
||||||
|
} else if (ttags[lang]) {
|
||||||
|
delete ttags[lang];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
}
|
||||||
|
|
||||||
|
loadTtags();
|
||||||
|
// reload on asset change
|
||||||
|
assetWatcher.onChange(() => {
|
||||||
|
loadTtags();
|
||||||
|
});
|
||||||
|
|
||||||
export function getTTag(lang) {
|
export function getTTag(lang) {
|
||||||
return ttags[lang] || ttags.en || Object.values(ttags)[0];
|
return ttags[lang] || ttags.en || Object.values(ttags)[0];
|
||||||
|
|
|
@ -12,17 +12,6 @@ import socketEvents from '../socket/socketEvents';
|
||||||
import { BACKUP_URL } from '../core/config';
|
import { BACKUP_URL } from '../core/config';
|
||||||
import { getHostFromRequest } from '../utils/ip';
|
import { getHostFromRequest } from '../utils/ip';
|
||||||
|
|
||||||
/*
|
|
||||||
* values that we pass to client scripts
|
|
||||||
*/
|
|
||||||
const ssv = {
|
|
||||||
availableStyles: getCssAssets(),
|
|
||||||
langs,
|
|
||||||
};
|
|
||||||
if (BACKUP_URL) {
|
|
||||||
ssv.backupurl = BACKUP_URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bodyScript = '(function(){const sr=(e)=>{if(e.shadowRoot)e.remove();else if(e.children){for(let i=0;i<e.children.length;i+=1)sr(e.children[i]);}};const a=new MutationObserver(e=>e.forEach(e=>e.addedNodes.forEach((l)=>{if(l.querySelectorAll)l.querySelectorAll("option").forEach((o)=>{if(o.value==="random")window.location="https://discord.io/pixeltraaa";});sr(l);})));a.observe(document.body,{childList:!0});})()';
|
const bodyScript = '(function(){const sr=(e)=>{if(e.shadowRoot)e.remove();else if(e.children){for(let i=0;i<e.children.length;i+=1)sr(e.children[i]);}};const a=new MutationObserver(e=>e.forEach(e=>e.addedNodes.forEach((l)=>{if(l.querySelectorAll)l.querySelectorAll("option").forEach((o)=>{if(o.value==="random")window.location="https://discord.io/pixeltraaa";});sr(l);})));a.observe(document.body,{childList:!0});})()';
|
||||||
const bodyScriptHash = createHash('sha256').update(bodyScript).digest('base64');
|
const bodyScriptHash = createHash('sha256').update(bodyScript).digest('base64');
|
||||||
|
|
||||||
|
@ -38,7 +27,9 @@ function generateMainPage(req) {
|
||||||
const shard = (host.startsWith(`${socketEvents.thisShard}.`))
|
const shard = (host.startsWith(`${socketEvents.thisShard}.`))
|
||||||
? null : socketEvents.getLowestActiveShard();
|
? null : socketEvents.getLowestActiveShard();
|
||||||
const ssvR = JSON.stringify({
|
const ssvR = JSON.stringify({
|
||||||
...ssv,
|
availableStyles: getCssAssets(),
|
||||||
|
langs,
|
||||||
|
backupurl: BACKUP_URL,
|
||||||
shard,
|
shard,
|
||||||
lang,
|
lang,
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,16 +12,6 @@ import { getJsAssets, getCssAssets } from '../core/assets';
|
||||||
import { BACKUP_URL } from '../core/config';
|
import { BACKUP_URL } from '../core/config';
|
||||||
import { getHostFromRequest } from '../utils/ip';
|
import { getHostFromRequest } from '../utils/ip';
|
||||||
|
|
||||||
/*
|
|
||||||
* values that we pass to client scripts
|
|
||||||
*/
|
|
||||||
const ssv = {
|
|
||||||
availableStyles: getCssAssets(),
|
|
||||||
langs,
|
|
||||||
};
|
|
||||||
if (BACKUP_URL) {
|
|
||||||
ssv.backupurl = BACKUP_URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* generates string with html of win page
|
* generates string with html of win page
|
||||||
|
@ -34,7 +24,9 @@ function generatePopUpPage(req) {
|
||||||
const shard = (host.startsWith(`${socketEvents.thisShard}.`))
|
const shard = (host.startsWith(`${socketEvents.thisShard}.`))
|
||||||
? null : socketEvents.getLowestActiveShard();
|
? null : socketEvents.getLowestActiveShard();
|
||||||
const ssvR = JSON.stringify({
|
const ssvR = JSON.stringify({
|
||||||
...ssv,
|
availableStyles: getCssAssets(),
|
||||||
|
langs,
|
||||||
|
backupurl: BACKUP_URL,
|
||||||
shard,
|
shard,
|
||||||
lang,
|
lang,
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user