counterfact 1.3.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/counterfact.js +7 -3
- package/dist/app.js +63 -4
- package/dist/server/module-tree.js +9 -1
- package/package.json +26 -25
package/bin/counterfact.js
CHANGED
|
@@ -111,7 +111,7 @@ async function main(source, destination) {
|
|
|
111
111
|
|
|
112
112
|
// If no action-related option is provided, default to all options
|
|
113
113
|
|
|
114
|
-
const actions = ["repl", "serve", "watch", "generate"];
|
|
114
|
+
const actions = ["repl", "serve", "watch", "generate", "buildCache"];
|
|
115
115
|
if (
|
|
116
116
|
!Object.keys(options).some((argument) =>
|
|
117
117
|
actions.some((action) => argument.startsWith(action)),
|
|
@@ -143,13 +143,15 @@ async function main(source, destination) {
|
|
|
143
143
|
options.generate ||
|
|
144
144
|
options.generateRoutes ||
|
|
145
145
|
options.watch ||
|
|
146
|
-
options.watchRoutes
|
|
146
|
+
options.watchRoutes ||
|
|
147
|
+
options.buildCache,
|
|
147
148
|
|
|
148
149
|
types:
|
|
149
150
|
options.generate ||
|
|
150
151
|
options.generateTypes ||
|
|
151
152
|
options.watch ||
|
|
152
|
-
options.watchTypes
|
|
153
|
+
options.watchTypes ||
|
|
154
|
+
options.buildCache,
|
|
153
155
|
},
|
|
154
156
|
|
|
155
157
|
openApiPath: source,
|
|
@@ -159,6 +161,7 @@ async function main(source, destination) {
|
|
|
159
161
|
routePrefix: options.prefix,
|
|
160
162
|
startRepl: options.repl,
|
|
161
163
|
startServer: options.serve,
|
|
164
|
+
buildCache: options.buildCache || false,
|
|
162
165
|
|
|
163
166
|
watch: {
|
|
164
167
|
routes: options.watch || options.watchRoutes,
|
|
@@ -262,6 +265,7 @@ program
|
|
|
262
265
|
.option("--watch-types", "generate + watch types for changes")
|
|
263
266
|
.option("--watch-routes", "generate + watch routes for changes")
|
|
264
267
|
.option("-s, --serve", "start the server")
|
|
268
|
+
.option("-b, --build-cache", "builds the cache of compiled routes and types")
|
|
265
269
|
.option("-r, --repl", "start the REPL")
|
|
266
270
|
.option("--proxy-url <string>", "proxy URL")
|
|
267
271
|
.option(
|
package/dist/app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { rm } from "node:fs/promises";
|
|
1
|
+
import fs, { rm } from "node:fs/promises";
|
|
2
2
|
import nodePath from "node:path";
|
|
3
3
|
import { dereference } from "@apidevtools/json-schema-ref-parser";
|
|
4
4
|
import { createHttpTerminator } from "http-terminator";
|
|
@@ -6,14 +6,24 @@ import yaml from "js-yaml";
|
|
|
6
6
|
import { startRepl } from "./repl/repl.js";
|
|
7
7
|
import { ContextRegistry } from "./server/context-registry.js";
|
|
8
8
|
import { createKoaApp } from "./server/create-koa-app.js";
|
|
9
|
-
import { Dispatcher } from "./server/dispatcher.js";
|
|
9
|
+
import { Dispatcher, } from "./server/dispatcher.js";
|
|
10
10
|
import { koaMiddleware } from "./server/koa-middleware.js";
|
|
11
11
|
import { ModuleLoader } from "./server/module-loader.js";
|
|
12
12
|
import { Registry } from "./server/registry.js";
|
|
13
13
|
import { Transpiler } from "./server/transpiler.js";
|
|
14
14
|
import { CodeGenerator } from "./typescript-generator/code-generator.js";
|
|
15
15
|
import { readFile } from "./util/read-file.js";
|
|
16
|
-
|
|
16
|
+
const allowedMethods = [
|
|
17
|
+
"all",
|
|
18
|
+
"head",
|
|
19
|
+
"get",
|
|
20
|
+
"post",
|
|
21
|
+
"put",
|
|
22
|
+
"delete",
|
|
23
|
+
"patch",
|
|
24
|
+
"options",
|
|
25
|
+
];
|
|
26
|
+
export async function loadOpenApiDocument(source) {
|
|
17
27
|
try {
|
|
18
28
|
const text = await readFile(source);
|
|
19
29
|
const openApiDocument = await yaml.load(text);
|
|
@@ -23,6 +33,50 @@ async function loadOpenApiDocument(source) {
|
|
|
23
33
|
return undefined;
|
|
24
34
|
}
|
|
25
35
|
}
|
|
36
|
+
const mswHandlers = {};
|
|
37
|
+
export async function handleMswRequest(request) {
|
|
38
|
+
const { method, rawPath } = request;
|
|
39
|
+
const handler = mswHandlers[`${method}:${rawPath}`];
|
|
40
|
+
if (handler) {
|
|
41
|
+
return handler(request);
|
|
42
|
+
}
|
|
43
|
+
console.warn(`No handler found for ${method} ${rawPath}`);
|
|
44
|
+
return { error: `No handler found for ${method} ${rawPath}`, status: 404 };
|
|
45
|
+
}
|
|
46
|
+
export async function createMswHandlers(config, ModuleLoaderClass = ModuleLoader) {
|
|
47
|
+
// TODO: For some reason the Vitest Custom Commands needed by Vitest Browser mode fail on fs.readFile when they are called from the nested loadOpenApiDocument function.
|
|
48
|
+
// If we "pre-read" the file here it works. This is a workaround to avoid the issue.
|
|
49
|
+
const _ = await fs.readFile(config.openApiPath);
|
|
50
|
+
const openApiDocument = await loadOpenApiDocument(config.openApiPath);
|
|
51
|
+
if (openApiDocument === undefined) {
|
|
52
|
+
throw new Error(`Could not load OpenAPI document from ${config.openApiPath}`);
|
|
53
|
+
}
|
|
54
|
+
const modulesPath = config.basePath;
|
|
55
|
+
const compiledPathsDirectory = nodePath
|
|
56
|
+
.join(modulesPath, ".cache")
|
|
57
|
+
.replaceAll("\\", "/");
|
|
58
|
+
const registry = new Registry();
|
|
59
|
+
const contextRegistry = new ContextRegistry();
|
|
60
|
+
const dispatcher = new Dispatcher(registry, contextRegistry, openApiDocument, config);
|
|
61
|
+
const moduleLoader = new ModuleLoaderClass(compiledPathsDirectory, registry, contextRegistry);
|
|
62
|
+
await moduleLoader.load();
|
|
63
|
+
const routes = registry.routes;
|
|
64
|
+
const handlers = routes.flatMap((route) => {
|
|
65
|
+
const { methods, path } = route;
|
|
66
|
+
return Object.keys(methods)
|
|
67
|
+
.filter((method) => allowedMethods.includes(method.toLowerCase()))
|
|
68
|
+
.map((method) => {
|
|
69
|
+
const lowerMethod = method.toLowerCase();
|
|
70
|
+
const apiPath = `${openApiDocument.basePath ?? ""}${path.replaceAll("{", ":").replaceAll("}", "")}`;
|
|
71
|
+
const handler = async (request) => {
|
|
72
|
+
return await dispatcher.request(request);
|
|
73
|
+
};
|
|
74
|
+
mswHandlers[`${method}:${apiPath}`] = handler;
|
|
75
|
+
return { method: lowerMethod, path: apiPath };
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
return handlers;
|
|
79
|
+
}
|
|
26
80
|
export async function counterfact(config) {
|
|
27
81
|
const modulesPath = config.basePath;
|
|
28
82
|
const compiledPathsDirectory = nodePath
|
|
@@ -38,7 +92,7 @@ export async function counterfact(config) {
|
|
|
38
92
|
const middleware = koaMiddleware(dispatcher, config);
|
|
39
93
|
const koaApp = createKoaApp(registry, middleware, config);
|
|
40
94
|
async function start(options) {
|
|
41
|
-
const { generate, startRepl: shouldStartRepl, startServer, watch, } = options;
|
|
95
|
+
const { generate, startRepl: shouldStartRepl, startServer, watch, buildCache, } = options;
|
|
42
96
|
if (generate.routes || generate.types) {
|
|
43
97
|
await codeGenerator.generate();
|
|
44
98
|
}
|
|
@@ -57,6 +111,11 @@ export async function counterfact(config) {
|
|
|
57
111
|
server,
|
|
58
112
|
});
|
|
59
113
|
}
|
|
114
|
+
else if (buildCache) {
|
|
115
|
+
// If we are not starting the server, we still want to transpile and load modules
|
|
116
|
+
await transpiler.watch();
|
|
117
|
+
await transpiler.stopWatching();
|
|
118
|
+
}
|
|
60
119
|
const replServer = shouldStartRepl && startRepl(contextRegistry, config);
|
|
61
120
|
return {
|
|
62
121
|
replServer,
|
|
@@ -67,7 +67,15 @@ export class ModuleTree {
|
|
|
67
67
|
return file.module[method] !== undefined;
|
|
68
68
|
}
|
|
69
69
|
buildMatch(directory, segment, pathVariables, matchedPath, method) {
|
|
70
|
-
|
|
70
|
+
function normalizedSegment(segment, directory) {
|
|
71
|
+
for (const file in directory.files) {
|
|
72
|
+
if (file.toLowerCase() === segment.toLowerCase()) {
|
|
73
|
+
return file;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return "";
|
|
77
|
+
}
|
|
78
|
+
const match = directory.files[normalizedSegment(segment, directory)] ??
|
|
71
79
|
Object.values(directory.files).find((file) => file.isWildcard && this.fileModuleDefined(file, method));
|
|
72
80
|
if (match === undefined) {
|
|
73
81
|
return undefined;
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "counterfact",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "a library for building a fake REST API for testing",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./
|
|
7
|
-
"exports": "./
|
|
8
|
-
"types": "./
|
|
6
|
+
"main": "./dist/app.js",
|
|
7
|
+
"exports": "./dist/app.js",
|
|
8
|
+
"types": "./dist/server/types.d.ts",
|
|
9
9
|
"author": "Patrick McElhaney <pmcelhaney@gmail.com> (https://patrickmcelhaney.com)",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"repository": "github:pmcelhaney/counterfact",
|
|
@@ -44,50 +44,50 @@
|
|
|
44
44
|
"postinstall": "patch-package"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@changesets/cli": "2.29.
|
|
48
|
-
"@stryker-mutator/core": "
|
|
49
|
-
"@stryker-mutator/jest-runner": "
|
|
50
|
-
"@stryker-mutator/typescript-checker": "
|
|
51
|
-
"@swc/core": "1.
|
|
52
|
-
"@swc/jest": "0.2.
|
|
47
|
+
"@changesets/cli": "2.29.4",
|
|
48
|
+
"@stryker-mutator/core": "9.0.1",
|
|
49
|
+
"@stryker-mutator/jest-runner": "9.0.1",
|
|
50
|
+
"@stryker-mutator/typescript-checker": "9.0.1",
|
|
51
|
+
"@swc/core": "1.12.1",
|
|
52
|
+
"@swc/jest": "0.2.38",
|
|
53
53
|
"@testing-library/dom": "10.4.0",
|
|
54
|
-
"@types/jest": "
|
|
54
|
+
"@types/jest": "30.0.0",
|
|
55
55
|
"@types/js-yaml": "4.0.9",
|
|
56
56
|
"@types/koa": "2.15.0",
|
|
57
57
|
"@types/koa-bodyparser": "4.3.12",
|
|
58
58
|
"@types/koa-proxy": "1.0.7",
|
|
59
59
|
"@types/koa-static": "4.0.4",
|
|
60
|
-
"@types/lodash": "4.17.
|
|
60
|
+
"@types/lodash": "4.17.17",
|
|
61
61
|
"copyfiles": "2.4.1",
|
|
62
|
-
"eslint": "9.
|
|
62
|
+
"eslint": "9.28.0",
|
|
63
63
|
"eslint-config-hardcore": "47.0.1",
|
|
64
64
|
"eslint-formatter-github-annotations": "0.1.0",
|
|
65
|
-
"eslint-import-resolver-typescript": "4.3
|
|
65
|
+
"eslint-import-resolver-typescript": "4.4.3",
|
|
66
66
|
"eslint-plugin-etc": "2.0.3",
|
|
67
67
|
"eslint-plugin-file-progress": "3.0.2",
|
|
68
68
|
"eslint-plugin-import": "2.31.0",
|
|
69
|
-
"eslint-plugin-jest": "28.
|
|
69
|
+
"eslint-plugin-jest": "28.14.0",
|
|
70
70
|
"eslint-plugin-jest-dom": "5.5.0",
|
|
71
71
|
"eslint-plugin-no-explicit-type-exports": "0.12.1",
|
|
72
|
-
"eslint-plugin-prettier": "5.
|
|
72
|
+
"eslint-plugin-prettier": "5.4.1",
|
|
73
73
|
"eslint-plugin-unused-imports": "4.1.4",
|
|
74
74
|
"husky": "9.1.7",
|
|
75
|
-
"jest": "
|
|
75
|
+
"jest": "30.0.0",
|
|
76
76
|
"jest-retries": "1.0.1",
|
|
77
|
-
"node-mocks-http": "1.
|
|
77
|
+
"node-mocks-http": "1.17.2",
|
|
78
78
|
"rimraf": "6.0.1",
|
|
79
79
|
"stryker-cli": "1.0.2",
|
|
80
|
-
"supertest": "7.1.
|
|
80
|
+
"supertest": "7.1.1",
|
|
81
81
|
"using-temporary-files": "2.2.1"
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
|
-
"@apidevtools/json-schema-ref-parser": "
|
|
84
|
+
"@apidevtools/json-schema-ref-parser": "13.0.5",
|
|
85
85
|
"@hapi/accept": "6.0.3",
|
|
86
86
|
"@types/json-schema": "7.0.15",
|
|
87
87
|
"ast-types": "0.14.2",
|
|
88
88
|
"chokidar": "4.0.3",
|
|
89
|
-
"commander": "
|
|
90
|
-
"debug": "4.4.
|
|
89
|
+
"commander": "14.0.0",
|
|
90
|
+
"debug": "4.4.1",
|
|
91
91
|
"fetch": "1.1.0",
|
|
92
92
|
"fs-extra": "11.3.0",
|
|
93
93
|
"handlebars": "4.7.8",
|
|
@@ -95,17 +95,18 @@
|
|
|
95
95
|
"js-yaml": "4.1.0",
|
|
96
96
|
"json-schema-faker": "0.5.9",
|
|
97
97
|
"jsonwebtoken": "9.0.2",
|
|
98
|
-
"koa": "
|
|
98
|
+
"koa": "3.0.0",
|
|
99
99
|
"koa-bodyparser": "4.4.1",
|
|
100
100
|
"koa-proxies": "0.12.4",
|
|
101
101
|
"koa2-swagger-ui": "5.11.0",
|
|
102
102
|
"lodash": "4.17.21",
|
|
103
103
|
"node-fetch": "3.3.2",
|
|
104
|
-
"open": "10.1.
|
|
104
|
+
"open": "10.1.2",
|
|
105
105
|
"patch-package": "8.0.0",
|
|
106
106
|
"precinct": "12.2.0",
|
|
107
107
|
"prettier": "3.5.3",
|
|
108
108
|
"recast": "0.23.11",
|
|
109
109
|
"typescript": "5.8.3"
|
|
110
|
-
}
|
|
110
|
+
},
|
|
111
|
+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
111
112
|
}
|