stoplightio / spectral

A flexible JSON/YAML linter for creating automated style guides, with baked in support for OpenAPI v3.1, v3.0, and v2.0 as well as AsyncAPI v2.x.
https://stoplight.io/spectral
Apache License 2.0
2.43k stars 235 forks source link

Pattern function does not work un-quoted numbers #2517

Closed CalemRoelofsSB closed 1 year ago

CalemRoelofsSB commented 1 year ago

Describe the bug When using the pattern function in combination with an unquoted number value, the function does not create an error even if the value breaks the rule specified in the match field.

To Reproduce Given this API definition snippet:

...
components:
  schemas:
    userId:
      type: string
      example: 00001

And this custom rule using the pattern function:

userId-example-must-start-with-37:
  message: "{{path}} does not start with '37'!"
  severity: error
  given: $.components.schemas.userId.example
  then:
    function: pattern
    functionOptions:
      match: "^37"

If the value of example is wrapped in quotes i.e. example: "00001" then the rule will execute successfully and outputs an error. However, in the case where the value is not quoted like in the above snippet, the rule does not appear to run. If I use an unquoted string i.e. example: Hello World then the rule also executes successfully and outputs an error.

Expected behavior Using the pattern function with a field that has a number value will execute the pattern matching function and return an error if the value of the field breaks the rule.

Screenshots N/A

Environment (remove any that are not applicable):

Additional context N/A

P0lip commented 1 year ago

The pattern is expected to run against strings, it won't run if you specify a number.

What is the expected behavior for your rule? Do you just want to verify whether it's higher than X or is it really whether it just starts with 37?

CalemRoelofsSB commented 1 year ago

What is the expected behavior for your rule? Do you just want to verify whether it's higher than X or is it really whether it just starts with 37?

In this example, we would want to assert that the example for this property starts with 37.

P0lip commented 1 year ago

I see. In such a case you'll need to write your own function.

You could do something as follows

import { createRulesetFunction } from '@stoplight/spectral-core';
import { pattern } from '@stoplight/spectral-functions';

export default createRulesetFunction(
  {
    input: {
      anyOf: [
        {
          type: 'number',
        },
        pattern.schemas.input,
      ],
    },
    options: pattern.schemas.options,
  },
  function numericPattern(input, ...args) {
    return pattern(String(input), ...args);
  },
);