Open KnutHaraldR opened 5 years ago
It happens when I have this property in my C# code used for generating the API definition with SwashBuckle:
public class MetadataValue
{
public IList<MetadataValue> Children { get; } // Remove this/change inner type => no error
}
So I was thinking it's a recursion problem or something.
@KnutHaraldR I have same issue with swagger.json, generated by PHP ApiPlatform.
How did you found a place in c# code that causes this error? I have about 100 resources in the project and test them on by one looks too difficult.
Right now i've patched util.js source code to get generation process done (tot test it)
function indent(input, level = 1) {
// --- start patch
if (!input) {
return '';
}
// -- end patch
if (Array.isArray(input))
input = input.join('\n');
let res;
res = input.replace(/^/gm, ' '.repeat(level * conf.indentation));
res = res.replace(/^\s+$/gm, '');
return res;
}
I found it because it was one of my latest additions to my API. You could always binary search by disabling half your API endpoints each time.
A have this problem again when using the latest SwashBuckle, which generates allOf clauses for enums. The allOf causes Swagger-angular-generator to fail.
there is another change needed in proccess-controller.js processController function.
`
function processController(methods, name, config, definitions) {
const filename = path.join(config.dest, conf.apiDir, `${name}.ts`);
let usesGlobalType = false;
// make simpleNames unique and process responses
const simpleNames = _.map(methods, 'simpleName');
methods.forEach(controller => {
if (simpleNames.filter(n => n === controller.simpleName).length > 1) {
//start patch
if(!(controller.operationId === undefined)){
const preserveCapitals = controller.operationId.replace(/([A-Z])/g, '-$1');
controller.simpleName = _.lowerFirst(_.camelCase(preserveCapitals));
}
//end patch
}
controller.responseDef = process_responses_1.processResponses(controller.responses, controller.simpleName, config);
usesGlobalType = usesGlobalType || controller.responseDef.usesGlobalType;
});
const processedMethods = methods.map(m => process_method_1.processMethod(m, config.unwrapSingleParamMethods));
usesGlobalType = usesGlobalType || processedMethods.some(c => c.usesGlobalType);
let content = '';
const angularCommonHttp = ['HttpClient'];
if (processedMethods.some(c => 'header' in c.paramGroups)) {
angularCommonHttp.push('HttpHeaders');
}
if (processedMethods.some(c => 'query' in c.paramGroups)) {
angularCommonHttp.push('HttpParams');
}
content += `import {${angularCommonHttp.join(', ')}} from \'@angular/common/http\';\n`;
content += 'import {Injectable} from \'@angular/core\';\n';
content += 'import {Observable} from \'rxjs\';\n\n';
if (usesGlobalType) {
content += `import * as __${conf.modelFile} from \'../${conf.modelFile}\';\n\n`;
}
const interfaceDef = _.map(processedMethods, 'interfaceDef').filter(Boolean).join('\n');
if (interfaceDef) {
content += interfaceDef;
content += '\n';
}
content += `@Injectable()\n`;
content += `export class ${name}Service {\n`;
content += utils_1.indent('constructor(private http: HttpClient) {}');
content += '\n';
content += utils_1.indent(_.map(processedMethods, 'methodDef').join('\n\n'));
content += '\n}\n';
if (conf.adHocExceptions.api[name]) {
content = content.replace(conf.adHocExceptions.api[name][0], conf.adHocExceptions.api[name][1]);
}
// controllers
utils_1.writeFile(filename, content, config.header);
// forms
generate_form_modules_1.createForms(config, name, processedMethods, definitions);
}`
Stack trace:
api definition:
{"swagger":"2.0","info":{"version":"1.0","title":"myApi"},"paths":{"/api/datasets":{"post":{"tags":["DataSet"],"operationId":"PostDataSet","consumes":["application/json-patch+json","application/json","text/json","application/*+json"],"produces":["application/json"],"parameters":[{"name":"dataSet","in":"body","required":false,"schema":{"$ref":"#/definitions/MetadataValue"}}],"responses":{"422":{"description":"Client Error","schema":{"$ref":"#/definitions/ErrorDetail"}},"500":{"description":"500","schema":{"$ref":"#/definitions/ErrorDetail"}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"security":[{"Bearer":[]}]}}},"definitions":{"MetadataValue":{"type":"object","properties":{"metaDataId":{"format":"int32","type":"integer"},"children":{"uniqueItems":false,"type":"array","items":{"$ref":"#/definitions/MetadataValue"},"readOnly":true},"metadataValueLanguages":{"uniqueItems":false,"type":"array","items":{"$ref":"#/definitions/MetadataValueLanguage"},"readOnly":true},"value":{"type":"string"}}},"MetadataValueLanguage":{"type":"object","properties":{"languageCode":{"type":"string"},"value":{"type":"string"}}},"ErrorDetail":{"type":"object","properties":{"errorMessage":{"type":"string"}}}},"securityDefinitions":{"Bearer":{"name":"Authorization","in":"header","type":"apiKey","description":"Standard Authorization header using the Bearer scheme. Example: \"bearer {token}\""}}}
Build command:
node_modules/.bin/swagger-angular-generator -s api.json -d src/api/forms