138 lines
4.2 KiB
TypeScript
138 lines
4.2 KiB
TypeScript
|
import * as interfaces from '../../dist_ts_interfaces/index.js';
|
||
|
import { type IServerOptions, TypedServer } from '../classes.typedserver.js';
|
||
|
import type { Request, Response } from '../index.js';
|
||
|
import * as plugins from '../plugins.js';
|
||
|
import * as servertools from '../servertools/index.js';
|
||
|
|
||
|
export interface IUtilityWebsiteServerConstructorOptions {
|
||
|
addCustomRoutes?: (serverArg: servertools.Server) => Promise<any>;
|
||
|
appSemVer?: string;
|
||
|
domain: string;
|
||
|
serveDir: string;
|
||
|
feedMetadata: IServerOptions['feedMetadata'];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* the utility website server implements a best practice server for websites
|
||
|
* It supports:
|
||
|
* * live reload
|
||
|
* * compression
|
||
|
* * serviceworker
|
||
|
* * pwa manifest
|
||
|
*/
|
||
|
export class UtilityWebsiteServer {
|
||
|
public options: IUtilityWebsiteServerConstructorOptions;
|
||
|
public typedserver: TypedServer;
|
||
|
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||
|
|
||
|
constructor(optionsArg: IUtilityWebsiteServerConstructorOptions) {
|
||
|
this.options = optionsArg;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
public async start(portArg = 3000) {
|
||
|
this.typedserver = new TypedServer({
|
||
|
cors: true,
|
||
|
injectReload: true,
|
||
|
watch: true,
|
||
|
serveDir: this.options.serveDir,
|
||
|
enableCompression: true,
|
||
|
preferredCompressionMethod: 'gzip',
|
||
|
domain: this.options.domain,
|
||
|
forceSsl: false,
|
||
|
manifest: {
|
||
|
name: this.options.domain,
|
||
|
short_name: this.options.domain,
|
||
|
start_url: '/',
|
||
|
display_override: ['window-controls-overlay'],
|
||
|
lang: 'en',
|
||
|
background_color: '#000000',
|
||
|
scope: '/',
|
||
|
},
|
||
|
port: portArg,
|
||
|
|
||
|
// features
|
||
|
robots: true,
|
||
|
sitemap: true,
|
||
|
});
|
||
|
|
||
|
let lswData: interfaces.serviceworker.IRequest_Serviceworker_Backend_VersionInfo['response'] =
|
||
|
{
|
||
|
appHash: 'xxxxxx',
|
||
|
appSemVer: this.options.appSemVer || 'x.x.x',
|
||
|
};
|
||
|
|
||
|
// -> /lsw* - anything regarding serviceworker
|
||
|
servertools.serviceworker.addServiceWorkerRoute(this.typedserver, () => {
|
||
|
return lswData;
|
||
|
});
|
||
|
|
||
|
// lets add ads.txt
|
||
|
this.typedserver.server.addRoute(
|
||
|
'/ads.txt',
|
||
|
new servertools.Handler('GET', async (req, res) => {
|
||
|
res.type('txt/plain');
|
||
|
const adsTxt =
|
||
|
['google.com, pub-4104137977476459, DIRECT, f08c47fec0942fa0'].join('\n') + '\n';
|
||
|
res.write(adsTxt);
|
||
|
res.end();
|
||
|
})
|
||
|
);
|
||
|
|
||
|
this.typedserver.server.addRoute(
|
||
|
'/assetbroker/manifest/:manifestAsset',
|
||
|
new servertools.Handler('GET', async (req, res) => {
|
||
|
let manifestAssetName = req.params.manifestAsset;
|
||
|
if (manifestAssetName === 'favicon.png') {
|
||
|
manifestAssetName = `favicon_${this.options.domain
|
||
|
.replace('.', '')
|
||
|
.replace('losslesscom', 'lossless')}@2x_transparent.png`;
|
||
|
}
|
||
|
const fullOriginAssetUrl = `https://assetbroker.lossless.one/brandfiles/00general/${manifestAssetName}`;
|
||
|
console.log(`Getting ${manifestAssetName} from ${fullOriginAssetUrl}`);
|
||
|
const dataBuffer: Buffer = (await plugins.smartrequest.getBinary(fullOriginAssetUrl)).body;
|
||
|
res.type('.png');
|
||
|
res.write(dataBuffer);
|
||
|
res.end();
|
||
|
})
|
||
|
);
|
||
|
|
||
|
// lets add any custom routes
|
||
|
if (this.options.addCustomRoutes) {
|
||
|
await this.options.addCustomRoutes(this.typedserver.server);
|
||
|
}
|
||
|
|
||
|
// -> /* - serve the files
|
||
|
this.typedserver.serveDirHashSubject.subscribe((appHash: string) => {
|
||
|
lswData = {
|
||
|
appHash,
|
||
|
appSemVer: '1.0.0',
|
||
|
};
|
||
|
});
|
||
|
|
||
|
// lets setup the typedrouter chain
|
||
|
this.typedserver.typedrouter.addTypedRouter(this.typedrouter);
|
||
|
|
||
|
// lets start everything
|
||
|
console.log('routes are all set. Startin up now!');
|
||
|
await this.typedserver.start();
|
||
|
console.log('typedserver started!');
|
||
|
}
|
||
|
|
||
|
public async stop() {
|
||
|
await this.typedserver.stop();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* allows you to hanlde requests from other server instances without the need to listen for yourself
|
||
|
* note smartexpress allows you start the instance wuith passing >>false<< as second parameter to .start();
|
||
|
* @param req
|
||
|
* @param res
|
||
|
*/
|
||
|
public async handleRequest(req: Request, res: Response) {
|
||
|
await this.typedserver.server.handleReqRes(req, res);
|
||
|
}
|
||
|
}
|