@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.
Files changed (119) hide show
  1. package/AI.md +55 -0
  2. package/dist/core/document.js +12 -10
  3. package/dist/core/formats.js +10 -13
  4. package/dist/core/glob.js +96 -118
  5. package/dist/core/index.d.ts +0 -1
  6. package/dist/core/index.js +30 -11
  7. package/dist/core/jsonpath.js +487 -561
  8. package/dist/core/lint.js +78 -85
  9. package/dist/core/plugin.js +21 -29
  10. package/dist/core/pointers.js +107 -151
  11. package/dist/core/ruleset.js +0 -0
  12. package/dist/core/runner.js +214 -272
  13. package/dist/core/types.js +4 -1
  14. package/dist/core/validate-ruleset.js +98 -112
  15. package/dist/fix/apply.d.ts +1 -1
  16. package/dist/fix/apply.js +58 -96
  17. package/dist/fix/index.js +7 -2
  18. package/dist/fix/plugin.js +15 -20
  19. package/dist/fix/types.d.ts +1 -1
  20. package/dist/functions/alphabetical.d.ts +1 -1
  21. package/dist/functions/alphabetical.js +39 -50
  22. package/dist/functions/casing.d.ts +1 -1
  23. package/dist/functions/casing.js +39 -45
  24. package/dist/functions/defined.d.ts +1 -1
  25. package/dist/functions/defined.js +7 -5
  26. package/dist/functions/enumeration.d.ts +1 -1
  27. package/dist/functions/enumeration.js +15 -25
  28. package/dist/functions/falsy.d.ts +1 -1
  29. package/dist/functions/falsy.js +7 -5
  30. package/dist/functions/index.d.ts +1 -1
  31. package/dist/functions/index.js +60 -44
  32. package/dist/functions/length.d.ts +1 -1
  33. package/dist/functions/length.js +22 -32
  34. package/dist/functions/or.d.ts +1 -1
  35. package/dist/functions/or.js +18 -24
  36. package/dist/functions/pattern.d.ts +1 -1
  37. package/dist/functions/pattern.js +39 -49
  38. package/dist/functions/schema.d.ts +1 -1
  39. package/dist/functions/schema.js +93 -119
  40. package/dist/functions/truthy.d.ts +1 -1
  41. package/dist/functions/truthy.js +7 -5
  42. package/dist/functions/typed-enum.d.ts +1 -1
  43. package/dist/functions/typed-enum.js +33 -36
  44. package/dist/functions/undefined.d.ts +1 -1
  45. package/dist/functions/undefined.js +7 -8
  46. package/dist/functions/unreferenced-reusable-object.d.ts +1 -1
  47. package/dist/functions/unreferenced-reusable-object.js +35 -47
  48. package/dist/functions/xor.d.ts +1 -1
  49. package/dist/functions/xor.js +13 -16
  50. package/dist/index.d.ts +17 -4
  51. package/dist/index.js +149 -164
  52. package/dist/parsers/edit-model.js +316 -444
  53. package/dist/parsers/index.d.ts +1 -1
  54. package/dist/parsers/index.js +23 -19
  55. package/dist/parsers/json.js +39 -37
  56. package/dist/parsers/lines.js +23 -26
  57. package/dist/parsers/types.js +9 -7
  58. package/dist/parsers/yaml.js +137 -204
  59. package/dist/rules/openapi/fixers.js +166 -221
  60. package/dist/rules/openapi/formats.js +26 -27
  61. package/dist/rules/openapi/functions/example-validation.d.ts +1 -1
  62. package/dist/rules/openapi/functions/example-validation.js +98 -138
  63. package/dist/rules/openapi/functions/helpers.js +8 -10
  64. package/dist/rules/openapi/functions/index.d.ts +1 -1
  65. package/dist/rules/openapi/functions/index.js +98 -72
  66. package/dist/rules/openapi/functions/oas-additional-operations.d.ts +1 -1
  67. package/dist/rules/openapi/functions/oas-additional-operations.js +16 -22
  68. package/dist/rules/openapi/functions/oas-discriminator.d.ts +1 -1
  69. package/dist/rules/openapi/functions/oas-discriminator.js +24 -22
  70. package/dist/rules/openapi/functions/oas-example-external-value.d.ts +1 -1
  71. package/dist/rules/openapi/functions/oas-example-external-value.js +13 -21
  72. package/dist/rules/openapi/functions/oas-example-value.d.ts +1 -1
  73. package/dist/rules/openapi/functions/oas-example-value.js +24 -27
  74. package/dist/rules/openapi/functions/oas-mutually-exclusive.d.ts +1 -1
  75. package/dist/rules/openapi/functions/oas-mutually-exclusive.js +15 -19
  76. package/dist/rules/openapi/functions/oas-no-nullable.d.ts +1 -1
  77. package/dist/rules/openapi/functions/oas-no-nullable.js +13 -21
  78. package/dist/rules/openapi/functions/oas-op-form-data-consume-check.d.ts +1 -1
  79. package/dist/rules/openapi/functions/oas-op-form-data-consume-check.js +21 -19
  80. package/dist/rules/openapi/functions/oas-op-id-unique.d.ts +1 -1
  81. package/dist/rules/openapi/functions/oas-op-id-unique.js +27 -27
  82. package/dist/rules/openapi/functions/oas-op-params.d.ts +1 -1
  83. package/dist/rules/openapi/functions/oas-op-params.js +36 -42
  84. package/dist/rules/openapi/functions/oas-op-security-defined.d.ts +1 -1
  85. package/dist/rules/openapi/functions/oas-op-security-defined.js +40 -39
  86. package/dist/rules/openapi/functions/oas-op-success-response.d.ts +1 -1
  87. package/dist/rules/openapi/functions/oas-op-success-response.js +11 -13
  88. package/dist/rules/openapi/functions/oas-path-param.d.ts +1 -1
  89. package/dist/rules/openapi/functions/oas-path-param.js +75 -96
  90. package/dist/rules/openapi/functions/oas-schema-example-deprecated.d.ts +1 -1
  91. package/dist/rules/openapi/functions/oas-schema-example-deprecated.js +33 -40
  92. package/dist/rules/openapi/functions/oas-schema.d.ts +1 -1
  93. package/dist/rules/openapi/functions/oas-schema.js +9 -14
  94. package/dist/rules/openapi/functions/oas-server-name-unique.d.ts +1 -1
  95. package/dist/rules/openapi/functions/oas-server-name-unique.js +21 -19
  96. package/dist/rules/openapi/functions/oas-server-variables.d.ts +1 -1
  97. package/dist/rules/openapi/functions/oas-server-variables.js +45 -49
  98. package/dist/rules/openapi/functions/oas-tag-defined.d.ts +1 -1
  99. package/dist/rules/openapi/functions/oas-tag-defined.js +20 -20
  100. package/dist/rules/openapi/functions/oas-tag-kind.d.ts +1 -1
  101. package/dist/rules/openapi/functions/oas-tag-kind.js +16 -16
  102. package/dist/rules/openapi/functions/oas-tag-parent-defined.d.ts +1 -1
  103. package/dist/rules/openapi/functions/oas-tag-parent-defined.js +40 -43
  104. package/dist/rules/openapi/functions/oas-tags-unique.d.ts +1 -1
  105. package/dist/rules/openapi/functions/oas-tags-unique.js +18 -16
  106. package/dist/rules/openapi/functions/oas-unused-component.d.ts +1 -1
  107. package/dist/rules/openapi/functions/oas-unused-component.js +48 -58
  108. package/dist/rules/openapi/functions/ref-siblings.d.ts +1 -1
  109. package/dist/rules/openapi/functions/ref-siblings.js +13 -11
  110. package/dist/rules/openapi/index.d.ts +2 -1
  111. package/dist/rules/openapi/index.js +99 -117
  112. package/dist/rules/openapi/oas.d.ts +1 -1
  113. package/dist/rules/openapi/oas.js +524 -536
  114. package/dist/rules/openapi/schemas/index.js +17 -33
  115. package/dist/rules/openapi/schemas/oas20.json +1 -1592
  116. package/dist/rules/openapi/schemas/oas30.json +1 -1651
  117. package/dist/rules/openapi/schemas/oas31.json +1 -1412
  118. package/dist/rules/openapi/schemas/oas32.json +1 -1684
  119. package/package.json +11 -6
