@e22m4u/js-openapi 0.0.7 → 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.
- package/dist/cjs/index.cjs +31 -14
- package/package.json +7 -7
- package/src/errors/oa-document-object-validation-error.d.ts +11 -1
- package/src/errors/oa-document-object-validation-error.js +15 -1
- package/src/errors/oa-document-object-validation-error.spec.js +10 -3
- package/src/oa-document-builder.js +2 -2
- package/src/oa-document-object/validate-oa-document-object.d.ts +3 -3
- package/src/oa-document-object/validate-oa-document-object.js +43 -16
- package/src/oa-document-object/validate-oa-document-object.spec.js +20 -6
package/dist/cjs/index.cjs
CHANGED
|
@@ -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
|
|
@@ -1807,7 +1819,7 @@ var OA_DOCUMENT_OBJECT_JSON_SCHEMA_URI = "https://spec.openapis.org/oas/3.1/sche
|
|
|
1807
1819
|
ajv.getSchema(OA_DOCUMENT_OBJECT_JSON_SCHEMA_URI);
|
|
1808
1820
|
|
|
1809
1821
|
// src/oa-document-object/validate-oa-document-object.js
|
|
1810
|
-
function validateOADocumentObject(
|
|
1822
|
+
function validateOADocumentObject(instance, options = {}) {
|
|
1811
1823
|
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
1812
1824
|
throw new import_js_format5.InvalidArgumentError(
|
|
1813
1825
|
'Parameter "options" must be an Object, but %v was given.',
|
|
@@ -1822,30 +1834,35 @@ function validateOADocumentObject(data, options = {}) {
|
|
|
1822
1834
|
);
|
|
1823
1835
|
}
|
|
1824
1836
|
}
|
|
1825
|
-
if (options.
|
|
1826
|
-
if (typeof options.
|
|
1837
|
+
if (options.sourceUri !== void 0) {
|
|
1838
|
+
if (typeof options.sourceUri !== "string") {
|
|
1827
1839
|
throw new import_js_format5.InvalidArgumentError(
|
|
1828
|
-
'Option "
|
|
1829
|
-
options.
|
|
1840
|
+
'Option "sourceUri" must be a String, but %v was given.',
|
|
1841
|
+
options.sourceUri
|
|
1830
1842
|
);
|
|
1831
1843
|
}
|
|
1832
1844
|
}
|
|
1833
1845
|
const validate = ajv.getSchema(
|
|
1834
1846
|
`${OA_DOCUMENT_OBJECT_JSON_SCHEMA_URI}${options.schemaUri || ""}`
|
|
1835
1847
|
);
|
|
1836
|
-
const isValid = validate(
|
|
1848
|
+
const isValid = validate(instance);
|
|
1837
1849
|
if (!isValid) {
|
|
1838
1850
|
const error = validate.errors[0];
|
|
1839
1851
|
let instancePath = error.instancePath || "";
|
|
1840
|
-
let
|
|
1841
|
-
if (!options.schemaUri && !options.
|
|
1842
|
-
|
|
1852
|
+
let sourceUri = options.sourceUri || "";
|
|
1853
|
+
if (!options.schemaUri && !options.sourceUri) {
|
|
1854
|
+
sourceUri = "#";
|
|
1843
1855
|
}
|
|
1844
|
-
|
|
1856
|
+
const sourceUriWithInstancePath = sourceUri && instancePath ? [sourceUri, instancePath].join("/").replace(/\/+/g, "/") : sourceUri + instancePath;
|
|
1857
|
+
const errorReason = error.message.replace(/'/g, '"');
|
|
1858
|
+
const validationError = new OADocumentObjectValidationError(
|
|
1845
1859
|
"Value at %v %s.",
|
|
1846
|
-
|
|
1847
|
-
|
|
1860
|
+
sourceUriWithInstancePath,
|
|
1861
|
+
errorReason
|
|
1848
1862
|
);
|
|
1863
|
+
validationError.instancePath = error.instancePath;
|
|
1864
|
+
validationError.reason = errorReason;
|
|
1865
|
+
throw validationError;
|
|
1849
1866
|
}
|
|
1850
1867
|
}
|
|
1851
1868
|
__name(validateOADocumentObject, "validateOADocumentObject");
|
|
@@ -1998,7 +2015,7 @@ var OADocumentBuilder = class extends import_js_service.Service {
|
|
|
1998
2015
|
}
|
|
1999
2016
|
validateOADocumentObject(component, {
|
|
2000
2017
|
schemaUri: `#/$defs/${definitionName}`,
|
|
2001
|
-
|
|
2018
|
+
sourceUri: `#/components/${componentsKey}/${escapeJsonPointer(name)}`
|
|
2002
2019
|
});
|
|
2003
2020
|
this._document.components = this._document.components || {};
|
|
2004
2021
|
this._document.components[componentsKey] = this._document.components[componentsKey] || {};
|
|
@@ -2229,7 +2246,7 @@ var OADocumentBuilder = class extends import_js_service.Service {
|
|
|
2229
2246
|
}
|
|
2230
2247
|
validateOADocumentObject(operationDef.operation, {
|
|
2231
2248
|
schemaUri: "#/$defs/operation",
|
|
2232
|
-
|
|
2249
|
+
sourceUri: `#/paths/${escapeJsonPointer(operationDef.path)}/${escapeJsonPointer(operationDef.method)}`
|
|
2233
2250
|
});
|
|
2234
2251
|
}
|
|
2235
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.
|
|
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.
|
|
39
|
+
"@e22m4u/js-format": "~0.4.0",
|
|
40
40
|
"@e22m4u/js-service": "~0.5.1",
|
|
41
|
-
"ajv": "~8.
|
|
41
|
+
"ajv": "~8.18.0",
|
|
42
42
|
"ajv-formats": "~3.0.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@commitlint/cli": "~20.4.
|
|
46
|
-
"@commitlint/config-conventional": "~20.4.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
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
|
-
|
|
470
|
+
sourceUri: `#/paths/${escapeJsonPointer(operationDef.path)}/${escapeJsonPointer(operationDef.method)}`,
|
|
471
471
|
});
|
|
472
472
|
}
|
|
473
473
|
// создание поверхностной копии определения
|
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export type OADocumentObjectValidationOptions = {
|
|
5
5
|
schemaUri?: string;
|
|
6
|
-
|
|
6
|
+
sourceUri?: string;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Validate OADocumentObject.
|
|
11
11
|
*
|
|
12
|
-
* @param
|
|
12
|
+
* @param instance
|
|
13
13
|
* @param options
|
|
14
14
|
*/
|
|
15
15
|
export function validateOADocumentObject(
|
|
16
|
-
|
|
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 {*}
|
|
9
|
-
* @param {
|
|
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(
|
|
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.
|
|
27
|
-
if (typeof options.
|
|
35
|
+
if (options.sourceUri !== undefined) {
|
|
36
|
+
if (typeof options.sourceUri !== 'string') {
|
|
28
37
|
throw new InvalidArgumentError(
|
|
29
|
-
'Option "
|
|
30
|
-
options.
|
|
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(
|
|
46
|
+
const isValid = validate(instance);
|
|
38
47
|
if (!isValid) {
|
|
39
48
|
const error = validate.errors[0];
|
|
40
49
|
let instancePath = error.instancePath || '';
|
|
41
|
-
let
|
|
42
|
-
|
|
43
|
-
|
|
50
|
+
let sourceUri = options.sourceUri || '';
|
|
51
|
+
// если URI схемы и источника экземпляра не определен,
|
|
52
|
+
// значит ошибка вызвана при проверке целого OpenAPI
|
|
53
|
+
// документа, и в таком случае, сообщение об ошибке
|
|
54
|
+
// должно содержать путь экземпляра с префиксом "#",
|
|
55
|
+
// указывающем на корень документа, пример: "#/info"
|
|
56
|
+
if (!options.schemaUri && !options.sourceUri) {
|
|
57
|
+
sourceUri = '#';
|
|
44
58
|
}
|
|
45
|
-
|
|
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
|
-
|
|
48
|
-
|
|
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 "
|
|
47
|
+
it('should require the option "sourceUri" to be a String', function () {
|
|
48
48
|
const throwable = v => () =>
|
|
49
|
-
validateOADocumentObject(VALID_DOC_SAMPLE, {
|
|
49
|
+
validateOADocumentObject(VALID_DOC_SAMPLE, {sourceUri: v});
|
|
50
50
|
const error = s =>
|
|
51
|
-
format('Option "
|
|
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 "
|
|
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
|
-
|
|
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
|
});
|