Skip to content

Commit

Permalink
Merge pull request #15 from ty-ras/issue/14-add-custom-listen-function
Browse files Browse the repository at this point in the history
Issue/14 add custom listen function
  • Loading branch information
stazz committed Aug 25, 2023
2 parents f3c1ce2 + 8c60252 commit 074a0dd
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 283 deletions.
4 changes: 2 additions & 2 deletions server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ty-ras/server-express",
"version": "2.0.1",
"version": "2.1.0",
"author": {
"name": "Stanislav Muhametsin",
"email": "346799+stazz@users.noreply.github.com",
Expand Down Expand Up @@ -31,7 +31,7 @@
}
},
"dependencies": {
"@ty-ras/server": "^2.0.0"
"@ty-ras/server": "^2.2.0"
},
"peerDependencies": {
"express": "^4.18.2"
Expand Down
31 changes: 31 additions & 0 deletions server/src/__test__/listen.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @file This file contains unit tests for functionality in file `../server-node.ts`.
*/

import test from "ava";
import * as spec from "../listen";
import * as server from "../server";
import getPort from "@ava/get-port";

test("Verify that listen overload for host and port as in starter template, works", async (c) => {
c.plan(1);
await c.notThrowsAsync(
async () =>
await spec.listenAsync(
server.createServer({ endpoints: [] }),
"localhost",
await getPort(),
),
);
});

test("Verify that listen overload for listen options works", async (c) => {
c.plan(1);
await c.notThrowsAsync(
async () =>
await spec.listenAsync(server.createServer({ endpoints: [] }), {
options: {},
listen: { host: "localhost", port: await getPort() },
}),
);
});
74 changes: 28 additions & 46 deletions server/src/__test__/server.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,39 @@ import test from "ava";

import * as spec from "../server";
import * as secure from "./secure";

import * as serverGeneric from "@ty-ras/server";
import * as testSupport from "@ty-ras/server-test-support";

const createServer: testSupport.CreateServer = (
endpoints,
info,
httpVersion,
secure,
) =>
httpVersion === 1
? secure
? spec.createServer({
endpoints,
...getCreateState(info),
options: {
...secureInfo,
},
})
: spec.createServer({ endpoints, ...getCreateState(info) })
: httpVersion === 2
? secure
? {
server: spec.createServer({
endpoints,
...getCreateState(info),
httpVersion,
options: {
...secureInfo,
},
}),
secure,
}
: {
server: spec.createServer({
endpoints,
...getCreateState(info),
httpVersion,
}),
secure,
}
: doThrow(`Invalid http version: ${httpVersion}`);
) => {
const server = spec.createServer({
endpoints,
...getCreateState(info),
});
return {
server: serverGeneric.createNodeServerGeneric(
httpVersion === 2
? {
httpVersion: 2,
secure,
options: secure ? secureInfo : {},
}
: httpVersion === 1
? {
httpVersion: 1,
secure,
options: secure ? secureInfo : {},
}
: doThrow(`Invalid http version: ${httpVersion}`),
server,
),
secure,
};
};

