fix(core): update

This commit is contained in:
2023-03-30 15:15:48 +02:00
parent 2372e36367
commit 87a5337db3
26 changed files with 1080 additions and 71 deletions

View File

@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@apiglobal/typedserver',
version: '2.0.37',
version: '2.0.38',
description: 'easy serving of static files'
}

View File

@ -1 +1,12 @@
import * as plugins from './typedserver.plugins.js';
import * as servertools from './servertools/index.js';
export {
servertools
}
export * from './typedserver.classes.typedserver.js';
// Type helpers
export type Request = plugins.express.Request;
export type Response = plugins.express.Response;

View File

@ -1,12 +1,3 @@
import * as typedrequestInterfaces from '@apiglobal/typedrequest-interfaces';
export interface IReq_PushLatestServerChangeTime extends typedrequestInterfaces.implementsTR<
typedrequestInterfaces.ITypedRequest,
IReq_PushLatestServerChangeTime
> {
method: 'pushLatestServerChangeTime',
request: {
time: number;
};
response: {}
}
export * from './requestmodifier.js';
export * from './responsemodifier.js';
export * from './typedrequests.js';

View File

@ -0,0 +1,11 @@
export type TRequestModifier = <T>(responseArg: {
headers: { [header: string]: string | string[] | undefined };
path: string;
body: string;
travelData?: T;
}) => Promise<{
headers: { [header: string]: string | string[] | undefined };
path: string;
body: string;
travelData?: T;
}>;

View File

@ -0,0 +1,11 @@
export type TResponseModifier = <T>(responseArg: {
headers: { [header: string]: number | string | string[] | undefined };
path: string;
responseContent: string;
travelData?: T;
}) => Promise<{
headers: { [header: string]: number | string | string[] | undefined };
path: string;
responseContent: string;
travelData?: T;
}>;

View File

@ -0,0 +1,12 @@
import * as typedrequestInterfaces from '@apiglobal/typedrequest-interfaces';
export interface IReq_PushLatestServerChangeTime extends typedrequestInterfaces.implementsTR<
typedrequestInterfaces.ITypedRequest,
IReq_PushLatestServerChangeTime
> {
method: 'pushLatestServerChangeTime',
request: {
time: number;
};
response: {}
}

View File

@ -0,0 +1,35 @@
import { Handler } from './classes.handler.js';
import { Server } from './classes.server.js';
import * as plugins from '../typedserver.plugins.js';
export class Feed {
public smartexpressRef: Server;
public smartfeedInstance = new plugins.smartfeed.Smartfeed();
public feedHandler = new Handler('GET', async (req, res) => {
if (!this.smartexpressRef.options.feedMetadata) {
res.status(500);
res.write('feed metadata is missing');
res.end();
return;
}
if (!this.smartexpressRef.options.articleGetterFunction) {
res.status(500);
res.write('no article getter function defined.');
res.end();
return;
}
const xmlString = await this.smartfeedInstance.createFeedFromArticleArray(
this.smartexpressRef.options.feedMetadata,
await this.smartexpressRef.options.articleGetterFunction()
);
res.type('.xml');
res.write(xmlString);
res.end();
});
constructor(smartexpressRefArg: Server) {
this.smartexpressRef = smartexpressRefArg;
this.smartexpressRef.addRouteBefore('/feed', this.feedHandler);
}
}

View File

@ -0,0 +1,17 @@
import * as plugins from '../typedserver.plugins.js';
import { Request, Response } from 'express';
export interface IHandlerFunction {
(requestArg: Request, responseArg: Response): void;
}
export type THttpMethods = 'ALL' | 'GET' | 'POST' | 'PUT' | 'DELETE';
export class Handler {
httpMethod: THttpMethods;
handlerFunction: IHandlerFunction;
constructor(httpMethodArg: THttpMethods, handlerArg: IHandlerFunction) {
this.httpMethod = httpMethodArg;
this.handlerFunction = handlerArg;
}
}

View File

