@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.
- package/dist/cjs/index.cjs +32 -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-builder.spec.js +4 -1
- 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/src/oa-specification.d.ts +1 -0
- package/src/oa-specification.js +1 -0
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
|
|
@@ -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(
|
|
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.
|
|
1825
|
-
if (typeof options.
|
|
1837
|
+
if (options.sourceUri !== void 0) {
|
|
1838
|
+
if (typeof options.sourceUri !== "string") {
|
|
1826
1839
|
throw new import_js_format5.InvalidArgumentError(
|
|
1827
|
-
'Option "
|
|
1828
|
-
options.
|
|
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(
|
|
1848
|
+
const isValid = validate(instance);
|
|
1836
1849
|
if (!isValid) {
|
|
1837
1850
|
const error = validate.errors[0];
|
|
1838
1851
|
let instancePath = error.instancePath || "";
|
|
1839
|
-
let
|
|
1840
|
-
if (!options.schemaUri && !options.
|
|
1841
|
-
|
|
1852
|
+
let sourceUri = options.sourceUri || "";
|
|
1853
|
+
if (!options.schemaUri && !options.sourceUri) {
|
|
1854
|
+
sourceUri = "#";
|
|
1842
1855
|
}
|
|
1843
|
-
|
|
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
|
-
|
|
1846
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
// создание поверхностной копии определения
|
|
@@ -1282,7 +1282,10 @@ describe('OADocumentBuilder', function () {
|
|
|
1282
1282
|
operation: {parameters: 123},
|
|
1283
1283
|
});
|
|
1284
1284
|
};
|
|
1285
|
-
expect(throwable).to.throw(
|
|
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
|
-
|
|
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
|
});
|
|
@@ -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
|
|
package/src/oa-specification.js
CHANGED
|
@@ -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
|
|