@oslo-flanders/swagger-generator 1.5.0 → 2.0.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.
- package/README.md +4 -1
- package/lib/SwaggerGenerationService.d.ts +2 -2
- package/lib/SwaggerGenerationService.js +81 -32
- package/lib/SwaggerGenerationServiceRunner.js +15 -0
- package/lib/config/SwaggerGenerationServiceConfiguration.d.ts +15 -0
- package/lib/config/SwaggerGenerationServiceConfiguration.js +12 -0
- package/lib/enums/Properties.d.ts +1 -1
- package/lib/enums/Properties.js +42 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,8 +37,11 @@ The service is executed from the CLI and expects the following parameters:
|
|
|
37
37
|
| `--licenseURL` | URL of the license of the API | No | |
|
|
38
38
|
| `--excludeClasses` | Classes to exclude from the generated Swagger | No | Persoon Organisatie Test |
|
|
39
39
|
| `--excludeProperties` | Properties to exclude from the generated Swagger | No | voornaam achternaam |
|
|
40
|
-
| `--outputFormat` | Output format for the generated files. Can be specified multiple times to generate multiple formats at once. | No | `application/json` (default) or `application/yaml` |
|
|
41
40
|
| `--disableLinks` | Disable the creation of links | No | `true` or `false` (default) |
|
|
41
|
+
| `--expanded` | Disable the creation of links | No | `true` or `false` (default) |
|
|
42
|
+
| `--excludeClassesExpanded` | Classes to exclude from expanding their properties in JSON-LD | No | Persoon Organisatie Test |
|
|
43
|
+
| `--excludePropertiesExpanded` | Properties to exclude from expanding in JSON-LD | No | voornaam achternaam |
|
|
44
|
+
| `--outputFormat` | Output format for the generated files. Can be specified multiple times to generate multiple formats at once. | No | `application/json` (default) or `application/yaml` |
|
|
42
45
|
| `--silent` | Suppress log messages | No | `true` or `false` (default) |
|
|
43
46
|
|
|
44
47
|
## Usage
|
|
@@ -6,8 +6,8 @@ export declare class SwaggerGenerationService implements IService {
|
|
|
6
6
|
readonly configuration: SwaggerGenerationServiceConfiguration;
|
|
7
7
|
readonly store: QuadStore;
|
|
8
8
|
constructor(logger: Logger, config: SwaggerGenerationServiceConfiguration, store: QuadStore);
|
|
9
|
-
private
|
|
10
|
-
private
|
|
9
|
+
private getProblemdetailsContent;
|
|
10
|
+
private getProblemdetailsLink;
|
|
11
11
|
private getContact;
|
|
12
12
|
private getLicense;
|
|
13
13
|
private schemaExists;
|
|
@@ -53,23 +53,23 @@ let SwaggerGenerationService = class SwaggerGenerationService {
|
|
|
53
53
|
this.configuration = config;
|
|
54
54
|
this.store = store;
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
getProblemdetailsContent() {
|
|
57
57
|
return {
|
|
58
58
|
[core_1.OutputFormat.JsonProblem]: {
|
|
59
59
|
schema: {
|
|
60
|
-
$ref: '#/components/schemas/
|
|
60
|
+
$ref: '#/components/schemas/Problemdetail',
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
-
|
|
65
|
+
getProblemdetailsLink(label) {
|
|
66
66
|
return {
|
|
67
|
-
'
|
|
67
|
+
'Problemdetail.type': {
|
|
68
68
|
operationId: `${label}GET`,
|
|
69
69
|
parameters: {
|
|
70
70
|
type: `$response.body#/type`,
|
|
71
71
|
},
|
|
72
|
-
description: 'De waarde van het attribuut `type` kan gebruikt worden om het gerefereerde object van het type `
|
|
72
|
+
description: 'De waarde van het attribuut `type` kan gebruikt worden om het gerefereerde object van het type `Problemdetail` op te halen.',
|
|
73
73
|
},
|
|
74
74
|
};
|
|
75
75
|
}
|
|
@@ -164,6 +164,9 @@ let SwaggerGenerationService = class SwaggerGenerationService {
|
|
|
164
164
|
for (const classId of this.store.findSubjects(core_1.ns.rdf('type'), core_1.ns.owl('Class'))) {
|
|
165
165
|
if (hasRootClasses && !this.store.isRootClass(classId))
|
|
166
166
|
continue;
|
|
167
|
+
/* Abstract classes should never be materialized as endpoint */
|
|
168
|
+
if (this.store.isAbstractClass(classId))
|
|
169
|
+
continue;
|
|
167
170
|
const filteredLinks = {};
|
|
168
171
|
let label = (_a = (0, core_1.getApplicationProfileLabel)(classId, this.store, this.configuration.language)) === null || _a === void 0 ? void 0 : _a.value;
|
|
169
172
|
const definition = (_b = (0, core_1.getApplicationProfileDefinition)(classId, this.store, this.configuration.language)) === null || _b === void 0 ? void 0 : _b.value;
|
|
@@ -217,48 +220,48 @@ let SwaggerGenerationService = class SwaggerGenerationService {
|
|
|
217
220
|
/* Error codes follow the RFC 7807 */
|
|
218
221
|
400: {
|
|
219
222
|
description: 'Invalid data supplied.',
|
|
220
|
-
content: this.
|
|
221
|
-
links: this.
|
|
223
|
+
content: this.getProblemdetailsContent(),
|
|
224
|
+
links: this.getProblemdetailsLink(label),
|
|
222
225
|
},
|
|
223
226
|
401: {
|
|
224
227
|
description: 'Invalid authorization.',
|
|
225
|
-
content: this.
|
|
226
|
-
links: this.
|
|
228
|
+
content: this.getProblemdetailsContent(),
|
|
229
|
+
links: this.getProblemdetailsLink(label),
|
|
227
230
|
},
|
|
228
231
|
403: {
|
|
229
232
|
description: 'Authentication failed.',
|
|
230
|
-
content: this.
|
|
231
|
-
links: this.
|
|
233
|
+
content: this.getProblemdetailsContent(),
|
|
234
|
+
links: this.getProblemdetailsLink(label),
|
|
232
235
|
},
|
|
233
236
|
404: {
|
|
234
237
|
description: 'Resource not found.',
|
|
235
|
-
content: this.
|
|
236
|
-
links: this.
|
|
238
|
+
content: this.getProblemdetailsContent(),
|
|
239
|
+
links: this.getProblemdetailsLink(label),
|
|
237
240
|
},
|
|
238
241
|
412: {
|
|
239
242
|
description: 'Pre-condition failed.',
|
|
240
|
-
content: this.
|
|
241
|
-
links: this.
|
|
243
|
+
content: this.getProblemdetailsContent(),
|
|
244
|
+
links: this.getProblemdetailsLink(label),
|
|
242
245
|
},
|
|
243
246
|
500: {
|
|
244
247
|
description: 'Unexpected Server Error.',
|
|
245
|
-
content: this.
|
|
246
|
-
links: this.
|
|
248
|
+
content: this.getProblemdetailsContent(),
|
|
249
|
+
links: this.getProblemdetailsLink(label),
|
|
247
250
|
},
|
|
248
251
|
502: {
|
|
249
252
|
description: 'Bad Gateway.',
|
|
250
|
-
content: this.
|
|
251
|
-
links: this.
|
|
253
|
+
content: this.getProblemdetailsContent(),
|
|
254
|
+
links: this.getProblemdetailsLink(label),
|
|
252
255
|
},
|
|
253
256
|
503: {
|
|
254
257
|
description: 'Service unavailable.',
|
|
255
|
-
content: this.
|
|
256
|
-
links: this.
|
|
258
|
+
content: this.getProblemdetailsContent(),
|
|
259
|
+
links: this.getProblemdetailsLink(label),
|
|
257
260
|
},
|
|
258
261
|
504: {
|
|
259
262
|
description: 'Gateway Timeout.',
|
|
260
|
-
content: this.
|
|
261
|
-
links: this.
|
|
263
|
+
content: this.getProblemdetailsContent(),
|
|
264
|
+
links: this.getProblemdetailsLink(label),
|
|
262
265
|
},
|
|
263
266
|
},
|
|
264
267
|
},
|
|
@@ -268,6 +271,32 @@ let SwaggerGenerationService = class SwaggerGenerationService {
|
|
|
268
271
|
swagger.components = {
|
|
269
272
|
schemas: {},
|
|
270
273
|
};
|
|
274
|
+
/* Add minimal ProblemDetail in case it is not present, but needed for example Swagger */
|
|
275
|
+
swagger.components.schemas['Problemdetail'] = {
|
|
276
|
+
title: 'Problemdetail',
|
|
277
|
+
type: 'object',
|
|
278
|
+
description: 'Meer gedetailleerde beschrijving van de fout in een HTTP response.',
|
|
279
|
+
properties: {
|
|
280
|
+
type: {
|
|
281
|
+
type: 'string',
|
|
282
|
+
format: 'uri',
|
|
283
|
+
},
|
|
284
|
+
title: {
|
|
285
|
+
type: 'string',
|
|
286
|
+
},
|
|
287
|
+
status: {
|
|
288
|
+
type: 'integer',
|
|
289
|
+
format: 'int64',
|
|
290
|
+
},
|
|
291
|
+
detail: {
|
|
292
|
+
type: 'string',
|
|
293
|
+
},
|
|
294
|
+
instance: {
|
|
295
|
+
type: 'string',
|
|
296
|
+
format: 'uri',
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
};
|
|
271
300
|
for (const schemaLabel of Object.keys(schemas))
|
|
272
301
|
swagger.components.schemas[schemaLabel] = schemas[schemaLabel];
|
|
273
302
|
return swagger;
|
|
@@ -382,9 +411,17 @@ let SwaggerGenerationService = class SwaggerGenerationService {
|
|
|
382
411
|
this.logger.error(`Unknown cardinality for attribute ${attributeId.value}`);
|
|
383
412
|
continue;
|
|
384
413
|
}
|
|
414
|
+
/* Expanded JSON-LD depends on configuration */
|
|
415
|
+
let expanded = this.configuration.expanded;
|
|
416
|
+
if (this.configuration.excludeClassesExpanded.includes(label)) {
|
|
417
|
+
expanded = false;
|
|
418
|
+
}
|
|
419
|
+
if (this.configuration.excludePropertiesExpanded.includes(`${label}.${attributeLabel}`)) {
|
|
420
|
+
expanded = false;
|
|
421
|
+
}
|
|
385
422
|
/* Arrays must be introduced into the schema if the max cardinality is 2 or more */
|
|
386
423
|
const description = `${attributeDefinition}${attributeUsageNote ? ' ' + attributeUsageNote : ''}`;
|
|
387
|
-
const properties = (0, Properties_1.mapProperties)(attributeDatatypeId, attributeDatatypeLabel, subclasses, attributeDatatypeAbstract, this.configuration.excludeClasses);
|
|
424
|
+
const properties = (0, Properties_1.mapProperties)(attributeDatatypeId, attributeDatatypeLabel, subclasses, attributeDatatypeAbstract, this.configuration.excludeClasses, expanded);
|
|
388
425
|
// If mapProperties returns nothing, the property pointed to an excluded class (this.configuration.excludeClasses)
|
|
389
426
|
if (!properties) {
|
|
390
427
|
continue;
|
|
@@ -397,13 +434,22 @@ let SwaggerGenerationService = class SwaggerGenerationService {
|
|
|
397
434
|
if (isPrimitive) {
|
|
398
435
|
/* Wrap primitive property in its own named schema to avoid naming collisions */
|
|
399
436
|
const schemaName = `${label}.${attributeLabel}`;
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
437
|
+
if (expanded) {
|
|
438
|
+
schemas[schemaName] = {
|
|
439
|
+
title: schemaName,
|
|
440
|
+
type: 'object',
|
|
441
|
+
description: description,
|
|
442
|
+
properties: properties,
|
|
443
|
+
required: requiredProperties,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
schemas[schemaName] = {
|
|
448
|
+
title: schemaName,
|
|
449
|
+
description: description,
|
|
450
|
+
...properties,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
407
453
|
item = { $ref: `#/components/schemas/${schemaName}` };
|
|
408
454
|
}
|
|
409
455
|
else {
|
|
@@ -537,7 +583,10 @@ let SwaggerGenerationService = class SwaggerGenerationService {
|
|
|
537
583
|
async writeOutput(outputFormat, obj, outputPath) {
|
|
538
584
|
const isYaml = outputFormat === core_1.OutputFormat.Yaml;
|
|
539
585
|
const data = isYaml
|
|
540
|
-
? yaml.dump(JSON.parse(JSON.stringify(obj)), {
|
|
586
|
+
? yaml.dump(JSON.parse(JSON.stringify(obj)), {
|
|
587
|
+
noRefs: true,
|
|
588
|
+
lineWidth: -1,
|
|
589
|
+
})
|
|
541
590
|
: JSON.stringify(obj, null, 2);
|
|
542
591
|
const filePath = path.join(this.configuration.output, outputPath);
|
|
543
592
|
(0, core_1.ensureOutputDirectory)(path.dirname(filePath));
|
|
@@ -46,6 +46,21 @@ class SwaggerGenerationServiceRunner extends core_1.AppRunner {
|
|
|
46
46
|
describe: 'Disable the creation of links.',
|
|
47
47
|
default: false,
|
|
48
48
|
boolean: true,
|
|
49
|
+
})
|
|
50
|
+
.option('expanded', {
|
|
51
|
+
describe: 'Use JSON-LD expanded format instead of default compact format.',
|
|
52
|
+
default: false,
|
|
53
|
+
boolean: true,
|
|
54
|
+
})
|
|
55
|
+
.option('excludeClassesExpanded', {
|
|
56
|
+
describe: 'A list of class names to exclude from expanding their properties with JSON-LD expansion.',
|
|
57
|
+
type: 'string',
|
|
58
|
+
array: true,
|
|
59
|
+
})
|
|
60
|
+
.option('excludePropertiesExpanded', {
|
|
61
|
+
describe: 'A list of property names to exclude from JSON-LD expansion.',
|
|
62
|
+
type: 'string',
|
|
63
|
+
array: true,
|
|
49
64
|
})
|
|
50
65
|
.option('silent', {
|
|
51
66
|
describe: 'All logs are suppressed',
|
|
@@ -73,6 +73,18 @@ export declare class SwaggerGenerationServiceConfiguration implements IConfigura
|
|
|
73
73
|
* Whether to disable the creation of links
|
|
74
74
|
*/
|
|
75
75
|
private _disableLinks;
|
|
76
|
+
/**
|
|
77
|
+
* Whether to use expanded JSON-LD format or not
|
|
78
|
+
*/
|
|
79
|
+
private _expanded;
|
|
80
|
+
/**
|
|
81
|
+
* An array of class names to be excluded from expansion
|
|
82
|
+
*/
|
|
83
|
+
private _excludeClassesExpanded;
|
|
84
|
+
/**
|
|
85
|
+
* An array of property names to be excluded from expansion
|
|
86
|
+
*/
|
|
87
|
+
private _excludePropertiesExpanded;
|
|
76
88
|
createFromCli(params: YargsParams): Promise<void>;
|
|
77
89
|
get input(): string;
|
|
78
90
|
get output(): string;
|
|
@@ -92,4 +104,7 @@ export declare class SwaggerGenerationServiceConfiguration implements IConfigura
|
|
|
92
104
|
get excludeProperties(): string[];
|
|
93
105
|
get outputFormat(): OutputFormat[];
|
|
94
106
|
get disableLinks(): boolean;
|
|
107
|
+
get expanded(): boolean;
|
|
108
|
+
get excludeClassesExpanded(): string[];
|
|
109
|
+
get excludePropertiesExpanded(): string[];
|
|
95
110
|
}
|
|
@@ -29,6 +29,9 @@ let SwaggerGenerationServiceConfiguration = class SwaggerGenerationServiceConfig
|
|
|
29
29
|
this._excludeProperties = params.excludeProperties;
|
|
30
30
|
this._outputFormat = params.outputFormat;
|
|
31
31
|
this._disableLinks = params.disableLinks;
|
|
32
|
+
this._expanded = params.expanded;
|
|
33
|
+
this._excludeClassesExpanded = params.excludeClassesExpanded;
|
|
34
|
+
this._excludePropertiesExpanded = (params.excludePropertiesExpanded);
|
|
32
35
|
}
|
|
33
36
|
get input() {
|
|
34
37
|
if (!this._input) {
|
|
@@ -108,6 +111,15 @@ let SwaggerGenerationServiceConfiguration = class SwaggerGenerationServiceConfig
|
|
|
108
111
|
get disableLinks() {
|
|
109
112
|
return !!this._disableLinks;
|
|
110
113
|
}
|
|
114
|
+
get expanded() {
|
|
115
|
+
return !!this._expanded;
|
|
116
|
+
}
|
|
117
|
+
get excludeClassesExpanded() {
|
|
118
|
+
return this._excludeClassesExpanded || [];
|
|
119
|
+
}
|
|
120
|
+
get excludePropertiesExpanded() {
|
|
121
|
+
return this._excludePropertiesExpanded || [];
|
|
122
|
+
}
|
|
111
123
|
};
|
|
112
124
|
SwaggerGenerationServiceConfiguration = __decorate([
|
|
113
125
|
(0, inversify_1.injectable)()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const mapProperties: (datatype: string, label: string, subclasses: string[], abstract: boolean, excludeClasses: string[]) => object | undefined;
|
|
1
|
+
export declare const mapProperties: (datatype: string, label: string, subclasses: string[], abstract: boolean, excludeClasses: string[], expanded: boolean) => object | undefined;
|
package/lib/enums/Properties.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.mapProperties = void 0;
|
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-loss-of-precision */
|
|
5
5
|
const core_1 = require("@oslo-flanders/core");
|
|
6
6
|
/* eslint-disable max-len */
|
|
7
|
-
const
|
|
7
|
+
const PropertiesExpanded = new Map([
|
|
8
8
|
[core_1.ns.rdf('langString').value, { '@value': { type: 'string' }, '@language': { type: 'string', pattern: '^nl$' } }],
|
|
9
9
|
[core_1.ns.rdfs('Literal').value, { '@value': { type: 'string' }, '@type': { type: 'string' } }],
|
|
10
10
|
[core_1.ns.xsd('string').value, { '@value': { type: 'string' } }],
|
|
@@ -32,12 +32,49 @@ const Properties = new Map([
|
|
|
32
32
|
[core_1.ns.xsd('decimal').value, { '@value': { type: 'string', pattern: '(+|-)?([0-9]+(.[0-9]*)?|.[0-9]+)' }, '@type': { type: 'string', pattern: '^Decimal$' } }],
|
|
33
33
|
[core_1.ns.xsd('language').value, { '@value': { type: 'string', pattern: '^[a-z]{2,3}(-[A-Z]{2})?' }, '@type': { type: 'string', pattern: '^Language$' } }],
|
|
34
34
|
]);
|
|
35
|
+
/* JSON-LD context provides values for @type and @language for primitive datatypes */
|
|
36
|
+
const PropertiesCompacted = new Map([
|
|
37
|
+
[core_1.ns.rdf('langString').value, { type: 'string' }],
|
|
38
|
+
[core_1.ns.rdfs('Literal').value, { type: 'string' }],
|
|
39
|
+
[core_1.ns.xsd('string').value, { type: 'string' }],
|
|
40
|
+
[core_1.ns.xsd('anyURI').value, { type: 'string', format: 'uri' }],
|
|
41
|
+
[core_1.ns.xsd('dateTime').value, { type: 'string', format: 'date-time' }],
|
|
42
|
+
[core_1.ns.xsd('date').value, { type: 'string', format: 'date' }],
|
|
43
|
+
[core_1.ns.xsd('boolean').value, { type: 'boolean' }],
|
|
44
|
+
[core_1.ns.xsd('integer').value, { type: 'number', format: 'int64' }],
|
|
45
|
+
[core_1.ns.xsd('long').value, { type: 'number', format: 'int64', minimum: -9223372036854776000, maximum: 9223372036854776000 }],
|
|
46
|
+
[core_1.ns.xsd('float').value, { type: 'number', format: 'float' }],
|
|
47
|
+
[core_1.ns.xsd('double').value, { type: 'number', format: 'double' }],
|
|
48
|
+
[core_1.ns.xsd('int').value, { type: 'number', format: 'int32', minimum: -2147483648, maximum: 2147483647 }],
|
|
49
|
+
[core_1.ns.xsd('short').value, { type: 'number', format: 'int32', minimum: -32768, maximum: 32767 }],
|
|
50
|
+
[core_1.ns.xsd('byte').value, { type: 'number', format: 'int32', minimum: -128, maximum: 127 }],
|
|
51
|
+
[core_1.ns.xsd('hexBinary').value, { type: 'string', format: 'binary' }],
|
|
52
|
+
[core_1.ns.xsd('base64Binary').value, { type: 'string', format: 'byte' }],
|
|
53
|
+
[core_1.ns.xsd('nonNegativeInteger').value, { type: 'number', format: 'int64' }],
|
|
54
|
+
[core_1.ns.xsd('nonPositiveInteger').value, { type: 'number', format: 'int64' }],
|
|
55
|
+
[core_1.ns.xsd('negativeInteger').value, { type: 'number', format: 'int64', maximum: 0 }],
|
|
56
|
+
[core_1.ns.xsd('positiveInteger').value, { type: 'number', format: 'int64', minimum: 1 }],
|
|
57
|
+
[core_1.ns.xsd('unsignedLong').value, { type: 'number', format: 'int64', minimum: 0, maximum: 18446744073709552000 }],
|
|
58
|
+
[core_1.ns.xsd('unsignedInt').value, { type: 'number', format: 'int32', minimum: 0, maximum: 4294967295 }],
|
|
59
|
+
[core_1.ns.xsd('unsignedShort').value, { type: 'number', format: 'int32', minimum: 0, maximum: 65535 }],
|
|
60
|
+
[core_1.ns.xsd('unsignedByte').value, { type: 'number', format: 'int32', minimum: 0, maximum: 255 }],
|
|
61
|
+
[core_1.ns.xsd('decimal').value, { type: 'string', pattern: '(+|-)?([0-9]+(.[0-9]*)?|.[0-9]+)' }],
|
|
62
|
+
[core_1.ns.xsd('language').value, { type: 'string', pattern: '^[a-z]{2,3}(-[A-Z]{2})?' }],
|
|
63
|
+
]);
|
|
35
64
|
/* eslint-enable max-len*/
|
|
36
|
-
const mapProperties = (datatype, label, subclasses, abstract, excludeClasses) => {
|
|
65
|
+
const mapProperties = (datatype, label, subclasses, abstract, excludeClasses, expanded) => {
|
|
37
66
|
/* Primitive data type conversion from Linked Data to Swagger */
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
|
|
67
|
+
if (expanded) {
|
|
68
|
+
if (PropertiesExpanded.has(datatype)) {
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
70
|
+
return PropertiesExpanded.get(datatype);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
if (PropertiesCompacted.has(datatype)) {
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
76
|
+
return PropertiesCompacted.get(datatype);
|
|
77
|
+
}
|
|
41
78
|
}
|
|
42
79
|
const oneOf = [];
|
|
43
80
|
// Add the superclass to the list if it's not abstract and not excluded
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oslo-flanders/swagger-generator",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Generate OpenAPI Swagger YAML documentation.",
|
|
5
5
|
"author": "Digitaal Vlaanderen <https://data.vlaanderen.be/id/organisatie/OVO002949>",
|
|
6
6
|
"homepage": "https://github.com/informatievlaanderen/OSLO-UML-Transformer/tree/main/packages/oslo-generator-swagger#readme",
|