@oslo-flanders/swagger-generator 1.4.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 CHANGED
@@ -37,6 +37,10 @@ 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
+ | `--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 |
40
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` |
41
45
  | `--silent` | Suppress log messages | No | `true` or `false` (default) |
42
46
 
@@ -6,14 +6,14 @@ 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 getProbleemdetailsContent;
10
- private getProbleemdetailsLink;
9
+ private getProblemdetailsContent;
10
+ private getProblemdetailsLink;
11
11
  private getContact;
12
12
  private getLicense;
13
13
  private schemaExists;
14
14
  init(): Promise<void>;
15
15
  run(): Promise<void>;
16
- createSwagger(schemas: any, links: any): Object;
16
+ createSwagger(schemas: any, links?: any): Object;
17
17
  createSchemas(): Object;
18
18
  createLinks(): Object;
19
19
  writeOutput(outputFormat: OutputFormat, obj: Object, outputPath: string): Promise<void>;
@@ -53,23 +53,23 @@ let SwaggerGenerationService = class SwaggerGenerationService {
53
53
  this.configuration = config;
54
54
  this.store = store;
55
55
  }
56
- getProbleemdetailsContent() {
56
+ getProblemdetailsContent() {
57
57
  return {
58
58
  [core_1.OutputFormat.JsonProblem]: {
59
59
  schema: {
60
- $ref: '#/components/schemas/Probleemdetail',
60
+ $ref: '#/components/schemas/Problemdetail',
61
61
  },
62
62
  },
63
63
  };
64
64
  }
65
- getProbleemdetailsLink(label) {
65
+ getProblemdetailsLink(label) {
66
66
  return {
67
- 'Probleemdetail.type': {
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 `ProblemDetails` op te halen.',
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
  }
@@ -110,7 +110,9 @@ let SwaggerGenerationService = class SwaggerGenerationService {
110
110
  var _a;
111
111
  /* Create schemas and links once, then write for each output format */
112
112
  const schemas = this.createSchemas();
113
- const links = this.createLinks();
113
+ const links = this.configuration.disableLinks
114
+ ? {}
115
+ : this.createLinks();
114
116
  /* Create self-standing referenceable components */
115
117
  const components = {
116
118
  openapi: this.configuration.versionSwagger,
@@ -121,7 +123,10 @@ let SwaggerGenerationService = class SwaggerGenerationService {
121
123
  license: this.getLicense(),
122
124
  version: this.configuration.versionAPI,
123
125
  },
124
- components: { schemas, links },
126
+ components: {
127
+ schemas,
128
+ ...(Object.keys(links).length > 0 ? { links } : {}),
129
+ },
125
130
  };
126
131
  /* Create Swagger endpoint paths as example */
127
132
  const swagger = this.createSwagger(schemas, links);
@@ -135,7 +140,7 @@ let SwaggerGenerationService = class SwaggerGenerationService {
135
140
  await this.writeOutput(format, swagger, `swagger/example${ext}`);
136
141
  }
137
142
  }
138
- createSwagger(schemas, links) {
143
+ createSwagger(schemas, links = {}) {
139
144
  var _a, _b, _c;
140
145
  const swagger = {
141
146
  openapi: this.configuration.versionSwagger,
@@ -159,6 +164,9 @@ let SwaggerGenerationService = class SwaggerGenerationService {
159
164
  for (const classId of this.store.findSubjects(core_1.ns.rdf('type'), core_1.ns.owl('Class'))) {
160
165
  if (hasRootClasses && !this.store.isRootClass(classId))
161
166
  continue;
167
+ /* Abstract classes should never be materialized as endpoint */
168
+ if (this.store.isAbstractClass(classId))
169
+ continue;
162
170
  const filteredLinks = {};
163
171
  let label = (_a = (0, core_1.getApplicationProfileLabel)(classId, this.store, this.configuration.language)) === null || _a === void 0 ? void 0 : _a.value;
164
172
  const definition = (_b = (0, core_1.getApplicationProfileDefinition)(classId, this.store, this.configuration.language)) === null || _b === void 0 ? void 0 : _b.value;
@@ -205,53 +213,55 @@ let SwaggerGenerationService = class SwaggerGenerationService {
205
213
  },
206
214
  },
207
215
  },
208
- links: filteredLinks,
216
+ ...(Object.keys(filteredLinks).length > 0
217
+ ? { links: filteredLinks }
218
+ : {}),
209
219
  },
210
220
  /* Error codes follow the RFC 7807 */
211
221
  400: {
212
222
  description: 'Invalid data supplied.',
213
- content: this.getProbleemdetailsContent(),
214
- links: this.getProbleemdetailsLink(label),
223
+ content: this.getProblemdetailsContent(),
224
+ links: this.getProblemdetailsLink(label),
215
225
  },
216
226
  401: {
217
227
  description: 'Invalid authorization.',
218
- content: this.getProbleemdetailsContent(),
219
- links: this.getProbleemdetailsLink(label),
228
+ content: this.getProblemdetailsContent(),
229
+ links: this.getProblemdetailsLink(label),
220
230
  },
221
231
  403: {
222
232
  description: 'Authentication failed.',
223
- content: this.getProbleemdetailsContent(),
224
- links: this.getProbleemdetailsLink(label),
233
+ content: this.getProblemdetailsContent(),
234
+ links: this.getProblemdetailsLink(label),
225
235
  },
226
236
  404: {
227
237
  description: 'Resource not found.',
228
- content: this.getProbleemdetailsContent(),
229
- links: this.getProbleemdetailsLink(label),
238
+ content: this.getProblemdetailsContent(),
239
+ links: this.getProblemdetailsLink(label),
230
240
  },
231
241
  412: {
232
242
  description: 'Pre-condition failed.',
233
- content: this.getProbleemdetailsContent(),
234
- links: this.getProbleemdetailsLink(label),
243
+ content: this.getProblemdetailsContent(),
244
+ links: this.getProblemdetailsLink(label),
235
245
  },
236
246
  500: {
237
247
  description: 'Unexpected Server Error.',
238
- content: this.getProbleemdetailsContent(),
239
- links: this.getProbleemdetailsLink(label),
248
+ content: this.getProblemdetailsContent(),
249
+ links: this.getProblemdetailsLink(label),
240
250
  },
241
251
  502: {
242
252
  description: 'Bad Gateway.',
243
- content: this.getProbleemdetailsContent(),
244
- links: this.getProbleemdetailsLink(label),
253
+ content: this.getProblemdetailsContent(),
254
+ links: this.getProblemdetailsLink(label),
245
255
  },
246
256
  503: {
247
257
  description: 'Service unavailable.',
248
- content: this.getProbleemdetailsContent(),
249
- links: this.getProbleemdetailsLink(label),
258
+ content: this.getProblemdetailsContent(),
259
+ links: this.getProblemdetailsLink(label),
250
260
  },
251
261
  504: {
252
262
  description: 'Gateway Timeout.',
253
- content: this.getProbleemdetailsContent(),
254
- links: this.getProbleemdetailsLink(label),
263
+ content: this.getProblemdetailsContent(),
264
+ links: this.getProblemdetailsLink(label),
255
265
  },
256
266
  },
257
267
  },
@@ -261,6 +271,32 @@ let SwaggerGenerationService = class SwaggerGenerationService {
261
271
  swagger.components = {
262
272
  schemas: {},
263
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
+ };
264
300
  for (const schemaLabel of Object.keys(schemas))
265
301
  swagger.components.schemas[schemaLabel] = schemas[schemaLabel];
266
302
  return swagger;
@@ -375,9 +411,17 @@ let SwaggerGenerationService = class SwaggerGenerationService {
375
411
  this.logger.error(`Unknown cardinality for attribute ${attributeId.value}`);
376
412
  continue;
377
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
+ }
378
422
  /* Arrays must be introduced into the schema if the max cardinality is 2 or more */
379
423
  const description = `${attributeDefinition}${attributeUsageNote ? ' ' + attributeUsageNote : ''}`;
380
- 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);
381
425
  // If mapProperties returns nothing, the property pointed to an excluded class (this.configuration.excludeClasses)
382
426
  if (!properties) {
383
427
  continue;
@@ -390,13 +434,22 @@ let SwaggerGenerationService = class SwaggerGenerationService {
390
434
  if (isPrimitive) {
391
435
  /* Wrap primitive property in its own named schema to avoid naming collisions */
392
436
  const schemaName = `${label}.${attributeLabel}`;
393
- schemas[schemaName] = {
394
- title: schemaName,
395
- type: 'object',
396
- description: description,
397
- properties: properties,
398
- required: requiredProperties,
399
- };
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
+ }
400
453
  item = { $ref: `#/components/schemas/${schemaName}` };
401
454
  }
402
455
  else {
@@ -530,7 +583,10 @@ let SwaggerGenerationService = class SwaggerGenerationService {
530
583
  async writeOutput(outputFormat, obj, outputPath) {
531
584
  const isYaml = outputFormat === core_1.OutputFormat.Yaml;
532
585
  const data = isYaml
533
- ? yaml.dump(JSON.parse(JSON.stringify(obj)), { noRefs: true, lineWidth: -1 })
586
+ ? yaml.dump(JSON.parse(JSON.stringify(obj)), {
587
+ noRefs: true,
588
+ lineWidth: -1,
589
+ })
534
590
  : JSON.stringify(obj, null, 2);
535
591
  const filePath = path.join(this.configuration.output, outputPath);
536
592
  (0, core_1.ensureOutputDirectory)(path.dirname(filePath));
@@ -41,6 +41,26 @@ class SwaggerGenerationServiceRunner extends core_1.AppRunner {
41
41
  describe: 'A list of property names to exclude from the output.',
42
42
  type: 'string',
43
43
  array: true,
44
+ })
45
+ .option('disableLinks', {
46
+ describe: 'Disable the creation of links.',
47
+ default: false,
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,
44
64
  })
45
65
  .option('silent', {
46
66
  describe: 'All logs are suppressed',
@@ -69,6 +69,22 @@ export declare class SwaggerGenerationServiceConfiguration implements IConfigura
69
69
  * Output formats
70
70
  */
71
71
  private _outputFormat;
72
+ /**
73
+ * Whether to disable the creation of links
74
+ */
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;
72
88
  createFromCli(params: YargsParams): Promise<void>;
73
89
  get input(): string;
74
90
  get output(): string;
@@ -87,4 +103,8 @@ export declare class SwaggerGenerationServiceConfiguration implements IConfigura
87
103
  get excludeClasses(): string[];
88
104
  get excludeProperties(): string[];
89
105
  get outputFormat(): OutputFormat[];
106
+ get disableLinks(): boolean;
107
+ get expanded(): boolean;
108
+ get excludeClassesExpanded(): string[];
109
+ get excludePropertiesExpanded(): string[];
90
110
  }
@@ -28,6 +28,10 @@ let SwaggerGenerationServiceConfiguration = class SwaggerGenerationServiceConfig
28
28
  this._excludeClasses = params.excludeClasses;
29
29
  this._excludeProperties = params.excludeProperties;
30
30
  this._outputFormat = params.outputFormat;
31
+ this._disableLinks = params.disableLinks;
32
+ this._expanded = params.expanded;
33
+ this._excludeClassesExpanded = params.excludeClassesExpanded;
34
+ this._excludePropertiesExpanded = (params.excludePropertiesExpanded);
31
35
  }
32
36
  get input() {
33
37
  if (!this._input) {
@@ -104,6 +108,18 @@ let SwaggerGenerationServiceConfiguration = class SwaggerGenerationServiceConfig
104
108
  get outputFormat() {
105
109
  return this._outputFormat || [core_1.OutputFormat.Json];
106
110
  }
111
+ get disableLinks() {
112
+ return !!this._disableLinks;
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
+ }
107
123
  };
108
124
  SwaggerGenerationServiceConfiguration = __decorate([
109
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;
@@ -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 Properties = new Map([
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 (Properties.has(datatype)) {
39
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
40
- return Properties.get(datatype);
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": "1.4.0",
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",