@@ -1,52 +1,46 @@
1
1
  const PATTERNS = {
2
- flat: '[a-z][a-z{d}]*',
3
- camel: '[a-z][a-z{d}]*(?:[A-Z{d}](?:[a-z{d}]+|$))*',
4
- pascal: '[A-Z][a-z{d}]*(?:[A-Z{d}](?:[a-z{d}]+|$))*',
5
- // Segments after a separator may start with a digit, matching Spectral (so
6
- // "foo-2fa" is valid kebab case). The sub-pattern is `[a-z{d}]+`, not the
7
- // stricter `[a-z][a-z{d}]*` which would require a letter right after the sep.
8
- kebab: '[a-z][a-z{d}]*(?:-[a-z{d}]+)*',
9
- cobol: '[A-Z][A-Z{d}]*(?:-[A-Z{d}]+)*',
10
- snake: '[a-z][a-z{d}]*(?:_[a-z{d}]+)*',
11
- macro: '[A-Z][A-Z{d}]*(?:_[A-Z{d}]+)*',
2
+ flat: "[a-z][a-z{d}]*",
3
+ camel: "[a-z][a-z{d}]*(?:[A-Z{d}](?:[a-z{d}]+|$))*",
4
+ pascal: "[A-Z][a-z{d}]*(?:[A-Z{d}](?:[a-z{d}]+|$))*",
5
+ // Segments after a separator may start with a digit, matching Spectral (so
6
+ // "foo-2fa" is valid kebab case). The sub-pattern is `[a-z{d}]+`, not the
7
+ // stricter `[a-z][a-z{d}]*` which would require a letter right after the sep.
8
+ kebab: "[a-z][a-z{d}]*(?:-[a-z{d}]+)*",
9
+ cobol: "[A-Z][A-Z{d}]*(?:-[A-Z{d}]+)*",
10
+ snake: "[a-z][a-z{d}]*(?:_[a-z{d}]+)*",
11
+ macro: "[A-Z][A-Z{d}]*(?:_[A-Z{d}]+)*"
12
12
  };
