@f3liz/rescript-autogen-openapi 0.1.7 → 0.3.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.

Potentially problematic release.


This version of @f3liz/rescript-autogen-openapi might be problematic. Click here for more details.

@@ -1,6 +1,7 @@
1
1
  // Generated by ReScript, PLEASE EDIT WITH CARE
2
2
 
3
3
  import * as Pipeline from "../core/Pipeline.mjs";
4
+ import * as Toposort from "../bindings/Toposort.mjs";
4
5
  import * as FileSystem from "../core/FileSystem.mjs";
5
6
  import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
6
7
  import * as CodegenUtils from "../core/CodegenUtils.mjs";
@@ -29,8 +30,7 @@ function extractReferencedSchemaNames(_irType) {
29
30
  case "Intersection" :
30
31
  return irType._0.flatMap(extractReferencedSchemaNames);
31
32
  case "Reference" :
32
- let parts = irType._0.split("/");
33
- return [Stdlib_Option.getOr(parts[parts.length - 1 | 0], "")];
33
+ return [irType._0];
34
34
  case "Option" :
35
35
  _irType = irType._0;
36
36
  continue;
@@ -56,7 +56,8 @@ function generate(spec, outputDir) {
56
56
  s.name,
57
57
  s
58
58
  ]));
59
- let dependencyMap = Stdlib_Array.reduce(schemas, {}, (acc, schema) => {
59
+ let allNodes = schemas.map(s => s.name);
60
+ let edges = schemas.flatMap(schema => {
60
61
  let references = extractReferencedSchemaNames(schema.type_).filter(name => {
61
62
  if (name in schemaNameMap) {
62
63
  return name !== schema.name;
@@ -64,50 +65,131 @@ function generate(spec, outputDir) {
64
65
  return false;
65
66
  }
66
67
  });
67
- acc[schema.name] = references;
68
- return acc;
68
+ return references.map(dep => [
69
+ schema.name,
70
+ dep
71
+ ]);
69
72
  });
70
- let sortedSchemas = [];
71
- let inDegreeMap = Stdlib_Array.reduce(schemas, {}, (acc, schema) => {
72
- let degree = Stdlib_Option.mapOr(dependencyMap[schema.name], 0, prim => prim.length);
73
- acc[schema.name] = degree;
74
- return acc;
75
- });
76
- let queue = schemas.filter(schema => Stdlib_Option.getOr(inDegreeMap[schema.name], 0) === 0);
77
- while (queue.length !== 0) {
78
- let v = queue.shift();
79
- let schema = v !== undefined ? v : schemas[0];
80
- sortedSchemas.push(schema);
81
- schemas.forEach(otherSchema => {
82
- let dependsOnCurrent = Stdlib_Option.getOr(dependencyMap[otherSchema.name], []).some(name => name === schema.name);
83
- if (!dependsOnCurrent) {
73
+ let sortedNames;
74
+ try {
75
+ sortedNames = Toposort.sortArray(allNodes, edges).toReversed();
76
+ } catch (exn) {
77
+ let visited = {};
78
+ let inStack = {};
79
+ let cycleEdges = [];
80
+ let dfs = node => {
81
+ if (Stdlib_Option.getOr(inStack[node], false) || Stdlib_Option.getOr(visited[node], false)) {
84
82
  return;
85
- }
86
- let currentDegree = Stdlib_Option.getOr(inDegreeMap[otherSchema.name], 0);
87
- let newDegree = currentDegree - 1 | 0;
88
- inDegreeMap[otherSchema.name] = newDegree;
89
- if (newDegree === 0) {
90
- queue.push(otherSchema);
83
+ } else {
84
+ visited[node] = true;
85
+ inStack[node] = true;
86
+ edges.forEach(param => {
87
+ let from = param[0];
88
+ if (from !== node) {
89
+ return;
90
+ }
91
+ let to = param[1];
92
+ if (Stdlib_Option.getOr(inStack[to], false)) {
93
+ cycleEdges.push([
94
+ from,
95
+ to
96
+ ]);
97
+ return;
98
+ } else {
99
+ return dfs(to);
100
+ }
101
+ });
102
+ inStack[node] = false;
91
103
  return;
92
104
  }
105
+ };
106
+ allNodes.forEach(dfs);
107
+ let nonCycleEdges = edges.filter(param => {
108
+ let to = param[1];
109
+ let from = param[0];
110
+ return !cycleEdges.some(param => {
111
+ if (param[0] === from) {
112
+ return param[1] === to;
113
+ } else {
114
+ return false;
115
+ }
116
+ });
93
117
  });
94
- };
95
- let sortedNames = sortedSchemas.map(s => s.name);
96
- let remainingSchemas = schemas.filter(s => !sortedNames.some(name => name === s.name)).toSorted((a, b) => Primitive_string.compare(a.name, b.name));
97
- let finalSortedSchemas = sortedSchemas.concat(remainingSchemas);
118
+ try {
119
+ sortedNames = Toposort.sortArray(allNodes, nonCycleEdges).toReversed();
120
+ } catch (exn$1) {
121
+ sortedNames = allNodes.toSorted(Primitive_string.compare);
122
+ }
123
+ }
124
+ let finalSortedSchemas = Stdlib_Array.filterMap(sortedNames, name => schemaNameMap[name]);
98
125
  let availableSchemaNames = finalSortedSchemas.map(s => s.name);
99
126
  let warnings = match[1].slice();
127
+ let selfRefSchemas = {};
128
+ finalSortedSchemas.forEach(schema => {
129
+ let refs = extractReferencedSchemaNames(schema.type_);
130
+ if (refs.some(name => name === schema.name)) {
131
+ selfRefSchemas[schema.name] = true;
132
+ return;
133
+ }
134
+ });
100
135
  let moduleCodes = finalSortedSchemas.map(schema => {
101
- let typeCtx = GenerationContext.make(`ComponentSchemas.` + schema.name, true, availableSchemaNames, undefined, undefined);
102
- let schemaCtx = GenerationContext.make(`ComponentSchemas.` + schema.name, true, availableSchemaNames, undefined, undefined);
103
- let typeCode = IRToTypeGenerator.generateTypeWithContext(typeCtx, 0, schema.type_);
104
- let schemaCode = IRToSuryGenerator.generateSchemaWithContext(schemaCtx, 0, schema.type_);
136
+ let isSelfRef = Stdlib_Option.getOr(selfRefSchemas[schema.name], false);
137
+ let selfRefName = isSelfRef ? schema.name : undefined;
138
+ let typeCtx = GenerationContext.make(`ComponentSchemas.` + schema.name, true, availableSchemaNames, undefined, selfRefName, undefined);
139
+ let typeCode = IRToTypeGenerator.generateTypeWithContext(typeCtx, 0, undefined, schema.type_);
140
+ let processed = 0;
141
+ while (processed < typeCtx.extractedTypes.length) {
142
+ let idx = processed;
143
+ let match = typeCtx.extractedTypes[idx];
144
+ let irType = match.irType;
145
+ if (match.isUnboxed && typeof irType === "object" && irType.TAG === "Union") {
146
+ irType._0.forEach(memberType => {
147
+ IRToTypeGenerator.generateTypeWithContext(typeCtx, 0, true, memberType);
148
+ });
149
+ } else {
150
+ IRToTypeGenerator.generateTypeWithContext(typeCtx, 0, false, irType);
151
+ }
152
+ processed = idx + 1 | 0;
153
+ };
154
+ let allExtracted = typeCtx.extractedTypes.slice().toReversed();
155
+ let extractedTypeMap = allExtracted.length !== 0 ? allExtracted : undefined;
156
+ let schemaCtx = GenerationContext.make(`ComponentSchemas.` + schema.name, true, availableSchemaNames, undefined, selfRefName, undefined);
157
+ let schemaCode = IRToSuryGenerator.generateSchemaWithContext(schemaCtx, 0, extractedTypeMap, schema.type_);
105
158
  warnings.push(...typeCtx.warnings);
106
159
  warnings.push(...schemaCtx.warnings);
160
+ let extractedTypeDefs = allExtracted.map(param => {
161
+ let irType = param.irType;
162
+ let typeName = param.typeName;
163
+ let auxTypeCode;
164
+ if (param.isUnboxed) {
165
+ let exit = 0;
166
+ if (typeof irType !== "object" || irType.TAG !== "Union") {
167
+ exit = 1;
168
+ } else {
169
+ let body = IRToTypeGenerator.generateUnboxedVariantBody(typeCtx, irType._0);
170
+ auxTypeCode = `@unboxed type ` + typeName + ` = ` + body;
171
+ }
172
+ if (exit === 1) {
173
+ let auxType = IRToTypeGenerator.generateTypeWithContext(typeCtx, 0, undefined, irType);
174
+ auxTypeCode = `type ` + typeName + ` = ` + auxType;
175
+ }
176
+ } else {
177
+ let auxType$1 = IRToTypeGenerator.generateTypeWithContext(typeCtx, 0, undefined, irType);
178
+ auxTypeCode = `type ` + typeName + ` = ` + auxType$1;
179
+ }
180
+ let auxSchemaCtx = GenerationContext.make(`ComponentSchemas.` + schema.name + `.` + typeName, true, availableSchemaNames, undefined, undefined, undefined);
181
+ let filteredMap = allExtracted.filter(param => param.typeName !== typeName);
182
+ let auxExtractedTypeMap = filteredMap.length !== 0 ? filteredMap : undefined;
183
+ let auxSchema = IRToSuryGenerator.generateSchemaWithContext(auxSchemaCtx, 0, auxExtractedTypeMap, irType);
184
+ return ` ` + auxTypeCode + `\n let ` + typeName + `Schema = ` + auxSchema;
185
+ });
107
186
  let docComment = Stdlib_Option.mapOr(schema.description, "", d => CodegenUtils.generateDocString(undefined, d, undefined));
187
+ let extractedBlock = extractedTypeDefs.length !== 0 ? extractedTypeDefs.join("\n") + "\n" : "";
188
+ let typeKeyword = isSelfRef ? "type rec t" : "type t";
189
+ let finalSchemaCode = isSelfRef ? `S.recursive("` + schema.name + `", schema => ` + schemaCode + `)` : schemaCode;
108
190
  return docComment + `module ` + JsConvertCase.toPascalCase(schema.name) + ` = {
109
- type t = ` + typeCode + `
110
- let schema = ` + schemaCode + `
191
+ ` + extractedBlock + ` ` + typeKeyword + ` = ` + typeCode + `
192
+ let schema = ` + finalSchemaCode + `
111
193
  }`;
112
194
  });
113
195
  let fileHeader = CodegenUtils.generateFileHeader("Shared component schemas");
@@ -122,4 +204,4 @@ export {
122
204
  extractReferencedSchemaNames,
123
205
  generate,
124
206
  }
125
- /* FileSystem Not a pure module */
207
+ /* Toposort Not a pure module */
@@ -26,7 +26,7 @@ function generateTypeCodeAndSchemaCode(jsonSchema, typeName, schemaName, moduleP
26
26
  name: schemaName,
27
27
  description: jsonSchema.description,
28
28
  type_: ir
29
- }, undefined, undefined, modulePrefix);
29
+ }, undefined, undefined, modulePrefix, match$1[2]);
30
30
  return [
31
31
  match$1[0],
32
32
  match$2[0]
@@ -45,7 +45,8 @@ function generateEndpointFunction(endpoint, overrideDir, moduleName) {
45
45
  let isRequestBodyRequired = Stdlib_Option.getOr(requestBody.required, false);
46
46
  let bodyParam = hasRequestBody ? (
47
47
  isRequestBodyRequired ? `~body: ` + requestTypeName : `~body: option<` + requestTypeName + `>=?`
48
- ) : "~body as _";
48
+ ) : "";
49
+ let paramSep = hasRequestBody ? ", " : "";
49
50
  let bodyValueConversion = hasRequestBody ? (
50
51
  isRequestBodyRequired ? ` let jsonBody = body->S.reverseConvertToJsonOrThrow(` + functionName + `RequestSchema)` : ` let jsonBody = body->Option.map(b => b->S.reverseConvertToJsonOrThrow(` + functionName + `RequestSchema))`
51
52
  ) : "";
@@ -86,7 +87,7 @@ function generateEndpointFunction(endpoint, overrideDir, moduleName) {
86
87
  let docComment = CodegenUtils.generateDocString(endpoint.summary, description, undefined);
87
88
  let code = `
88
89
  |` + docComment.trimEnd() + `
89
- |let ` + functionName + ` = (` + bodyParam + `, ~fetch: ` + CodegenUtils.fetchTypeSignature + `): promise<` + functionName + `Response> => {
90
+ |let ` + functionName + ` = (` + bodyParam + paramSep + `~fetch: ` + CodegenUtils.fetchTypeSignature + `): promise<` + functionName + `Response> => {
90
91
  |` + bodyValueConversion + `
91
92
  | fetch(
92
93
  | ~url="` + endpoint.path + `",