@amritk/lint 0.3.2 → 0.3.3

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.
Files changed (72) hide show
  1. package/dist/core/document.js +12 -10
  2. package/dist/core/formats.js +10 -13
  3. package/dist/core/glob.js +96 -118
  4. package/dist/core/index.js +31 -11
  5. package/dist/core/jsonpath.js +487 -561
  6. package/dist/core/lint.js +78 -85
  7. package/dist/core/plugin.js +21 -29
  8. package/dist/core/pointers.js +107 -151
  9. package/dist/core/ruleset.js +0 -0
  10. package/dist/core/runner.js +214 -272
  11. package/dist/core/types.js +4 -1
  12. package/dist/core/validate-ruleset.js +98 -112
  13. package/dist/fix/apply.js +58 -96
  14. package/dist/fix/index.js +7 -2
  15. package/dist/fix/plugin.js +15 -20
  16. package/dist/functions/alphabetical.js +39 -50
  17. package/dist/functions/casing.js +39 -45
  18. package/dist/functions/defined.js +7 -5
  19. package/dist/functions/enumeration.js +15 -25
  20. package/dist/functions/falsy.js +7 -5
  21. package/dist/functions/index.js +60 -44
  22. package/dist/functions/length.js +22 -32
  23. package/dist/functions/or.js +18 -24
  24. package/dist/functions/pattern.js +39 -49
  25. package/dist/functions/schema.js +93 -119
  26. package/dist/functions/truthy.js +7 -5
  27. package/dist/functions/typed-enum.js +33 -36
  28. package/dist/functions/undefined.js +7 -8
  29. package/dist/functions/unreferenced-reusable-object.js +35 -47
  30. package/dist/functions/xor.js +13 -16
  31. package/dist/index.js +114 -164
  32. package/dist/parsers/edit-model.js +316 -444
  33. package/dist/parsers/index.js +22 -19
  34. package/dist/parsers/json.js +39 -37
  35. package/dist/parsers/lines.js +23 -26
  36. package/dist/parsers/types.js +9 -7
  37. package/dist/parsers/yaml.js +137 -204
  38. package/dist/rules/openapi/fixers.js +166 -221
  39. package/dist/rules/openapi/formats.js +26 -27
  40. package/dist/rules/openapi/functions/example-validation.js +98 -138
  41. package/dist/rules/openapi/functions/helpers.js +8 -10
  42. package/dist/rules/openapi/functions/index.js +98 -72
  43. package/dist/rules/openapi/functions/oas-additional-operations.js +16 -22
  44. package/dist/rules/openapi/functions/oas-discriminator.js +24 -22
  45. package/dist/rules/openapi/functions/oas-example-external-value.js +13 -21
  46. package/dist/rules/openapi/functions/oas-example-value.js +24 -27
  47. package/dist/rules/openapi/functions/oas-mutually-exclusive.js +15 -19
  48. package/dist/rules/openapi/functions/oas-no-nullable.js +13 -21
  49. package/dist/rules/openapi/functions/oas-op-form-data-consume-check.js +21 -19
  50. package/dist/rules/openapi/functions/oas-op-id-unique.js +27 -27
  51. package/dist/rules/openapi/functions/oas-op-params.js +36 -42
  52. package/dist/rules/openapi/functions/oas-op-security-defined.js +40 -39
  53. package/dist/rules/openapi/functions/oas-op-success-response.js +11 -13
  54. package/dist/rules/openapi/functions/oas-path-param.js +75 -96
  55. package/dist/rules/openapi/functions/oas-schema-example-deprecated.js +33 -40
  56. package/dist/rules/openapi/functions/oas-schema.js +9 -14
  57. package/dist/rules/openapi/functions/oas-server-name-unique.js +21 -19
  58. package/dist/rules/openapi/functions/oas-server-variables.js +45 -49
  59. package/dist/rules/openapi/functions/oas-tag-defined.js +20 -20
  60. package/dist/rules/openapi/functions/oas-tag-kind.js +16 -16
  61. package/dist/rules/openapi/functions/oas-tag-parent-defined.js +40 -43
  62. package/dist/rules/openapi/functions/oas-tags-unique.js +18 -16
  63. package/dist/rules/openapi/functions/oas-unused-component.js +48 -58
  64. package/dist/rules/openapi/functions/ref-siblings.js +13 -11
  65. package/dist/rules/openapi/index.js +99 -117
  66. package/dist/rules/openapi/oas.js +524 -536
  67. package/dist/rules/openapi/schemas/index.js +17 -33
  68. package/dist/rules/openapi/schemas/oas20.json +1 -1592
  69. package/dist/rules/openapi/schemas/oas30.json +1 -1651
  70. package/dist/rules/openapi/schemas/oas31.json +1 -1412
  71. package/dist/rules/openapi/schemas/oas32.json +1 -1684
  72. package/package.json +5 -5
