Skip to content

Commit

Permalink
Merge branch 'main' into renovate/koa2-swagger-ui-5.x
Browse files Browse the repository at this point in the history
  • Loading branch information
pmcelhaney committed Nov 17, 2023
2 parents 599bd20 + e01a41f commit be03c3f
Show file tree
Hide file tree
Showing 20 changed files with 405 additions and 180 deletions.
5 changes: 0 additions & 5 deletions .changeset/dependencies-GH-638.md

This file was deleted.

5 changes: 0 additions & 5 deletions .changeset/dependencies-GH-648.md

This file was deleted.

3 changes: 3 additions & 0 deletions .eslintrc.cjs
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
7 changes: 3 additions & 4 deletions .github/workflows/debug-windows.yaml
@@ -1,6 +1,7 @@
name: Debug Windows

on:
pull_request:
workflow_dispatch:

env:
Expand Down Expand Up @@ -33,7 +34,5 @@ jobs:
run: yarn install --frozen-lockfile --network-timeout 100000
- name: Build
run: yarn build
- name: Try running the petstore
run: npx . https://petstore3.swagger.io/api/v3/openapi.json out
timeout-minutes: 2
continue-on-error: true
- name: Show files
run: Get-ChildItem -Recurse
11 changes: 11 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,16 @@
# counterfact

## 0.30.0

### Minor Changes

- 0dc11ea: added a --prefix option to specify prefix from which routes are served (e.g. /api/v1)

### Patch Changes

- 4de94f0: Update dependency @types/jest to v29.5.7
- 5f8e97b: chore(deps): update dependency @types/jest to v29.5.8

## 0.29.0

### Minor Changes
Expand Down
9 changes: 7 additions & 2 deletions bin/counterfact.js
Expand Up @@ -6,8 +6,8 @@ import { program } from "commander";
import createDebug from "debug";
import open from "open";

import { migrate } from "../dist/src/migrations/0.27.js";
import { counterfact } from "../dist/src/server/app.js";
import { migrate } from "../dist/migrations/0.27.js";
import { counterfact } from "../dist/server/app.js";

const DEFAULT_PORT = 3100;

Expand Down 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
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
12 changes: 6 additions & 6 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "counterfact",
"version": "0.29.0",
"version": "0.30.0",
"description": "a library for building a fake REST API for testing",
"type": "module",
"main": "./src/server/counterfact.js",
Expand Down Expand Up @@ -31,7 +31,7 @@
"test": "yarn node --experimental-vm-modules ./node_modules/jest-cli/bin/jest --testPathIgnorePatterns=black-box --forceExit",
"test:black-box": "rimraf dist && rimraf out && yarn build && yarn node --experimental-vm-modules ./node_modules/jest-cli/bin/jest black-box --forceExit --coverage=false",
"test:mutants": "stryker run stryker.config.json",
"build": "tsc && copyfiles src/client/** dist && copyfiles templates/** dist",
"build": "tsc && copyfiles -f \"src/client/**\" dist/client",
"prepack": "yarn build",
"release": "npx changeset publish",
"prepare": "husky install",
Expand All @@ -51,9 +51,9 @@
"@swc/jest": "0.2.29",
"@testing-library/dom": "9.3.3",
"@types/jest": "29.5.8",
"@types/js-yaml": "4.0.8",
"@types/koa": "2.13.10",
"@types/koa-bodyparser": "4.3.11",
"@types/js-yaml": "4.0.9",
"@types/koa": "2.13.11",
"@types/koa-bodyparser": "4.3.12",
"@types/koa-proxy": "1.0.7",
"@types/koa-static": "4.0.4",
"copyfiles": "2.4.1",
Expand Down Expand Up @@ -97,7 +97,7 @@
"koa2-swagger-ui": "5.10.0",
"node-fetch": "3.3.2",
"open": "9.1.0",
"prettier": "3.0.3",
"prettier": "3.1.0",
"typescript": "5.2.2"
}
}
17 changes: 2 additions & 15 deletions src/server/dispatcher.ts
@@ -1,5 +1,4 @@
/* eslint-disable import/newline-after-import */
/* eslint-disable max-lines */

