Skip to content

Commit

Permalink
Merge pull request #652 from pmcelhaney/routes-prefix
Browse files Browse the repository at this point in the history
add a --prefix option for route prefix
  • Loading branch information
pmcelhaney authored Nov 17, 2023
2 parents e82725a + b340407 commit bbaebd0
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/mighty-penguins-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"counterfact": minor
---

added a --prefix option to specify prefix from which routes are served (e.g. /api/v1)
3 changes: 3 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const rules = {
},
],

"max-lines": "warn",

"n/shebang": "off",

"no-magic-numbers": [
Expand All @@ -30,6 +32,7 @@ const rules = {

"node/file-extension-in-import": "off",
"node/no-callback-literal": "off",

"node/no-missing-import": "off",

"prettier/prettier": [
Expand Down
5 changes: 5 additions & 0 deletions bin/counterfact.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ async function main(source, destination) {
port: options.port,
proxyEnabled: Boolean(options.proxyUrl),
proxyUrl: options.proxyUrl,
routePrefix: options.prefix,
};

debug("loading counterfact (%o)", config);
Expand Down Expand Up @@ -106,6 +107,10 @@ program
.option("--swagger", "include swagger-ui")
.option("--open", "open a browser")
.option("--proxy-url <string>", "proxy URL")
.option(
"--prefix <string>",
"base path from which routes will be served (e.g. /api/v1)",
)
.action(main)
// eslint-disable-next-line sonar/process-argv
.parse(process.argv);
15 changes: 8 additions & 7 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ Usage: counterfact [options] <openapi.yaml> [destination]
Counterfact is a tool for generating a REST API from an OpenAPI document.
Arguments:
openapi.yaml path or URL to OpenAPI document
destination path to generated code (default: ".")
openapi.yaml path or URL to OpenAPI document
destination path to generated code (default: ".")
Options:
--serve start the server after generating code
--port <number> server port number (default: 3100)
--swagger include swagger-ui (implies --serve)
--open open a browser to swagger-ui (implies --swagger and --serve)
-h, --help display help for command
--port <number> server port number (default: 3100)
--swagger include swagger-ui
--open open a browser
--proxy-url <string> proxy URL
--prefix <string> base path from which routes will be served (e.g. /api/v1)
-h, --help display help for command
```

Expand Down
11 changes: 9 additions & 2 deletions src/server/koa-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,20 @@ function addCors(ctx: Koa.ExtendableContext, headers?: IncomingHttpHeaders) {

export function koaMiddleware(
dispatcher: Dispatcher,
{ proxyEnabled = false, proxyUrl = "" } = {},
{ proxyEnabled = false, proxyUrl = "", routePrefix = "" } = {},
proxy = koaProxy,
): Koa.Middleware {
// eslint-disable-next-line max-statements
return async function middleware(ctx, next) {
if (!ctx.request.path.startsWith(routePrefix)) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return await next();
}

/* @ts-expect-error the body comes from koa-bodyparser, not sure how to fix this */
const { body, headers, path, query } = ctx.request;
const { body, headers, query } = ctx.request;

const path = ctx.request.path.slice(routePrefix.length);

// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const method = ctx.request.method as HttpMethods;
Expand Down
1 change: 1 addition & 0 deletions src/server/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ export class Registry {
}
} else {
node = node.children[matchingChild];

matchedParts.push(matchingChild);
}
}
Expand Down
37 changes: 37 additions & 0 deletions test/server/koa-middleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,4 +263,41 @@ describe("koa middleware", () => {

expect(ctx.set).toHaveBeenCalledWith("X-Custom-Header", "custom value");
});

it("passes the request to the dispatcher and returns the response", async () => {
const registry = new Registry();

registry.add("/hello", {
// @ts-expect-error - not obvious how to make TS happy here, and it's just a unit test
POST({ body }: { body: { name: string } }) {
return {
body: `Hello, ${body.name}!`,
};
},
});

const dispatcher = new Dispatcher(registry, new ContextRegistry());
const middleware = koaMiddleware(dispatcher, { routePrefix: "/api/v1" });
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const ctx = {
req: {
path: "/api/v1/hello",
},

request: {
body: { name: "Homer" },
method: "POST",
path: "/api/v1/hello",
},

set: jest.fn(),
} as unknown as ParameterizedContext;

await middleware(ctx, async () => {
await Promise.resolve(undefined);
});

expect(ctx.status).toBe(200);
expect(ctx.body).toBe("Hello, Homer!");
});
});

0 comments on commit bbaebd0

Please sign in to comment.