Skip to content

Commit

Permalink
Merge pull request #37 from ty-ras/issue/36-use-generic-create-node-s…
Browse files Browse the repository at this point in the history
…erver

#36 Taking new generic server package into use, a…
  • Loading branch information
stazz committed Aug 25, 2023
2 parents a43efd5 + 1999532 commit aff8b7e
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 262 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-node",
"version": "2.1.1",
"version": "2.2.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.1.1"
"@ty-ras/server": "^2.2.0"
},
"devDependencies": {
"@ava/get-port": "2.0.0",
Expand Down
29 changes: 20 additions & 9 deletions server/src/__test__/listen.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,25 @@ import getPort from "@ava/get-port";
import * as spec from "../listen";
import * as server from "../server";

test("Validate that listening to server does not crash", async (c) => {
// Not much else we can do since CORS callbacks are just call-thru to @ty-ras/server functionality
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(),
);
});
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: [] }), {
host: "localhost",
port: await getPort(),
}),
);
});
2 changes: 1 addition & 1 deletion server/src/__test__/server.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ testSupport.registerTests(test, createServer, {
const getCreateState = (
info: testSupport.ServerTestAdditionalInfo[0],
): Pick<
spec.ServerCreationOptions<ctx.ServerContext, unknown, never, never, never>,
spec.ServerCreationOptions<ctx.ServerContext, unknown, never>,
"createState"
> =>
info == 500
Expand Down
5 changes: 4 additions & 1 deletion server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
*/

export type * from "./context.types";
export * from "./server";
export * from "./cors";
export * from "./middleware";
export * from "./server";
export * from "./listen";

// Don't export anything from ./internal.ts.
62 changes: 62 additions & 0 deletions server/src/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* @file This file contains helper function to create Node server callback.
*/

import type * as ep from "@ty-ras/endpoint";
import * as server from "@ty-ras/server";
import type * as context from "./context.types";
import * as internal from "./internal";

import type * as http from "node:http";
import type * as http2 from "node:http2";

/**
* 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, TState>(
endpoints: ReadonlyArray<ep.AppEndpoint<context.ServerContext, TStateInfo>>,
createState?: context.CreateState<TStateInfo>,
events?: server.ServerEventHandler<
server.GetContext<context.ServerContext>,
TState
>,
): server.HTTP1Handler | server.HTTP2Handler => {
const flow = server.createTypicalServerFlow<
context.ServerContext,
TStateInfo,
TState
>(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
endpoints as any,
{
...internal.staticCallbacks,
getState: async ({ req }, stateInfo) =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
await createState?.({ context: req as any, stateInfo }),
},
events,
);
return async (
req: http.IncomingMessage | http2.Http2ServerRequest,
res: http.ServerResponse | http2.Http2ServerResponse,
) => {
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const ctx: context.ServerContext = {
req,
res,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any;
// Perform flow (typicalServerFlow is no-throw (as much as there can be one in JS) function)
await flow(ctx);
} finally {
if (!res.writableEnded) {
res.end();
}
}
};
};

0 comments on commit aff8b7e

Please sign in to comment.