counterfact 1.0.1 → 1.0.2
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 +2 -8
- package/dist/app.js +0 -4
- package/dist/migrate/paths-to-routes.js +0 -3
- package/dist/repl/repl.js +0 -3
- package/dist/server/context-registry.js +0 -4
- package/dist/server/convert-js-extensions-to-cjs.js +1 -2
- package/dist/server/create-koa-app.js +0 -2
- package/dist/server/determine-module-kind.js +1 -2
- package/dist/server/dispatcher.js +1 -8
- package/dist/server/json-to-xml.js +0 -4
- package/dist/server/koa-middleware.js +0 -8
- package/dist/server/module-dependency-graph.js +0 -2
- package/dist/server/module-loader.js +3 -10
- package/dist/server/module-tree.js +0 -6
- package/dist/server/openapi-middleware.js +0 -3
- package/dist/server/page-middleware.js +0 -2
- package/dist/server/registry.js +1 -3
- package/dist/server/response-builder.js +1 -5
- package/dist/server/tools.js +0 -1
- package/dist/server/transpiler.js +1 -7
- package/dist/server/types.ts +11 -15
- package/dist/server/uncached-import.js +0 -1
- package/dist/server/uncached-require.cjs +1 -1
- package/dist/typescript-generator/code-generator.js +1 -3
- package/dist/typescript-generator/generate.js +1 -1
- package/dist/typescript-generator/operation-coder.js +0 -1
- package/dist/typescript-generator/operation-type-coder.js +4 -5
- package/dist/typescript-generator/repository.js +1 -3
- package/dist/typescript-generator/requirement.js +0 -4
- package/dist/typescript-generator/schema-type-coder.js +0 -1
- package/dist/typescript-generator/script.js +0 -4
- package/dist/typescript-generator/specification.js +1 -4
- package/dist/util/read-file.js +0 -1
- package/dist/util/wait-for-event.js +0 -1
- package/package.json +22 -21
package/bin/counterfact.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/* eslint-disable complexity */
|
|
3
2
|
|
|
4
3
|
import fs from "node:fs";
|
|
5
4
|
import { readFile } from "node:fs/promises";
|
|
@@ -19,7 +18,7 @@ if (Number.parseInt(process.versions.node.split("."), 10) < MIN_NODE_VERSION) {
|
|
|
19
18
|
process.stdout.write(
|
|
20
19
|
`Counterfact works with Node version ${MIN_NODE_VERSION}+. You are running version ${process.version}`,
|
|
21
20
|
);
|
|
22
|
-
|
|
21
|
+
|
|
23
22
|
process.exit(1);
|
|
24
23
|
}
|
|
25
24
|
|
|
@@ -46,7 +45,6 @@ function padTagLine(tagLine) {
|
|
|
46
45
|
return `${padding}${tagLine}`;
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
// eslint-disable-next-line max-statements
|
|
50
48
|
function createWatchMessage(config) {
|
|
51
49
|
let watchMessage = "";
|
|
52
50
|
|
|
@@ -98,13 +96,10 @@ function createWatchMessage(config) {
|
|
|
98
96
|
|
|
99
97
|
return watchMessage;
|
|
100
98
|
}
|
|
101
|
-
|
|
102
|
-
// eslint-disable-next-line max-statements, sonarjs/cognitive-complexity
|
|
103
99
|
async function main(source, destination) {
|
|
104
100
|
debug("executing the main function");
|
|
105
101
|
|
|
106
102
|
const options = program.opts();
|
|
107
|
-
// eslint-disable-next-line sonar/process-argv
|
|
108
103
|
const args = process.argv;
|
|
109
104
|
|
|
110
105
|
const destinationPath = nodePath
|
|
@@ -193,7 +188,7 @@ async function main(source, destination) {
|
|
|
193
188
|
|
|
194
189
|
const introduction = [
|
|
195
190
|
"____ ____ _ _ _ _ ___ ____ ____ ____ ____ ____ ___",
|
|
196
|
-
|
|
191
|
+
String.raw`|___ [__] |__| |\| | |=== |--< |--- |--| |___ | `,
|
|
197
192
|
padTagLine(taglines[Math.floor(Math.random() * taglines.length)]),
|
|
198
193
|
"",
|
|
199
194
|
`| API Base URL ==> ${url}`,
|
|
@@ -270,5 +265,4 @@ program
|
|
|
270
265
|
"",
|
|
271
266
|
)
|
|
272
267
|
.action(main)
|
|
273
|
-
// eslint-disable-next-line sonar/process-argv
|
|
274
268
|
.parse(process.argv);
|
package/dist/app.js
CHANGED
|
@@ -17,14 +17,12 @@ async function loadOpenApiDocument(source) {
|
|
|
17
17
|
try {
|
|
18
18
|
const text = await readFile(source);
|
|
19
19
|
const openApiDocument = await yaml.load(text);
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-unnecessary-type-assertion
|
|
21
20
|
return (await dereference(openApiDocument));
|
|
22
21
|
}
|
|
23
22
|
catch {
|
|
24
23
|
return undefined;
|
|
25
24
|
}
|
|
26
25
|
}
|
|
27
|
-
// eslint-disable-next-line max-statements
|
|
28
26
|
export async function counterfact(config) {
|
|
29
27
|
const modulesPath = config.basePath;
|
|
30
28
|
const compiledPathsDirectory = nodePath
|
|
@@ -39,7 +37,6 @@ export async function counterfact(config) {
|
|
|
39
37
|
const moduleLoader = new ModuleLoader(compiledPathsDirectory, registry, contextRegistry);
|
|
40
38
|
const middleware = koaMiddleware(dispatcher, config);
|
|
41
39
|
const koaApp = createKoaApp(registry, middleware, config);
|
|
42
|
-
// eslint-disable-next-line max-statements
|
|
43
40
|
async function start(options) {
|
|
44
41
|
const { generate, startRepl: shouldStartRepl, startServer, watch, } = options;
|
|
45
42
|
if (generate.routes || generate.types) {
|
|
@@ -48,7 +45,6 @@ export async function counterfact(config) {
|
|
|
48
45
|
if (watch.routes || watch.types) {
|
|
49
46
|
await codeGenerator.watch();
|
|
50
47
|
}
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
52
48
|
let httpTerminator;
|
|
53
49
|
if (startServer) {
|
|
54
50
|
await transpiler.watch();
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
/* eslint-disable no-await-in-loop */
|
|
2
|
-
/* eslint-disable no-console */
|
|
3
1
|
import { promises as fs } from "node:fs";
|
|
4
2
|
import path from "node:path";
|
|
5
|
-
// eslint-disable-next-line max-statements
|
|
6
3
|
async function copyAndModifyFiles(sourceDirectory, destinationDirectory) {
|
|
7
4
|
try {
|
|
8
5
|
const entries = await fs.readdir(sourceDirectory, { withFileTypes: true });
|
package/dist/repl/repl.js
CHANGED
|
@@ -3,7 +3,6 @@ function printToStdout(line) {
|
|
|
3
3
|
process.stdout.write(`${line}\n`);
|
|
4
4
|
}
|
|
5
5
|
export function startRepl(contextRegistry, config, print = printToStdout) {
|
|
6
|
-
// eslint-disable-next-line max-statements
|
|
7
6
|
function printProxyStatus() {
|
|
8
7
|
if (config.proxyUrl === "") {
|
|
9
8
|
print("The proxy URL is not set.");
|
|
@@ -17,7 +16,6 @@ export function startRepl(contextRegistry, config, print = printToStdout) {
|
|
|
17
16
|
print("Paths prefixed with [+] will be proxied.");
|
|
18
17
|
print("Paths prefixed with [-] will not be proxied.");
|
|
19
18
|
print("");
|
|
20
|
-
// eslint-disable-next-line array-func/prefer-array-from
|
|
21
19
|
const entries = [...config.proxyPaths.entries()].sort(([path1], [path2]) => path1 < path2 ? -1 : 1);
|
|
22
20
|
for (const [path, state] of entries) {
|
|
23
21
|
print(`${state ? "[+]" : "[-]"} ${path}/`);
|
|
@@ -81,7 +79,6 @@ export function startRepl(contextRegistry, config, print = printToStdout) {
|
|
|
81
79
|
help: 'proxy configuration (".proxy help" for details)',
|
|
82
80
|
});
|
|
83
81
|
replServer.context.loadContext = (path) => contextRegistry.find(path);
|
|
84
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
|
|
85
82
|
replServer.context.context = replServer.context.loadContext("/");
|
|
86
83
|
return replServer;
|
|
87
84
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
/* eslint-disable max-classes-per-file */
|
|
2
|
-
/* eslint-disable max-statements */
|
|
3
1
|
import cloneDeep from "lodash/cloneDeep.js";
|
|
4
2
|
export class Context {
|
|
5
|
-
// eslint-disable-next-line @typescript-eslint/no-useless-constructor, @typescript-eslint/no-empty-function
|
|
6
3
|
constructor() { }
|
|
7
4
|
}
|
|
8
5
|
export function parentPath(path) {
|
|
@@ -47,7 +44,6 @@ export class ContextRegistry {
|
|
|
47
44
|
context[property] = updatedContext[property];
|
|
48
45
|
}
|
|
49
46
|
}
|
|
50
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
51
47
|
Object.setPrototypeOf(context, Object.getPrototypeOf(updatedContext));
|
|
52
48
|
this.cache.set(path, cloneDeep(updatedContext));
|
|
53
49
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { namedTypes, visit } from "ast-types";
|
|
2
2
|
import { parse, print } from "recast";
|
|
3
3
|
export function convertFileExtensionsToCjs(code) {
|
|
4
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
5
4
|
const ast = parse(code);
|
|
6
5
|
// Visit the nodes in the AST looking for `require` calls
|
|
7
6
|
visit(ast, {
|
|
@@ -18,7 +17,7 @@ export function convertFileExtensionsToCjs(code) {
|
|
|
18
17
|
node.arguments[0].value.startsWith(".")) {
|
|
19
18
|
// Change the module string from "foo.js" to "foo.cjs"
|
|
20
19
|
node.arguments[0].value = node.arguments[0].value.replace(
|
|
21
|
-
// eslint-disable-next-line
|
|
20
|
+
// eslint-disable-next-line regexp/prefer-named-capture-group
|
|
22
21
|
/(\.js|\.ts)?$/u, ".cjs");
|
|
23
22
|
}
|
|
24
23
|
// Continue traversing the AST
|
|
@@ -6,7 +6,6 @@ import { koaSwagger } from "koa2-swagger-ui";
|
|
|
6
6
|
import { openapiMiddleware } from "./openapi-middleware.js";
|
|
7
7
|
import { pageMiddleware } from "./page-middleware.js";
|
|
8
8
|
const debug = createDebug("counterfact:server:create-koa-app");
|
|
9
|
-
// eslint-disable-next-line max-statements
|
|
10
9
|
export function createKoaApp(registry, koaMiddleware, config) {
|
|
11
10
|
const app = new Koa();
|
|
12
11
|
app.use(openapiMiddleware(config.openApiPath, `//localhost:${config.port}${config.routePrefix}`));
|
|
@@ -34,7 +33,6 @@ export function createKoaApp(registry, koaMiddleware, config) {
|
|
|
34
33
|
ctx.redirect("/counterfact/");
|
|
35
34
|
return;
|
|
36
35
|
}
|
|
37
|
-
// eslint-disable-next-line n/callback-return
|
|
38
36
|
await next();
|
|
39
37
|
});
|
|
40
38
|
app.use(pageMiddleware("/counterfact/rapidoc", "rapi-doc", {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
/* eslint-disable n/no-sync */
|
|
1
2
|
import { existsSync } from "node:fs";
|
|
2
3
|
import fs from "node:fs/promises";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
const DEFAULT_MODULE_KIND = "commonjs";
|
|
5
|
-
// eslint-disable-next-line max-statements
|
|
6
6
|
export async function determineModuleKind(modulePath) {
|
|
7
7
|
if (modulePath.endsWith(".cjs")) {
|
|
8
8
|
return "commonjs";
|
|
@@ -16,7 +16,6 @@ export async function determineModuleKind(modulePath) {
|
|
|
16
16
|
const packageJsonPath = path.join(modulePath, "package.json");
|
|
17
17
|
if (existsSync(packageJsonPath)) {
|
|
18
18
|
try {
|
|
19
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
20
19
|
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
|
|
21
20
|
if (typeof packageJson.type !== "string") {
|
|
22
21
|
return DEFAULT_MODULE_KIND;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
/* eslint-disable import/newline-after-import */
|
|
2
1
|
import { mediaTypes } from "@hapi/accept";
|
|
3
2
|
import createDebugger from "debug";
|
|
4
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
5
3
|
import fetch, { Headers } from "node-fetch";
|
|
6
4
|
import { createResponseBuilder } from "./response-builder.js";
|
|
7
5
|
import { Tools } from "./tools.js";
|
|
@@ -43,9 +41,7 @@ export class Dispatcher {
|
|
|
43
41
|
if (this.openApiDocument) {
|
|
44
42
|
for (const key in this.openApiDocument.paths) {
|
|
45
43
|
if (key.toLowerCase() === path.toLowerCase()) {
|
|
46
|
-
return this.openApiDocument.paths[key]?.[
|
|
47
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
48
|
-
method.toLowerCase()];
|
|
44
|
+
return this.openApiDocument.paths[key]?.[method.toLowerCase()];
|
|
49
45
|
}
|
|
50
46
|
}
|
|
51
47
|
}
|
|
@@ -84,7 +80,6 @@ export class Dispatcher {
|
|
|
84
80
|
}
|
|
85
81
|
const normalizedResponse = {
|
|
86
82
|
...response,
|
|
87
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
88
83
|
body: content.body,
|
|
89
84
|
contentType: content.type,
|
|
90
85
|
};
|
|
@@ -120,13 +115,11 @@ export class Dispatcher {
|
|
|
120
115
|
}
|
|
121
116
|
return false;
|
|
122
117
|
}
|
|
123
|
-
// eslint-disable-next-line sonarjs/cognitive-complexity, max-statements
|
|
124
118
|
async request({ auth, body, headers = {}, method, path, query, req, }) {
|
|
125
119
|
debug(`request: ${method} ${path}`);
|
|
126
120
|
// If the incoming path includes the base path, remove it
|
|
127
121
|
if (this.openApiDocument?.basePath !== undefined &&
|
|
128
122
|
path.toLowerCase().startsWith(this.openApiDocument.basePath.toLowerCase())) {
|
|
129
|
-
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
130
123
|
path = path.replace(new RegExp(this.openApiDocument.basePath, "iu"), "");
|
|
131
124
|
}
|
|
132
125
|
const { matchedPath } = this.registry.handler(path);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
function xmlEscape(xmlString) {
|
|
2
|
-
// eslint-disable-next-line unicorn/prefer-string-replace-all
|
|
3
2
|
return xmlString.replace(/["&'<>]/gu, (character) => {
|
|
4
3
|
switch (character) {
|
|
5
4
|
case "<": {
|
|
@@ -28,12 +27,10 @@ function objectToXml(json, schema, name) {
|
|
|
28
27
|
const attributes = [];
|
|
29
28
|
Object.entries(json).forEach(([key, value]) => {
|
|
30
29
|
const properties = schema?.properties?.[key];
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
32
30
|
if (properties?.attribute) {
|
|
33
31
|
attributes.push(` ${key}="${xmlEscape(String(value))}"`);
|
|
34
32
|
}
|
|
35
33
|
else {
|
|
36
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
37
34
|
xml.push(jsonToXml(value, properties, key));
|
|
38
35
|
}
|
|
39
36
|
});
|
|
@@ -45,7 +42,6 @@ export function jsonToXml(json, schema, keyName = "root") {
|
|
|
45
42
|
const items = json
|
|
46
43
|
.map((item) => jsonToXml(item, schema?.items, name))
|
|
47
44
|
.join("");
|
|
48
|
-
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
49
45
|
if (schema?.xml?.wrapped) {
|
|
50
46
|
return `<${name}>${items}</${name}>`;
|
|
51
47
|
}
|
|
@@ -25,23 +25,18 @@ function getAuthObject(ctx) {
|
|
|
25
25
|
return { password, username };
|
|
26
26
|
}
|
|
27
27
|
export function koaMiddleware(dispatcher, config, proxy = koaProxy) {
|
|
28
|
-
// eslint-disable-next-line max-statements
|
|
29
28
|
return async function middleware(ctx, next) {
|
|
30
29
|
const { proxyUrl, routePrefix } = config;
|
|
31
30
|
debug("middleware running for path: %s", ctx.request.path);
|
|
32
31
|
debug("routePrefix: %s", routePrefix);
|
|
33
32
|
if (!ctx.request.path.startsWith(routePrefix)) {
|
|
34
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
35
33
|
return await next();
|
|
36
34
|
}
|
|
37
35
|
const auth = getAuthObject(ctx);
|
|
38
|
-
/* @ts-expect-error the body comes from koa-bodyparser, not sure how to fix this */
|
|
39
36
|
const { body, headers, query } = ctx.request;
|
|
40
37
|
const path = ctx.request.path.slice(routePrefix.length);
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
42
38
|
const method = ctx.request.method;
|
|
43
39
|
if (isProxyEnabledForPath(path, config) && proxyUrl) {
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
45
40
|
return proxy("/", { changeOrigin: true, target: proxyUrl })(ctx, next);
|
|
46
41
|
}
|
|
47
42
|
addCors(ctx, headers);
|
|
@@ -51,7 +46,6 @@ export function koaMiddleware(dispatcher, config, proxy = koaProxy) {
|
|
|
51
46
|
}
|
|
52
47
|
const response = await dispatcher.request({
|
|
53
48
|
auth,
|
|
54
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
55
49
|
body,
|
|
56
50
|
/* @ts-expect-error the value of a header can be an array and we don't have a solution for that yet */
|
|
57
51
|
headers,
|
|
@@ -61,7 +55,6 @@ export function koaMiddleware(dispatcher, config, proxy = koaProxy) {
|
|
|
61
55
|
query,
|
|
62
56
|
req: { path: "", ...ctx.req },
|
|
63
57
|
});
|
|
64
|
-
/* eslint-disable require-atomic-updates */
|
|
65
58
|
ctx.body = response.body;
|
|
66
59
|
if (response.headers) {
|
|
67
60
|
for (const [key, value] of Object.entries(response.headers)) {
|
|
@@ -69,7 +62,6 @@ export function koaMiddleware(dispatcher, config, proxy = koaProxy) {
|
|
|
69
62
|
}
|
|
70
63
|
}
|
|
71
64
|
ctx.status = response.status ?? HTTP_STATUS_CODE_OK;
|
|
72
|
-
/* eslint-enable require-atomic-updates */
|
|
73
65
|
return undefined;
|
|
74
66
|
};
|
|
75
67
|
}
|
|
@@ -4,7 +4,6 @@ export class ModuleDependencyGraph {
|
|
|
4
4
|
dependents = new Map();
|
|
5
5
|
loadDependencies(path) {
|
|
6
6
|
try {
|
|
7
|
-
// eslint-disable-next-line import/no-named-as-default-member
|
|
8
7
|
return precinct.paperwork(path);
|
|
9
8
|
}
|
|
10
9
|
catch {
|
|
@@ -29,7 +28,6 @@ export class ModuleDependencyGraph {
|
|
|
29
28
|
this.dependents.get(key)?.add(path);
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
|
-
// eslint-disable-next-line max-statements, sonarjs/cognitive-complexity
|
|
33
31
|
dependentsOf(path) {
|
|
34
32
|
const marked = new Set();
|
|
35
33
|
const dependents = new Set();
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable n/no-sync */
|
|
1
2
|
import { once } from "node:events";
|
|
2
3
|
import { existsSync } from "node:fs";
|
|
3
4
|
import fs from "node:fs/promises";
|
|
@@ -20,9 +21,7 @@ export class ModuleLoader extends EventTarget {
|
|
|
20
21
|
watcher;
|
|
21
22
|
contextRegistry;
|
|
22
23
|
dependencyGraph = new ModuleDependencyGraph();
|
|
23
|
-
uncachedImport =
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
25
|
-
async function (moduleName) {
|
|
24
|
+
uncachedImport = async function (moduleName) {
|
|
26
25
|
throw new Error(`uncachedImport not set up; importing ${moduleName}`);
|
|
27
26
|
};
|
|
28
27
|
constructor(basePath, registry, contextRegistry = new ContextRegistry()) {
|
|
@@ -32,9 +31,7 @@ export class ModuleLoader extends EventTarget {
|
|
|
32
31
|
this.contextRegistry = contextRegistry;
|
|
33
32
|
}
|
|
34
33
|
async watch() {
|
|
35
|
-
this.watcher = watch(`${this.basePath}/**/*.{js,mjs,ts,mts,cjs,cts}`, CHOKIDAR_OPTIONS).on("all",
|
|
36
|
-
// eslint-disable-next-line max-statements
|
|
37
|
-
(eventName, pathNameOriginal) => {
|
|
34
|
+
this.watcher = watch(`${this.basePath}/**/*.{js,mjs,ts,mts,cjs,cts}`, CHOKIDAR_OPTIONS).on("all", (eventName, pathNameOriginal) => {
|
|
38
35
|
const pathName = pathNameOriginal.replaceAll("\\", "/");
|
|
39
36
|
if (pathName.includes("$.context") && eventName === "add") {
|
|
40
37
|
process.stdout.write(`\n\n!!! The file at ${pathName} needs a minor update.\n See https://github.com/pmcelhaney/counterfact/blob/main/docs/context-change.md\n\n\n`);
|
|
@@ -85,7 +82,6 @@ export class ModuleLoader extends EventTarget {
|
|
|
85
82
|
});
|
|
86
83
|
await Promise.all(imports);
|
|
87
84
|
}
|
|
88
|
-
// eslint-disable-next-line max-statements
|
|
89
85
|
async loadEndpoint(pathName) {
|
|
90
86
|
debug("importing module: %s", pathName);
|
|
91
87
|
const directory = dirname(pathName.slice(this.basePath.length)).replaceAll("\\", "/");
|
|
@@ -97,7 +93,6 @@ export class ModuleLoader extends EventTarget {
|
|
|
97
93
|
const doImport = (await determineModuleKind(pathName)) === "commonjs"
|
|
98
94
|
? uncachedRequire
|
|
99
95
|
: uncachedImport;
|
|
100
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
101
96
|
const endpoint = (await doImport(pathName));
|
|
102
97
|
this.dispatchEvent(new Event("add"));
|
|
103
98
|
if (basename(pathName).startsWith("_.context")) {
|
|
@@ -105,14 +100,12 @@ export class ModuleLoader extends EventTarget {
|
|
|
105
100
|
const loadContext = (path) => this.contextRegistry.find(path);
|
|
106
101
|
this.contextRegistry.update(directory,
|
|
107
102
|
// @ts-expect-error TS says Context has no constructable signatures but that's not true?
|
|
108
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
109
103
|
new endpoint.Context({
|
|
110
104
|
loadContext,
|
|
111
105
|
}));
|
|
112
106
|
}
|
|
113
107
|
}
|
|
114
108
|
else {
|
|
115
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
116
109
|
this.registry.add(url, endpoint);
|
|
117
110
|
}
|
|
118
111
|
}
|
|
@@ -26,7 +26,6 @@ export class ModuleTree {
|
|
|
26
26
|
};
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
30
29
|
directory.directories[segment.toLowerCase()] ??= {
|
|
31
30
|
directories: {},
|
|
32
31
|
files: {},
|
|
@@ -48,7 +47,6 @@ export class ModuleTree {
|
|
|
48
47
|
return;
|
|
49
48
|
}
|
|
50
49
|
if (remainingSegments.length === 0) {
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
52
50
|
delete directory.files[segment.toLowerCase()];
|
|
53
51
|
return;
|
|
54
52
|
}
|
|
@@ -58,7 +56,6 @@ export class ModuleTree {
|
|
|
58
56
|
const segments = url.split("/").slice(1);
|
|
59
57
|
this.removeModuleFromDirectory(this.root, segments);
|
|
60
58
|
}
|
|
61
|
-
// eslint-disable-next-line max-params
|
|
62
59
|
buildMatch(directory, segment, pathVariables, matchedPath) {
|
|
63
60
|
const match = directory.files[segment.toLowerCase()] ??
|
|
64
61
|
Object.values(directory.files).find((file) => file.isWildcard);
|
|
@@ -81,7 +78,6 @@ export class ModuleTree {
|
|
|
81
78
|
pathVariables,
|
|
82
79
|
};
|
|
83
80
|
}
|
|
84
|
-
// eslint-disable-next-line max-statements, max-params
|
|
85
81
|
matchWithinDirectory(directory, segments, pathVariables, matchedPath) {
|
|
86
82
|
if (segments.length === 0) {
|
|
87
83
|
return undefined;
|
|
@@ -124,12 +120,10 @@ export class ModuleTree {
|
|
|
124
120
|
});
|
|
125
121
|
});
|
|
126
122
|
}
|
|
127
|
-
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
128
123
|
function stripBrackets(string) {
|
|
129
124
|
return string.replaceAll(/\{|\}/gu, "");
|
|
130
125
|
}
|
|
131
126
|
traverse(this.root, "");
|
|
132
|
-
// eslint-disable-next-line etc/no-assign-mutated-array
|
|
133
127
|
return routes.sort((first, second) => stripBrackets(first.path).localeCompare(stripBrackets(second.path)));
|
|
134
128
|
}
|
|
135
129
|
}
|
|
@@ -3,7 +3,6 @@ import { readFile } from "../util/read-file.js";
|
|
|
3
3
|
export function openapiMiddleware(openApiPath, url) {
|
|
4
4
|
return async (ctx, next) => {
|
|
5
5
|
if (ctx.URL.pathname === "/counterfact/openapi") {
|
|
6
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
7
6
|
const openApiDocument = (await yaml.load(await readFile(openApiPath)));
|
|
8
7
|
openApiDocument.servers ??= [];
|
|
9
8
|
openApiDocument.servers.unshift({
|
|
@@ -12,11 +11,9 @@ export function openapiMiddleware(openApiPath, url) {
|
|
|
12
11
|
});
|
|
13
12
|
// OpenApi 2 support:
|
|
14
13
|
openApiDocument.host = url;
|
|
15
|
-
// eslint-disable-next-line require-atomic-updates
|
|
16
14
|
ctx.body = yaml.dump(openApiDocument);
|
|
17
15
|
return;
|
|
18
16
|
}
|
|
19
|
-
// eslint-disable-next-line n/callback-return
|
|
20
17
|
await next();
|
|
21
18
|
};
|
|
22
19
|
}
|
|
@@ -3,7 +3,6 @@ import { fileURLToPath } from "node:url";
|
|
|
3
3
|
import createDebug from "debug";
|
|
4
4
|
import Handlebars from "handlebars";
|
|
5
5
|
import { readFile } from "../util/read-file.js";
|
|
6
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
7
6
|
const __dirname = nodePath.dirname(fileURLToPath(import.meta.url));
|
|
8
7
|
const debug = createDebug("counterfact:server:page-middleware");
|
|
9
8
|
Handlebars.registerHelper("escape_route", (route) => route.replaceAll(/[^\w/]/gu, "-"));
|
|
@@ -19,7 +18,6 @@ export function pageMiddleware(pathname, templateName, locals) {
|
|
|
19
18
|
ctx.body = render(locals);
|
|
20
19
|
return;
|
|
21
20
|
}
|
|
22
|
-
// eslint-disable-next-line n/callback-return
|
|
23
21
|
await next();
|
|
24
22
|
};
|
|
25
23
|
}
|
package/dist/server/registry.js
CHANGED
|
@@ -6,8 +6,7 @@ function castParameters(parameters, parameterTypes) {
|
|
|
6
6
|
Object.entries(copy).forEach(([key, value]) => {
|
|
7
7
|
copy[key] =
|
|
8
8
|
parameterTypes?.[key] === "number"
|
|
9
|
-
?
|
|
10
|
-
Number.parseInt(value, 10)
|
|
9
|
+
? Number.parseInt(value, 10)
|
|
11
10
|
: value;
|
|
12
11
|
});
|
|
13
12
|
return copy;
|
|
@@ -54,7 +53,6 @@ export class Registry {
|
|
|
54
53
|
path: castParameters(handler.path, parameterTypes.path),
|
|
55
54
|
query: castParameters(requestData.query, parameterTypes.query),
|
|
56
55
|
};
|
|
57
|
-
// eslint-disable-next-line id-length
|
|
58
56
|
operationArgument.x = operationArgument;
|
|
59
57
|
return await execute(operationArgument);
|
|
60
58
|
};
|
|
@@ -29,9 +29,7 @@ function unknownStatusCodeResponse(statusCode) {
|
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
export function createResponseBuilder(operation) {
|
|
32
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
33
32
|
return new Proxy({}, {
|
|
34
|
-
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
35
33
|
get: (target, statusCode) => ({
|
|
36
34
|
header(name, value) {
|
|
37
35
|
return {
|
|
@@ -78,9 +76,7 @@ export function createResponseBuilder(operation) {
|
|
|
78
76
|
...this,
|
|
79
77
|
content: Object.keys(content).map((type) => ({
|
|
80
78
|
body: convertToXmlIfNecessary(type, content[type]?.examples
|
|
81
|
-
? oneOf(
|
|
82
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
83
|
-
Object.values(content[type]?.examples ?? []).map((example) => example.value))
|
|
79
|
+
? oneOf(Object.values(content[type]?.examples ?? []).map((example) => example.value))
|
|
84
80
|
: JSONSchemaFaker.generate(content[type]?.schema ?? { type: "object" }), content[type]?.schema),
|
|
85
81
|
type,
|
|
86
82
|
})),
|
package/dist/server/tools.js
CHANGED
|
@@ -31,9 +31,7 @@ export class Transpiler extends EventTarget {
|
|
|
31
31
|
ignoreInitial: false,
|
|
32
32
|
});
|
|
33
33
|
const transpiles = [];
|
|
34
|
-
this.watcher.on("all",
|
|
35
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises, max-statements
|
|
36
|
-
async (eventName, sourcePathOriginal) => {
|
|
34
|
+
this.watcher.on("all", async (eventName, sourcePathOriginal) => {
|
|
37
35
|
debug("transpiler event: %s <%s>", eventName, sourcePathOriginal);
|
|
38
36
|
const sourcePath = sourcePathOriginal.replaceAll("\\", "/");
|
|
39
37
|
const destinationPath = sourcePath
|
|
@@ -48,7 +46,6 @@ export class Transpiler extends EventTarget {
|
|
|
48
46
|
await fs.rm(destinationPath);
|
|
49
47
|
}
|
|
50
48
|
catch (error) {
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
52
49
|
if (error.code !== "ENOENT") {
|
|
53
50
|
debug("error removing %s: %o", destinationPath, error);
|
|
54
51
|
this.dispatchEvent(new Event("error"));
|
|
@@ -64,18 +61,15 @@ export class Transpiler extends EventTarget {
|
|
|
64
61
|
async stopWatching() {
|
|
65
62
|
await this.watcher?.close();
|
|
66
63
|
}
|
|
67
|
-
// eslint-disable-next-line max-statements
|
|
68
64
|
async transpileFile(eventName, sourcePath, destinationPath) {
|
|
69
65
|
ensureDirectoryExists(destinationPath);
|
|
70
66
|
const source = await fs.readFile(sourcePath, "utf8");
|
|
71
|
-
/* eslint-disable import/no-named-as-default-member */
|
|
72
67
|
const result = ts.transpileModule(source, {
|
|
73
68
|
compilerOptions: {
|
|
74
69
|
module: ts.ModuleKind[this.moduleKind.toLowerCase() === "module" ? "ES2022" : "CommonJS"],
|
|
75
70
|
target: ts.ScriptTarget.ES2015,
|
|
76
71
|
},
|
|
77
72
|
}).outputText;
|
|
78
|
-
/* eslint-enable import/no-named-as-default-member */
|
|
79
73
|
const fullDestination = nodePath
|
|
80
74
|
.join(sourcePath
|
|
81
75
|
.replace(this.sourcePath, this.destinationPath)
|
package/dist/server/types.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
/* eslint-disable etc/no-t */
|
|
3
1
|
interface OpenApiHeader {
|
|
4
2
|
schema: unknown;
|
|
5
3
|
}
|
|
@@ -52,8 +50,8 @@ type IfHasKey<SomeObject, Keys extends (keyof any)[], Yes, No> = Keys extends [
|
|
|
52
50
|
? FirstKey extends keyof SomeObject
|
|
53
51
|
? Yes
|
|
54
52
|
: RestKeys extends (keyof any)[]
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
? IfHasKey<SomeObject, RestKeys, Yes, No>
|
|
54
|
+
: No
|
|
57
55
|
: No;
|
|
58
56
|
|
|
59
57
|
type SchemasOf<T extends { [key: string]: { schema: any } }> = {
|
|
@@ -74,7 +72,6 @@ type MaybeShortcut<
|
|
|
74
72
|
never
|
|
75
73
|
>;
|
|
76
74
|
|
|
77
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
78
75
|
type NeverIfEmpty<Record> = {} extends Record ? never : Record;
|
|
79
76
|
|
|
80
77
|
type MatchFunction<Response extends OpenApiResponse> = <
|
|
@@ -100,7 +97,6 @@ type HeaderFunction<Response extends OpenApiResponse> = <
|
|
|
100
97
|
}>;
|
|
101
98
|
|
|
102
99
|
type RandomFunction<Response extends OpenApiResponse> = <
|
|
103
|
-
// eslint-disable-next-line etc/no-misused-generics, unused-imports/no-unused-vars
|
|
104
100
|
Header extends string & keyof Response["headers"],
|
|
105
101
|
>() => COUNTERFACT_RESPONSE;
|
|
106
102
|
|
|
@@ -148,15 +144,15 @@ type GenericResponseBuilderInner<
|
|
|
148
144
|
|
|
149
145
|
type GenericResponseBuilder<
|
|
150
146
|
Response extends OpenApiResponse = OpenApiResponse,
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
147
|
+
> =
|
|
148
|
+
object extends OmitValueWhenNever<Response>
|
|
149
|
+
? COUNTERFACT_RESPONSE
|
|
150
|
+
: keyof OmitValueWhenNever<Response> extends "headers"
|
|
151
|
+
? {
|
|
152
|
+
ALL_REMAINING_HEADERS_ARE_OPTIONAL: COUNTERFACT_RESPONSE;
|
|
153
|
+
header: HeaderFunction<Response>;
|
|
154
|
+
}
|
|
155
|
+
: GenericResponseBuilderInner<Response>;
|
|
160
156
|
|
|
161
157
|
type ResponseBuilderFactory<
|
|
162
158
|
Responses extends OpenApiResponses = OpenApiResponses,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { pathToFileURL } from "node:url";
|
|
2
2
|
export async function uncachedImport(pathName) {
|
|
3
3
|
const fileUrl = `${pathToFileURL(pathName).toString()}?cacheBust=${Date.now()}`;
|
|
4
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, import/no-dynamic-require, no-unsanitized/method
|
|
5
4
|
return await import(fileUrl);
|
|
6
5
|
}
|
|
@@ -4,7 +4,7 @@ module.exports = {
|
|
|
4
4
|
uncachedRequire: function uncachedRequire(moduleName) {
|
|
5
5
|
delete require.cache[require.resolve(moduleName)];
|
|
6
6
|
|
|
7
|
-
// eslint-disable-next-line
|
|
7
|
+
// eslint-disable-next-line security/detect-non-literal-require
|
|
8
8
|
return Promise.resolve(require(moduleName));
|
|
9
9
|
},
|
|
10
10
|
};
|
|
@@ -21,9 +21,7 @@ export class CodeGenerator extends EventTarget {
|
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
this.watcher = watch(this.openapiPath, CHOKIDAR_OPTIONS).on("change", () => {
|
|
24
|
-
void generate(this.openapiPath, this.destination, this.generateOptions)
|
|
25
|
-
// eslint-disable-next-line promise/prefer-await-to-then
|
|
26
|
-
.then(() => {
|
|
24
|
+
void generate(this.openapiPath, this.destination, this.generateOptions).then(() => {
|
|
27
25
|
this.dispatchEvent(new Event("generate"));
|
|
28
26
|
return true;
|
|
29
27
|
}, () => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable n/no-sync */
|
|
1
2
|
import { existsSync } from "node:fs";
|
|
2
3
|
import fs from "node:fs/promises";
|
|
3
4
|
import nodePath from "node:path";
|
|
@@ -29,7 +30,6 @@ async function getPathsFromSpecification(specification) {
|
|
|
29
30
|
return new Set();
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
|
-
// eslint-disable-next-line max-statements, max-params
|
|
33
33
|
export async function generate(source, destination, generateOptions, repository = new Repository()) {
|
|
34
34
|
debug("generating code from %s to %s", source, destination);
|
|
35
35
|
debug("initializing the .cache directory");
|
|
@@ -63,9 +63,7 @@ export class OperationTypeCoder extends TypeCoder {
|
|
|
63
63
|
}
|
|
64
64
|
return "never";
|
|
65
65
|
}
|
|
66
|
-
// eslint-disable-next-line max-statements
|
|
67
66
|
writeCode(script) {
|
|
68
|
-
// eslint-disable-next-line no-param-reassign
|
|
69
67
|
script.comments = READ_ONLY_COMMENTS;
|
|
70
68
|
const xType = script.importSharedType("WideOperationArgument");
|
|
71
69
|
script.importSharedType("OmitValueWhenNever");
|
|
@@ -75,10 +73,11 @@ export class OperationTypeCoder extends TypeCoder {
|
|
|
75
73
|
const queryType = new ParametersTypeCoder(parameters, "query").write(script);
|
|
76
74
|
const pathType = new ParametersTypeCoder(parameters, "path").write(script);
|
|
77
75
|
const headerType = new ParametersTypeCoder(parameters, "header").write(script);
|
|
78
|
-
const bodyRequirement = this.requirement.get("consumes")
|
|
76
|
+
const bodyRequirement = this.requirement.get("consumes") ||
|
|
77
|
+
this.requirement.specification?.rootRequirement?.get("consumes")
|
|
79
78
|
? parameters
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
?.find((parameter) => ["body", "formData"].includes(parameter.get("in").data))
|
|
80
|
+
?.get("schema")
|
|
82
81
|
: this.requirement.select("requestBody/content/application~1json/schema");
|
|
83
82
|
const bodyType = bodyRequirement === undefined
|
|
84
83
|
? "never"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* eslint-disable
|
|
1
|
+
/* eslint-disable n/no-sync */
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import nodePath, { dirname } from "node:path";
|
|
@@ -8,7 +8,6 @@ import { ensureDirectoryExists } from "../util/ensure-directory-exists.js";
|
|
|
8
8
|
import { CONTEXT_FILE_TOKEN } from "./context-file-token.js";
|
|
9
9
|
import { Script } from "./script.js";
|
|
10
10
|
const debug = createDebug("counterfact:server:repository");
|
|
11
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
12
11
|
const __dirname = dirname(fileURLToPath(import.meta.url)).replaceAll("\\", "/");
|
|
13
12
|
debug("dirname is %s", __dirname);
|
|
14
13
|
export class Repository {
|
|
@@ -29,7 +28,6 @@ export class Repository {
|
|
|
29
28
|
async finished() {
|
|
30
29
|
while (Array.from(this.scripts.values()).some((script) => script.isInProgress())) {
|
|
31
30
|
debug("waiting for %i scripts to finish", this.scripts.size);
|
|
32
|
-
// eslint-disable-next-line no-await-in-loop
|
|
33
31
|
await Promise.all(Array.from(this.scripts.values(), (script) => script.finished()));
|
|
34
32
|
}
|
|
35
33
|
}
|
|
@@ -37,19 +37,15 @@ export class Requirement {
|
|
|
37
37
|
}
|
|
38
38
|
map(callback) {
|
|
39
39
|
const result = [];
|
|
40
|
-
// eslint-disable-next-line array-callback-return
|
|
41
40
|
this.forEach((value, key) => result.push(callback(value, key)));
|
|
42
41
|
return result;
|
|
43
42
|
}
|
|
44
43
|
flatMap(callback) {
|
|
45
|
-
// eslint-disable-next-line unicorn/prefer-array-flat-map
|
|
46
44
|
return this.map(callback).flat();
|
|
47
45
|
}
|
|
48
46
|
find(callback) {
|
|
49
|
-
// eslint-disable-next-line init-declarations
|
|
50
47
|
let result;
|
|
51
48
|
this.forEach((value, key) => {
|
|
52
|
-
// eslint-disable-next-line n/callback-return
|
|
53
49
|
if (result === undefined && callback(value, key)) {
|
|
54
50
|
result = value;
|
|
55
51
|
}
|
|
@@ -45,18 +45,15 @@ export class Script {
|
|
|
45
45
|
};
|
|
46
46
|
exportStatement.promise = coder
|
|
47
47
|
.delegate()
|
|
48
|
-
// eslint-disable-next-line promise/prefer-await-to-then
|
|
49
48
|
.then((availableCoder) => {
|
|
50
49
|
exportStatement.name = name;
|
|
51
50
|
exportStatement.code = availableCoder.write(this);
|
|
52
51
|
return availableCoder;
|
|
53
52
|
})
|
|
54
|
-
// eslint-disable-next-line promise/prefer-await-to-then
|
|
55
53
|
.catch((error) => {
|
|
56
54
|
exportStatement.code = `{/* error creating export "${name}" for ${this.path}: ${error.stack} */}`;
|
|
57
55
|
exportStatement.error = error;
|
|
58
56
|
})
|
|
59
|
-
// eslint-disable-next-line promise/prefer-await-to-then
|
|
60
57
|
.finally(() => {
|
|
61
58
|
exportStatement.done = true;
|
|
62
59
|
});
|
|
@@ -66,7 +63,6 @@ export class Script {
|
|
|
66
63
|
exportDefault(coder, isType = false) {
|
|
67
64
|
this.export(coder, isType, true);
|
|
68
65
|
}
|
|
69
|
-
// eslint-disable-next-line max-statements
|
|
70
66
|
import(coder, isType = false, isDefault = false) {
|
|
71
67
|
debug("import coder: %s", coder.id);
|
|
72
68
|
const modulePath = coder.modulePath();
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
/* eslint-disable n/no-missing-import */
|
|
2
1
|
import nodePath from "node:path";
|
|
3
2
|
import createDebug from "debug";
|
|
4
3
|
import yaml from "js-yaml";
|
|
5
|
-
// eslint-disable-next-line import/no-unresolved
|
|
6
4
|
import { readFile } from "../util/read-file.js";
|
|
7
5
|
import { Requirement } from "./requirement.js";
|
|
8
6
|
const debug = createDebug("counterfact:typescript-generator:specification");
|
|
@@ -25,7 +23,7 @@ export class Specification {
|
|
|
25
23
|
const filePath = nodePath
|
|
26
24
|
.join(fromUrl.split("#").at(0), file)
|
|
27
25
|
.replaceAll("\\", "/")
|
|
28
|
-
// eslint-disable-next-line
|
|
26
|
+
// eslint-disable-next-line regexp/prefer-named-capture-group
|
|
29
27
|
.replace(/:\/([^/])/u, "://$1");
|
|
30
28
|
const fileUrl = filePath === "." ? this.rootUrl : filePath;
|
|
31
29
|
debug("reading specification at %s", fileUrl);
|
|
@@ -34,7 +32,6 @@ export class Specification {
|
|
|
34
32
|
const rootRequirement = new Requirement(data, `${fileUrl}#`, this);
|
|
35
33
|
return rootRequirement.select(path.slice(1));
|
|
36
34
|
}
|
|
37
|
-
// eslint-disable-next-line max-statements
|
|
38
35
|
async loadFile(urlOrPath) {
|
|
39
36
|
debug("loading file %s", urlOrPath);
|
|
40
37
|
if (this.cache.has(urlOrPath)) {
|
package/dist/util/read-file.js
CHANGED
|
@@ -6,7 +6,6 @@ export async function readFile(urlOrPath) {
|
|
|
6
6
|
return await response.text();
|
|
7
7
|
}
|
|
8
8
|
if (urlOrPath.startsWith("file")) {
|
|
9
|
-
// eslint-disable-next-line total-functions/no-partial-url-constructor
|
|
10
9
|
return await fs.readFile(new URL(urlOrPath), "utf8");
|
|
11
10
|
}
|
|
12
11
|
return await fs.readFile(urlOrPath, "utf8");
|
|
@@ -6,7 +6,6 @@ import { EventEmitter } from "node:events";
|
|
|
6
6
|
* @returns {Promise<Event>} A promise that resolves with the event object when the event is fired.
|
|
7
7
|
*/
|
|
8
8
|
export async function waitForEvent(target, eventName) {
|
|
9
|
-
// eslint-disable-next-line promise/avoid-new
|
|
10
9
|
return await new Promise((resolve) => {
|
|
11
10
|
const handler = (event) => {
|
|
12
11
|
if (target instanceof EventTarget) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "counterfact",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "a library for building a fake REST API for testing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/server/counterfact.js",
|
|
@@ -44,49 +44,50 @@
|
|
|
44
44
|
"postinstall": "patch-package"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@changesets/cli": "2.27.
|
|
48
|
-
"@stryker-mutator/core": "8.
|
|
49
|
-
"@stryker-mutator/jest-runner": "8.
|
|
50
|
-
"@stryker-mutator/typescript-checker": "8.
|
|
51
|
-
"@swc/core": "1.7.
|
|
47
|
+
"@changesets/cli": "2.27.8",
|
|
48
|
+
"@stryker-mutator/core": "8.5.0",
|
|
49
|
+
"@stryker-mutator/jest-runner": "8.5.0",
|
|
50
|
+
"@stryker-mutator/typescript-checker": "8.5.0",
|
|
51
|
+
"@swc/core": "1.7.26",
|
|
52
52
|
"@swc/jest": "0.2.36",
|
|
53
53
|
"@testing-library/dom": "10.4.0",
|
|
54
|
-
"@types/jest": "29.5.
|
|
54
|
+
"@types/jest": "29.5.13",
|
|
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.9",
|
|
61
61
|
"copyfiles": "2.4.1",
|
|
62
|
-
"eslint": "
|
|
63
|
-
"eslint-config-hardcore": "
|
|
62
|
+
"eslint": "9.11.1",
|
|
63
|
+
"eslint-config-hardcore": "47.0.1",
|
|
64
64
|
"eslint-formatter-github-annotations": "0.1.0",
|
|
65
|
-
"eslint-import-resolver-typescript": "3.6.
|
|
65
|
+
"eslint-import-resolver-typescript": "3.6.3",
|
|
66
66
|
"eslint-plugin-etc": "2.0.3",
|
|
67
|
-
"eslint-plugin-file-progress": "1.
|
|
68
|
-
"eslint-plugin-import": "2.
|
|
69
|
-
"eslint-plugin-jest": "28.
|
|
67
|
+
"eslint-plugin-file-progress": "1.5.0",
|
|
68
|
+
"eslint-plugin-import": "2.30.0",
|
|
69
|
+
"eslint-plugin-jest": "28.8.3",
|
|
70
70
|
"eslint-plugin-jest-dom": "5.4.0",
|
|
71
71
|
"eslint-plugin-no-explicit-type-exports": "0.12.1",
|
|
72
|
-
"eslint-plugin-
|
|
73
|
-
"
|
|
72
|
+
"eslint-plugin-prettier": "5.2.1",
|
|
73
|
+
"eslint-plugin-unused-imports": "4.1.4",
|
|
74
|
+
"husky": "9.1.6",
|
|
74
75
|
"jest": "29.7.0",
|
|
75
|
-
"node-mocks-http": "1.
|
|
76
|
-
"nodemon": "3.1.
|
|
76
|
+
"node-mocks-http": "1.16.0",
|
|
77
|
+
"nodemon": "3.1.7",
|
|
77
78
|
"rimraf": "6.0.1",
|
|
78
79
|
"stryker-cli": "1.0.2",
|
|
79
80
|
"supertest": "7.0.0",
|
|
80
81
|
"using-temporary-files": "2.2.1"
|
|
81
82
|
},
|
|
82
83
|
"dependencies": {
|
|
83
|
-
"@apidevtools/json-schema-ref-parser": "11.
|
|
84
|
+
"@apidevtools/json-schema-ref-parser": "11.7.0",
|
|
84
85
|
"@hapi/accept": "6.0.3",
|
|
85
86
|
"@types/json-schema": "7.0.15",
|
|
86
87
|
"ast-types": "0.14.2",
|
|
87
88
|
"chokidar": "3.6.0",
|
|
88
89
|
"commander": "12.1.0",
|
|
89
|
-
"debug": "4.3.
|
|
90
|
+
"debug": "4.3.7",
|
|
90
91
|
"fetch": "1.1.0",
|
|
91
92
|
"fs-extra": "11.2.0",
|
|
92
93
|
"handlebars": "4.7.8",
|
|
@@ -105,6 +106,6 @@
|
|
|
105
106
|
"precinct": "12.1.2",
|
|
106
107
|
"prettier": "3.3.3",
|
|
107
108
|
"recast": "0.23.9",
|
|
108
|
-
"typescript": "5.
|
|
109
|
+
"typescript": "5.6.2"
|
|
109
110
|
}
|
|
110
111
|
}
|