@amritk/lint 0.3.2 → 0.4.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/AI.md +55 -0
- package/dist/core/document.js +12 -10
- package/dist/core/formats.js +10 -13
- package/dist/core/glob.js +96 -118
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.js +30 -11
- package/dist/core/jsonpath.js +487 -561
- package/dist/core/lint.js +78 -85
- package/dist/core/plugin.js +21 -29
- package/dist/core/pointers.js +107 -151
- package/dist/core/ruleset.js +0 -0
- package/dist/core/runner.js +214 -272
- package/dist/core/types.js +4 -1
- package/dist/core/validate-ruleset.js +98 -112
- package/dist/fix/apply.d.ts +1 -1
- package/dist/fix/apply.js +58 -96
- package/dist/fix/index.js +7 -2
- package/dist/fix/plugin.js +15 -20
- package/dist/fix/types.d.ts +1 -1
- package/dist/functions/alphabetical.d.ts +1 -1
- package/dist/functions/alphabetical.js +39 -50
- package/dist/functions/casing.d.ts +1 -1
- package/dist/functions/casing.js +39 -45
- package/dist/functions/defined.d.ts +1 -1
- package/dist/functions/defined.js +7 -5
- package/dist/functions/enumeration.d.ts +1 -1
- package/dist/functions/enumeration.js +15 -25
- package/dist/functions/falsy.d.ts +1 -1
- package/dist/functions/falsy.js +7 -5
- package/dist/functions/index.d.ts +1 -1
- package/dist/functions/index.js +60 -44
- package/dist/functions/length.d.ts +1 -1
- package/dist/functions/length.js +22 -32
- package/dist/functions/or.d.ts +1 -1
- package/dist/functions/or.js +18 -24
- package/dist/functions/pattern.d.ts +1 -1
- package/dist/functions/pattern.js +39 -49
- package/dist/functions/schema.d.ts +1 -1
- package/dist/functions/schema.js +93 -119
- package/dist/functions/truthy.d.ts +1 -1
- package/dist/functions/truthy.js +7 -5
- package/dist/functions/typed-enum.d.ts +1 -1
- package/dist/functions/typed-enum.js +33 -36
- package/dist/functions/undefined.d.ts +1 -1
- package/dist/functions/undefined.js +7 -8
- package/dist/functions/unreferenced-reusable-object.d.ts +1 -1
- package/dist/functions/unreferenced-reusable-object.js +35 -47
- package/dist/functions/xor.d.ts +1 -1
- package/dist/functions/xor.js +13 -16
- package/dist/index.d.ts +17 -4
- package/dist/index.js +149 -164
- package/dist/parsers/edit-model.js +316 -444
- package/dist/parsers/index.d.ts +1 -1
- package/dist/parsers/index.js +23 -19
- package/dist/parsers/json.js +39 -37
- package/dist/parsers/lines.js +23 -26
- package/dist/parsers/types.js +9 -7
- package/dist/parsers/yaml.js +137 -204
- package/dist/rules/openapi/fixers.js +166 -221
- package/dist/rules/openapi/formats.js +26 -27
- package/dist/rules/openapi/functions/example-validation.d.ts +1 -1
- package/dist/rules/openapi/functions/example-validation.js +98 -138
- package/dist/rules/openapi/functions/helpers.js +8 -10
- package/dist/rules/openapi/functions/index.d.ts +1 -1
- package/dist/rules/openapi/functions/index.js +98 -72
- package/dist/rules/openapi/functions/oas-additional-operations.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-additional-operations.js +16 -22
- package/dist/rules/openapi/functions/oas-discriminator.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-discriminator.js +24 -22
- package/dist/rules/openapi/functions/oas-example-external-value.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-example-external-value.js +13 -21
- package/dist/rules/openapi/functions/oas-example-value.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-example-value.js +24 -27
- package/dist/rules/openapi/functions/oas-mutually-exclusive.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-mutually-exclusive.js +15 -19
- package/dist/rules/openapi/functions/oas-no-nullable.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-no-nullable.js +13 -21
- package/dist/rules/openapi/functions/oas-op-form-data-consume-check.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-op-form-data-consume-check.js +21 -19
- package/dist/rules/openapi/functions/oas-op-id-unique.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-op-id-unique.js +27 -27
- package/dist/rules/openapi/functions/oas-op-params.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-op-params.js +36 -42
- package/dist/rules/openapi/functions/oas-op-security-defined.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-op-security-defined.js +40 -39
- package/dist/rules/openapi/functions/oas-op-success-response.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-op-success-response.js +11 -13
- package/dist/rules/openapi/functions/oas-path-param.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-path-param.js +75 -96
- package/dist/rules/openapi/functions/oas-schema-example-deprecated.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-schema-example-deprecated.js +33 -40
- package/dist/rules/openapi/functions/oas-schema.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-schema.js +9 -14
- package/dist/rules/openapi/functions/oas-server-name-unique.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-server-name-unique.js +21 -19
- package/dist/rules/openapi/functions/oas-server-variables.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-server-variables.js +45 -49
- package/dist/rules/openapi/functions/oas-tag-defined.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-tag-defined.js +20 -20
- package/dist/rules/openapi/functions/oas-tag-kind.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-tag-kind.js +16 -16
- package/dist/rules/openapi/functions/oas-tag-parent-defined.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-tag-parent-defined.js +40 -43
- package/dist/rules/openapi/functions/oas-tags-unique.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-tags-unique.js +18 -16
- package/dist/rules/openapi/functions/oas-unused-component.d.ts +1 -1
- package/dist/rules/openapi/functions/oas-unused-component.js +48 -58
- package/dist/rules/openapi/functions/ref-siblings.d.ts +1 -1
- package/dist/rules/openapi/functions/ref-siblings.js +13 -11
- package/dist/rules/openapi/index.d.ts +2 -1
- package/dist/rules/openapi/index.js +99 -117
- package/dist/rules/openapi/oas.d.ts +1 -1
- package/dist/rules/openapi/oas.js +524 -536
- package/dist/rules/openapi/schemas/index.js +17 -33
- package/dist/rules/openapi/schemas/oas20.json +1 -1592
- package/dist/rules/openapi/schemas/oas30.json +1 -1651
- package/dist/rules/openapi/schemas/oas31.json +1 -1412
- package/dist/rules/openapi/schemas/oas32.json +1 -1684
- package/package.json +11 -6
|
@@ -1,31 +1,28 @@
|
|
|
1
|
-
import { isObject } from
|
|
2
|
-
// OpenAPI 3.2 Example Object exclusivity (MUST-level, per the spec's field
|
|
3
|
-
// table). The `value`/`externalValue` pair is intentionally omitted here — the
|
|
4
|
-
// 3.x-wide `oas3-examples-value-or-externalValue` rule already covers it, so we
|
|
5
|
-
// only police the constraints introduced with the new `dataValue` /
|
|
6
|
-
// `serializedValue` fields to avoid double-reporting.
|
|
1
|
+
import { isObject } from "./helpers.js";
|
|
7
2
|
const EXAMPLE_EXCLUSIONS = [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
// dataValue MUST NOT accompany value.
|
|
4
|
+
{ field: "dataValue", conflicts: ["value"] },
|
|
5
|
+
// serializedValue MUST NOT accompany value or externalValue.
|
|
6
|
+
{ field: "serializedValue", conflicts: ["value", "externalValue"] }
|
|
12
7
|
];
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
}
|
|
8
|
+
const oasExampleValue = (example, _options, context) => {
|
|
9
|
+
if (!isObject(example))
|
|
10
|
+
return [];
|
|
11
|
+
const results = [];
|
|
12
|
+
for (const { field, conflicts } of EXAMPLE_EXCLUSIONS) {
|
|
13
|
+
if (example[field] === void 0)
|
|
14
|
+
continue;
|
|
15
|
+
for (const other of conflicts) {
|
|
16
|
+
if (example[other] !== void 0) {
|
|
17
|
+
results.push({
|
|
18
|
+
message: `"${field}" must not be used together with "${other}"`,
|
|
19
|
+
path: [...context.path, other]
|
|
20
|
+
});
|
|
21
|
+
}
|
|
29
22
|
}
|
|
30
|
-
|
|
23
|
+
}
|
|
24
|
+
return results;
|
|
25
|
+
};
|
|
26
|
+
export {
|
|
27
|
+
oasExampleValue
|
|
31
28
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RulesetFunction } from '../../../core/
|
|
1
|
+
import type { RulesetFunction } from '../../../core/types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Flags objects that carry more than one of a set of mutually exclusive
|
|
4
4
|
* properties. OpenAPI 3.1's License Object, for example, defines `identifier`
|
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
import { isObject } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return conflicts.map((property) => ({
|
|
17
|
-
message: `"${property}" must not be used together with "${anchor}" (mutually exclusive)`,
|
|
18
|
-
path: [...context.path, property],
|
|
19
|
-
}));
|
|
1
|
+
import { isObject } from "./helpers.js";
|
|
2
|
+
const oasMutuallyExclusive = (input, options, context) => {
|
|
3
|
+
if (!isObject(input))
|
|
4
|
+
return [];
|
|
5
|
+
const present = (options?.properties ?? []).filter((property) => input[property] !== void 0);
|
|
6
|
+
if (present.length <= 1)
|
|
7
|
+
return [];
|
|
8
|
+
const [anchor, ...conflicts] = present;
|
|
9
|
+
return conflicts.map((property) => ({
|
|
10
|
+
message: `"${property}" must not be used together with "${anchor}" (mutually exclusive)`,
|
|
11
|
+
path: [...context.path, property]
|
|
12
|
+
}));
|
|
13
|
+
};
|
|
14
|
+
export {
|
|
15
|
+
oasMutuallyExclusive
|
|
20
16
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RulesetFunction } from '../../../core/
|
|
1
|
+
import type { RulesetFunction } from '../../../core/types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Flags a Schema Object's `nullable` keyword, removed in OpenAPI 3.1+ (JSON
|
|
4
4
|
* Schema 2020-12 uses a `"null"` type instead). Targets the *parent* of a
|
|
@@ -1,22 +1,14 @@
|
|
|
1
|
-
import { isObject } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if (!isObject(parent) || typeof parent['nullable'] !== 'boolean')
|
|
15
|
-
return [];
|
|
16
|
-
return [
|
|
17
|
-
{
|
|
18
|
-
message: 'nullable is not available in OpenAPI 3.1 or later; use a "null" type instead.',
|
|
19
|
-
path: [...context.path, 'nullable'],
|
|
20
|
-
},
|
|
21
|
-
];
|
|
1
|
+
import { isObject } from "./helpers.js";
|
|
2
|
+
const oasNoNullable = (parent, _options, context) => {
|
|
3
|
+
if (!isObject(parent) || typeof parent["nullable"] !== "boolean")
|
|
4
|
+
return [];
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
message: 'nullable is not available in OpenAPI 3.1 or later; use a "null" type instead.',
|
|
8
|
+
path: [...context.path, "nullable"]
|
|
9
|
+
}
|
|
10
|
+
];
|
|
11
|
+
};
|
|
12
|
+
export {
|
|
13
|
+
oasNoNullable
|
|
22
14
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { RulesetFunction } from '../../../core/
|
|
1
|
+
import type { RulesetFunction } from '../../../core/types.js';
|
|
2
2
|
/** Validates OpenAPI v2 formData operations declare a compatible `consumes`. */
|
|
3
3
|
export declare const oasOpFormDataConsumeCheck: RulesetFunction;
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import { isObject } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if (!isObject(operation))
|
|
5
|
-
return [];
|
|
6
|
-
const params = Array.isArray(operation['parameters']) ? operation['parameters'] : [];
|
|
7
|
-
const hasFormData = params.some((param) => isObject(param) && param['in'] === 'formData');
|
|
8
|
-
if (!hasFormData)
|
|
9
|
-
return [];
|
|
10
|
-
const consumes = Array.isArray(operation['consumes']) ? operation['consumes'] : [];
|
|
11
|
-
const ok = consumes.some((type) => type === 'application/x-www-form-urlencoded' || type === 'multipart/form-data');
|
|
12
|
-
if (!ok) {
|
|
13
|
-
return [
|
|
14
|
-
{
|
|
15
|
-
message: 'Operations with formData parameters must consume application/x-www-form-urlencoded or multipart/form-data',
|
|
16
|
-
path: [...context.path, 'consumes'],
|
|
17
|
-
},
|
|
18
|
-
];
|
|
19
|
-
}
|
|
1
|
+
import { isObject } from "./helpers.js";
|
|
2
|
+
const oasOpFormDataConsumeCheck = (operation, _options, context) => {
|
|
3
|
+
if (!isObject(operation))
|
|
20
4
|
return [];
|
|
5
|
+
const params = Array.isArray(operation["parameters"]) ? operation["parameters"] : [];
|
|
6
|
+
const hasFormData = params.some((param) => isObject(param) && param["in"] === "formData");
|
|
7
|
+
if (!hasFormData)
|
|
8
|
+
return [];
|
|
9
|
+
const consumes = Array.isArray(operation["consumes"]) ? operation["consumes"] : [];
|
|
10
|
+
const ok = consumes.some((type) => type === "application/x-www-form-urlencoded" || type === "multipart/form-data");
|
|
11
|
+
if (!ok) {
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
message: "Operations with formData parameters must consume application/x-www-form-urlencoded or multipart/form-data",
|
|
15
|
+
path: [...context.path, "consumes"]
|
|
16
|
+
}
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
return [];
|
|
20
|
+
};
|
|
21
|
+
export {
|
|
22
|
+
oasOpFormDataConsumeCheck
|
|
21
23
|
};
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import { isObject, OPERATION_METHODS } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
seen.add(id);
|
|
26
|
-
}
|
|
1
|
+
import { isObject, OPERATION_METHODS } from "./helpers.js";
|
|
2
|
+
const oasOpIdUnique = (paths, _options, context) => {
|
|
3
|
+
if (!isObject(paths))
|
|
4
|
+
return [];
|
|
5
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6
|
+
const results = [];
|
|
7
|
+
for (const [path, item] of Object.entries(paths)) {
|
|
8
|
+
if (!isObject(item))
|
|
9
|
+
continue;
|
|
10
|
+
for (const [method, operation] of Object.entries(item)) {
|
|
11
|
+
if (!OPERATION_METHODS.has(method) || !isObject(operation))
|
|
12
|
+
continue;
|
|
13
|
+
const id = operation["operationId"];
|
|
14
|
+
if (typeof id !== "string")
|
|
15
|
+
continue;
|
|
16
|
+
if (seen.has(id)) {
|
|
17
|
+
results.push({
|
|
18
|
+
message: `operationId "${id}" must be unique`,
|
|
19
|
+
path: [...context.path, path, method, "operationId"]
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
seen.add(id);
|
|
27
23
|
}
|
|
28
|
-
|
|
24
|
+
}
|
|
25
|
+
return results;
|
|
26
|
+
};
|
|
27
|
+
export {
|
|
28
|
+
oasOpIdUnique
|
|
29
29
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RulesetFunction } from '../../../core/
|
|
1
|
+
import type { RulesetFunction } from '../../../core/types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Validates an operation's `parameters` array, mirroring Spectral's `oasOpParams`:
|
|
4
4
|
* flags duplicate `name`+`in` combinations, and — for OpenAPI 2.0, where the body
|
|
@@ -1,46 +1,40 @@
|
|
|
1
|
-
import { isObject } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (!
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const formDataIndices = [];
|
|
16
|
-
params.forEach((param, index) => {
|
|
17
|
-
if (!isObject(param) || '$ref' in param)
|
|
18
|
-
return;
|
|
19
|
-
if (param['name'] !== undefined && param['in'] !== undefined) {
|
|
20
|
-
const key = `${String(param['in'])}:${String(param['name'])}`;
|
|
21
|
-
if (seen.has(key)) {
|
|
22
|
-
results.push({
|
|
23
|
-
message: `Duplicate parameter "${String(param['name'])}" in "${String(param['in'])}"`,
|
|
24
|
-
path: [...context.path, index],
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
seen.add(key);
|
|
28
|
-
}
|
|
29
|
-
if (param['in'] === 'body')
|
|
30
|
-
bodyIndices.push(index);
|
|
31
|
-
else if (param['in'] === 'formData')
|
|
32
|
-
formDataIndices.push(index);
|
|
33
|
-
});
|
|
34
|
-
// OAS2 allows at most one body parameter, and body and formData are mutually
|
|
35
|
-
// exclusive within a single operation.
|
|
36
|
-
if (bodyIndices.length > 0 && formDataIndices.length > 0) {
|
|
37
|
-
results.push({ message: 'Operation must not have both "in:body" and "in:formData" parameters' });
|
|
38
|
-
}
|
|
39
|
-
for (let i = 1; i < bodyIndices.length; i++) {
|
|
1
|
+
import { isObject } from "./helpers.js";
|
|
2
|
+
const oasOpParams = (params, _options, context) => {
|
|
3
|
+
if (!Array.isArray(params))
|
|
4
|
+
return [];
|
|
5
|
+
const results = [];
|
|
6
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7
|
+
const bodyIndices = [];
|
|
8
|
+
const formDataIndices = [];
|
|
9
|
+
params.forEach((param, index) => {
|
|
10
|
+
if (!isObject(param) || "$ref" in param)
|
|
11
|
+
return;
|
|
12
|
+
if (param["name"] !== void 0 && param["in"] !== void 0) {
|
|
13
|
+
const key = `${String(param["in"])}:${String(param["name"])}`;
|
|
14
|
+
if (seen.has(key)) {
|
|
40
15
|
results.push({
|
|
41
|
-
|
|
42
|
-
|
|
16
|
+
message: `Duplicate parameter "${String(param["name"])}" in "${String(param["in"])}"`,
|
|
17
|
+
path: [...context.path, index]
|
|
43
18
|
});
|
|
19
|
+
}
|
|
20
|
+
seen.add(key);
|
|
44
21
|
}
|
|
45
|
-
|
|
22
|
+
if (param["in"] === "body")
|
|
23
|
+
bodyIndices.push(index);
|
|
24
|
+
else if (param["in"] === "formData")
|
|
25
|
+
formDataIndices.push(index);
|
|
26
|
+
});
|
|
27
|
+
if (bodyIndices.length > 0 && formDataIndices.length > 0) {
|
|
28
|
+
results.push({ message: 'Operation must not have both "in:body" and "in:formData" parameters' });
|
|
29
|
+
}
|
|
30
|
+
for (let i = 1; i < bodyIndices.length; i++) {
|
|
31
|
+
results.push({
|
|
32
|
+
message: 'Operation must not have more than a single instance of the "in:body" parameter',
|
|
33
|
+
path: [...context.path, bodyIndices[i]]
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return results;
|
|
37
|
+
};
|
|
38
|
+
export {
|
|
39
|
+
oasOpParams
|
|
46
40
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RulesetFunction } from '../../../core/
|
|
1
|
+
import type { RulesetFunction } from '../../../core/types.js';
|
|
2
2
|
/** Validates that every referenced security scheme is defined. */
|
|
3
3
|
export declare const oasOpSecurityDefined: RulesetFunction<Record<string, unknown>, {
|
|
4
4
|
schemesPath: string[];
|
|
@@ -1,44 +1,45 @@
|
|
|
1
|
-
import { isObject, OPERATION_METHODS } from
|
|
2
|
-
/** Walks `path` into `root`, returning the nested value or undefined. */
|
|
1
|
+
import { isObject, OPERATION_METHODS } from "./helpers.js";
|
|
3
2
|
const getIn = (root, path) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
let current = root;
|
|
4
|
+
for (const key of path) {
|
|
5
|
+
if (!isObject(current))
|
|
6
|
+
return void 0;
|
|
7
|
+
current = current[key];
|
|
8
|
+
}
|
|
9
|
+
return current;
|
|
11
10
|
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
results.push({ message: `Security scheme "${name}" is not defined`, path: [...path, index, name] });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
};
|
|
32
|
-
check(root['security'], [...context.path, 'security']);
|
|
33
|
-
const paths = isObject(root['paths']) ? root['paths'] : {};
|
|
34
|
-
for (const [path, item] of Object.entries(paths)) {
|
|
35
|
-
if (!isObject(item))
|
|
36
|
-
continue;
|
|
37
|
-
for (const [method, operation] of Object.entries(item)) {
|
|
38
|
-
if (OPERATION_METHODS.has(method) && isObject(operation)) {
|
|
39
|
-
check(operation['security'], [...context.path, 'paths', path, method, 'security']);
|
|
40
|
-
}
|
|
11
|
+
const oasOpSecurityDefined = (root, options, context) => {
|
|
12
|
+
if (!isObject(root))
|
|
13
|
+
return [];
|
|
14
|
+
const schemes = getIn(root, options?.schemesPath ?? []);
|
|
15
|
+
const defined = new Set(isObject(schemes) ? Object.keys(schemes) : []);
|
|
16
|
+
const results = [];
|
|
17
|
+
const check = (security, path) => {
|
|
18
|
+
if (!Array.isArray(security))
|
|
19
|
+
return;
|
|
20
|
+
security.forEach((requirement, index) => {
|
|
21
|
+
if (!isObject(requirement))
|
|
22
|
+
return;
|
|
23
|
+
for (const name of Object.keys(requirement)) {
|
|
24
|
+
if (!defined.has(name)) {
|
|
25
|
+
results.push({ message: `Security scheme "${name}" is not defined`, path: [...path, index, name] });
|
|
41
26
|
}
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
check(root["security"], [...context.path, "security"]);
|
|
31
|
+
const paths = isObject(root["paths"]) ? root["paths"] : {};
|
|
32
|
+
for (const [path, item] of Object.entries(paths)) {
|
|
33
|
+
if (!isObject(item))
|
|
34
|
+
continue;
|
|
35
|
+
for (const [method, operation] of Object.entries(item)) {
|
|
36
|
+
if (OPERATION_METHODS.has(method) && isObject(operation)) {
|
|
37
|
+
check(operation["security"], [...context.path, "paths", path, method, "security"]);
|
|
38
|
+
}
|
|
42
39
|
}
|
|
43
|
-
|
|
40
|
+
}
|
|
41
|
+
return results;
|
|
42
|
+
};
|
|
43
|
+
export {
|
|
44
|
+
oasOpSecurityDefined
|
|
44
45
|
};
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import { isObject } from
|
|
2
|
-
// A success response is any 2xx/3xx status code, or a `2XX`/`3XX` wildcard (3.x).
|
|
3
|
-
// `default` is intentionally NOT counted — it can carry any status, including an
|
|
4
|
-
// error, so it does not prove the operation has a success response (this matches
|
|
5
|
-
// Spectral, which counts only codes in the [200, 400) range plus the wildcards).
|
|
1
|
+
import { isObject } from "./helpers.js";
|
|
6
2
|
const SUCCESS_CODE = /^[23](\d\d|XX)$/;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (!isObject(responses))
|
|
10
|
-
return [];
|
|
11
|
-
const hasSuccess = Object.keys(responses).some((code) => SUCCESS_CODE.test(code));
|
|
12
|
-
if (!hasSuccess) {
|
|
13
|
-
return [{ message: 'Operation must define at least one 2xx or 3xx response' }];
|
|
14
|
-
}
|
|
3
|
+
const oasOpSuccessResponse = (responses) => {
|
|
4
|
+
if (!isObject(responses))
|
|
15
5
|
return [];
|
|
6
|
+
const hasSuccess = Object.keys(responses).some((code) => SUCCESS_CODE.test(code));
|
|
7
|
+
if (!hasSuccess) {
|
|
8
|
+
return [{ message: "Operation must define at least one 2xx or 3xx response" }];
|
|
9
|
+
}
|
|
10
|
+
return [];
|
|
11
|
+
};
|
|
12
|
+
export {
|
|
13
|
+
oasOpSuccessResponse
|
|
16
14
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RulesetFunction } from '../../../core/
|
|
1
|
+
import type { RulesetFunction } from '../../../core/types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Validates path templating per operation, mirroring Spectral's `oasPathParam`.
|
|
4
4
|
* For each operation on a path it checks that (a) every `{template}` in the path
|