@@ -1,6 +1,8 @@
1
- /** Flags a value that is `undefined`. */
2
- export const defined = (input) => {
3
- if (input === undefined)
4
- return [{ message: 'The value must be defined' }];
5
- return [];
1
+ const defined = (input) => {
2
+ if (input === void 0)
3
+ return [{ message: "The value must be defined" }];
4
+ return [];
5
+ };
6
+ export {
7
+ defined
6
8
  };
@@ -1,27 +1,17 @@
1
- /**
2
- * True for the primitive kinds Spectral's input schema accepts
3
- * (`string`, `number`, `null`, `boolean`). Objects and arrays are excluded so
4
- * they cannot slip through the reference-equality `includes` check below and be
5
- * flagged against a list they could never be `===` to.
6
- */
7
- const isPrimitive = (value) => value === null || (typeof value !== 'object' && typeof value !== 'function');
8
- /** Flags a value that is not one of the allowed `values`. */
9
- export const enumeration = (input, options) => {
10
- const values = options?.values;
11
- // Without a valid list of allowed values there is nothing to compare against.
12
- // Spectral requires `values` in its option schema and no-ops when it is
13
- // missing, so skip rather than flag everything against an empty allow-list.
14
- if (!Array.isArray(values))
15
- return [];
16
- // Spectral's input schema only lets primitives reach this function. `includes`
17
- // uses reference equality, so a non-primitive would always be reported as
18
- // "not allowed"; match Spectral by skipping objects and arrays entirely.
19
- if (!isPrimitive(input))
20
- return [];
21
- if (!values.includes(input)) {
22
- return [
23
- { message: `The value must be one of the allowed values: ${values.map((v) => JSON.stringify(v)).join(', ')}` },
24
- ];
25
- }
1
+ const isPrimitive = (value) => value === null || typeof value !== "object" && typeof value !== "function";
2
+ const enumeration = (input, options) => {
3
+ const values = options?.values;
4
+ if (!Array.isArray(values))
26
5
  return [];
6
+ if (!isPrimitive(input))
7
+ return [];
8
+ if (!values.includes(input)) {
9
+ return [
10
+ { message: `The value must be one of the allowed values: ${values.map((v) => JSON.stringify(v)).join(", ")}` }
11
+ ];
12
+ }
13
+ return [];
14
+ };
15
+ export {
16
+ enumeration
27
17
  };
@@ -1,6 +1,8 @@
1
- /** Flags a value that is not falsy. */
2
- export const falsy = (input) => {
3
- if (input)
4
- return [{ message: 'The value must be falsy' }];
5
- return [];
1
+ const falsy = (input) => {
2
+ if (input)
3
+ return [{ message: "The value must be falsy" }];
4
+ return [];
5
+ };
6
+ export {
7
+ falsy
6
8
  };
@@ -1,45 +1,61 @@
1
- import { alphabetical } from './alphabetical.js';
2
- import { casing } from './casing.js';
3
- import { defined } from './defined.js';
4
- import { enumeration } from './enumeration.js';
5
- import { falsy } from './falsy.js';
6
- import { length } from './length.js';
7
- import { or } from './or.js';
8
- import { pattern } from './pattern.js';
9
- import { schema } from './schema.js';
10
- import { truthy } from './truthy.js';
11
- import { typedEnum } from './typed-enum.js';
12
- import { undefinedFn } from './undefined.js';
13
- import { unreferencedReusableObject } from './unreferenced-reusable-object.js';
14
- import { xor } from './xor.js';
15
- export { alphabetical } from './alphabetical.js';
16
- export { casing } from './casing.js';
17
- export { defined } from './defined.js';
18
- export { enumeration } from './enumeration.js';
19
- export { falsy } from './falsy.js';
20
- export { length } from './length.js';
21
- export { or } from './or.js';
22
- export { pattern } from './pattern.js';
23
- export { schema } from './schema.js';
24
- export { truthy } from './truthy.js';
25
- export { typedEnum } from './typed-enum.js';
26
- export { undefinedFn } from './undefined.js';
27
- export { unreferencedReusableObject } from './unreferenced-reusable-object.js';
28
- export { xor } from './xor.js';
29
- /** All built-in functions, keyed by their Linter-compatible names. */
30
- export const builtinFunctions = {
31
- alphabetical: alphabetical,
32
- casing: casing,
33
- defined,
34
- enumeration: enumeration,
35
- falsy,
36
- length: length,
37
- or: or,
38
- pattern: pattern,
39
- schema: schema,
40
- truthy,
41
- undefined: undefinedFn,
42
- unreferencedReusableObject: unreferencedReusableObject,
43
- xor: xor,
44
- typedEnum: typedEnum,
1
+ import { alphabetical } from "./alphabetical.js";
2
+ import { casing } from "./casing.js";
3
+ import { defined } from "./defined.js";
4
+ import { enumeration } from "./enumeration.js";
5
+ import { falsy } from "./falsy.js";
6
+ import { length } from "./length.js";
7
+ import { or } from "./or.js";
8
+ import { pattern } from "./pattern.js";
9
+ import { schema } from "./schema.js";
10
+ import { truthy } from "./truthy.js";
11
+ import { typedEnum } from "./typed-enum.js";
12
+ import { undefinedFn } from "./undefined.js";
13
+ import { unreferencedReusableObject } from "./unreferenced-reusable-object.js";
14
+ import { xor } from "./xor.js";
15
+ import { alphabetical as alphabetical2 } from "./alphabetical.js";
16
+ import { casing as casing2 } from "./casing.js";
17
+ import { defined as defined2 } from "./defined.js";
18
+ import { enumeration as enumeration2 } from "./enumeration.js";
19
+ import { falsy as falsy2 } from "./falsy.js";
20
+ import { length as length2 } from "./length.js";
21
+ import { or as or2 } from "./or.js";
22
+ import { pattern as pattern2 } from "./pattern.js";
23
+ import { schema as schema2 } from "./schema.js";
24
+ import { truthy as truthy2 } from "./truthy.js";
25
+ import { typedEnum as typedEnum2 } from "./typed-enum.js";
26
+ import { undefinedFn as undefinedFn2 } from "./undefined.js";
27
+ import { unreferencedReusableObject as unreferencedReusableObject2 } from "./unreferenced-reusable-object.js";
28
+ import { xor as xor2 } from "./xor.js";
29
+ const builtinFunctions = {
30
+ alphabetical,
31
+ casing,
32
+ defined,
33
+ enumeration,
34
+ falsy,
35
+ length,
36
+ or,
37
+ pattern,
38
+ schema,
39
+ truthy,
40
+ undefined: undefinedFn,
41
+ unreferencedReusableObject,
42
+ xor,
43
+ typedEnum
44
+ };
45
+ export {
46
+ alphabetical2 as alphabetical,
47
+ builtinFunctions,
48
+ casing2 as casing,
49
+ defined2 as defined,
50
+ enumeration2 as enumeration,
51
+ falsy2 as falsy,
52
+ length2 as length,
53
+ or2 as or,
54
+ pattern2 as pattern,
55
+ schema2 as schema,
56
+ truthy2 as truthy,
57
+ typedEnum2 as typedEnum,
58
+ undefinedFn2 as undefinedFn,
59
+ unreferencedReusableObject2 as unreferencedReusableObject,
60
+ xor2 as xor
45
61
  };
@@ -1,35 +1,25 @@
1
- /**
2
- * Returns the comparable size of a value: string/array length, object key count,
3
- * or the number itself. `undefined` for anything else (so the rule is skipped).
4
- */
5
1
  const measure = (input) => {
6
- if (typeof input === 'string' || Array.isArray(input))
7
- return input.length;
8
- if (typeof input === 'object' && input !== null)
9
- return Object.keys(input).length;
10
- if (typeof input === 'number')
11
- return input;
12
- return undefined;
2
+ if (typeof input === "string" || Array.isArray(input))
3
+ return input.length;
4
+ if (typeof input === "object" && input !== null)
5
+ return Object.keys(input).length;
6
+ if (typeof input === "number")
7
+ return input;
8
+ return void 0;
13
9
  };
14
- /**
15
- * Flags a value whose size falls outside the `min`/`max` bounds.
16
- *
17
- * With neither `min` nor `max` supplied this is a no-op on every node. That
18
- * matches Spectral, which requires at least one bound in its option schema and
19
- * simply produces no results once the options load without them. We also ignore
20
- * a `min`/`max` that is not a number so a stray string like "3" cannot slip into
21
- * the `<`/`>` comparison and be coerced into a misleading result.
22
- */
23
- export const length = (input, options) => {
24
- const size = measure(input);
25
- if (size === undefined)
26
- return [];
27
- const results = [];
28
- if (typeof options?.min === 'number' && size < options.min) {
29
- results.push({ message: `The value must not be shorter than ${options.min}` });
30
- }
31
- if (typeof options?.max === 'number' && size > options.max) {
32
- results.push({ message: `The value must not be longer than ${options.max}` });
33
- }
34
- return results;
10
+ const length = (input, options) => {
11
+ const size = measure(input);
12
+ if (size === void 0)
13
+ return [];
14
+ const results = [];
15
+ if (typeof options?.min === "number" && size < options.min) {
16
+ results.push({ message: `The value must not be shorter than ${options.min}` });
17
+ }
18
+ if (typeof options?.max === "number" && size > options.max) {
19
+ results.push({ message: `The value must not be longer than ${options.max}` });
20
+ }
21
+ return results;
22
+ };
23
+ export {
24
+ length
35
25
  };
@@ -1,25 +1,19 @@
1
- /**
2
- * Flags an object when none of the listed `properties` is defined on it. Where
3
- * {@link xor} requires exactly one, `or` requires at least one — it stays quiet
4
- * as soon as a single listed property is present.
5
- */
6
- export const or = (input, options) => {
7
- if (typeof input !== 'object' || input === null)
8
- return [];
9
- const properties = options?.properties;
10
- // Spectral validates that at least two properties are supplied and no-ops when
11
- // that is not the case, so we skip in silence rather than flag every node.
12
- if (!Array.isArray(properties) || properties.length < 2)
13
- return [];
14
- const present = properties.filter((property) => property in input);
15
- if (present.length > 0)
16
- return [];
17
- // Match Spectral's message: a long list is abbreviated to the first three
18
- // properties plus a count of the rest so the finding stays readable.
19
- if (properties.length > 4) {
20
- const shortProps = properties.slice(0, 3);
21
- const count = `${properties.length - 3} other properties must be defined`;
22
- return [{ message: `At least one of "${shortProps.join('" or "')}" or ${count}` }];
23
- }
24
- return [{ message: `At least one of "${properties.join('" or "')}" must be defined` }];
1
+ const or = (input, options) => {
2
+ if (typeof input !== "object" || input === null)
3
+ return [];
4
+ const properties = options?.properties;
5
+ if (!Array.isArray(properties) || properties.length < 2)
6
+ return [];
7
+ const present = properties.filter((property) => property in input);
8
+ if (present.length > 0)
9
+ return [];
10
+ if (properties.length > 4) {
11
+ const shortProps = properties.slice(0, 3);
12
+ const count = `${properties.length - 3} other properties must be defined`;
13
+ return [{ message: `At least one of "${shortProps.join('" or "')}" or ${count}` }];
14
+ }
15
+ return [{ message: `At least one of "${properties.join('" or "')}" must be defined` }];
16
+ };
17
+ export {
18
+ or
25
19
  };
@@ -1,53 +1,43 @@
1
- // Compiling a RegExp is not free, and rules run this function once per matched
2
- // node, so we memoize by the raw pattern string (which carries its own flags in
3
- // the `/re/flags` form). A failed compile is cached as its `Error` so a bad
4
- // pattern is reported without being re-thrown on every node. Mirrors Spectral's
5
- // own module-level cache.
6
- const cache = new Map();
7
- /** Parses a `/pattern/flags` string (or a bare pattern) into a RegExp, or the compile error. */
8
- const toRegExp = (pattern) => {
9
- const cached = cache.get(pattern);
10
- if (cached !== undefined) {
11
- // A cached RegExp carrying the `g`/`y` flag keeps `lastIndex` between calls,
12
- // which would make `.test` skip characters on the next node. Reset it so a
13
- // reused pattern behaves the same as a freshly compiled one.
14
- if (cached instanceof RegExp)
15
- cached.lastIndex = 0;
16
- return cached;
17
- }
18
- let compiled;
19
- try {
20
- const match = /^\/(.+)\/([a-z]*)$/s.exec(pattern);
21
- compiled = match ? new RegExp(match[1], match[2]) : new RegExp(pattern);
22
- }
23
- catch (error) {
24
- compiled = error instanceof Error ? error : new Error(String(error));
25
- }
26
- cache.set(pattern, compiled);
27
- return compiled;
1
+ const cache = /* @__PURE__ */ new Map();
2
+ const toRegExp = (pattern2) => {
3
+ const cached = cache.get(pattern2);
4
+ if (cached !== void 0) {
5
+ if (cached instanceof RegExp)
6
+ cached.lastIndex = 0;
7
+ return cached;
8
+ }
9
+ let compiled;
10
+ try {
11
+ const match = /^\/(.+)\/([a-z]*)$/s.exec(pattern2);
12
+ compiled = match ? new RegExp(match[1], match[2]) : new RegExp(pattern2);
13
+ } catch (error) {
14
+ compiled = error instanceof Error ? error : new Error(String(error));
15
+ }
16
+ cache.set(pattern2, compiled);
17
+ return compiled;
28
18
  };
29
- /** Flags a string that fails `match` or satisfies `notMatch`. */
30
- export const pattern = (input, options) => {
31
- if (typeof input !== 'string')
32
- return [];
33
- const results = [];
34
- if (options?.match !== undefined) {
35
- const re = toRegExp(options.match);
36
- if (re instanceof Error) {
37
- results.push({ message: `The "match" option is not a valid regular expression: ${re.message}` });
38
- }
39
- else if (!re.test(input)) {
40
- results.push({ message: `The value must match the pattern "${options.match}"` });
41
- }
19
+ const pattern = (input, options) => {
20
+ if (typeof input !== "string")
21
+ return [];
22
+ const results = [];
23
+ if (options?.match !== void 0) {
24
+ const re = toRegExp(options.match);
25
+ if (re instanceof Error) {
26
+ results.push({ message: `The "match" option is not a valid regular expression: ${re.message}` });
27
+ } else if (!re.test(input)) {
28
+ results.push({ message: `The value must match the pattern "${options.match}"` });
42
29
  }
43
- if (options?.notMatch !== undefined) {
44
- const re = toRegExp(options.notMatch);
45
- if (re instanceof Error) {
46
- results.push({ message: `The "notMatch" option is not a valid regular expression: ${re.message}` });
47
- }
48
- else if (re.test(input)) {
49
- results.push({ message: `The value must not match the pattern "${options.notMatch}"` });
50
- }
30
+ }
31
+ if (options?.notMatch !== void 0) {
32
+ const re = toRegExp(options.notMatch);
33
+ if (re instanceof Error) {
34
+ results.push({ message: `The "notMatch" option is not a valid regular expression: ${re.message}` });
35
+ } else if (re.test(input)) {
36
+ results.push({ message: `The value must not match the pattern "${options.notMatch}"` });
51
37
  }
52
- return results;
38
+ }
39
+ return results;
40
+ };
41
+ export {
42
+ pattern
53
43
  };
@@ -1,129 +1,103 @@
1
- import { validate as buildValidator } from '@amritk/runtime-validators';
2
- // The rule's `options.schema` is a stable object, so cache the prepared
3
- // validator by identity. `@amritk/runtime-validators` interprets the schema at
4
- // runtime (no `new Function`), keeping this eval-free and dependency-light.
5
- const validators = new WeakMap();
6
- const getValidator = (schema) => {
7
- let validator = validators.get(schema);
8
- if (!validator) {
9
- // The `schema` built-in historically enforced string formats (ajv
10
- // `validateFormats: true`); keep that by opting into all formats here.
11
- validator = buildValidator(schema, { formats: 'all' });
12
- validators.set(schema, validator);
13
- }
14
- return validator;
1
+ import { validate as buildValidator } from "@amritk/runtime-validators";
2
+ const validators = /* @__PURE__ */ new WeakMap();
3
+ const getValidator = (schema2) => {
4
+ let validator = validators.get(schema2);
5
+ if (!validator) {
6
+ validator = buildValidator(schema2, { formats: "all" });
7
+ validators.set(schema2, validator);
8
+ }
9
+ return validator;
15
10
  };
16
- const KNOWN_TYPES = new Set(['string', 'number', 'integer', 'boolean', 'null', 'object', 'array']);
17
- // Keywords whose value is itself a schema, a list of schemas, or a map of
18
- // schemas. We recurse through them to reach every `type` a schema declares.
19
- const SCHEMA_VALUE_KEYS = ['additionalProperties', 'not', 'if', 'then', 'else', 'propertyNames', 'contains'];
20
- const SCHEMA_ITEMS_KEYS = ['items', 'additionalItems'];
21
- const SCHEMA_LIST_KEYS = ['allOf', 'anyOf', 'oneOf'];
22
- const SCHEMA_MAP_KEYS = ['properties', 'patternProperties', 'definitions', '$defs', 'dependencies'];
23
- /**
24
- * Walks a schema looking for a `type` keyword whose value is not a JSON Schema
25
- * type. `@amritk/runtime-validators` treats an unknown `type` as "always
26
- * matches" (so it never rejects data it does not model), which means a typo like
27
- * `type: "Pascal"` would silently disable the rule. Finding it up front lets us
28
- * report it instead. Returns the offending type, or `undefined` when the schema
29
- * only uses known types.
30
- */
11
+ const KNOWN_TYPES = /* @__PURE__ */ new Set(["string", "number", "integer", "boolean", "null", "object", "array"]);
12
+ const SCHEMA_VALUE_KEYS = ["additionalProperties", "not", "if", "then", "else", "propertyNames", "contains"];
13
+ const SCHEMA_ITEMS_KEYS = ["items", "additionalItems"];
14
+ const SCHEMA_LIST_KEYS = ["allOf", "anyOf", "oneOf"];
15
+ const SCHEMA_MAP_KEYS = ["properties", "patternProperties", "definitions", "$defs", "dependencies"];
31
16
  const findInvalidType = (node) => {
32
- if (Array.isArray(node) || typeof node !== 'object' || node === null)
33
- return undefined;
34
- const schema = node;
35
- const declared = schema['type'];
36
- if (declared !== undefined) {
37
- const types = Array.isArray(declared) ? declared : [declared];
38
- for (const type of types) {
39
- if (typeof type !== 'string' || !KNOWN_TYPES.has(type)) {
40
- return typeof type === 'string' ? type : String(type);
41
- }
42
- }
43
- }
44
- for (const key of SCHEMA_VALUE_KEYS) {
45
- const found = findInvalidType(schema[key]);
46
- if (found !== undefined)
47
- return found;
17
+ if (Array.isArray(node) || typeof node !== "object" || node === null)
18
+ return void 0;
19
+ const schema2 = node;
20
+ const declared = schema2["type"];
21
+ if (declared !== void 0) {
22
+ const types = Array.isArray(declared) ? declared : [declared];
23
+ for (const type of types) {
24
+ if (typeof type !== "string" || !KNOWN_TYPES.has(type)) {
25
+ return typeof type === "string" ? type : String(type);
26
+ }
48
27
  }
49
- for (const key of SCHEMA_ITEMS_KEYS) {
50
- const value = schema[key];
51
- const list = Array.isArray(value) ? value : [value];
52
- for (const item of list) {
53
- const found = findInvalidType(item);
54
- if (found !== undefined)
55
- return found;
56
- }
28
+ }
29
+ for (const key of SCHEMA_VALUE_KEYS) {
30
+ const found = findInvalidType(schema2[key]);
31
+ if (found !== void 0)
32
+ return found;
33
+ }
34
+ for (const key of SCHEMA_ITEMS_KEYS) {
35
+ const value = schema2[key];
36
+ const list = Array.isArray(value) ? value : [value];
37
+ for (const item of list) {
38
+ const found = findInvalidType(item);
39
+ if (found !== void 0)
40
+ return found;
57
41
  }
58
- for (const key of SCHEMA_LIST_KEYS) {
59
- const value = schema[key];
60
- if (Array.isArray(value)) {
61
- for (const item of value) {
62
- const found = findInvalidType(item);
63
- if (found !== undefined)
64
- return found;
65
- }
66
- }
42
+ }
43
+ for (const key of SCHEMA_LIST_KEYS) {
44
+ const value = schema2[key];
45
+ if (Array.isArray(value)) {
46
+ for (const item of value) {
47
+ const found = findInvalidType(item);
48
+ if (found !== void 0)
49
+ return found;
50
+ }
67
51
  }
68
- for (const key of SCHEMA_MAP_KEYS) {
69
- const value = schema[key];
70
- if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
71
- for (const item of Object.values(value)) {
72
- const found = findInvalidType(item);
73
- if (found !== undefined)
74
- return found;
75
- }
76
- }
52
+ }
53
+ for (const key of SCHEMA_MAP_KEYS) {
54
+ const value = schema2[key];
55
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
56
+ for (const item of Object.values(value)) {
57
+ const found = findInvalidType(item);
58
+ if (found !== void 0)
59
+ return found;
60
+ }
77
61
  }
78
- return undefined;
62
+ }
63
+ return void 0;
79
64
  };
80
- const pointerToPath = (pointer) => pointer
81
- .split('/')
82
- .slice(1)
83
- .map((segment) => segment.replace(/~1/g, '/').replace(/~0/g, '~'))
84
- .map((segment) => (/^\d+$/.test(segment) ? Number(segment) : segment));
65
+ const pointerToPath = (pointer) => pointer.split("/").slice(1).map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~")).map((segment) => /^\d+$/.test(segment) ? Number(segment) : segment);
85
66
  const formatError = (error) => {
86
- const location = error.path || 'value';
87
- return `${location} ${error.message}`.trim();
67
+ const location = error.path || "value";
68
+ return `${location} ${error.message}`.trim();
88
69
  };
89
- /** Validates a value against a JSON Schema supplied in the rule's options. */
90
- export const schema = (input, options, context) => {
91
- if (!options?.schema)
92
- return [];
93
- // A malformed schema would otherwise validate everything and silently disable
94
- // the rule. Surface it as a finding, the way Spectral reports schema compile
95
- // errors as results, so the ruleset author notices the mistake.
96
- const invalidType = findInvalidType(options.schema);
97
- if (invalidType !== undefined) {
98
- return [
99
- {
100
- message: `Invalid schema: unknown type "${invalidType}". Valid types are: ${[...KNOWN_TYPES].join(', ')}`,
101
- path: [...context.path],
102
- },
103
- ];
104
- }
105
- let result;
106
- try {
107
- result = getValidator(options.schema)(input);
108
- }
109
- catch (error) {
110
- // Preparing or running the validator can throw on a schema shape we cannot
111
- // interpret. Report it rather than letting it bubble up and crash the run.
112
- return [
113
- {
114
- message: `Invalid schema: ${error instanceof Error ? error.message : String(error)}`,
115
- path: [...context.path],
116
- },
117
- ];
118
- }
119
- if (result === true)
120
- return [];
121
- // Spectral's ajv defaults to `allErrors: false`, reporting only the first
122
- // failure. Honor the same default and only expand to the full list when the
123
- // caller opts in.
124
- const errors = options.allErrors ? result.errors : result.errors.slice(0, 1);
125
- return errors.map((error) => ({
126
- message: formatError(error),
127
- path: [...context.path, ...pointerToPath(error.path)],
128
- }));
70
+ const schema = (input, options, context) => {
71
+ if (!options?.schema)
72
+ return [];
73
+ const invalidType = findInvalidType(options.schema);
74
+ if (invalidType !== void 0) {
75
+ return [
76
+ {
77
+ message: `Invalid schema: unknown type "${invalidType}". Valid types are: ${[...KNOWN_TYPES].join(", ")}`,
78
+ path: [...context.path]
79
+ }
80
+ ];
81
+ }
82
+ let result;
83
+ try {
84
+ result = getValidator(options.schema)(input);
85
+ } catch (error) {
86
+ return [
87
+ {
88
+ message: `Invalid schema: ${error instanceof Error ? error.message : String(error)}`,
89
+ path: [...context.path]
90
+ }
91
+ ];
92
+ }
93
+ if (result === true)
94
+ return [];
95
+ const errors = options.allErrors ? result.errors : result.errors.slice(0, 1);
96
+ return errors.map((error) => ({
97
+ message: formatError(error),
98
+ path: [...context.path, ...pointerToPath(error.path)]
99
+ }));
100
+ };
101
+ export {
102
+ schema
129
103
  };
@@ -1,6 +1,8 @@
1
- /** Flags a value that is not truthy. */
2
- export const truthy = (input) => {
3
- if (!input)
4
- return [{ message: 'The value must be truthy' }];
5
- return [];
1
+ const truthy = (input) => {
2
+ if (!input)
3
+ return [{ message: "The value must be truthy" }];
4
+ return [];
5
+ };
6
+ export {
7
+ truthy
6
8
  };