import { mediaTypes } from "@hapi/accept";
import createDebugger from "debug";
Expand All @@ -13,11 +12,9 @@ import type {
NormalizedCounterfactResponseObject,
Registry,
} from "./registry.js";
import {
createResponseBuilder,
type OpenApiOperation,
} from "./response-builder.js";
import { createResponseBuilder } from "./response-builder.js";
import { Tools } from "./tools.js";
import type { OpenApiOperation, OpenApiParameters } from "./types.d.ts";

const debug = createDebugger("counterfact:server:dispatcher");

Expand All @@ -42,14 +39,6 @@ interface ParameterTypes {
};
}

interface OpenApiParameters {
in: "body" | "cookie" | "formData" | "header" | "path" | "query";
name: string;
schema?: {
type: string;
};
}

export interface OpenApiDocument {
paths: {
[key: string]: {
Expand Down Expand Up @@ -304,5 +293,3 @@ export class Dispatcher {
return normalizedResponse;
}
}

export type { OpenApiParameters };
11 changes: 9 additions & 2 deletions src/server/koa-middleware.ts
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
4 changes: 2 additions & 2 deletions src/server/registry.ts
@@ -1,8 +1,7 @@
import createDebugger from "debug";

import type { ResponseBuilderFactory } from "../../templates/response-builder-factory.js";
import type { MediaType } from "./response-builder.js";
import type { Tools } from "./tools.js";
import type { MediaType, ResponseBuilderFactory } from "./types.d.ts";

const debug = createDebugger("counterfact:server:registry");

Expand Down Expand Up @@ -204,6 +203,7 @@ export class Registry {
}
} else {
node = node.children[matchingChild];

matchedParts.push(matchingChild);
}
}
Expand Down
61 changes: 6 additions & 55 deletions src/server/response-builder.ts
@@ -1,28 +1,6 @@
import { JSONSchemaFaker, type Schema } from "json-schema-faker";

import type { OpenApiParameters } from "./dispatcher.js";

interface ResponseBuilder {
[status: number | `${number} ${string}`]: ResponseBuilder;
content?: { body: unknown; type: string }[];
header: (name: string, value: string) => ResponseBuilder;
headers: { [name: string]: string };
html: (body: unknown) => ResponseBuilder;
json: (body: unknown) => ResponseBuilder;
match: (contentType: string, body: unknown) => ResponseBuilder;
random: () => ResponseBuilder;
randomLegacy: () => ResponseBuilder;
status?: number;
text: (body: unknown) => ResponseBuilder;
}

interface OpenApiHeader {
schema: unknown;
}
import { JSONSchemaFaker } from "json-schema-faker";

interface OpenApiContent {
schema: unknown;
}
import type { OpenApiOperation, ResponseBuilder } from "./types.d.ts";

JSONSchemaFaker.option("useExamplesValue", true);
JSONSchemaFaker.option("minItems", 0);
Expand Down Expand Up @@ -52,36 +30,6 @@ function unknownStatusCodeResponse(statusCode: number | undefined) {
};
}

interface Example {
description: string;
summary: string;
value: unknown;
}

export type MediaType = `${string}/${string}`;

export interface OpenApiResponse {
content: { [key: MediaType]: OpenApiContent };
headers: { [key: string]: OpenApiHeader };
}

export interface OpenApiOperation {
parameters?: OpenApiParameters[];
produces?: string[];
responses: {
[status: string]: {
content?: {
[type: number | string]: {
examples?: { [key: string]: Example };
schema: unknown;
};
};
examples?: { [key: string]: unknown };
schema?: Schema;
};
};
}

export function createResponseBuilder(
operation: OpenApiOperation,
): ResponseBuilder {
Expand Down Expand Up @@ -176,7 +124,8 @@ export function createResponseBuilder(

const body = response.examples
? oneOf(response.examples)
: JSONSchemaFaker.generate(response.schema ?? { type: "object" });
: // eslint-disable-next-line total-functions/no-unsafe-readonly-mutable-assignment
JSONSchemaFaker.generate(response.schema ?? { type: "object" });

return {
...this,
Expand All @@ -196,3 +145,5 @@ export function createResponseBuilder(
}),
});
}

export type { OpenApiOperation };

0 comments on commit be03c3f

Please sign in to comment.