@ -0,0 +1,77 @@
import * as plugins from '../typedserver.plugins.js';
import { Handler } from './classes.handler.js';
import * as interfaces from '../interfaces/index.js';
export class HandlerProxy extends Handler {
/**
* The constuctor of HandlerProxy
* @param remoteMountPointArg
*/
constructor(
remoteMountPointArg: string,
optionsArg?: {
responseModifier?: interfaces.TResponseModifier;
headers?: { [key: string]: string };
}
) {
super('ALL', async (req, res) => {
const relativeRequestPath = req.path.slice(req.route.path.length - 1);
const proxyRequestUrl = remoteMountPointArg + relativeRequestPath;
console.log(`proxy ${req.path} to ${proxyRequestUrl}`);
let proxiedResponse: plugins.smartrequest.IExtendedIncomingMessage;
try {
proxiedResponse = await plugins.smartrequest.request(proxyRequestUrl, {
method: req.method,
autoJsonParse: false,
});
} catch {
res.end('failed to fullfill request');
return;
}
for (const header of Object.keys(proxiedResponse.headers)) {
res.set(header, proxiedResponse.headers[header] as string);
}
// set additional headers
if (optionsArg && optionsArg.headers) {
for (const key of Object.keys(optionsArg.headers)) {
res.set(key, optionsArg.headers[key]);
}
}
let responseToSend: string = proxiedResponse.body;
if (typeof responseToSend !== 'string') {
console.log(proxyRequestUrl);
console.log(responseToSend);
throw new Error(`Proxied response is not a string, but ${typeof responseToSend}`);
}
if (optionsArg && optionsArg.responseModifier) {
const modifiedResponse = await optionsArg.responseModifier({
headers: res.getHeaders(),
path: req.path,
responseContent: responseToSend,
});
// headers
for (const key of Object.keys(res.getHeaders())) {
if (!modifiedResponse.headers[key]) {
res.removeHeader(key);
}
}
for (const key of Object.keys(modifiedResponse.headers)) {
res.setHeader(key, modifiedResponse.headers[key]);
}
// responseContent
responseToSend = modifiedResponse.responseContent;
}
res.status(200);
res.write(responseToSend);
res.end();
});
}
}

View File

@ -0,0 +1,126 @@
import * as plugins from '../typedserver.plugins.js';
import * as interfaces from '../interfaces/index.js';
import { Handler } from './classes.handler.js';
export class HandlerStatic extends Handler {
constructor(
pathArg: string,
optionsArg?: {
requestModifier?: interfaces.TRequestModifier;
responseModifier?: interfaces.TResponseModifier;
headers?: { [key: string]: string };
serveIndexHtmlDefault?: boolean;
}
) {
super('GET', async (req, res) => {
let requestPath = req.path;
let requestHeaders = req.headers;
let requestBody = req.body;
let travelData: unknown;
if (optionsArg && optionsArg.requestModifier) {
const modifiedRequest = await optionsArg.requestModifier({
headers: requestHeaders,
path: requestPath,
body: requestBody,
});
requestHeaders = modifiedRequest.headers;
requestPath = modifiedRequest.path;
requestBody = modifiedRequest.body;
travelData = modifiedRequest.travelData;
}
// lets compute some paths
let filePath: string = requestPath.slice(req.route.path.length - 1); // lets slice of the root
if (requestPath === '') {
console.log('replaced root with index.html');
filePath = 'index.html';
}
console.log(filePath);
const joinedPath = plugins.path.join(pathArg, filePath);
const defaultPath = plugins.path.join(pathArg, 'index.html');
let parsedPath = plugins.path.parse(joinedPath);
let usedPath: string;
// important security checks
if (
requestPath.includes('..') || // don't allow going up the filePath
requestPath.includes('~') || // don't allow referencing of home directory
!joinedPath.startsWith(pathArg) // make sure the joined path is within the directory
) {
res.writeHead(500);
res.end();
return;
}
// set additional headers
if (optionsArg && optionsArg.headers) {
for (const key of Object.keys(optionsArg.headers)) {
res.set(key, optionsArg.headers[key]);
}
}
// lets actually care about serving, if security checks pass
let fileString: string;
let fileEncoding: 'binary' | 'utf8';
try {
fileString = plugins.smartfile.fs.toStringSync(joinedPath);
fileEncoding = plugins.smartmime.getEncoding(joinedPath);
usedPath = joinedPath;
} catch (err) {
// try serving index.html instead
console.log(`could not resolve ${joinedPath}`);
if (optionsArg && optionsArg.serveIndexHtmlDefault) {
console.log(`serving default path ${defaultPath} instead of ${joinedPath}`);
try {
parsedPath = plugins.path.parse(defaultPath);
fileString = plugins.smartfile.fs.toStringSync(defaultPath);
fileEncoding = plugins.smartmime.getEncoding(defaultPath);
usedPath = defaultPath;
} catch (err) {
res.writeHead(500);
res.end('File not found!');
return;
}
} else {
res.writeHead(500);
res.end('File not found!');
return;
}
}
res.type(parsedPath.ext);
const headers = res.getHeaders();
// lets modify the response at last
if (optionsArg && optionsArg.responseModifier) {
const modifiedResponse = await optionsArg.responseModifier({
headers: res.getHeaders(),
path: usedPath,
responseContent: fileString,
travelData,
});
// headers
for (const key of Object.keys(res.getHeaders())) {
if (!modifiedResponse.headers[key]) {
res.removeHeader(key);
}
}
for (const key of Object.keys(modifiedResponse.headers)) {
res.setHeader(key, modifiedResponse.headers[key]);
}
// responseContent
fileString = modifiedResponse.responseContent;
}
res.status(200);
res.write(Buffer.from(fileString, fileEncoding));
res.end();
});
}
}

