@f3liz/rescript-autogen-openapi 0.3.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/LICENSE +373 -0
- package/README.md +111 -0
- package/lib/es6/src/Codegen.d.ts +28 -0
- package/lib/es6/src/Codegen.mjs +423 -0
- package/lib/es6/src/Types.d.ts +286 -0
- package/lib/es6/src/Types.mjs +20 -0
- package/lib/es6/src/bindings/Toposort.mjs +12 -0
- package/lib/es6/src/core/CodegenUtils.mjs +261 -0
- package/lib/es6/src/core/DocOverride.mjs +399 -0
- package/lib/es6/src/core/FileSystem.d.ts +4 -0
- package/lib/es6/src/core/FileSystem.mjs +78 -0
- package/lib/es6/src/core/IRBuilder.mjs +201 -0
- package/lib/es6/src/core/OpenAPIParser.mjs +168 -0
- package/lib/es6/src/core/Pipeline.d.ts +6 -0
- package/lib/es6/src/core/Pipeline.mjs +150 -0
- package/lib/es6/src/core/ReferenceResolver.mjs +41 -0
- package/lib/es6/src/core/Result.mjs +378 -0
- package/lib/es6/src/core/SchemaIR.mjs +425 -0
- package/lib/es6/src/core/SchemaIRParser.mjs +683 -0
- package/lib/es6/src/core/SchemaRefResolver.mjs +146 -0
- package/lib/es6/src/core/SchemaRegistry.mjs +92 -0
- package/lib/es6/src/core/SpecDiffer.mjs +251 -0
- package/lib/es6/src/core/SpecMerger.mjs +237 -0
- package/lib/es6/src/generators/ComponentSchemaGenerator.mjs +207 -0
- package/lib/es6/src/generators/DiffReportGenerator.mjs +155 -0
- package/lib/es6/src/generators/EndpointGenerator.mjs +173 -0
- package/lib/es6/src/generators/IRToSuryGenerator.mjs +543 -0
- package/lib/es6/src/generators/IRToTypeGenerator.mjs +592 -0
- package/lib/es6/src/generators/IRToTypeScriptGenerator.mjs +143 -0
- package/lib/es6/src/generators/ModuleGenerator.mjs +285 -0
- package/lib/es6/src/generators/SchemaCodeGenerator.mjs +77 -0
- package/lib/es6/src/generators/ThinWrapperGenerator.mjs +97 -0
- package/lib/es6/src/generators/TypeScriptDtsGenerator.mjs +172 -0
- package/lib/es6/src/generators/TypeScriptWrapperGenerator.mjs +145 -0
- package/lib/es6/src/types/CodegenError.d.ts +66 -0
- package/lib/es6/src/types/CodegenError.mjs +79 -0
- package/lib/es6/src/types/Config.d.ts +31 -0
- package/lib/es6/src/types/Config.mjs +42 -0
- package/lib/es6/src/types/GenerationContext.mjs +47 -0
- package/package.json +53 -0
- package/rescript.json +26 -0
- package/src/Codegen.res +231 -0
- package/src/Types.res +222 -0
- package/src/bindings/Toposort.res +16 -0
- package/src/core/CodegenUtils.res +180 -0
- package/src/core/DocOverride.res +504 -0
- package/src/core/FileSystem.res +63 -0
- package/src/core/IRBuilder.res +66 -0
- package/src/core/OpenAPIParser.res +144 -0
- package/src/core/Pipeline.res +52 -0
- package/src/core/ReferenceResolver.res +41 -0
- package/src/core/Result.res +187 -0
- package/src/core/SchemaIR.res +291 -0
- package/src/core/SchemaIRParser.res +454 -0
- package/src/core/SchemaRefResolver.res +143 -0
- package/src/core/SchemaRegistry.res +107 -0
- package/src/core/SpecDiffer.res +270 -0
- package/src/core/SpecMerger.res +245 -0
- package/src/generators/ComponentSchemaGenerator.res +210 -0
- package/src/generators/DiffReportGenerator.res +152 -0
- package/src/generators/EndpointGenerator.res +176 -0
- package/src/generators/IRToSuryGenerator.res +386 -0
- package/src/generators/IRToTypeGenerator.res +423 -0
- package/src/generators/IRToTypeScriptGenerator.res +77 -0
- package/src/generators/ModuleGenerator.res +363 -0
- package/src/generators/SchemaCodeGenerator.res +84 -0
- package/src/generators/ThinWrapperGenerator.res +124 -0
- package/src/generators/TypeScriptDtsGenerator.res +193 -0
- package/src/generators/TypeScriptWrapperGenerator.res +166 -0
- package/src/types/CodegenError.res +85 -0
- package/src/types/Config.res +95 -0
- package/src/types/GenerationContext.res +56 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
|
|
4
|
+
import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
|
|
5
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
|
+
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
7
|
+
import * as OpenapiParser from "@readme/openapi-parser";
|
|
8
|
+
|
|
9
|
+
function jsonToSpec(json) {
|
|
10
|
+
let obj = Stdlib_JSON.Decode.object(json);
|
|
11
|
+
if (obj === undefined) {
|
|
12
|
+
return {
|
|
13
|
+
TAG: "Error",
|
|
14
|
+
_0: "Invalid OpenAPI spec: root is not an object"
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
let pathsDict = Stdlib_Option.getOr(Stdlib_Option.flatMap(obj["paths"], Stdlib_JSON.Decode.object), {});
|
|
18
|
+
let infoObj = Stdlib_Option.getOr(Stdlib_Option.flatMap(obj["info"], Stdlib_JSON.Decode.object), {});
|
|
19
|
+
let openAPISpec_openapi = Stdlib_Option.getOr(Stdlib_Option.flatMap(obj["openapi"], Stdlib_JSON.Decode.string), "3.1.0");
|
|
20
|
+
let openAPISpec_info = {
|
|
21
|
+
title: Stdlib_Option.getOr(Stdlib_Option.flatMap(infoObj["title"], Stdlib_JSON.Decode.string), "Untitled API"),
|
|
22
|
+
version: Stdlib_Option.getOr(Stdlib_Option.flatMap(infoObj["version"], Stdlib_JSON.Decode.string), "0.0.0"),
|
|
23
|
+
description: Stdlib_Option.flatMap(infoObj["description"], Stdlib_JSON.Decode.string)
|
|
24
|
+
};
|
|
25
|
+
let openAPISpec_paths = Object.fromEntries(Object.entries(pathsDict).map(param => [
|
|
26
|
+
param[0],
|
|
27
|
+
param[1]
|
|
28
|
+
]));
|
|
29
|
+
let openAPISpec_components = Stdlib_Option.map(obj["components"], _comp => ({
|
|
30
|
+
schemas: Stdlib_Option.map(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(_comp), c => c["schemas"]), Stdlib_JSON.Decode.object), schemas => Object.fromEntries(Object.entries(schemas).map(param => [
|
|
31
|
+
param[0],
|
|
32
|
+
param[1]
|
|
33
|
+
])))
|
|
34
|
+
}));
|
|
35
|
+
let openAPISpec = {
|
|
36
|
+
openapi: openAPISpec_openapi,
|
|
37
|
+
info: openAPISpec_info,
|
|
38
|
+
paths: openAPISpec_paths,
|
|
39
|
+
components: openAPISpec_components
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
TAG: "Ok",
|
|
43
|
+
_0: openAPISpec
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function resolve(source, timeout) {
|
|
48
|
+
try {
|
|
49
|
+
let options = {
|
|
50
|
+
timeoutMs: Stdlib_Option.getOr(timeout, 60000)
|
|
51
|
+
};
|
|
52
|
+
return jsonToSpec(await OpenapiParser.bundle(source, options));
|
|
53
|
+
} catch (raw_err) {
|
|
54
|
+
let err = Primitive_exceptions.internalToException(raw_err);
|
|
55
|
+
if (err.RE_EXN_ID !== "JsExn") {
|
|
56
|
+
return {
|
|
57
|
+
TAG: "Error",
|
|
58
|
+
_0: "Unknown error resolving spec"
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
let message = Stdlib_Option.getOr(Stdlib_JsExn.message(err._1), "Unknown error resolving spec");
|
|
62
|
+
return {
|
|
63
|
+
TAG: "Error",
|
|
64
|
+
_0: `Failed to resolve spec: ` + message
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function parseOnly(source, timeout) {
|
|
70
|
+
try {
|
|
71
|
+
let options = {
|
|
72
|
+
timeoutMs: Stdlib_Option.getOr(timeout, 60000)
|
|
73
|
+
};
|
|
74
|
+
return jsonToSpec(await OpenapiParser.parse(source, options));
|
|
75
|
+
} catch (raw_err) {
|
|
76
|
+
let err = Primitive_exceptions.internalToException(raw_err);
|
|
77
|
+
if (err.RE_EXN_ID !== "JsExn") {
|
|
78
|
+
return {
|
|
79
|
+
TAG: "Error",
|
|
80
|
+
_0: "Unknown error parsing spec"
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
let message = Stdlib_Option.getOr(Stdlib_JsExn.message(err._1), "Unknown error parsing spec");
|
|
84
|
+
return {
|
|
85
|
+
TAG: "Error",
|
|
86
|
+
_0: `Failed to parse spec: ` + message
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function bundleSpec(source, timeout) {
|
|
92
|
+
try {
|
|
93
|
+
let options = {
|
|
94
|
+
timeoutMs: Stdlib_Option.getOr(timeout, 60000)
|
|
95
|
+
};
|
|
96
|
+
let bundled = await OpenapiParser.bundle(source, options);
|
|
97
|
+
return {
|
|
98
|
+
TAG: "Ok",
|
|
99
|
+
_0: bundled
|
|
100
|
+
};
|
|
101
|
+
} catch (raw_err) {
|
|
102
|
+
let err = Primitive_exceptions.internalToException(raw_err);
|
|
103
|
+
if (err.RE_EXN_ID !== "JsExn") {
|
|
104
|
+
return {
|
|
105
|
+
TAG: "Error",
|
|
106
|
+
_0: "Unknown error bundling spec"
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
let message = Stdlib_Option.getOr(Stdlib_JsExn.message(err._1), "Unknown error bundling spec");
|
|
110
|
+
return {
|
|
111
|
+
TAG: "Error",
|
|
112
|
+
_0: `Failed to bundle spec: ` + message
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function validateSpec(source, timeout) {
|
|
118
|
+
try {
|
|
119
|
+
let options = {
|
|
120
|
+
timeoutMs: Stdlib_Option.getOr(timeout, 60000)
|
|
121
|
+
};
|
|
122
|
+
return jsonToSpec(await OpenapiParser.validate(source, options));
|
|
123
|
+
} catch (raw_err) {
|
|
124
|
+
let err = Primitive_exceptions.internalToException(raw_err);
|
|
125
|
+
if (err.RE_EXN_ID !== "JsExn") {
|
|
126
|
+
return {
|
|
127
|
+
TAG: "Error",
|
|
128
|
+
_0: "Unknown error validating spec"
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
let message = Stdlib_Option.getOr(Stdlib_JsExn.message(err._1), "Unknown error validating spec");
|
|
132
|
+
return {
|
|
133
|
+
TAG: "Error",
|
|
134
|
+
_0: `Failed to validate spec: ` + message
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export {
|
|
140
|
+
jsonToSpec,
|
|
141
|
+
resolve,
|
|
142
|
+
parseOnly,
|
|
143
|
+
bundleSpec,
|
|
144
|
+
validateSpec,
|
|
145
|
+
}
|
|
146
|
+
/* Stdlib_JsExn Not a pure module */
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
4
|
+
|
|
5
|
+
function fromSpec(spec) {
|
|
6
|
+
let components = spec.components;
|
|
7
|
+
let schemas;
|
|
8
|
+
if (components !== undefined) {
|
|
9
|
+
let s = components.schemas;
|
|
10
|
+
schemas = s !== undefined ? s : ({});
|
|
11
|
+
} else {
|
|
12
|
+
schemas = {};
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
schemas: schemas,
|
|
16
|
+
visiting: []
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function empty() {
|
|
21
|
+
return {
|
|
22
|
+
schemas: {},
|
|
23
|
+
visiting: []
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function extractSchemaName(ref) {
|
|
28
|
+
let prefix = "#/components/schemas/";
|
|
29
|
+
if (ref.startsWith(prefix)) {
|
|
30
|
+
return ref.slice(prefix.length);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function isVisiting(registry, name) {
|
|
35
|
+
return registry.visiting.includes(name);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function startVisiting(registry, name) {
|
|
39
|
+
registry.visiting = registry.visiting.concat([name]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function stopVisiting(registry, name) {
|
|
43
|
+
registry.visiting = registry.visiting.filter(n => n !== name);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getSchema(registry, name) {
|
|
47
|
+
return registry.schemas[name];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function resolveRef(registry, ref) {
|
|
51
|
+
let name = extractSchemaName(ref);
|
|
52
|
+
if (name !== undefined) {
|
|
53
|
+
return registry.schemas[name];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getSchemaNames(registry) {
|
|
58
|
+
return Object.keys(registry.schemas);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function hasSchema(registry, name) {
|
|
62
|
+
return Stdlib_Option.isSome(registry.schemas[name]);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function addSchema(registry, name, schema) {
|
|
66
|
+
registry.schemas[name] = schema;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function merge(registry, other) {
|
|
70
|
+
Object.entries(other.schemas).forEach(param => {
|
|
71
|
+
let name = param[0];
|
|
72
|
+
if (!hasSchema(registry, name)) {
|
|
73
|
+
return addSchema(registry, name, param[1]);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export {
|
|
79
|
+
fromSpec,
|
|
80
|
+
empty,
|
|
81
|
+
extractSchemaName,
|
|
82
|
+
isVisiting,
|
|
83
|
+
startVisiting,
|
|
84
|
+
stopVisiting,
|
|
85
|
+
getSchema,
|
|
86
|
+
resolveRef,
|
|
87
|
+
getSchemaNames,
|
|
88
|
+
hasSchema,
|
|
89
|
+
addSchema,
|
|
90
|
+
merge,
|
|
91
|
+
}
|
|
92
|
+
/* No side effect */
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
4
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
5
|
+
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
6
|
+
import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
|
|
7
|
+
|
|
8
|
+
function makeEndpointKey(method, path) {
|
|
9
|
+
return method + `:` + path;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function schemasEqual(schema1, schema2) {
|
|
13
|
+
let match = schema1.type;
|
|
14
|
+
let match$1 = schema2.type;
|
|
15
|
+
let typeMatches = match !== undefined ? (
|
|
16
|
+
match$1 !== undefined ? Primitive_object.equal(match, match$1) : false
|
|
17
|
+
) : match$1 === undefined;
|
|
18
|
+
if (!typeMatches) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
if (Primitive_object.notequal(schema1.format, schema2.format)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
if (Primitive_object.notequal(schema1.nullable, schema2.nullable)) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
if (Primitive_object.notequal(schema1.enum, schema2.enum)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
let match$2 = schema1.properties;
|
|
31
|
+
let match$3 = schema2.properties;
|
|
32
|
+
if (match$2 === undefined) {
|
|
33
|
+
return match$3 === undefined;
|
|
34
|
+
}
|
|
35
|
+
if (match$3 === undefined) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
let keys1 = Object.keys(match$2).toSorted(Primitive_string.compare);
|
|
39
|
+
let keys2 = Object.keys(match$3).toSorted(Primitive_string.compare);
|
|
40
|
+
if (Primitive_object.notequal(keys1, keys2)) {
|
|
41
|
+
return false;
|
|
42
|
+
} else {
|
|
43
|
+
return keys1.every(key => {
|
|
44
|
+
let match$4 = match$2[key];
|
|
45
|
+
let match$5 = match$3[key];
|
|
46
|
+
if (match$4 !== undefined && match$5 !== undefined) {
|
|
47
|
+
return schemasEqual(match$4, match$5);
|
|
48
|
+
} else {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function compareEndpoints(endpoint1, endpoint2) {
|
|
56
|
+
let match = endpoint1.requestBody;
|
|
57
|
+
let match$1 = endpoint2.requestBody;
|
|
58
|
+
let hasRequestBodyChanged;
|
|
59
|
+
if (match !== undefined) {
|
|
60
|
+
if (match$1 !== undefined) {
|
|
61
|
+
let keys1 = Object.keys(match.content).toSorted(Primitive_string.compare);
|
|
62
|
+
let keys2 = Object.keys(match$1.content).toSorted(Primitive_string.compare);
|
|
63
|
+
hasRequestBodyChanged = Primitive_object.notequal(keys1, keys2) ? true : keys1.some(contentType => {
|
|
64
|
+
let match$2 = match.content[contentType];
|
|
65
|
+
let match$3 = match$1.content[contentType];
|
|
66
|
+
if (match$2 === undefined) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
if (match$3 === undefined) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
let match$4 = match$2.schema;
|
|
73
|
+
let match$5 = match$3.schema;
|
|
74
|
+
if (match$4 !== undefined && match$5 !== undefined) {
|
|
75
|
+
return !schemasEqual(match$4, match$5);
|
|
76
|
+
} else {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
} else {
|
|
81
|
+
hasRequestBodyChanged = true;
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
hasRequestBodyChanged = match$1 !== undefined;
|
|
85
|
+
}
|
|
86
|
+
let codes1 = Object.keys(endpoint1.responses).toSorted(Primitive_string.compare);
|
|
87
|
+
let codes2 = Object.keys(endpoint2.responses).toSorted(Primitive_string.compare);
|
|
88
|
+
let hasResponseChanged = Primitive_object.notequal(codes1, codes2) ? true : codes1.some(code => {
|
|
89
|
+
let match = endpoint1.responses[code];
|
|
90
|
+
let match$1 = endpoint2.responses[code];
|
|
91
|
+
if (match === undefined) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
if (match$1 === undefined) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
let match$2 = match.content;
|
|
98
|
+
let match$3 = match$1.content;
|
|
99
|
+
if (match$2 === undefined) {
|
|
100
|
+
return match$3 !== undefined;
|
|
101
|
+
}
|
|
102
|
+
if (match$3 === undefined) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
let contentKeys1 = Object.keys(match$2).toSorted(Primitive_string.compare);
|
|
106
|
+
let contentKeys2 = Object.keys(match$3).toSorted(Primitive_string.compare);
|
|
107
|
+
if (Primitive_object.notequal(contentKeys1, contentKeys2)) {
|
|
108
|
+
return true;
|
|
109
|
+
} else {
|
|
110
|
+
return contentKeys1.some(contentType => {
|
|
111
|
+
let match$4 = match$2[contentType];
|
|
112
|
+
let match$5 = match$3[contentType];
|
|
113
|
+
if (match$4 === undefined) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
if (match$5 === undefined) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
let match$6 = match$4.schema;
|
|
120
|
+
let match$7 = match$5.schema;
|
|
121
|
+
if (match$6 !== undefined && match$7 !== undefined) {
|
|
122
|
+
return !schemasEqual(match$6, match$7);
|
|
123
|
+
} else {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
if (hasRequestBodyChanged || hasResponseChanged) {
|
|
130
|
+
return {
|
|
131
|
+
path: endpoint1.path,
|
|
132
|
+
method: endpoint1.method,
|
|
133
|
+
requestBodyChanged: hasRequestBodyChanged,
|
|
134
|
+
responseChanged: hasResponseChanged,
|
|
135
|
+
breakingChange: hasResponseChanged
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function compareEndpointLists(baseEndpoints, forkEndpoints) {
|
|
141
|
+
let baseMap = {};
|
|
142
|
+
baseEndpoints.forEach(ep => {
|
|
143
|
+
let key = makeEndpointKey(ep.method, ep.path);
|
|
144
|
+
baseMap[key] = ep;
|
|
145
|
+
});
|
|
146
|
+
let forkMap = {};
|
|
147
|
+
forkEndpoints.forEach(ep => {
|
|
148
|
+
let key = makeEndpointKey(ep.method, ep.path);
|
|
149
|
+
forkMap[key] = ep;
|
|
150
|
+
});
|
|
151
|
+
let baseKeys = new Set(Object.keys(baseMap));
|
|
152
|
+
let forkKeys = new Set(Object.keys(forkMap));
|
|
153
|
+
let added = Stdlib_Array.filterMap(Array.from(forkKeys).filter(key => !baseKeys.has(key)), key => forkMap[key]);
|
|
154
|
+
let removed = Stdlib_Array.filterMap(Array.from(baseKeys).filter(key => !forkKeys.has(key)), key => baseMap[key]);
|
|
155
|
+
let modified = Stdlib_Array.filterMap(Array.from(baseKeys).filter(key => forkKeys.has(key)), key => {
|
|
156
|
+
let match = baseMap[key];
|
|
157
|
+
let match$1 = forkMap[key];
|
|
158
|
+
if (match !== undefined && match$1 !== undefined) {
|
|
159
|
+
return compareEndpoints(match, match$1);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
return [
|
|
163
|
+
added,
|
|
164
|
+
removed,
|
|
165
|
+
modified
|
|
166
|
+
];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function compareComponentSchemas(baseSchemas, forkSchemas) {
|
|
170
|
+
if (baseSchemas === undefined) {
|
|
171
|
+
if (forkSchemas !== undefined) {
|
|
172
|
+
return [
|
|
173
|
+
Object.keys(forkSchemas),
|
|
174
|
+
[],
|
|
175
|
+
[]
|
|
176
|
+
];
|
|
177
|
+
} else {
|
|
178
|
+
return [
|
|
179
|
+
[],
|
|
180
|
+
[],
|
|
181
|
+
[]
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (forkSchemas === undefined) {
|
|
186
|
+
return [
|
|
187
|
+
[],
|
|
188
|
+
Object.keys(baseSchemas),
|
|
189
|
+
[]
|
|
190
|
+
];
|
|
191
|
+
}
|
|
192
|
+
let baseKeys = new Set(Object.keys(baseSchemas));
|
|
193
|
+
let forkKeys = new Set(Object.keys(forkSchemas));
|
|
194
|
+
let added = Array.from(forkKeys).filter(key => !baseKeys.has(key));
|
|
195
|
+
let removed = Array.from(baseKeys).filter(key => !forkKeys.has(key));
|
|
196
|
+
let modified = Stdlib_Array.filterMap(Array.from(baseKeys).filter(key => forkKeys.has(key)), name => {
|
|
197
|
+
let match = baseSchemas[name];
|
|
198
|
+
let match$1 = forkSchemas[name];
|
|
199
|
+
if (match !== undefined && match$1 !== undefined && !schemasEqual(match, match$1)) {
|
|
200
|
+
return {
|
|
201
|
+
name: name,
|
|
202
|
+
breakingChange: true
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
return [
|
|
207
|
+
added,
|
|
208
|
+
removed,
|
|
209
|
+
modified
|
|
210
|
+
];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function generateDiff(baseSpec, forkSpec, baseEndpoints, forkEndpoints) {
|
|
214
|
+
let match = compareEndpointLists(baseEndpoints, forkEndpoints);
|
|
215
|
+
let match$1 = compareComponentSchemas(Stdlib_Option.flatMap(baseSpec.components, c => c.schemas), Stdlib_Option.flatMap(forkSpec.components, c => c.schemas));
|
|
216
|
+
return {
|
|
217
|
+
addedEndpoints: match[0],
|
|
218
|
+
removedEndpoints: match[1],
|
|
219
|
+
modifiedEndpoints: match[2],
|
|
220
|
+
addedSchemas: match$1[0],
|
|
221
|
+
removedSchemas: match$1[1],
|
|
222
|
+
modifiedSchemas: match$1[2]
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function hasBreakingChanges(diff) {
|
|
227
|
+
let hasRemovedEndpoints = diff.removedEndpoints.length !== 0;
|
|
228
|
+
let hasBreakingEndpointChanges = diff.modifiedEndpoints.some(d => d.breakingChange);
|
|
229
|
+
let hasBreakingSchemaChanges = diff.modifiedSchemas.some(d => d.breakingChange);
|
|
230
|
+
if (hasRemovedEndpoints || hasBreakingEndpointChanges) {
|
|
231
|
+
return true;
|
|
232
|
+
} else {
|
|
233
|
+
return hasBreakingSchemaChanges;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function countChanges(diff) {
|
|
238
|
+
return ((((diff.addedEndpoints.length + diff.removedEndpoints.length | 0) + diff.modifiedEndpoints.length | 0) + diff.addedSchemas.length | 0) + diff.removedSchemas.length | 0) + diff.modifiedSchemas.length | 0;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export {
|
|
242
|
+
makeEndpointKey,
|
|
243
|
+
schemasEqual,
|
|
244
|
+
compareEndpoints,
|
|
245
|
+
compareEndpointLists,
|
|
246
|
+
compareComponentSchemas,
|
|
247
|
+
generateDiff,
|
|
248
|
+
hasBreakingChanges,
|
|
249
|
+
countChanges,
|
|
250
|
+
}
|
|
251
|
+
/* No side effect */
|