Skip to content

Commit

Permalink
Merge pull request #17 from ty-ras/issue/16-add-custom-listen-function
Browse files Browse the repository at this point in the history
Issue/16 add custom listen function
  • Loading branch information
stazz authored Aug 25, 2023
2 parents bee2fb3 + f8ec595 commit e87ad25
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 267 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-koa",
"version": "2.1.0",
"version": "2.2.0",
"author": {
"name": "Stanislav Muhametsin",
"email": "[email protected]",
Expand Down Expand Up @@ -34,7 +34,7 @@
"koa": "^2.14.2"
},
"dependencies": {
"@ty-ras/server": "^2.0.0"
"@ty-ras/server": "^2.2.0"
},
"devDependencies": {
"@ava/get-port": "2.0.0",
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() },
}),
);
});
65 changes: 27 additions & 38 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.callback(),
),
secure,
};
};

const secureInfo = secure.generateKeyAndCert();
const doThrow = (msg: string) => {
Expand Down Expand Up @@ -83,10 +75,7 @@ testSupport.registerTests(test, createServer, {

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} or {@link ListenOptions2}.
* @returns Asynchronously nothing.
*/
export function listenAsync(
server: server.HttpServer,
options: ListenOptions1 | ListenOptions2,
): 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} or {@link ListenOptions2}.
* @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 | ListenOptions2,
port?: number,
backlog?: number,
) {
const opts: ListenOptions1 | ListenOptions2 =
typeof hostOrOptions === "string"
? {
listen: {
host: hostOrOptions,
port,
backlog,
},
}
: hostOrOptions;

return serverGeneric.listenAsyncGeneric(
serverGeneric.createNodeServerGeneric(opts, server.callback()),
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 serverGeneric.NodeServerOptions2<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 koa.Middleware} to server the given TyRAS {@link ep.AppEndpoint}s.
* Creates a new {@link koa.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
>,
): koa.Middleware<TStateInfo> => {
return server.createTypicalServerFlow(
Expand Down
Loading

0 comments on commit e87ad25

Please sign in to comment.