View File

@ -0,0 +1,17 @@
import * as plugins from '../typedserver.plugins.js';
import { Handler } from './classes.handler.js';
import * as interfaces from '../interfaces/index.js';
export class HandlerTypedRouter extends Handler {
/**
* The constuctor of HandlerProxy
* @param remoteMountPointArg
*/
constructor(typedrouter: plugins.typedrequest.TypedRouter) {
super('POST', async (req, res) => {
const response = await typedrouter.routeAndAddResponse(req.body);
res.json(response);
});
}
}

View File

@ -0,0 +1,32 @@
import * as plugins from '../typedserver.plugins.js';
import { Handler } from './classes.handler.js';
import { Server } from './classes.server.js';
import { ObjectMap } from '@pushrocks/lik';
import { IRoute as IExpressRoute } from 'express';
export class Route {
public routeString: string;
public handlerObjectMap = new ObjectMap<Handler>();
public expressMiddlewareObjectMap = new ObjectMap<any>();
public expressRoute: IExpressRoute; // will be set to server route on server start
constructor(ServerArg: Server, routeStringArg: string) {
this.routeString = routeStringArg;
}
/**
* add a handler to do something with requests
* @param handlerArg
*/
public addHandler(handlerArg: Handler) {
this.handlerObjectMap.add(handlerArg);
}
/**
* add a express middleware
* @param middlewareArg
*/
public addExpressMiddleWare(middlewareArg: plugins.express.Application) {
this.expressMiddlewareObjectMap.add(middlewareArg);
}
}

View File

@ -0,0 +1,296 @@
import * as plugins from '../typedserver.plugins.js';
import { Route } from './classes.route.js';
import { Handler } from './classes.handler.js';
import { HandlerTypedRouter } from './classes.handlertypedrouter.js';
// export types
import { setupRobots } from './tools.robots.js';
import { setupManifest } from './tools.manifest.js';
import { Sitemap } from './classes.sitemap.js';
import { Feed } from './classes.feed.js';
import { IServerOptions } from '../typedserver.classes.typedserver.js'
export type TServerStatus = 'initiated' | 'running' | 'stopped';
/**
* can be used to spawn a server to answer http/https calls
* for constructor options see [[IServerOptions]]
*/
export class Server {
public httpServer: plugins.http.Server | plugins.https.Server;
public expressAppInstance: plugins.express.Application;
public routeObjectMap = new Array<Route>();
public options: IServerOptions;
public serverStatus: TServerStatus = 'initiated';
public feed: Feed;
public sitemap: Sitemap;
public executeAfterStartFunctions: (() => Promise<void>)[] = [];
// do stuff when server is ready
private startedDeferred = plugins.smartpromise.defer();
// tslint:disable-next-line:member-ordering
public startedPromise = this.startedDeferred.promise;
private socketMap = new plugins.lik.ObjectMap<plugins.net.Socket>();
constructor(optionsArg: IServerOptions) {
this.options = {
...optionsArg,
};
}
/**
* allows updating of server options
* @param optionsArg
*/
public updateServerOptions(optionsArg: IServerOptions) {
Object.assign(this.options, optionsArg);
}
public addTypedRequest(typedrouter: plugins.typedrequest.TypedRouter) {
this.addRoute('/typedrequest', new HandlerTypedRouter(typedrouter));
}
public addTypedSocket(typedrouter: plugins.typedrequest.TypedRouter): void {
this.executeAfterStartFunctions.push(async () => {
plugins.typedsocket.TypedSocket.createServer(typedrouter, this);
});
}
public addRoute(routeStringArg: string, handlerArg?: Handler) {
const route = new Route(this, routeStringArg);
if (handlerArg) {
route.addHandler(handlerArg);
}
this.routeObjectMap.push(route);
return route;
}
public addRouteBefore(routeStringArg: string, handlerArg?: Handler) {
const route = new Route(this, routeStringArg);
if (handlerArg) {
route.addHandler(handlerArg);
}
this.routeObjectMap.unshift(route);
return route;
}
public async start(portArg: number | string = this.options.port, doListen = true) {
const done = plugins.smartpromise.defer();
if (typeof portArg === 'string') {
portArg = parseInt(portArg);
}
this.expressAppInstance = plugins.express();
if (!this.httpServer && (!this.options.privateKey || !this.options.publicKey)) {
console.log('Got no SSL certificates. Please ensure encryption using e.g. a reverse proxy');
this.httpServer = plugins.http.createServer(this.expressAppInstance);
} else if (!this.httpServer) {
console.log('Got SSL certificate. Using it for the http server');
this.httpServer = plugins.https.createServer(
{
key: this.options.privateKey,
cert: this.options.publicKey,
},
this.expressAppInstance
);
} else {
console.log('Using externally supplied http server');
}
this.httpServer.keepAliveTimeout = 600 * 1000;
this.httpServer.headersTimeout = 600 * 1000;
// general request handlling
this.expressAppInstance.use((req, res, next) => {
req.on('error', () => {
req.destroy();
});
req.on('timeout', () => {
req.destroy();
});
next();
});
// forceSsl
if (this.options.forceSsl) {
this.expressAppInstance.set('forceSSLOptions', {
enable301Redirects: true,
trustXFPHeader: true,
sslRequiredMessage: 'SSL Required.',
});
this.expressAppInstance.use(plugins.expressForceSsl);
}
// cors
if (this.options.cors) {
const cors = plugins.cors({
allowedHeaders: '*',
methods: '*',
origin: '*',
});
this.expressAppInstance.use(cors);
this.expressAppInstance.options('/*', cors);
}
this.expressAppInstance.use((req, res, next) => {
res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
res.setHeader('Cross-Origin-Embedder-Policy', 'unsafe-none');
res.setHeader('Access-Control-Allow-Origin', '*');
next();
});
// body parsing
this.expressAppInstance.use(plugins.bodyParser.json({ limit: 100000000 })); // for parsing application/json
this.expressAppInstance.use(plugins.bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
// robots
if (this.options.robots && this.options.domain) {
await setupRobots(this, this.options.domain);
}
// manifest.json
if (this.options.manifest) {
await setupManifest(this.expressAppInstance, this.options.manifest);
}
// sitemaps
if (this.options.sitemap) {
this.sitemap = new Sitemap(this);
}
if (this.options.feed) {
// feed
this.feed = new Feed(this);
}
// appVersion
if (this.options.appVersion) {
this.expressAppInstance.use((req, res, next) => {
res.set('appversion', this.options.appVersion);
next();
});
this.addRoute(
'/appversion',
new Handler('GET', async (req, res) => {
res.write(this.options.appVersion);
res.end();
})
);
}
// set up routes in for express
await this.routeObjectMap.forEach(async (routeArg) => {
console.log(
`"${routeArg.routeString}" maps to ${routeArg.handlerObjectMap.getArray().length} handlers`
);
const expressRoute = this.expressAppInstance.route(routeArg.routeString);
routeArg.handlerObjectMap.forEach(async (handler) => {
console.log(` -> ${handler.httpMethod}`);
switch (handler.httpMethod) {
case 'GET':
expressRoute.get(handler.handlerFunction);
return;
case 'POST':
expressRoute.post(handler.handlerFunction);
return;
case 'PUT':
expressRoute.put(handler.handlerFunction);
return;
case 'ALL':
expressRoute.all(handler.handlerFunction);
return;
case 'DELETE':
expressRoute.delete(handler.handlerFunction);
return;
default:
return;
}
});
});
if (this.options.defaultAnswer) {
this.expressAppInstance.get('/', async (request, response) => {
response.send(await this.options.defaultAnswer());
});
}
this.httpServer.on('connection', (connection: plugins.net.Socket) => {
this.socketMap.add(connection);
console.log(`added connection. now ${this.socketMap.getArray().length} sockets connected.`);
const cleanupConnection = () => {
if (this.socketMap.checkForObject(connection)) {
this.socketMap.remove(connection);
console.log(`removed connection. ${this.socketMap.getArray().length} sockets remaining.`);
connection.destroy();
}
};
connection.on('close', () => {
cleanupConnection();
});
connection.on('error', () => {
cleanupConnection();
});
connection.on('end', () => {
cleanupConnection();
});
connection.on('timeout', () => {
cleanupConnection();
});
});
// finally listen on a port
if (doListen) {
this.httpServer.listen(portArg, '0.0.0.0', () => {
console.log(`now listening on ${portArg}!`);
this.startedDeferred.resolve();
this.serverStatus = 'running';
done.resolve();
});
} else {
console.log(
'The server does not listen on a network stack and instead expects to get handed requests by other mechanics'
);
}
await done.promise;
for (const executeAfterStartFunction of this.executeAfterStartFunctions) {
await executeAfterStartFunction();
}
}
public getHttpServer() {
return this.httpServer;
}
public getExpressAppInstance() {
return this.expressAppInstance;
}
public async stop() {
const done = plugins.smartpromise.defer();
if (this.httpServer) {
this.httpServer.close(async () => {
this.serverStatus = 'stopped';
done.resolve();
});
await this.socketMap.forEach(async (socket) => {
socket.destroy();
});
} else {
throw new Error('There is no Server to be stopped. Have you started it?');
}
return await done.promise;
}
/**
* allows handling requests and responses that come from other
* @param req
* @param res
*/
public async handleReqRes(req: plugins.express.Request, res: plugins.express.Response) {
this.expressAppInstance(req, res);
}
}

View File

@ -0,0 +1,68 @@
import { Server } from './classes.server.js';
import { Handler } from './classes.handler.js';
import * as plugins from '../typedserver.plugins.js';
import { IUrlInfo } from '@pushrocks/smartsitemap';
export class Sitemap {
public smartexpressRef: Server;
public smartSitemap = new plugins.smartsitemap.SmartSitemap();
public urls: plugins.smartsitemap.IUrlInfo[] = [];
/**
* handles the normal sitemap request
*/
public sitemapHandler = new Handler('GET', async (req, res) => {
const sitemapXmlString = await this.smartSitemap.createSitemapFromUrlInfoArray(this.urls);
res.type('.xml');
res.write(sitemapXmlString);
res.end();
});
/**
* handles the sitemap-news request
*/
public sitemapNewsHandler = new Handler('GET', async (req, res) => {
if (!this.smartexpressRef.options.articleGetterFunction) {
res.status(500);
res.write('no article getter function defined.');
res.end();
return;
}
const sitemapNewsXml = await this.smartSitemap.createSitemapNewsFromArticleArray(
await this.smartexpressRef.options.articleGetterFunction()
);
res.type('.xml');
res.write(sitemapNewsXml);
res.end();
});
constructor(smartexpressRefArg: Server) {
this.smartexpressRef = smartexpressRefArg;
this.smartexpressRef.addRouteBefore('/sitemap', this.sitemapHandler);
this.smartexpressRef.addRouteBefore('/sitemap-news', this.sitemapNewsHandler);
// lets set the default url
if (this.smartexpressRef.options.domain) {
this.urls.push({
url: `https://${this.smartexpressRef.options.domain}/`,
timestamp: Date.now(),
frequency: 'daily',
});
}
}
/**
* replaces the current urlsArray
* @param urlsArg
*/
public replaceUrls(urlsArg: IUrlInfo[]) {
this.urls = urlsArg;
}
/**
* adds urls to the current set of urls
*/
public addUrls(urlsArg: IUrlInfo[]) {
this.urls = this.urls.concat(this.urls, urlsArg);
}
}

6
ts/servertools/index.ts Normal file
View File

@ -0,0 +1,6 @@
export * from './classes.server.js';
export * from './classes.route.js';
export * from './classes.handler.js';
export * from './classes.handlerstatic.js';
export * from './classes.handlerproxy.js';
export * from './classes.handlertypedrouter.js';

View File

@ -0,0 +1,14 @@
import * as plugins from '../typedserver.plugins.js';
export const setupManifest = async (
expressInstanceArg: plugins.express.Application,
manifestArg: plugins.smartmanifest.ISmartManifestConstructorOptions
) => {
const smartmanifestInstance = new plugins.smartmanifest.SmartManifest(manifestArg);
expressInstanceArg.get('/manifest.json', async (req, res) => {
res.status(200);
res.type('json');
res.write(smartmanifestInstance.jsonString());
res.end();
});
};

View File

@ -0,0 +1,33 @@
import * as plugins from '../typedserver.plugins.js';
import { Server } from './classes.server.js';
import { Handler } from './classes.handler.js';
export const setupRobots = async (smartexpressRefArg: Server, domainArg: string) => {
smartexpressRefArg.addRouteBefore(
'/robots.txt',
new Handler('GET', async (req, res) => {
res.type('text/plain');
res.send(`
User-agent: Googlebot-News
Disallow: /account
Disallow: /login
User-agent: *
Disallow: /account
Disallow: /login
${
smartexpressRefArg.options.blockWaybackMachine
? `
User-Agent: ia_archiver
Disallow: /
`
: ``
}
Sitemap: https://${domainArg}/sitemap
Sitemap: https://${domainArg}/sitemap-news
`);
})
);
};

View File

@ -0,0 +1,22 @@
import * as plugins from '../typedserver.plugins.js';
import { Server } from './classes.server.js';
import { Handler } from './classes.handler.js';
export const redirectFrom80To443 = async () => {
const smartexpressInstance = new Server({
cors: true,
forceSsl: true,
port: 80,
});
smartexpressInstance.addRoute(
'*',
new Handler('ALL', async (req, res) => {
res.redirect('https://' + req.headers.host + req.url);
})
);
await smartexpressInstance.start();
return smartexpressInstance;
};

View File

@ -1,12 +1,58 @@
import * as plugins from './typedserver.plugins.js';
import * as paths from './typedserver.paths.js';
import * as interfaces from './interfaces/index.js';
import * as servertools from './servertools/index.js';
export interface IEasyServerConstructorOptions {
serveDir: string;
injectReload: boolean;
port?: number;
export interface IServerOptions {
/**
* serve a particular directory
*/
serveDir?: string;
/**
* inject a reload script that takes care of live reloading
*/
injectReload?: boolean;
/**
* watch the serve directory?
*/
watch?: boolean;
cors: boolean;
/**
* a default answer given in case there is no other handler.
* @returns
*/
defaultAnswer?: () => Promise<string>;
/**
* will try to reroute traffic to an ssl connection using headers
*/
forceSsl?: boolean;
/**
* allows serving manifests
*/
manifest?: plugins.smartmanifest.ISmartManifestConstructorOptions;
/**
* the port to listen on
* can be overwritten when actually starting the server
*/
port?: number | string;
publicKey?: string;
privateKey?: string;
sitemap?: boolean;
feed?: boolean;
robots?: boolean;
domain?: string;
/**
* convey information about the app being served
*/
appVersion?: string;
feedMetadata?: plugins.smartfeed.IFeedOptions;
articleGetterFunction?: () => Promise<plugins.tsclass.content.IArticle[]>;
blockWaybackMachine?: boolean;
}
export class TypedServer {
@ -14,8 +60,8 @@ export class TypedServer {
// nothing here yet
// instance
public options: IEasyServerConstructorOptions;
public smartexpressInstance: plugins.smartexpress.Server;
public options: IServerOptions;
public serverInstance: servertools.Server;
public smartchokInstance: plugins.smartchok.Smartchok;
public serveDirHashSubject = new plugins.smartrx.rxjs.ReplaySubject<string>(1);
public serveHash: string = '000000';
@ -24,12 +70,13 @@ export class TypedServer {
public lastReload: number = Date.now();
public ended = false;
constructor(optionsArg: IEasyServerConstructorOptions) {
const standardOptions: IEasyServerConstructorOptions = {
constructor(optionsArg: IServerOptions) {
const standardOptions: IServerOptions = {
injectReload: true,
port: 3000,
serveDir: process.cwd(),
watch: true,
cors: true,
};
this.options = {
...standardOptions,
@ -42,16 +89,16 @@ export class TypedServer {
*/
public async start() {
// set the smartexpress instance
this.smartexpressInstance = new plugins.smartexpress.Server({
this.serverInstance = new servertools.Server({
port: this.options.port,
forceSsl: false,
cors: true,
});
// add routes to the smartexpress instance
this.smartexpressInstance.addRoute(
this.serverInstance.addRoute(
'/typedserver/:request',
new plugins.smartexpress.Handler('ALL', async (req, res) => {
new servertools.Handler('ALL', async (req, res) => {
switch (req.params.request) {
case 'devtools':
res.setHeader('Content-Type', 'text/javascript');
@ -74,9 +121,9 @@ export class TypedServer {
})
);
this.smartexpressInstance.addRoute(
this.serverInstance.addRoute(
'/*',
new plugins.smartexpress.HandlerStatic(this.options.serveDir, {
new servertools.HandlerStatic(this.options.serveDir, {
responseModifier: async (responseArg) => {
let fileString = responseArg.responseContent;
if (plugins.path.parse(responseArg.path).ext === '.html') {
@ -126,12 +173,12 @@ export class TypedServer {
await this.createServeDirHash();
// lets start the server
await this.smartexpressInstance.start();
await this.serverInstance.start();
console.log('open url in browser');
this.typedsocket = await plugins.typedsocket.TypedSocket.createServer(
this.typedrouter,
this.smartexpressInstance
this.serverInstance
);
// await plugins.smartopen.openUrl(`http://testing.git.zone:${this.options.port}`);
@ -156,7 +203,7 @@ export class TypedServer {
public async stop() {
this.ended = true;
await this.smartexpressInstance.stop();
await this.serverInstance.stop();
await this.typedsocket.stop();
await this.smartchokInstance.stop();
}

View File

@ -1,7 +1,17 @@
// node native
import * as http from 'http';
import * as https from 'https';
import * as net from 'net';
import * as path from 'path';
export { path };
export { http, https, net, path };
// @tsclass scope
import * as tsclass from '@tsclass/tsclass';
export {
tsclass
}
// @apiglobal scope
import * as typedrequest from '@apiglobal/typedrequest';
@ -15,22 +25,43 @@ export {
}
// @pushrocks scope
import * as lik from '@pushrocks/lik';
import * as smartchok from '@pushrocks/smartchok';
import * as smartdelay from '@pushrocks/smartdelay';
import * as smartexpress from '@pushrocks/smartexpress';
import * as smartfeed from '@pushrocks/smartfeed';
import * as smartfile from '@pushrocks/smartfile';
import * as smartmanifest from '@pushrocks/smartmanifest';
import * as smartmime from '@pushrocks/smartmime';
import * as smartopen from '@pushrocks/smartopen';
import * as smartpath from '@pushrocks/smartpath';
import * as smartpromise from '@pushrocks/smartpromise';
import * as smartrequest from '@pushrocks/smartrequest';
import * as smartrx from '@pushrocks/smartrx';
import * as smartsitemap from '@pushrocks/smartsitemap';
import * as smarttime from '@pushrocks/smarttime';
export {
lik,
smartchok,
smartdelay,
smartexpress,
smartfeed,
smartfile,
smartmanifest,
smartmime,
smartopen,
smartpath,
smartpromise,
smartrequest,
smartsitemap,
smarttime,
smartrx,
};
// express
import bodyParser from 'body-parser';
import cors from 'cors';
import express from 'express';
// @ts-ignore
import expressForceSsl from 'express-force-ssl';
export { bodyParser, cors, express, expressForceSsl };