13
13
  const VALID_TYPES = Object.keys(PATTERNS);
14
- const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
14
+ const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
15
15
  const buildRegExp = (options) => {
16
- const digits = options.disallowDigits ? '' : '0-9';
17
- const base = PATTERNS[options.type].replace(/\{d\}/g, digits);
18
- if (!options.separator)
19
- return new RegExp(`^${base}$`);
20
- const sep = escapeRegExp(options.separator.char);
21
- const leading = options.separator.allowLeading ? `${sep}?` : '';
22
- return new RegExp(`^${leading}${base}(?:${sep}${base})*$`);
16
+ const digits = options.disallowDigits ? "" : "0-9";
17
+ const base = PATTERNS[options.type].replace(/\{d\}/g, digits);
18
+ if (!options.separator)
19
+ return new RegExp(`^${base}$`);
20
+ const sep = escapeRegExp(options.separator.char);
21
+ const leading = options.separator.allowLeading ? `${sep}?` : "";
22
+ return new RegExp(`^${leading}${base}(?:${sep}${base})*$`);
23
23
  };
24
- /** Flags a string that does not match the configured casing style. */
25
- export const casing = (input, options) => {
26
- if (!options?.type)
27
- return [];
28
- // Guard an unknown `type` before it reaches `PATTERNS[type]`, which would be
29
- // `undefined` and crash on `.replace`. Mirror Spectral's option schema by
30
- // naming every accepted value in a single, clear error finding.
31
- if (!VALID_TYPES.includes(options.type)) {
32
- return [
33
- {
34
- message: `"casing" function and its "type" option accept the following values: ${VALID_TYPES.join(', ')}`,
35
- },
36
- ];
37
- }
38
- if (typeof input !== 'string' || input.length === 0)
39
- return [];
40
- // Spectral special-cases a lone separator char with `allowLeading` as valid.
41
- // This is what keeps the OpenAPI root path "/" from being flagged.
42
- if (input.length === 1 &&
43
- options.separator !== undefined &&
44
- options.separator.allowLeading === true &&
45
- input === options.separator.char) {
46
- return [];
47
- }
48
- if (!buildRegExp(options).test(input)) {
49
- return [{ message: `The value must be in ${options.type} case` }];
50
- }
24
+ const casing = (input, options) => {
25
+ if (!options?.type)
51
26
  return [];
27
+ if (!VALID_TYPES.includes(options.type)) {
28
+ return [
29
+ {
30
+ message: `"casing" function and its "type" option accept the following values: ${VALID_TYPES.join(", ")}`
31
+ }
32
+ ];
33
+ }
34
+ if (typeof input !== "string" || input.length === 0)
35
+ return [];
36
+ if (input.length === 1 && options.separator !== void 0 && options.separator.allowLeading === true && input === options.separator.char) {
37
+ return [];
38
+ }
39
+ if (!buildRegExp(options).test(input)) {
40
+ return [{ message: `The value must be in ${options.type} case` }];
41
+ }
42
+ return [];
43
+ };
44
+ export {
45
+ casing
52
46
  };
@@ -1,3 +1,3 @@
1
- import type { RulesetFunction } from '../core/index.js';
1
+ import type { RulesetFunction } from '../core/types.js';
2
2
  /** Flags a value that is `undefined`. */
3
3
  export declare const defined: RulesetFunction;
@@ -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,4 +1,4 @@
1
- import type { RulesetFunction } from '../core/index.js';
1
+ import type { RulesetFunction } from '../core/types.js';
2
2
  /** Options for {@link enumeration}. */
3
3
  export type IEnumerationOptions = {
4
4
  values: unknown[];
@@ -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,3 +1,3 @@
1
- import type { RulesetFunction } from '../core/index.js';
1
+ import type { RulesetFunction } from '../core/types.js';
2
2
  /** Flags a value that is not falsy. */
3
3
  export declare const falsy: RulesetFunction;
@@ -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,4 +1,4 @@
1
- import type { FunctionRegistry } from '../core/index.js';
1
+ import type { FunctionRegistry } from '../core/types.js';
2
2
  export { alphabetical, type IAlphabeticalOptions } from './alphabetical.js';
3
3
  export { type CasingType, casing, type ICasingOptions } from './casing.js';
4
4
  export { defined } from './defined.js';
@@ -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,4 +1,4 @@
1
- import type { RulesetFunction } from '../core/index.js';
1
+ import type { RulesetFunction } from '../core/types.js';
2
2
  /** Options for {@link length}. */
3
3
  export type ILengthOptions = {
4
4
  min?: number;
@@ -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,4 +1,4 @@
1
- import type { RulesetFunction } from '../core/index.js';
1
+ import type { RulesetFunction } from '../core/types.js';
2
2
  /** Options for {@link or}. */
3
3
  export type IOrOptions = {
4
4
  properties: string[];
@@ -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,4 +1,4 @@
1
- import type { RulesetFunction } from '../core/index.js';
1
+ import type { RulesetFunction } from '../core/types.js';
2
2
  /** Options for {@link pattern}. */
3
3
  export type IPatternOptions = {
4
4
  match?: string;
@@ -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,4 +1,4 @@
1
- import type { RulesetFunction } from '../core/index.js';
1
+ import type { RulesetFunction } from '../core/types.js';
2
2
  /** Options for {@link schema}. */
3
3
  export type ISchemaOptions = {
4
4
  /** The JSON Schema to validate the matched value against. */