Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/refactor-admin-api-middleware-param.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"counterfact": patch
---

Refactor `createKoaApp()` to accept `adminApiMiddleware` as a parameter instead of constructing it internally. Rename the `koaMiddleware` parameter and export to `routesMiddleware`.
2 changes: 1 addition & 1 deletion docs/features/programmatic-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ it("prompts for a password change when the password has expired", async () => {
| `contextRegistry` | `ContextRegistry` | Registry of all context objects keyed by path. Call `.find(path)` to get the context for a given route prefix. |
| `registry` | `Registry` | Registry of all loaded route modules. |
| `koaApp` | `Koa` | The underlying Koa application. |
| `koaMiddleware` | `Koa.Middleware` | The Counterfact request-dispatch middleware. |
| `routesMiddleware` | `Koa.Middleware` | The Counterfact request-dispatch middleware. |
| `start(config)` | `async (config) => { stop() }` | Starts the server (and optionally the file watcher and code generator). Returns a `stop()` function to gracefully shut down. |
| `startRepl()` | `() => REPLServer` | Starts the interactive REPL. Returns the REPL server instance. |

Expand Down
13 changes: 9 additions & 4 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import { createHttpTerminator, type HttpTerminator } from "http-terminator";

import { startRepl as startReplServer } from "./repl/repl.js";
import { createRouteFunction } from "./repl/route-builder.js";
import { adminApiMiddleware } from "./server/admin-api-middleware.js";
import type { Config } from "./server/config.js";
import { ContextRegistry } from "./server/context-registry.js";
import { createKoaApp } from "./server/create-koa-app.js";
import { Dispatcher, type DispatcherRequest } from "./server/dispatcher.js";
import { koaMiddleware } from "./server/koa-middleware.js";
import { routesMiddleware } from "./server/koa-middleware.js";
import { loadOpenApiDocument } from "./server/load-openapi-document.js";
import { ModuleLoader } from "./server/module-loader.js";
import { Registry } from "./server/registry.js";
Expand Down Expand Up @@ -224,9 +225,13 @@ export async function counterfact(config: Config) {
void writeScenarioContextType(modulesPath);
});

const middleware = koaMiddleware(dispatcher, config);
const middleware = routesMiddleware(dispatcher, config);

const koaApp = createKoaApp(registry, middleware, config, contextRegistry);
const adminMiddleware = config.startAdminApi
? adminApiMiddleware(registry, contextRegistry, config)
: undefined;

const koaApp = createKoaApp(middleware, config, adminMiddleware);

async function start(options: Config) {
const { generate, startServer, watch, buildCache } = options;
Expand Down Expand Up @@ -284,7 +289,7 @@ export async function counterfact(config: Config) {
return {
contextRegistry,
koaApp,
koaMiddleware: middleware,
routesMiddleware: middleware,
registry,
start,
startRepl: () =>
Expand Down
23 changes: 9 additions & 14 deletions src/server/create-koa-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ import Koa from "koa";
import bodyParser from "koa-bodyparser";
import { koaSwagger } from "koa2-swagger-ui";

import { adminApiMiddleware } from "./admin-api-middleware.js";
import type { Config } from "./config.js";
import type { ContextRegistry } from "./context-registry.js";
import { openapiMiddleware } from "./openapi-middleware.js";
import type { Registry } from "./registry.js";

const debug = createDebug("counterfact:server:create-koa-app");

Expand All @@ -17,23 +14,22 @@ const debug = createDebug("counterfact:server:create-koa-app");
* The middleware stack (in order) is:
* 1. OpenAPI document serving at `/counterfact/openapi`
* 2. Swagger UI at `/counterfact/swagger`
* 3. Admin API (when enabled) at `/_counterfact/api/`
* 3. Admin API (when provided) at `/_counterfact/api/`
* 4. Redirect `/counterfact` → `/counterfact/swagger`
* 5. Body parser
* 6. JSON serialisation of object bodies
* 7. Route-dispatching middleware
*
* @param registry - The route registry used by the admin API and dispatcher.
* @param koaMiddleware - The pre-built route-dispatching middleware.
* @param routesMiddleware - The pre-built route-dispatching middleware.
* @param config - Server configuration.
* @param contextRegistry - The context registry used by the admin API.
* @param adminApiMiddleware - Optional pre-built admin API middleware; when
* provided it is mounted at `/_counterfact/api/`.
* @returns A configured Koa application (not yet listening).
*/
export function createKoaApp(
registry: Registry,
koaMiddleware: Koa.Middleware,
routesMiddleware: Koa.Middleware,
config: Config,
contextRegistry: ContextRegistry,
adminApiMiddleware?: Koa.Middleware,
) {
const app = new Koa();

Expand All @@ -56,12 +52,11 @@ export function createKoaApp(
}),
);

if (config.startAdminApi) {
app.use(adminApiMiddleware(registry, contextRegistry, config));
if (adminApiMiddleware) {
app.use(adminApiMiddleware);
}

debug("basePath: %s", config.basePath);
debug("routes", registry.routes);

app.use(async (ctx, next) => {
if (ctx.URL.pathname === "/counterfact") {
Expand Down Expand Up @@ -89,7 +84,7 @@ export function createKoaApp(
}
});

app.use(koaMiddleware);
app.use(routesMiddleware);

return app;
}
2 changes: 1 addition & 1 deletion src/server/koa-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ function getAuthObject(
* @param proxy - Proxy factory; injectable for testing.
* @returns A Koa middleware function.
*/
export function koaMiddleware(
export function routesMiddleware(
dispatcher: Dispatcher,
config: Config,
proxy = koaProxy,
Expand Down
4 changes: 2 additions & 2 deletions test/app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ describe("counterfact", () => {
expect(typeof result.startRepl).toBe("function");
});

it("returns contextRegistry, registry, koaApp, koaMiddleware, and start", async () => {
it("returns contextRegistry, registry, koaApp, routesMiddleware, and start", async () => {
const result = await (app as any).counterfact(mockConfig);
expect(result.contextRegistry).toBeDefined();
expect(result.registry).toBeDefined();
expect(result.koaApp).toBeDefined();
expect(result.koaMiddleware).toBeDefined();
expect(result.routesMiddleware).toBeDefined();
expect(typeof result.start).toBe("function");
});

Expand Down
22 changes: 11 additions & 11 deletions test/server/koa-middleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { IBaseKoaProxiesOptions } from "koa-proxies";
import type { Config } from "../../src/server/config.js";
import { ContextRegistry } from "../../src/server/context-registry.js";
import { Dispatcher } from "../../src/server/dispatcher.js";
import { koaMiddleware } from "../../src/server/koa-middleware.js";
import { routesMiddleware } from "../../src/server/koa-middleware.js";
import { Registry } from "../../src/server/registry.js";

const CONFIG: Config = {
Expand Down Expand Up @@ -54,7 +54,7 @@ describe("koa middleware", () => {
});

const dispatcher = new Dispatcher(registry, new ContextRegistry());
const middleware = koaMiddleware(dispatcher, CONFIG);
const middleware = routesMiddleware(dispatcher, CONFIG);

const ctx = {
req: {
Expand Down Expand Up @@ -91,7 +91,7 @@ describe("koa middleware", () => {
});

const dispatcher = new Dispatcher(registry, new ContextRegistry());
const middleware = koaMiddleware(dispatcher, CONFIG);
const middleware = routesMiddleware(dispatcher, CONFIG);
const ctx = {
request: { headers: {}, method: "GET", path: "/not-modified" },

Expand All @@ -117,7 +117,7 @@ describe("koa middleware", () => {
});

const dispatcher = new Dispatcher(registry, new ContextRegistry());
const middleware = koaMiddleware(
const middleware = routesMiddleware(
dispatcher,
{
...CONFIG,
Expand Down Expand Up @@ -157,7 +157,7 @@ describe("koa middleware", () => {
});

const dispatcher = new Dispatcher(registry, new ContextRegistry());
const middleware = koaMiddleware(dispatcher, CONFIG);
const middleware = routesMiddleware(dispatcher, CONFIG);
const ctx = {
body: undefined,

Expand Down Expand Up @@ -205,7 +205,7 @@ describe("koa middleware", () => {
});

const dispatcher = new Dispatcher(registry, new ContextRegistry());
const middleware = koaMiddleware(dispatcher, CONFIG);
const middleware = routesMiddleware(dispatcher, CONFIG);
const ctx = {
body: undefined,

Expand Down Expand Up @@ -269,7 +269,7 @@ describe("koa middleware", () => {
});

const dispatcher = new Dispatcher(registry, new ContextRegistry());
const middleware = koaMiddleware(dispatcher, CONFIG);
const middleware = routesMiddleware(dispatcher, CONFIG);
const ctx = {
body: undefined,

Expand Down Expand Up @@ -313,7 +313,7 @@ describe("koa middleware", () => {
});

const dispatcher = new Dispatcher(registry, new ContextRegistry());
const middleware = koaMiddleware(dispatcher, {
const middleware = routesMiddleware(dispatcher, {
...CONFIG,
routePrefix: "/api/v1",
});
Expand Down Expand Up @@ -353,7 +353,7 @@ describe("koa middleware", () => {
});

const dispatcher = new Dispatcher(registry, new ContextRegistry());
const middleware = koaMiddleware(dispatcher, {
const middleware = routesMiddleware(dispatcher, {
...CONFIG,
routePrefix: "/api/v1",
});
Expand Down Expand Up @@ -393,7 +393,7 @@ describe("koa middleware", () => {
});

const dispatcher = new Dispatcher(registry, new ContextRegistry());
const middleware = koaMiddleware(dispatcher, CONFIG);
const middleware = routesMiddleware(dispatcher, CONFIG);

const ctx = {
req: {
Expand Down Expand Up @@ -435,7 +435,7 @@ describe("koa middleware", () => {
});

const dispatcher = new Dispatcher(registry, new ContextRegistry());
const middleware = koaMiddleware(dispatcher, CONFIG);
const middleware = routesMiddleware(dispatcher, CONFIG);

const ctx = {
body: undefined,
Expand Down
Loading