@scalar/openapi-validator 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specifications.d.ts","sourceRoot":"","sources":["../src/specifications.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKjC,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,qBAAqB,CAAA;AAE/D,eAAO,MAAM,eAAe,EAAyC,cAAc,EAAE,CAAA"}
@@ -0,0 +1,14 @@
1
+ import Swagger20 from './schemas/v2.0/schema.js';
2
+ import OpenApi30 from './schemas/v3.0/schema.js';
3
+ import OpenApi31 from './schemas/v3.1/schema.js';
4
+ import OpenApi32 from './schemas/v3.2/schema.js';
5
+ /**
6
+ * The OpenAPI/Swagger JSON Schemas supported by the validator, keyed by version.
7
+ */
8
+ export const OpenApiSpecifications = {
9
+ '2.0': Swagger20,
10
+ '3.0': OpenApi30,
11
+ '3.1': OpenApi31,
12
+ '3.2': OpenApi32,
13
+ };
14
+ export const OpenApiVersions = Object.keys(OpenApiSpecifications);
@@ -0,0 +1,17 @@
1
+ import type { ValidationOutcome as GenericValidationOutcome } from '@scalar/json-schema-validator';
2
+ import type { OpenApiVersion } from './specifications.js';
3
+ export type { ErrorObject } from '@scalar/json-schema-validator';
4
+ export type { OpenApiVersion } from './specifications.js';
5
+ export type ThrowOnErrorOption = {
6
+ /**
7
+ * If `true`, the function will throw an error if the document is invalid.
8
+ *
9
+ * @default false
10
+ */
11
+ throwOnError?: boolean;
12
+ };
13
+ /**
14
+ * The result of validating an OpenAPI document.
15
+ */
16
+ export type ValidationOutcome = GenericValidationOutcome<OpenApiVersion>;
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,IAAI,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AAElG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,YAAY,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAEhE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,cAAc,CAAC,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { AnyObject } from '@scalar/types/utils';
2
+ import type { ErrorObject } from './types.js';
3
+ /**
4
+ * Validates path-template semantics that are not enforced by the JSON schema.
5
+ */
6
+ export declare function validatePathParameters(specification: AnyObject): ErrorObject[];
7
+ //# sourceMappingURL=validate-path-parameters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-path-parameters.d.ts","sourceRoot":"","sources":["../src/validate-path-parameters.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAEpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAmB1C;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,SAAS,GAAG,WAAW,EAAE,CAoE9E"}
@@ -0,0 +1,90 @@
1
+ import { isObjectLike } from '@scalar/helpers/object/is-object';
2
+ import { deduplicateErrors } from '@scalar/json-schema-validator';
3
+ /**
4
+ * Any non-array object, whatever its prototype.
5
+ *
6
+ * `isObject` is deliberately not used here: it also rejects objects with a
7
+ * custom prototype, which would silently skip whole path items in a
8
+ * hand-constructed document rather than validating them.
9
+ */
10
+ const isRecord = (value) => isObjectLike(value) && !Array.isArray(value);
11
+ const OPERATION_KEYS = new Set(['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace']);
12
+ const PATH_PARAMETER_PATTERN = /{([^}]+)}/g;
13
+ /**
14
+ * Validates path-template semantics that are not enforced by the JSON schema.
15
+ */
16
+ export function validatePathParameters(specification) {
17
+ const paths = specification?.paths;
18
+ if (!paths || typeof paths !== 'object') {
19
+ return [];
20
+ }
21
+ const errors = [];
22
+ for (const [pathName, pathItem] of Object.entries(paths)) {
23
+ if (!isRecord(pathItem)) {
24
+ continue;
25
+ }
26
+ const operations = Object.entries(pathItem).filter(([key, value]) => OPERATION_KEYS.has(key) && isRecord(value));
27
+ // Preserve the repo's current behaviour for empty path items.
28
+ if (operations.length === 0) {
29
+ continue;
30
+ }
31
+ const templateParameters = new Set(getTemplateParameterNames(pathName));
32
+ const pathLevelParameters = getPathParameters(pathItem.parameters, ['paths', pathName, 'parameters']);
33
+ for (const parameter of pathLevelParameters) {
34
+ if (!templateParameters.has(parameter.name)) {
35
+ errors.push({
36
+ path: parameter.path,
37
+ message: `Path parameter "${parameter.name}" must have the corresponding {${parameter.name}} segment in the "${pathName}" path`,
38
+ });
39
+ }
40
+ }
41
+ for (const [operationKey, operation] of operations) {
42
+ const operationParameters = getPathParameters(operation.parameters, [
43
+ 'paths',
44
+ pathName,
45
+ operationKey,
46
+ 'parameters',
47
+ ]);
48
+ for (const parameter of operationParameters) {
49
+ if (!templateParameters.has(parameter.name)) {
50
+ errors.push({
51
+ path: parameter.path,
52
+ message: `Path parameter "${parameter.name}" must have the corresponding {${parameter.name}} segment in the "${pathName}" path`,
53
+ });
54
+ }
55
+ }
56
+ const effectiveParameters = new Set([...pathLevelParameters, ...operationParameters].map((parameter) => parameter.name));
57
+ for (const templateParameter of templateParameters) {
58
+ if (!effectiveParameters.has(templateParameter)) {
59
+ errors.push({
60
+ path: ['paths', pathName, operationKey],
61
+ message: `Declared path parameter "${templateParameter}" needs to be defined as a path parameter at either the path or operation level`,
62
+ });
63
+ }
64
+ }
65
+ }
66
+ }
67
+ return deduplicateErrors(errors);
68
+ }
69
+ function getTemplateParameterNames(pathName) {
70
+ return [...pathName.matchAll(PATH_PARAMETER_PATTERN)].map((match) => normalizeTemplateParameterName(match[1]));
71
+ }
72
+ function normalizeTemplateParameterName(name) {
73
+ return name.endsWith('+') ? name.slice(0, -1) : name;
74
+ }
75
+ function getPathParameters(parameters, pathPrefix) {
76
+ if (!Array.isArray(parameters)) {
77
+ return [];
78
+ }
79
+ return parameters.flatMap((parameter, index) => {
80
+ if (!isRecord(parameter) || parameter.in !== 'path' || typeof parameter.name !== 'string') {
81
+ return [];
82
+ }
83
+ return [
84
+ {
85
+ name: parameter.name,
86
+ path: [...pathPrefix, String(index), 'name'],
87
+ },
88
+ ];
89
+ });
90
+ }
@@ -0,0 +1,36 @@
1
+ import type { AnyObject } from '@scalar/types/utils';
2
+ import type { ThrowOnErrorOption, ValidationOutcome } from './types.js';
3
+ export type ValidateOptions = ThrowOnErrorOption & {
4
+ /**
5
+ * Run the path-parameter semantic checks (declared parameters match the
6
+ * `{template}` segments in the path, and vice versa).
7
+ *
8
+ * Off by default: these checks need a fully resolved document, because a path
9
+ * parameter can be declared through a `$ref`, and this validator does not
10
+ * resolve references — running them on an unresolved document would report
11
+ * false positives. Callers that resolve references first (bundle or
12
+ * dereference) can opt in; `@scalar/openapi-parser` leaves them off here and
13
+ * runs `validatePathParameters` on the resolved document itself.
14
+ *
15
+ * @default false
16
+ */
17
+ checkPathParameters?: boolean;
18
+ };
19
+ /**
20
+ * Validates a single OpenAPI document against the OpenAPI Specification.
21
+ *
22
+ * Schema validation is delegated to `@scalar/json-schema-validator`; version
23
+ * detection and the path-parameter semantic checks are OpenAPI-specific.
24
+ *
25
+ * This validator is strict about the specification: every required field,
26
+ * including `info.version`, must be present. Callers that want to be lenient
27
+ * (as `@scalar/openapi-parser` is) should fill in defaults before validating.
28
+ *
29
+ * The input must be a self-contained document. This validator does not resolve
30
+ * external `$ref`s, so bundle or dereference documents that span multiple files
31
+ * before validating them.
32
+ *
33
+ * @param document - A JSON string, a YAML string, or an object.
34
+ */
35
+ export declare function validate(document: string | AnyObject, options?: ValidateOptions): ValidationOutcome;
36
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAKpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAGpE,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAAG;IACjD;;;;;;;;;;;;OAYG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B,CAAA;AAeD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,iBAAiB,CAEnG"}
@@ -0,0 +1,35 @@
1
+ import { createSpecificationValidator } from '@scalar/json-schema-validator';
2
+ import { detectVersion } from './detect-version.js';
3
+ import { ERRORS } from './errors.js';
4
+ import { OpenApiSpecifications } from './specifications.js';
5
+ import { validatePathParameters } from './validate-path-parameters.js';
6
+ const validateDocument = createSpecificationValidator({
7
+ schemas: OpenApiSpecifications,
8
+ detectVersion,
9
+ // OpenAPI 3.1 and 3.2 use the media-range format.
10
+ formats: (version) => (version === '3.1' || version === '3.2' ? { 'media-range': true } : undefined),
11
+ errors: { emptyOrInvalid: ERRORS.EMPTY_OR_INVALID, versionNotSupported: ERRORS.OPENAPI_VERSION_NOT_SUPPORTED },
12
+ // Path-template semantics that the JSON schema cannot express. These need a
13
+ // fully resolved document (a path parameter can be declared via `$ref`), so
14
+ // they are opt-in: callers that resolve references first can enable them.
15
+ postValidate: (specification, _version, options) => options?.checkPathParameters ? validatePathParameters(specification) : [],
16
+ });
17
+ /**
18
+ * Validates a single OpenAPI document against the OpenAPI Specification.
19
+ *
20
+ * Schema validation is delegated to `@scalar/json-schema-validator`; version
21
+ * detection and the path-parameter semantic checks are OpenAPI-specific.
22
+ *
23
+ * This validator is strict about the specification: every required field,
24
+ * including `info.version`, must be present. Callers that want to be lenient
25
+ * (as `@scalar/openapi-parser` is) should fill in defaults before validating.
26
+ *
27
+ * The input must be a self-contained document. This validator does not resolve
28
+ * external `$ref`s, so bundle or dereference documents that span multiple files
29
+ * before validating them.
30
+ *
31
+ * @param document - A JSON string, a YAML string, or an object.
32
+ */
33
+ export function validate(document, options) {
34
+ return validateDocument(document, options);
35
+ }
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@scalar/openapi-validator",
3
+ "description": "Validate OpenAPI documents against the OpenAPI Specification",
4
+ "license": "MIT",
5
+ "author": "Scalar (https://github.com/scalar)",
6
+ "homepage": "https://github.com/scalar/scalar",
7
+ "bugs": "https://github.com/scalar/scalar/issues/new/choose",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/scalar/scalar.git",
11
+ "directory": "packages/openapi-validator"
12
+ },
13
+ "keywords": [
14
+ "openapi",
15
+ "scalar",
16
+ "swagger",
17
+ "validator",
18
+ "typescript"
19
+ ],
20
+ "version": "0.1.0",
21
+ "engines": {
22
+ "node": ">=22"
23
+ },
24
+ "type": "module",
25
+ "main": "./dist/index.js",
26
+ "module": "./dist/index.js",
27
+ "types": "./dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "import": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "default": "./dist/index.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "CHANGELOG.md"
38
+ ],
39
+ "sideEffects": false,
40
+ "dependencies": {
41
+ "yaml": "^2.9.0",
42
+ "@scalar/types": "0.18.3",
43
+ "@scalar/json-schema-validator": "0.1.0",
44
+ "@scalar/helpers": "0.11.2"
45
+ },
46
+ "devDependencies": {
47
+ "@tailwindcss/vite": "^4.3.3",
48
+ "@types/node": "^24.1.0",
49
+ "@vitejs/plugin-vue": "^6.0.8",
50
+ "tailwindcss": "^4.3.3",
51
+ "vite": "8.1.5",
52
+ "vue": "^3.5.40",
53
+ "@scalar/themes": "0.17.4",
54
+ "@scalar/use-codemirror": "0.14.15"
55
+ },
56
+ "scripts": {
57
+ "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
58
+ "dev": "pnpm playground",
59
+ "playground": "cd playground && vite",
60
+ "test": "vitest --run",
61
+ "types:check": "tsgo --noEmit"
62
+ }
63
+ }