const secureInfo = secure.generateKeyAndCert();
const doThrow = (msg: string) => {
Expand All @@ -71,14 +63,7 @@ testSupport.registerTests(test, createServer, {
secure: true,
});

test("HTTP2 support should not work yet until 5.x release", (c) => {
c.plan(1);
c.throws(() => spec.createServer({ endpoints: [], httpVersion: 2 }), {
instanceOf: Error,
message:
"Unfortunately, express v4.x does not support HTTP protocol version 2, and couldn't find any workaround for that (http2-express-bridge didn't work).",
});
});
// Express 4.x does not support HTTP2

// testSupport.registerTests(test, createServer, {
// ...defaultOpts,
Expand All @@ -94,10 +79,7 @@ test("HTTP2 support should not work yet until 5.x release", (c) => {

const getCreateState = (
info: testSupport.ServerTestAdditionalInfo[0],
): Pick<
spec.ServerCreationOptions<unknown, never, never, never>,
"createState"
> =>
): Pick<spec.ServerCreationOptions<unknown, never>, "createState"> =>
info == 500
? {
createState: () => {
Expand Down
2 changes: 2 additions & 0 deletions server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@
export type * from "./context.types";
export * from "./middleware";
export * from "./cors";
export * from "./server";
export * from "./listen";

// Don't export anything from ./internal.ts.
100 changes: 100 additions & 0 deletions server/src/listen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* @file This file contains function that can be used to expose uniform way to listen to TyRAS servers.
*/

import type * as server from "./server";
import * as serverGeneric from "@ty-ras/server";
import * as net from "node:net";

/**
* The helper function to listen to given {@link server.HttpServer} asynchronously.
* @param server The {@link server.HttpServer} to listen to.
* @param host The hostname as string.
* @param port The port as number.
* @param backlog The backlog parameter, if any.
* @returns Asynchronously nothing.
*/
export function listenAsync(
server: server.HttpServer,
host: string,
port: number,
backlog?: number,
): Promise<void>;

/**
*The helper function to listen to given {@link server.HttpServer} asynchronously.
* @param server The {@link server.HttpServer} to listen to.
* @param options The {@link ListenOptions1}. Notice that Express 4.x does not support HTTP2.
* @returns Asynchronously nothing.
*/
export function listenAsync(
server: server.HttpServer,
options: ListenOptions1,
): Promise<void>;

/**
* The helper function to listen to given {@link server.HttpServer} asynchronously.
* @param server The {@link server.HttpServer} to listen to.
* @param hostOrOptions The {@link ListenOptions1}. Notice that Express 4.x does not support HTTP2.
* @param port The port to listen to.
* @param backlog The backlog parameter, if any.
* @returns Asynchronously nothing.
*/
export function listenAsync(
server: server.HttpServer,
hostOrOptions: string | ListenOptions1,
port?: number,
backlog?: number,
) {
const opts: ListenOptions1 =
typeof hostOrOptions === "string"
? {
listen: {
host: hostOrOptions,
port,
backlog,
},
}
: hostOrOptions;

return serverGeneric.listenAsyncGeneric(
serverGeneric.createNodeServerGeneric(opts, server),
typeof hostOrOptions === "string" ? hostOrOptions : hostOrOptions.listen,
port,
backlog,
);
}

/**
* This interface contains options for both HTTP 1 and 2 servers when listening to them via {@link listenAsync}.
*/
export interface ListenOptionsBase {
/**
* Options related to listening for connections.
*/
listen: net.ListenOptions;
}

/**
* This interface contains options for HTTP 1 servers when listening to them via {@link listenAsync}.
*/
export interface ListenOptions1
extends serverGeneric.NodeServerOptions1<boolean>,
ListenOptionsBase {
/**
* Use this property if needed.
*/
httpVersion?: 1;
}

// /**
// * This interface contains options for HTTP 2 servers when listening to them via {@link listenAsync}.
// */
// export interface ListenOptions2
// extends serverNode.ServerOptions2<boolean>,
// ListenOptionsBase {
// /**
// * Set this property to `2` in order to use HTTP2 server when listening.
// */
// httpVersion: 2;
// }
6 changes: 3 additions & 3 deletions server/src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ import type * as context from "./context.types";
import * as internal from "./internal";

/**
* Creates a new {@link express.Middleware} to server the given TyRAS {@link ep.AppEndpoint}s.
* Creates a new {@link express.Middleware} to serve the given TyRAS {@link ep.AppEndpoint}s.
* @param endpoints The TyRAS {@link ep.AppEndpoint}s to serve through this Koa middleware.
* @param createState The optional callback to create state for the endpoints.
* @param events The optional {@link server.ServerEventHandler} callback to observe server events.
* @returns The Koa middleware which will serve the given endpoints.
*/
export const createMiddleware = <TStateInfo>(
export const createMiddleware = <TStateInfo, TState>(
endpoints: ReadonlyArray<ep.AppEndpoint<context.ServerContext, TStateInfo>>,
createState?: context.CreateState<TStateInfo>,
events?: server.ServerEventHandler<
server.GetContext<context.ServerContext>,
TStateInfo
TState
>,
): express.RequestHandler => {
const flow = server.createTypicalServerFlow(
Expand Down

0 comments on commit 074a0dd

Please sign in to comment.