Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@haibun/web-server-express

Package Overview
Dependencies
Maintainers
1
Versions
130
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@haibun/web-server-express - npm Package Compare versions

Comparing version 0.2.1 to 1.0.0

build/defs.d.ts

20

build/server-express.d.ts
import { RequestHandler } from 'express';
import { TLogger } from '@haibun/core/build/lib/defs';
import { IWebServer, TRouteType } from './web-server-stepper';
import { IWebServer, TRouteType } from './defs';
import { ILogger } from '@haibun/core/src/lib/interfaces/logger';
export declare const DEFAULT_PORT = 8123;
export declare class ServerExpress implements IWebServer {
logger: TLogger;
static listener: any;
static app: import("express-serve-static-core").Express;
logger: ILogger;
static listening: boolean;
listener: any;
app: import("express-serve-static-core").Express;
static mounted: {

@@ -13,6 +14,9 @@ [named: string]: string;

base: string;
constructor(logger: TLogger, base: string, port?: number);
listening(port: number): Promise<void>;
port: number;
constructor(logger: ILogger, base: string, port?: number);
listen(): Promise<IWebServer>;
addRoute(type: TRouteType, path: string, route: RequestHandler): Promise<any>;
addStaticFolder(subdir: string): Promise<string | undefined>;
addStaticFolder(relativeFolder: string, mountAt?: string): Promise<string | undefined>;
addKnownStaticFolder(folder: string, mountAt?: string): Promise<string | undefined>;
doAddStaticFolder(folder: string, mountAt?: string): Promise<string | undefined>;
checkMountBadOrMounted(loc: string, what: string): boolean;

@@ -19,0 +23,0 @@ close(): Promise<void>;

60

build/server-express.js

@@ -12,12 +12,22 @@ "use strict";

constructor(logger, base, port = exports.DEFAULT_PORT) {
this.app = express_1.default();
this.logger = logger;
this.base = base;
this.port = port;
}
async listening(port) {
if (!ServerExpress.listener) {
ServerExpress.listener = await ServerExpress.app.listen(port, () => this.logger.log(`Server listening on port: ${port}`));
async listen() {
if (!ServerExpress.listening) {
try {
ServerExpress.listening = true;
this.listener = await this.app.listen(this.port, () => this.logger.log(`Server listening on port: ${this.port}`));
this.logger.log('express listening');
}
catch (e) {
console.error(e);
}
}
else {
this.logger.log('express already started');
this.logger.log('express already listening');
}
return this;
}

@@ -35,11 +45,23 @@ async addRoute(type, path, route) {

this.logger.log(`serving route from ${path}`);
await ServerExpress.app[type](path, route);
await this.app[type](path, route);
await this.listen();
}
async addStaticFolder(subdir) {
const folder = [this.base, subdir].join('/');
const loc = '/';
// add a static folder restricted to relative paths from files
async addStaticFolder(relativeFolder, mountAt = '/') {
if (relativeFolder !== relativeFolder.replace(/[^a-zA-Z-0-9\/-_]/g, '').replace(/^\//g, '')) {
throw Error(`mount folder ${relativeFolder} has illegal characters`);
}
const folder = [this.base, relativeFolder].join('/');
return this.doAddStaticFolder(folder, mountAt);
}
// add a static folder at any path
async addKnownStaticFolder(folder, mountAt = '/') {
return this.doAddStaticFolder(folder, mountAt);
}
async doAddStaticFolder(folder, mountAt = '/') {
try {
const alreadyMounted = this.checkMountBadOrMounted(loc, folder);
const alreadyMounted = this.checkMountBadOrMounted(mountAt, folder);
if (alreadyMounted) {
return;
// FIXME
// return;
}

@@ -57,10 +79,11 @@ }

}
ServerExpress.mounted[loc] = folder;
this.logger.info(`serving files from ${folder} at ${loc}`);
await ServerExpress.app.use(express_1.default.static(folder));
ServerExpress.mounted[mountAt] = folder;
this.logger.info(`serving files from ${folder} at ${mountAt}`);
await this.app.use(mountAt, express_1.default.static(folder));
await this.listen();
return;
}
checkMountBadOrMounted(loc, what) {
if (!ServerExpress.listener) {
throw Error(`listening must be called before mount`);
if (!ServerExpress.listening) {
throw Error(`listen must be called before mount`);
}

@@ -70,5 +93,2 @@ if (!loc) {

}
if (loc !== loc.replace(/[^a-zA-Z-0-9\/]/g, '')) {
throw Error(`mount folder ${loc} has illegal characters`);
}
const alreadyMounted = ServerExpress.mounted[loc];

@@ -86,8 +106,8 @@ if (alreadyMounted === what) {

this.logger.info('closing server');
await ServerExpress.listener?.close();
await this.listener?.close();
}
}
exports.ServerExpress = ServerExpress;
ServerExpress.app = express_1.default();
ServerExpress.listening = false;
ServerExpress.mounted = {};
//# sourceMappingURL=server-express.js.map
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -27,4 +8,5 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

const util_1 = require("@haibun/core/build/lib/util");
const TestSteps_1 = require("@haibun/core/build/lib/TestSteps");
const web_server_stepper_1 = __importStar(require("./web-server-stepper"));
const defs_1 = require("./defs");
const web_server_stepper_1 = __importDefault(require("./web-server-stepper"));
const TestSteps_1 = require("@haibun/core/src/lib/TestSteps");
describe('route mount', () => {

@@ -39,6 +21,5 @@ it('mounts a route', async () => {

const route = (req, res) => res.status(200).send('ok');
const webserver = util_1.getFromRuntime(this.world.runtime, web_server_stepper_1.WEBSERVER);
const checkListener = util_1.getFromRuntime(this.world.runtime, web_server_stepper_1.CHECK_LISTENER);
await checkListener(this.world.options, webserver);
const webserver = await util_1.getFromRuntime(this.world.runtime, defs_1.WEBSERVER);
await webserver.addRoute('get', loc, route);
webserver.listen(8123);
return util_1.actionOK();

@@ -51,15 +32,15 @@ },

};
const { world } = util_1.getDefaultWorld();
const { result, steppers } = await TestSteps_1.testRun('/test/route', [web_server_stepper_1.default, TestRoute], world, {
const feature = { path: '/features/test.feature', content: `serve test route to /test\n` };
const { result, steppers } = await TestSteps_1.testWithDefaults([feature], [web_server_stepper_1.default, TestRoute], {
options: {},
extraOptions: {
[`HAIBUN_O_${web_server_stepper_1.WEBSERVER_STEPPER.toUpperCase()}_PORT`]: '8124',
[`HAIBUN_O_${defs_1.WEBSERVER_STEPPER.toUpperCase()}_PORT`]: '8124',
},
});
expect(result.ok).toBe(true);
const content = await node_fetch_1.default('http://localhost:8124/test');
const content = await node_fetch_1.default('http://localhost:8123/test');
expect(await content.text()).toEqual('ok');
util_1.getStepper(steppers, web_server_stepper_1.WEBSERVER_STEPPER).close();
util_1.getStepper(steppers, defs_1.WEBSERVER_STEPPER).close();
});
});
//# sourceMappingURL=web-server-stepper-route.test.js.map
import { IExtensionConstructor, TOptions } from '@haibun/core/build/lib/defs';
import { RequestHandler } from 'express';
export declare const WEBSERVER = "webserver";
export declare const WEBSERVER_STEPPER = "WebServerStepper";
export declare const CHECK_LISTENER = "CHECK_LISTENER";
import { IWebServer } from './defs';
declare const WebServerStepper: IExtensionConstructor;

@@ -14,8 +11,2 @@ export default WebServerStepper;

}
export interface IWebServer {
addStaticFolder(subdir: string): Promise<string | undefined>;
listening(port: number): void;
addRoute(type: TRouteType, path: string, route: RequestHandler): void;
}
export declare type TRouteType = 'get';
//# sourceMappingURL=web-server-stepper.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CHECK_LISTENER = exports.WEBSERVER_STEPPER = exports.WEBSERVER = void 0;
const defs_1 = require("@haibun/core/build/lib/defs");
const util_1 = require("@haibun/core/build/lib/util");
const defs_2 = require("./defs");
const server_express_1 = require("./server-express");
exports.WEBSERVER = 'webserver';
exports.WEBSERVER_STEPPER = 'WebServerStepper';
exports.CHECK_LISTENER = 'CHECK_LISTENER';
const WebServerStepper = class WebServerStepper {

@@ -19,10 +16,22 @@ constructor(world) {

this.steps = {
isListening: {
gwta: 'webserver is listening',
action: async () => {
await this.checkListener(this.world.options);
return defs_1.OK;
},
},
serveFiles: {
gwta: 'serve files from {loc}',
action: async ({ loc }) => {
await WebServerStepper.checkListener(this.world.options, this.world.runtime[exports.WEBSERVER]);
const ws = await this.world.runtime[exports.WEBSERVER];
const ws = await this.world.runtime[defs_2.WEBSERVER];
await ws.listen(8123);
const error = await ws.addStaticFolder(loc);
this.world.shared.set('file_location', loc);
return error === undefined ? defs_1.OK : util_1.actionNotOK(error);
},
build: async ({ loc }) => {
this.world.shared.set('file_location', loc);
return defs_1.OK;
}
},

@@ -32,11 +41,11 @@ };

this.webserver = new server_express_1.ServerExpress(this.world.logger, [process.cwd(), 'files'].join('/'));
this.world.runtime[exports.WEBSERVER] = this.webserver;
this.world.runtime[exports.CHECK_LISTENER] = WebServerStepper.checkListener;
this.world.runtime[defs_2.WEBSERVER] = this.webserver;
// this.world.runtime[CHECK_LISTENER] = WebServerStepper.checkListener;
}
async close() {
async finish() {
await this.webserver?.close();
}
static async checkListener(options, webserver) {
const port = options[`HAIBUN_O_${exports.WEBSERVER_STEPPER.toUpperCase()}_PORT`];
await webserver.listening(port || server_express_1.DEFAULT_PORT);
async checkListener(options) {
const port = options[`HAIBUN_O_${defs_2.WEBSERVER_STEPPER.toUpperCase()}_PORT`];
await this.webserver.listen();
}

@@ -43,0 +52,0 @@ };

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -26,35 +7,29 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

const node_fetch_1 = __importDefault(require("node-fetch"));
const Executor_1 = require("@haibun/core/build/lib/Executor");
const util_1 = require("@haibun/core/build/lib/util");
const TestSteps_1 = require("@haibun/core/build/lib/TestSteps");
const web_server_stepper_1 = __importStar(require("./web-server-stepper"));
const web_server_stepper_1 = __importDefault(require("./web-server-stepper"));
const serverLoc = [process.cwd(), 'build', 'web-server-stepper'].join('/');
describe('static mount', () => {
it('listens on serve files', async () => {
const { world, vstep, steppers } = await TestSteps_1.getTestEnv([serverLoc], 'serve files from test', util_1.getDefaultWorld().world);
const res = await Executor_1.Executor.doFeatureStep(vstep, world);
expect(res.ok).toBe(true);
const server = util_1.getStepper(steppers, web_server_stepper_1.WEBSERVER_STEPPER);
expect(server.webserver).toBeDefined();
it('serves files', async () => {
const feature = { path: '/features/test.feature', content: `serve files from test\n` };
const { result } = await TestSteps_1.testWithDefaults([feature], [web_server_stepper_1.default]);
expect(result.ok).toBe(true);
const content = await node_fetch_1.default('http://localhost:8123/testfile');
expect(await content.text()).toEqual('content');
await server.close();
});
it('restricts characters used in static mount folder name', async () => {
const { world, vstep, steppers } = await TestSteps_1.getTestEnv([serverLoc], 'serve files from l*(*$**', util_1.getDefaultWorld().world);
const res = await Executor_1.Executor.doFeatureStep(vstep, world);
expect(res.ok).toBe(false);
util_1.getStepper(steppers, web_server_stepper_1.WEBSERVER_STEPPER).close();
const feature = { path: '/features/test.feature', content: `serve files from l*(*$\n` };
const { result } = await TestSteps_1.testWithDefaults([feature], [web_server_stepper_1.default]);
expect(result.ok).toBe(false);
});
it("doesn't re-mount same static mount", async () => {
const { result, steppers } = await TestSteps_1.testRun('/test/static-no-remount', [web_server_stepper_1.default], util_1.getDefaultWorld().world);
const feature = { path: '/features/test.feature', content: `serve files from test\nserve files from test\n` };
const { result } = await TestSteps_1.testWithDefaults([feature], [web_server_stepper_1.default]);
expect(result.ok).toBe(true);
util_1.getStepper(steppers, web_server_stepper_1.WEBSERVER_STEPPER).close();
});
it("doesn't permit different static mount", async () => {
const { result, steppers } = await TestSteps_1.testRun('/test/static-fails', [web_server_stepper_1.default], util_1.getDefaultWorld().world);
const feature = { path: '/features/test.feature', content: `serve files from test\nserve files from fails\n` };
const { result } = await TestSteps_1.testWithDefaults([feature], [web_server_stepper_1.default]);
expect(result.ok).toBe(false);
util_1.getStepper(steppers, web_server_stepper_1.WEBSERVER_STEPPER).close();
});
});
//# sourceMappingURL=web-server-stepper.test.js.map
{
"name": "@haibun/web-server-express",
"version": "0.2.1",
"version": "1.0.0",
"description": "",

@@ -5,0 +5,0 @@ "main": "build/web-server-stepper.js",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc