@zenera/faker 1.1.0

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.
@@ -0,0 +1,83 @@
1
+ // Both packages are CommonJS. `ajv/dist/2020` has a real named export, so it is
2
+ // imported by name; `ajv-formats` sets `module.exports` to the plugin function
3
+ // but also declares named exports, which NodeNext models as a namespace with a
4
+ // synthetic default. The value is callable at runtime; only the type is wrong.
5
+ import addFormatsDefault from 'ajv-formats';
6
+ import { Ajv2020 } from 'ajv/dist/2020.js';
7
+ const addFormats = addFormatsDefault;
8
+ export class Checks {
9
+ // `logger: false` silences "unknown format … ignored". Real documents are
10
+ // full of vendor formats (`ip`, `mac-address`) and there is nothing to do
11
+ // about them; left on, one spec buries the request log in warnings.
12
+ #strict = new Ajv2020({
13
+ allErrors: true,
14
+ strict: false,
15
+ validateFormats: true,
16
+ logger: false,
17
+ });
18
+ #loose = new Ajv2020({
19
+ allErrors: true,
20
+ strict: false,
21
+ coerceTypes: true,
22
+ useDefaults: false,
23
+ validateFormats: true,
24
+ logger: false,
25
+ });
26
+ #cache = new Map();
27
+ constructor() {
28
+ addFormats(this.#strict);
29
+ addFormats(this.#loose);
30
+ }
31
+ for(operation) {
32
+ const hit = this.#cache.get(operation.key);
33
+ if (hit) {
34
+ return hit;
35
+ }
36
+ const compiled = {
37
+ path: this.#loose.compile(envelope(operation.params, 'path')),
38
+ query: this.#loose.compile(envelope(operation.params, 'query')),
39
+ body: operation.requestBody
40
+ ? this.#strict.compile(operation.requestBody.schema)
41
+ : undefined,
42
+ bodyRequired: operation.requestBody?.required === true,
43
+ response: operation.success.schema
44
+ ? this.#strict.compile(operation.success.schema)
45
+ : undefined,
46
+ };
47
+ this.#cache.set(operation.key, compiled);
48
+ return compiled;
49
+ }
50
+ }
51
+ /**
52
+ * Parameters are validated as one object rather than one at a time, so a
53
+ * request with three wrong values is answered once with all three.
54
+ */
55
+ function envelope(params, where) {
56
+ const mine = params.filter((p) => p.in === where);
57
+ return {
58
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
59
+ type: 'object',
60
+ properties: Object.fromEntries(mine.map((p) => [p.name, stripped(p.schema)])),
61
+ required: mine.filter((p) => p.required).map((p) => p.name),
62
+ // A query string may carry anything; only what the spec names is checked.
63
+ additionalProperties: true,
64
+ };
65
+ }
66
+ /** A subschema must not carry its own `$schema`; only the envelope may. */
67
+ function stripped(schema) {
68
+ const { $schema: _ignored, ...rest } = schema;
69
+ return rest;
70
+ }
71
+ // ---------------------------------------------------------------------------
72
+ // Reporting
73
+ // ---------------------------------------------------------------------------
74
+ export function issues(prefix, errors) {
75
+ return (errors ?? []).map((e) => ({
76
+ where: `${prefix}${e.instancePath}`,
77
+ message: e.message ?? 'is invalid',
78
+ }));
79
+ }
80
+ export function describeIssues(list) {
81
+ return list.map((i) => `${i.where || '(root)'} ${i.message}`).join('; ');
82
+ }
83
+ //# sourceMappingURL=validate.js.map
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@zenera/faker",
3
+ "version": "1.1.0",
4
+ "description": "Mock HTTP server for swagger/OpenAPI documents, with response bodies generated by a model.",
5
+ "keywords": [
6
+ "openapi",
7
+ "swagger",
8
+ "mock-server",
9
+ "llm",
10
+ "testing"
11
+ ],
12
+ "license": "MIT",
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "author": "Andrey Ryabov",
17
+ "homepage": "https://github.com/andreyryabov/ZeneraNeo#readme",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/andreyryabov/ZeneraNeo.git",
21
+ "directory": "packages/faker"
22
+ },
23
+ "bugs": "https://github.com/andreyryabov/ZeneraNeo/issues",
24
+ "private": false,
25
+ "type": "module",
26
+ "exports": {
27
+ "./command": {
28
+ "types": "./dist/command.d.ts",
29
+ "default": "./dist/command.js"
30
+ }
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "!dist/**/*.map"
35
+ ],
36
+ "engines": {
37
+ "node": ">=24"
38
+ },
39
+ "scripts": {
40
+ "build": "tsc -b",
41
+ "clean": "tsc -b --clean && rm -rf dist",
42
+ "prepack": "tsc -b"
43
+ },
44
+ "dependencies": {
45
+ "@apidevtools/swagger-parser": "^12.0.0",
46
+ "ajv": "^8.17.1",
47
+ "ajv-formats": "^3.0.1",
48
+ "@zenera/cli": "^1.1.0",
49
+ "@zenera/neo": "^1.1.0"
50
+ }
51
+ }