@e22m4u/js-openapi 0.0.6 → 0.0.8

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.
@@ -73,6 +73,18 @@ var OADocumentObjectValidationError = class extends import_js_format.Errorf {
73
73
  static {
74
74
  __name(this, "OADocumentObjectValidationError");
75
75
  }
76
+ /**
77
+ * Instance path.
78
+ *
79
+ * @type {string|undefined}
80
+ */
81
+ instancePath;
82
+ /**
83
+ * Reason.
84
+ *
85
+ * @type {string|undefined}
86
+ */
87
+ reason;
76
88
  };
77
89
 
78
90
  // src/oa-specification.js
@@ -148,6 +160,7 @@ var OAMediaType = {
148
160
  TEXT_HTML: "text/html",
149
161
  APPLICATION_XML: "application/xml",
150
162
  APPLICATION_JSON: "application/json",
163
+ APPLICATION_OCTET_STREAM: "application/octet-stream",
151
164
  MULTIPART_FORM_DATA: "multipart/form-data"
152
165
  };
153
166
  var OASecuritySchemeType = {
@@ -1806,7 +1819,7 @@ var OA_DOCUMENT_OBJECT_JSON_SCHEMA_URI = "https://spec.openapis.org/oas/3.1/sche
1806
1819
  ajv.getSchema(OA_DOCUMENT_OBJECT_JSON_SCHEMA_URI);
1807
1820
 
1808
1821
  // src/oa-document-object/validate-oa-document-object.js
1809
- function validateOADocumentObject(data, options = {}) {
1822
+ function validateOADocumentObject(instance, options = {}) {
1810
1823
  if (!options || typeof options !== "object" || Array.isArray(options)) {
1811
1824
  throw new import_js_format5.InvalidArgumentError(
1812
1825
  'Parameter "options" must be an Object, but %v was given.',
@@ -1821,30 +1834,35 @@ function validateOADocumentObject(data, options = {}) {
1821
1834
  );
1822
1835
  }
1823
1836
  }
1824
- if (options.dataSourceUri !== void 0) {
1825
- if (typeof options.dataSourceUri !== "string") {
1837
+ if (options.sourceUri !== void 0) {
1838
+ if (typeof options.sourceUri !== "string") {
1826
1839
  throw new import_js_format5.InvalidArgumentError(
1827
- 'Option "dataSourceUri" must be a String, but %v was given.',
1828
- options.dataSourceUri
1840
+ 'Option "sourceUri" must be a String, but %v was given.',
1841
+ options.sourceUri
1829
1842
  );
1830
1843
  }
1831
1844
  }
1832
1845
  const validate = ajv.getSchema(
1833
1846
  `${OA_DOCUMENT_OBJECT_JSON_SCHEMA_URI}${options.schemaUri || ""}`
1834
1847
  );
1835
- const isValid = validate(data);
1848
+ const isValid = validate(instance);
1836
1849
  if (!isValid) {
1837
1850
  const error = validate.errors[0];
1838
1851
  let instancePath = error.instancePath || "";
1839
- let dataSourceUri = options.dataSourceUri || "";
1840
- if (!options.schemaUri && !options.dataSourceUri) {
1841
- dataSourceUri = "#";
1852
+ let sourceUri = options.sourceUri || "";
1853
+ if (!options.schemaUri && !options.sourceUri) {
1854
+ sourceUri = "#";
1842
1855
  }
1843
- throw new OADocumentObjectValidationError(
1856
+ const sourceUriWithInstancePath = sourceUri && instancePath ? [sourceUri, instancePath].join("/").replace(/\/+/g, "/") : sourceUri + instancePath;
1857
+ const errorReason = error.message.replace(/'/g, '"');
1858
+ const validationError = new OADocumentObjectValidationError(
1844
1859
  "Value at %v %s.",
1845
- dataSourceUri && error.instancePath ? [dataSourceUri, error.instancePath].join("/").replace(/\/+/g, "/") : dataSourceUri + instancePath,
1846
- error.message.replace(/'/g, '"')
1860
+ sourceUriWithInstancePath,
1861
+ errorReason
1847
1862
  );
1863
+ validationError.instancePath = error.instancePath;
1864
+ validationError.reason = errorReason;
1865
+ throw validationError;
1848
1866
  }
1849
1867
  }
1850
1868
  __name(validateOADocumentObject, "validateOADocumentObject");
@@ -1997,7 +2015,7 @@ var OADocumentBuilder = class extends import_js_service.Service {
1997
2015
  }
1998
2016
  validateOADocumentObject(component, {
1999
2017
  schemaUri: `#/$defs/${definitionName}`,
2000
- dataSourceUri: `#/components/${componentsKey}/${escapeJsonPointer(name)}`
2018
+ sourceUri: `#/components/${componentsKey}/${escapeJsonPointer(name)}`
2001
2019
  });
2002
2020
  this._document.components = this._document.components || {};
2003
2021
  this._document.components[componentsKey] = this._document.components[componentsKey] || {};
@@ -2228,7 +2246,7 @@ var OADocumentBuilder = class extends import_js_service.Service {
2228
2246
  }
2229
2247
  validateOADocumentObject(operationDef.operation, {
2230
2248
  schemaUri: "#/$defs/operation",
2231
- dataSourceUri: `/paths/${escapeJsonPointer(operationDef.path)}/${escapeJsonPointer(operationDef.method)}`
2249
+ sourceUri: `#/paths/${escapeJsonPointer(operationDef.path)}/${escapeJsonPointer(operationDef.method)}`
2232
2250
  });
2233
2251
  }
2234
2252
  const operation = operationDef.operation ? structuredClone(operationDef.operation) : {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e22m4u/js-openapi",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "JavaScript модуль для создания OpenAPI Документа",
5
5
  "author": "Mikhail Evstropov <e22m4u@yandex.ru>",
6
6
  "license": "MIT",
@@ -36,14 +36,14 @@
36
36
  "prepare": "husky"
37
37
  },
38
38
  "dependencies": {
39
- "@e22m4u/js-format": "~0.3.2",
39
+ "@e22m4u/js-format": "~0.4.0",
40
40
  "@e22m4u/js-service": "~0.5.1",
41
- "ajv": "~8.17.1",
41
+ "ajv": "~8.18.0",
42
42
  "ajv-formats": "~3.0.1"
43
43
  },
44
44
  "devDependencies": {
45
- "@commitlint/cli": "~20.4.1",
46
- "@commitlint/config-conventional": "~20.4.1",
45
+ "@commitlint/cli": "~20.4.2",
46
+ "@commitlint/config-conventional": "~20.4.2",
47
47
  "@eslint/js": "~9.39.2",
48
48
  "@types/chai": "~5.2.3",
49
49
  "@types/mocha": "~10.0.10",
@@ -54,13 +54,13 @@
54
54
  "eslint-config-prettier": "~10.1.8",
55
55
  "eslint-plugin-chai-expect": "~3.1.0",
56
56
  "eslint-plugin-import": "~2.32.0",
57
- "eslint-plugin-jsdoc": "~62.5.4",
57
+ "eslint-plugin-jsdoc": "~62.7.1",
58
58
  "eslint-plugin-mocha": "~11.2.0",
59
59
  "globals": "~17.3.0",
60
60
  "husky": "~9.1.7",
61
61
  "mocha": "~11.7.5",
62
62
  "prettier": "~3.8.1",
63
- "rimraf": "~6.1.2",
63
+ "rimraf": "~6.1.3",
64
64
  "typescript": "~5.9.3"
65
65
  }
66
66
  }
@@ -3,4 +3,14 @@ import {Errorf} from '@e22m4u/js-format';
3
3
  /**
4
4
  * Document object validation error.
5
5
  */
6
- export declare class OADocumentObjectValidationError extends Errorf {}
6
+ export declare class OADocumentObjectValidationError extends Errorf {
7
+ /**
8
+ * Instance path.
9
+ */
10
+ readonly instancePath?: string;
11
+
12
+ /**
13
+ * Reason.
14
+ */
15
+ readonly reason?: string;
16
+ }
@@ -3,4 +3,18 @@ import {Errorf} from '@e22m4u/js-format';
3
3
  /**
4
4
  * Document object validation error.
5
5
  */
6
- export class OADocumentObjectValidationError extends Errorf {}
6
+ export class OADocumentObjectValidationError extends Errorf {
7
+ /**
8
+ * Instance path.
9
+ *
10
+ * @type {string|undefined}
11
+ */
12
+ instancePath;
13
+
14
+ /**
15
+ * Reason.
16
+ *
17
+ * @type {string|undefined}
18
+ */
19
+ reason;
20
+ }
@@ -3,8 +3,15 @@ import {Errorf} from '@e22m4u/js-format';
3
3
  import {OADocumentObjectValidationError} from './oa-document-object-validation-error.js';
4
4
 
5
5
  describe('OADocumentObjectValidationError', function () {
6
- it('should extend the Errorf class', function () {
7
- const error = new OADocumentObjectValidationError();
8
- expect(error).to.be.instanceof(Errorf);
6
+ describe('constructor', function () {
7
+ it('should extend Errorf class', function () {
8
+ const error = new OADocumentObjectValidationError();
9
+ expect(error).to.be.instanceof(Errorf);
10
+ });
11
+
12
+ it('should interpolate the given message with arguments', function () {
13
+ const error = new OADocumentObjectValidationError('%v and %v', 1, 2);
14
+ expect(error.message).to.be.eq('1 and 2');
15
+ });
9
16
  });
10
17
  });
@@ -198,7 +198,7 @@ export class OADocumentBuilder extends Service {
198
198
  // validation
199
199
  validateOADocumentObject(component, {
200
200
  schemaUri: `#/$defs/${definitionName}`,
201
- dataSourceUri: `#/components/${componentsKey}/${escapeJsonPointer(name)}`,
201
+ sourceUri: `#/components/${componentsKey}/${escapeJsonPointer(name)}`,
202
202
  });
203
203
  this._document.components = this._document.components || {};
204
204
  this._document.components[componentsKey] =
@@ -467,7 +467,7 @@ export class OADocumentBuilder extends Service {
467
467
  // validation
468
468
  validateOADocumentObject(operationDef.operation, {
469
469
  schemaUri: '#/$defs/operation',
470
- dataSourceUri: `/paths/${escapeJsonPointer(operationDef.path)}/${escapeJsonPointer(operationDef.method)}`,
470
+ sourceUri: `#/paths/${escapeJsonPointer(operationDef.path)}/${escapeJsonPointer(operationDef.method)}`,
471
471
  });
472
472
  }
473
473
  // создание поверхностной копии определения
@@ -1282,7 +1282,10 @@ describe('OADocumentBuilder', function () {
1282
1282
  operation: {parameters: 123},
1283
1283
  });
1284
1284
  };
1285
- expect(throwable).to.throw(OADocumentObjectValidationError);
1285
+ expect(throwable).to.throw(
1286
+ OADocumentObjectValidationError,
1287
+ 'Value at "#/paths/~1/get/parameters" must be array.',
1288
+ );
1286
1289
  });
1287
1290
 
1288
1291
  it('should define the operation object', function () {
@@ -3,16 +3,16 @@
3
3
  */
4
4
  export type OADocumentObjectValidationOptions = {
5
5
  schemaUri?: string;
6
- dataSourceUri?: string;
6
+ sourceUri?: string;
7
7
  };
8
8
 
9
9
  /**
10
10
  * Validate OADocumentObject.
11
11
  *
12
- * @param data
12
+ * @param instance
13
13
  * @param options
14
14
  */
15
15
  export function validateOADocumentObject(
16
- data: any,
16
+ instance: any,
17
17
  options?: OADocumentObjectValidationOptions,
18
18
  ): void;
@@ -5,10 +5,19 @@ import {OADocumentObjectValidationError} from '../errors/index.js';
5
5
  /**
6
6
  * Validate OADocumentObject.
7
7
  *
8
- * @param {*} data
9
- * @param {*} options
8
+ * @param {*} instance Проверяемый экземпляр.
9
+ * @param {object} [options] Параметры проверки.
10
+ * @param {string} [options.schemaUri]
11
+ * URI участка JSON-схемы, согласно которому будет
12
+ * выполняться проверка (прим. "#/$defs/operation").
13
+ * Используется, если нужно проверить часть OpenAPI
14
+ * документа, когда в первый аргумент данной функции
15
+ * передается только проверяемый участок.
16
+ * @param {string} [options.sourceUri]
17
+ * Строка добавляется префиксом к URI проблемного
18
+ * значения в сообщении об ошибке (прим. "#/paths/~1/get").
10
19
  */
11
- export function validateOADocumentObject(data, options = {}) {
20
+ export function validateOADocumentObject(instance, options = {}) {
12
21
  if (!options || typeof options !== 'object' || Array.isArray(options)) {
13
22
  throw new InvalidArgumentError(
14
23
  'Parameter "options" must be an Object, but %v was given.',
@@ -23,31 +32,49 @@ export function validateOADocumentObject(data, options = {}) {
23
32
  );
24
33
  }
25
34
  }
26
- if (options.dataSourceUri !== undefined) {
27
- if (typeof options.dataSourceUri !== 'string') {
35
+ if (options.sourceUri !== undefined) {
36
+ if (typeof options.sourceUri !== 'string') {
28
37
  throw new InvalidArgumentError(
29
- 'Option "dataSourceUri" must be a String, but %v was given.',
30
- options.dataSourceUri,
38
+ 'Option "sourceUri" must be a String, but %v was given.',
39
+ options.sourceUri,
31
40
  );
32
41
  }
33
42
  }
34
43
  const validate = ajv.getSchema(
35
44
  `${OA_DOCUMENT_OBJECT_JSON_SCHEMA_URI}${options.schemaUri || ''}`,
36
45
  );
37
- const isValid = validate(data);
46
+ const isValid = validate(instance);
38
47
  if (!isValid) {
39
48
  const error = validate.errors[0];
40
49
  let instancePath = error.instancePath || '';
41
- let dataSourceUri = options.dataSourceUri || '';
42
- if (!options.schemaUri && !options.dataSourceUri) {
43
- dataSourceUri = '#';
50
+ let sourceUri = options.sourceUri || '';
51
+ // если URI схемы и источника экземпляра не определен,
52
+ // значит ошибка вызвана при проверке целого OpenAPI
53
+ // документа, и в таком случае, сообщение об ошибке
54
+ // должно содержать путь экземпляра с префиксом "#",
55
+ // указывающем на корень документа, пример: "#/info"
56
+ if (!options.schemaUri && !options.sourceUri) {
57
+ sourceUri = '#';
44
58
  }
45
- throw new OADocumentObjectValidationError(
59
+ // если передан URI источника экземпляра, то значение
60
+ // объединяется с путем экземпляра косой чертой,
61
+ // пример: "#/components/schemas/city" + "/type"
62
+ const sourceUriWithInstancePath =
63
+ sourceUri && instancePath
64
+ ? [sourceUri, instancePath].join('/').replace(/\/+/g, '/')
65
+ : sourceUri + instancePath;
66
+ const errorReason = error.message.replace(/'/g, '"');
67
+ // при создании ошибки выполняется интерполяция сообщения,
68
+ // пример: Value at "#" must have required property "info".
69
+ const validationError = new OADocumentObjectValidationError(
46
70
  'Value at %v %s.',
47
- dataSourceUri && error.instancePath
48
- ? [dataSourceUri, error.instancePath].join('/').replace(/\/+/g, '/')
49
- : dataSourceUri + instancePath,
50
- error.message.replace(/'/g, '"'),
71
+ sourceUriWithInstancePath,
72
+ errorReason,
51
73
  );
74
+ // в экземпляр ошибки устанавливаются
75
+ // дополнительные свойства из данных AJV
76
+ validationError.instancePath = error.instancePath;
77
+ validationError.reason = errorReason;
78
+ throw validationError;
52
79
  }
53
80
  }
@@ -1,6 +1,6 @@
1
1
  import {expect} from 'chai';
2
- import {validateOADocumentObject} from './validate-oa-document-object.js';
3
2
  import {format} from '@e22m4u/js-format';
3
+ import {validateOADocumentObject} from './validate-oa-document-object.js';
4
4
 
5
5
  const VALID_DOC_SAMPLE = {
6
6
  openapi: '3.1.2',
@@ -44,11 +44,11 @@ describe('validateOADocumentObject', function () {
44
44
  throwable(undefined)();
45
45
  });
46
46
 
47
- it('should require the option "dataSourceUri" to be a String', function () {
47
+ it('should require the option "sourceUri" to be a String', function () {
48
48
  const throwable = v => () =>
49
- validateOADocumentObject(VALID_DOC_SAMPLE, {dataSourceUri: v});
49
+ validateOADocumentObject(VALID_DOC_SAMPLE, {sourceUri: v});
50
50
  const error = s =>
51
- format('Option "dataSourceUri" must be a String, but %s was given.', s);
51
+ format('Option "sourceUri" must be a String, but %s was given.', s);
52
52
  expect(throwable(10)).to.throw(error('10'));
53
53
  expect(throwable(0)).to.throw(error('0'));
54
54
  expect(throwable(true)).to.throw(error('true'));
@@ -105,13 +105,13 @@ describe('validateOADocumentObject', function () {
105
105
  );
106
106
  });
107
107
 
108
- it('should add the "dataSourceUri" option as prefix to the instance path', function () {
108
+ it('should add the option "sourceUri" as a path prefix to the error message', function () {
109
109
  const throwable = () =>
110
110
  validateOADocumentObject(
111
111
  {type: 123},
112
112
  {
113
113
  schemaUri: '#/$defs/schema',
114
- dataSourceUri: '#/components/schemas/mySchema',
114
+ sourceUri: '#/components/schemas/mySchema',
115
115
  },
116
116
  );
117
117
  expect(throwable).to.throw(
@@ -119,4 +119,18 @@ describe('validateOADocumentObject', function () {
119
119
  'must be equal to one of the allowed values.',
120
120
  );
121
121
  });
122
+
123
+ it('should set the "instancePath" and "reason" properties to the validation error', function () {
124
+ let isCaught = false;
125
+ try {
126
+ validateOADocumentObject({type: 123}, {schemaUri: '#/$defs/schema'});
127
+ } catch (error) {
128
+ isCaught = true;
129
+ expect(error.instancePath).to.be.eql('/type');
130
+ expect(error.reason).to.be.eq(
131
+ 'must be equal to one of the allowed values',
132
+ );
133
+ }
134
+ expect(isCaught).to.be.true;
135
+ });
122
136
  });
@@ -421,6 +421,7 @@ export declare const OAMediaType: {
421
421
  TEXT_HTML: 'text/html';
422
422
  APPLICATION_XML: 'application/xml';
423
423
  APPLICATION_JSON: 'application/json';
424
+ APPLICATION_OCTET_STREAM: 'application/octet-stream';
424
425
  MULTIPART_FORM_DATA: 'multipart/form-data';
425
426
  };
426
427
 
@@ -106,6 +106,7 @@ export const OAMediaType = {
106
106
  TEXT_HTML: 'text/html',
107
107
  APPLICATION_XML: 'application/xml',
108
108
  APPLICATION_JSON: 'application/json',
109
+ APPLICATION_OCTET_STREAM: 'application/octet-stream',
109
110
  MULTIPART_FORM_DATA: 'multipart/form-data',
110
111
  };
111
112