diff --git a/packages/core/src/ruleset/function.ts b/packages/core/src/ruleset/function.ts index b187fc13b..8360ba90c 100644 --- a/packages/core/src/ruleset/function.ts +++ b/packages/core/src/ruleset/function.ts @@ -22,10 +22,27 @@ export class RulesetFunctionValidationError extends RulesetValidationError { super( 'invalid-function-options', RulesetFunctionValidationError.printMessage(fn, error), - error.instancePath.slice(1).split('/'), + RulesetFunctionValidationError.getPath(error), ); } + private static getPath(error: ErrorObject): string[] { + const path: string[] = [ + 'functionOptions', + ...(error.instancePath === '' ? [] : error.instancePath.slice(1).split('/')), + ]; + + switch (error.keyword) { + case 'additionalProperties': { + const additionalProperty = (error as AdditionalPropertiesError).params.additionalProperty; + path.push(additionalProperty); + break; + } + } + + return path; + } + private static printMessage(fn: string, error: ErrorObject): string { switch (error.keyword) { case 'type': { @@ -157,7 +174,7 @@ export function createRulesetFunction( throw new RulesetValidationError( 'invalid-function-options', `"${fn.name || ''}" function does not accept any options`, - [], + ['functionOptions'], ); } else if ( 'errors' in validateOptions && @@ -171,7 +188,7 @@ export function createRulesetFunction( throw new RulesetValidationError( 'invalid-function-options', `"functionOptions" of "${fn.name || ''}" function must be valid`, - [], + ['functionOptions'], ); } }; diff --git a/packages/core/src/ruleset/ruleset.ts b/packages/core/src/ruleset/ruleset.ts index 560957485..8cc01a72e 100644 --- a/packages/core/src/ruleset/ruleset.ts +++ b/packages/core/src/ruleset/ruleset.ts @@ -63,10 +63,10 @@ export class Ruleset { if (isPlainObject(maybeDefinition) && 'extends' in maybeDefinition) { const { extends: _, ...def } = maybeDefinition; // we don't want to validate extends - this is going to happen later on (line 29) - assertValidRuleset({ extends: [], ...def }); + assertValidRuleset({ extends: [], ...def }, 'js'); definition = maybeDefinition as RulesetDefinition; } else { - assertValidRuleset(maybeDefinition); + assertValidRuleset(maybeDefinition, 'js'); definition = maybeDefinition; } diff --git a/packages/core/src/ruleset/validation/__tests__/validation.test.ts b/packages/core/src/ruleset/validation/__tests__/validation.test.ts index 3cfab69b9..59a88f911 100644 --- a/packages/core/src/ruleset/validation/__tests__/validation.test.ts +++ b/packages/core/src/ruleset/validation/__tests__/validation.test.ts @@ -773,7 +773,12 @@ describe('JS Ruleset Validation', () => { }), ).toThrowAggregateError( new AggregateError([ - new RulesetValidationError('undefined-function', 'Function is not defined', ['rules', 'rule', 'then']), + new RulesetValidationError('undefined-function', 'Function is not defined', [ + 'rules', + 'rule', + 'then', + 'function', + ]), ]), ); }); diff --git a/packages/core/src/ruleset/validation/errors.ts b/packages/core/src/ruleset/validation/errors.ts index af8660783..3c92aa7d0 100644 --- a/packages/core/src/ruleset/validation/errors.ts +++ b/packages/core/src/ruleset/validation/errors.ts @@ -18,7 +18,7 @@ export type RulesetValidationErrorCode = | 'undefined-alias'; interface IRulesetValidationSingleError extends Pick { - code: RulesetValidationErrorCode; + readonly code: RulesetValidationErrorCode; } export class RulesetValidationError extends Error implements IRulesetValidationSingleError { diff --git a/packages/core/src/ruleset/validation/validators/function.ts b/packages/core/src/ruleset/validation/validators/function.ts index 834425227..bf6249eba 100644 --- a/packages/core/src/ruleset/validation/validators/function.ts +++ b/packages/core/src/ruleset/validation/validators/function.ts @@ -24,7 +24,7 @@ export function validateFunction( validator(opts); } catch (ex) { if (ex instanceof ReferenceError) { - return new RulesetValidationError('undefined-function', ex.message, toParsedPath(path)); + return new RulesetValidationError('undefined-function', ex.message, [...toParsedPath(path), 'function']); } return wrapError(ex, path); diff --git a/packages/functions/src/__tests__/__helpers__/tester.ts b/packages/functions/src/__tests__/__helpers__/tester.ts index fe1355623..bc77112c5 100644 --- a/packages/functions/src/__tests__/__helpers__/tester.ts +++ b/packages/functions/src/__tests__/__helpers__/tester.ts @@ -6,15 +6,8 @@ import { IRuleResult, RulesetFunction, RulesetFunctionWithValidator, - RulesetValidationError, } from '@stoplight/spectral-core'; -import { isError } from 'lodash'; - -function isAggregateError(maybeAggregateError: unknown): maybeAggregateError is Error & { errors: unknown[] } { - return isError(maybeAggregateError) && maybeAggregateError.constructor.name === 'AggregateError'; -} - export default async function ( // eslint-disable-next-line @typescript-eslint/no-explicit-any fn: RulesetFunction | RulesetFunctionWithValidator, @@ -23,31 +16,19 @@ export default async function ( rule?: Partial> & { then?: Partial }, ): Promise[]> { const s = new Spectral(); - try { - s.setRuleset({ - rules: { - 'my-rule': { - given: '$', - ...rule, - then: { - ...(rule?.then as Ruleset['rules']['then']), - function: fn, - functionOptions: opts, - }, + s.setRuleset({ + rules: { + 'my-rule': { + given: '$', + ...rule, + then: { + ...(rule?.then as Ruleset['rules']['then']), + function: fn, + functionOptions: opts, }, }, - }); - } catch (ex) { - if (isAggregateError(ex)) { - for (const e of ex.errors) { - if (e instanceof RulesetValidationError) { - e.path.length = 0; - } - } - } - - throw ex; - } + }, + }); const results = await s.run(input instanceof Document ? input : JSON.stringify(input)); return results diff --git a/packages/functions/src/__tests__/alphabetical.test.ts b/packages/functions/src/__tests__/alphabetical.test.ts index fe6c20073..d8ba91d86 100644 --- a/packages/functions/src/__tests__/alphabetical.test.ts +++ b/packages/functions/src/__tests__/alphabetical.test.ts @@ -132,17 +132,33 @@ describe('Core Functions / Alphabetical', () => { expect(await runAlphabetical([], opts)).toEqual([]); }); - it.each<[unknown, string]>([ - [{ foo: true }, '"alphabetical" function does not support "foo" option'], + it.each<[unknown, RulesetValidationError]>([ + [ + { foo: true }, + new RulesetValidationError( + 'invalid-function-options', + '"alphabetical" function does not support "foo" option', + ['rules', 'my-rule', 'then', 'functionOptions', 'foo'], + ), + ], [ 2, - '"alphabetical" function has invalid options specified. Example valid options: null (no options), { "keyedBy": "my-key" }', + new RulesetValidationError( + 'invalid-function-options', + '"alphabetical" function has invalid options specified. Example valid options: null (no options), { "keyedBy": "my-key" }', + ['rules', 'my-rule', 'then', 'functionOptions'], + ), + ], + [ + { keyedBy: 2 }, + new RulesetValidationError( + 'invalid-function-options', + '"alphabetical" function and its "keyedBy" option accepts only the following types: string', + ['rules', 'my-rule', 'then', 'functionOptions', 'keyedBy'], + ), ], - [{ keyedBy: 2 }, '"alphabetical" function and its "keyedBy" option accepts only the following types: string'], ])('given invalid %p options, should throw', async (opts, error) => { - await expect(runAlphabetical([], opts)).rejects.toThrowAggregateError( - new AggregateError([new RulesetValidationError('invalid-function-options', error, [])]), - ); + await expect(runAlphabetical([], opts)).rejects.toThrowAggregateError(new AggregateError([error])); }); }); }); diff --git a/packages/functions/src/__tests__/casing.test.ts b/packages/functions/src/__tests__/casing.test.ts index b78605265..b0c2e03a5 100644 --- a/packages/functions/src/__tests__/casing.test.ts +++ b/packages/functions/src/__tests__/casing.test.ts @@ -381,13 +381,21 @@ describe('Core Functions / Casing', () => { new RulesetValidationError( 'invalid-function-options', '"casing" function and its "type" option accept the following values: flat, camel, pascal, kebab, cobol, snake, macro', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'type'], ), ], ], [ { type: 'macro', foo: true }, - [new RulesetValidationError('invalid-function-options', '"casing" function does not support "foo" option', [])], + [ + new RulesetValidationError('invalid-function-options', '"casing" function does not support "foo" option', [ + 'rules', + 'my-rule', + 'then', + 'functionOptions', + 'foo', + ]), + ], ], [ { @@ -399,7 +407,7 @@ describe('Core Functions / Casing', () => { new RulesetValidationError( 'invalid-function-options', '"casing" function is missing "separator.char" option', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'separator'], ), ], ], @@ -413,7 +421,7 @@ describe('Core Functions / Casing', () => { new RulesetValidationError( 'invalid-function-options', '"casing" function is missing "separator.char" option', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'separator'], ), ], ], @@ -423,7 +431,7 @@ describe('Core Functions / Casing', () => { new RulesetValidationError( 'invalid-function-options', '"casing" function does not support "separator.foo" option', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'separator', 'foo'], ), ], ], @@ -438,7 +446,7 @@ describe('Core Functions / Casing', () => { new RulesetValidationError( 'invalid-function-options', '"casing" function and its "separator.char" option accepts only char, i.e. "I" or "/"', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'separator', 'char'], ), ], ], @@ -453,7 +461,7 @@ describe('Core Functions / Casing', () => { new RulesetValidationError( 'invalid-function-options', '"casing" function and its "separator.char" option accepts only char, i.e. "I" or "/"', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'separator', 'char'], ), ], ], diff --git a/packages/functions/src/__tests__/defined.test.ts b/packages/functions/src/__tests__/defined.test.ts index 05d3e54b9..56ebc51a5 100644 --- a/packages/functions/src/__tests__/defined.test.ts +++ b/packages/functions/src/__tests__/defined.test.ts @@ -25,7 +25,12 @@ describe('Core Functions / Defined', () => { it.each([{}, 2])('given invalid %p options, should throw', async opts => { await expect(runDefined([], opts)).rejects.toThrowAggregateError( new AggregateError([ - new RulesetValidationError('invalid-function-options', '"defined" function does not accept any options', []), + new RulesetValidationError('invalid-function-options', '"defined" function does not accept any options', [ + 'rules', + 'my-rule', + 'then', + 'functionOptions', + ]), ]), ); }); diff --git a/packages/functions/src/__tests__/enumeration.test.ts b/packages/functions/src/__tests__/enumeration.test.ts index ab92c140c..019cd6610 100644 --- a/packages/functions/src/__tests__/enumeration.test.ts +++ b/packages/functions/src/__tests__/enumeration.test.ts @@ -44,7 +44,7 @@ describe('Core Functions / Enumeration', () => { new RulesetValidationError( 'invalid-function-options', '"enumeration" function does not support "foo" option', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'foo'], ), ], ], @@ -56,7 +56,7 @@ describe('Core Functions / Enumeration', () => { new RulesetValidationError( 'invalid-function-options', '"enumeration" and its "values" option support only arrays of primitive values, i.e. ["Berlin", "London", "Paris"]', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'values'], ), ], ], @@ -66,7 +66,7 @@ describe('Core Functions / Enumeration', () => { new RulesetValidationError( 'invalid-function-options', '"enumeration" function has invalid options specified. Example valid options: { "values": ["Berlin", "London", "Paris"] }, { "values": [2, 3, 5, 8, 13, 21] }', - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], @@ -76,7 +76,7 @@ describe('Core Functions / Enumeration', () => { new RulesetValidationError( 'invalid-function-options', '"enumeration" function has invalid options specified. Example valid options: { "values": ["Berlin", "London", "Paris"] }, { "values": [2, 3, 5, 8, 13, 21] }', - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], diff --git a/packages/functions/src/__tests__/falsy.test.ts b/packages/functions/src/__tests__/falsy.test.ts index 7799b442b..a63c9878a 100644 --- a/packages/functions/src/__tests__/falsy.test.ts +++ b/packages/functions/src/__tests__/falsy.test.ts @@ -25,7 +25,12 @@ describe('Core Functions / Falsy', () => { it.each([{}, 2])('given invalid %p options, should throw', async opts => { await expect(runFalsy([], opts)).rejects.toThrowAggregateError( new AggregateError([ - new RulesetValidationError('invalid-function-options', '"falsy" function does not accept any options', []), + new RulesetValidationError('invalid-function-options', '"falsy" function does not accept any options', [ + 'rules', + 'my-rule', + 'then', + 'functionOptions', + ]), ]), ); }); diff --git a/packages/functions/src/__tests__/length.test.ts b/packages/functions/src/__tests__/length.test.ts index 9e3fff231..4ab9cb38f 100644 --- a/packages/functions/src/__tests__/length.test.ts +++ b/packages/functions/src/__tests__/length.test.ts @@ -61,7 +61,7 @@ describe('Core Functions / Length', () => { new RulesetValidationError( 'invalid-function-options', '"length" function has invalid options specified. Example valid options: { "min": 2 }, { "max": 5 }, { "min": 0, "max": 10 }', - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], @@ -71,7 +71,7 @@ describe('Core Functions / Length', () => { new RulesetValidationError( 'invalid-function-options', '"length" function has invalid options specified. Example valid options: { "min": 2 }, { "max": 5 }, { "min": 0, "max": 10 }', - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], @@ -80,15 +80,23 @@ describe('Core Functions / Length', () => { min: 2, foo: true, }, - [new RulesetValidationError('invalid-function-options', '"length" function does not support "foo" option', [])], + [ + new RulesetValidationError('invalid-function-options', '"length" function does not support "foo" option', [ + 'rules', + 'my-rule', + 'then', + 'functionOptions', + 'foo', + ]), + ], ], [ { min: '2' }, [ new RulesetValidationError( 'invalid-function-options', - '"length" function and its "min" option accepts only the following types: number', - [], + `"length" function and its "min" option accepts only the following types: number`, + ['rules', 'my-rule', 'then', 'functionOptions', 'min'], ), ], ], @@ -99,7 +107,7 @@ describe('Core Functions / Length', () => { new RulesetValidationError( 'invalid-function-options', `"length" function and its "max" option accepts only the following types: number`, - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'max'], ), ], ], @@ -109,12 +117,12 @@ describe('Core Functions / Length', () => { new RulesetValidationError( 'invalid-function-options', `"length" function and its "min" option accepts only the following types: number`, - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'min'], ), new RulesetValidationError( 'invalid-function-options', `"length" function and its "max" option accepts only the following types: number`, - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'max'], ), ], ], diff --git a/packages/functions/src/__tests__/pattern.test.ts b/packages/functions/src/__tests__/pattern.test.ts index 74b98e084..9cc030cc7 100644 --- a/packages/functions/src/__tests__/pattern.test.ts +++ b/packages/functions/src/__tests__/pattern.test.ts @@ -59,7 +59,7 @@ describe('Core Functions / Pattern', () => { new RulesetValidationError( 'invalid-function-options', '"pattern" function has invalid options specified. Example valid options: { "match": "^Stoplight" }, { "notMatch": "Swagger" }, { "match": "Stoplight", "notMatch": "Swagger" }', - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], @@ -69,18 +69,20 @@ describe('Core Functions / Pattern', () => { new RulesetValidationError( 'invalid-function-options', `"pattern" function has invalid options specified. Example valid options: { "match": "^Stoplight" }, { "notMatch": "Swagger" }, { "match": "Stoplight", "notMatch": "Swagger" }`, - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], [ { foo: true }, [ - new RulesetValidationError( - 'invalid-function-options', - '"pattern" function does not support "foo" option', - [], - ), + new RulesetValidationError('invalid-function-options', '"pattern" function does not support "foo" option', [ + 'rules', + 'my-rule', + 'then', + 'functionOptions', + 'foo', + ]), ], ], [ @@ -89,7 +91,7 @@ describe('Core Functions / Pattern', () => { new RulesetValidationError( 'invalid-function-options', '"pattern" function and its "match" option must be string or RegExp instance', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'match'], ), ], ], @@ -99,7 +101,7 @@ describe('Core Functions / Pattern', () => { new RulesetValidationError( 'invalid-function-options', '"pattern" function and its "notMatch" option must be string or RegExp instance', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'notMatch'], ), ], ], @@ -109,12 +111,12 @@ describe('Core Functions / Pattern', () => { new RulesetValidationError( 'invalid-function-options', `"pattern" function and its "match" option must be string or RegExp instance`, - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'match'], ), new RulesetValidationError( 'invalid-function-options', `"pattern" function and its "notMatch" option must be string or RegExp instance`, - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'notMatch'], ), ], ], diff --git a/packages/functions/src/__tests__/schema.test.ts b/packages/functions/src/__tests__/schema.test.ts index ee7b53950..ec45b5fd0 100644 --- a/packages/functions/src/__tests__/schema.test.ts +++ b/packages/functions/src/__tests__/schema.test.ts @@ -485,13 +485,21 @@ describe('Core Functions / Schema', () => { new RulesetValidationError( 'invalid-function-options', '"schema" function has invalid options specified. Example valid options: { "schema": { /* any JSON Schema can be defined here */ } , { "schema": { "type": "object" }, "dialect": "auto" }', - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], [ { schema: { type: 'object' }, foo: true }, - [new RulesetValidationError('invalid-function-options', '"schema" function does not support "foo" option', [])], + [ + new RulesetValidationError('invalid-function-options', '"schema" function does not support "foo" option', [ + 'rules', + 'my-rule', + 'then', + 'functionOptions', + 'foo', + ]), + ], ], [ { schema: { type: 'object' }, oasVersion: 1 }, @@ -499,7 +507,7 @@ describe('Core Functions / Schema', () => { new RulesetValidationError( 'invalid-function-options', '"schema" function does not support "oasVersion" option', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'oasVersion'], ), ], ], @@ -509,7 +517,7 @@ describe('Core Functions / Schema', () => { new RulesetValidationError( 'invalid-function-options', '"schema" function and its "dialect" option accepts only the following values: "auto", "draft4", "draft6", "draft7", "draft2019-09", "draft2020-12"', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'dialect'], ), ], ], @@ -519,7 +527,7 @@ describe('Core Functions / Schema', () => { new RulesetValidationError( 'invalid-function-options', '"schema" function and its "allErrors" option accepts only the following types: boolean', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'allErrors'], ), ], ], @@ -529,12 +537,12 @@ describe('Core Functions / Schema', () => { new RulesetValidationError( 'invalid-function-options', `"schema" function and its "schema" option accepts only the following types: object`, - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'schema'], ), new RulesetValidationError( 'invalid-function-options', `"schema" function and its "allErrors" option accepts only the following types: boolean`, - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'allErrors'], ), ], ], diff --git a/packages/functions/src/__tests__/truthy.test.ts b/packages/functions/src/__tests__/truthy.test.ts index b135382a2..32da4fb4a 100644 --- a/packages/functions/src/__tests__/truthy.test.ts +++ b/packages/functions/src/__tests__/truthy.test.ts @@ -25,7 +25,12 @@ describe('Core Functions / Truthy', () => { it.each([{}, 2])('given invalid %p options, should throw', async opts => { await expect(runTruthy([], opts)).rejects.toThrowAggregateError( new AggregateError([ - new RulesetValidationError('invalid-function-options', '"truthy" function does not accept any options', []), + new RulesetValidationError('invalid-function-options', '"truthy" function does not accept any options', [ + 'rules', + 'my-rule', + 'then', + 'functionOptions', + ]), ]), ); }); diff --git a/packages/functions/src/__tests__/unreferencedReusableObject.test.ts b/packages/functions/src/__tests__/unreferencedReusableObject.test.ts index 7fdcbe80b..3f1deb95c 100644 --- a/packages/functions/src/__tests__/unreferencedReusableObject.test.ts +++ b/packages/functions/src/__tests__/unreferencedReusableObject.test.ts @@ -34,7 +34,7 @@ describe('Core Functions / UnreferencedReusableObject', () => { new RulesetValidationError( 'invalid-function-options', '"unreferencedReusableObject" function has invalid options specified. Example valid options: { "reusableObjectsLocation": "#/components/schemas" }, { "reusableObjectsLocation": "#/$defs" }', - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], @@ -44,7 +44,7 @@ describe('Core Functions / UnreferencedReusableObject', () => { new RulesetValidationError( 'invalid-function-options', '"unreferencedReusableObject" function has invalid options specified. Example valid options: { "reusableObjectsLocation": "#/components/schemas" }, { "reusableObjectsLocation": "#/$defs" }', - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], @@ -54,7 +54,7 @@ describe('Core Functions / UnreferencedReusableObject', () => { new RulesetValidationError( 'invalid-function-options', '"unreferencedReusableObject" function is missing "reusableObjectsLocation" option. Example valid options: { "reusableObjectsLocation": "#/components/schemas" }, { "reusableObjectsLocation": "#/$defs" }', - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], @@ -67,7 +67,7 @@ describe('Core Functions / UnreferencedReusableObject', () => { new RulesetValidationError( 'invalid-function-options', '"unreferencedReusableObject" function does not support "foo" option', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'foo'], ), ], ], @@ -79,7 +79,7 @@ describe('Core Functions / UnreferencedReusableObject', () => { new RulesetValidationError( 'invalid-function-options', '"unreferencedReusableObject" and its "reusableObjectsLocation" option support only valid JSON Pointer fragments, i.e. "#", "#/foo", "#/paths/~1user"', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'reusableObjectsLocation'], ), ], ], @@ -91,7 +91,7 @@ describe('Core Functions / UnreferencedReusableObject', () => { new RulesetValidationError( 'invalid-function-options', '"unreferencedReusableObject" and its "reusableObjectsLocation" option support only valid JSON Pointer fragments, i.e. "#", "#/foo", "#/paths/~1user"', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'reusableObjectsLocation'], ), ], ], diff --git a/packages/functions/src/__tests__/xor.test.ts b/packages/functions/src/__tests__/xor.test.ts index 2bf7deed7..6ea29e233 100644 --- a/packages/functions/src/__tests__/xor.test.ts +++ b/packages/functions/src/__tests__/xor.test.ts @@ -73,7 +73,7 @@ describe('Core Functions / Xor', () => { new RulesetValidationError( 'invalid-function-options', '"xor" function has invalid options specified. Example valid options: { "properties": ["id", "name"] }, { "properties": ["country", "street"] }', - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], @@ -83,13 +83,21 @@ describe('Core Functions / Xor', () => { new RulesetValidationError( 'invalid-function-options', '"xor" function has invalid options specified. Example valid options: { "properties": ["id", "name"] }, { "properties": ["country", "street"] }', - [], + ['rules', 'my-rule', 'then', 'functionOptions'], ), ], ], [ { properties: ['foo', 'bar'], foo: true }, - [new RulesetValidationError('invalid-function-options', '"xor" function does not support "foo" option', [])], + [ + new RulesetValidationError('invalid-function-options', '"xor" function does not support "foo" option', [ + 'rules', + 'my-rule', + 'then', + 'functionOptions', + 'foo', + ]), + ], ], [ { properties: ['foo', 'bar', 'baz'] }, @@ -97,7 +105,7 @@ describe('Core Functions / Xor', () => { new RulesetValidationError( 'invalid-function-options', '"xor" and its "properties" option support 2-item tuples, i.e. ["id", "name"]', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'properties'], ), ], ], @@ -107,7 +115,7 @@ describe('Core Functions / Xor', () => { new RulesetValidationError( 'invalid-function-options', '"xor" and its "properties" option support 2-item tuples, i.e. ["id", "name"]', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'properties'], ), ], ], @@ -117,7 +125,7 @@ describe('Core Functions / Xor', () => { new RulesetValidationError( 'invalid-function-options', '"xor" and its "properties" option support 2-item tuples, i.e. ["id", "name"]', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'properties'], ), ], ], @@ -127,7 +135,7 @@ describe('Core Functions / Xor', () => { new RulesetValidationError( 'invalid-function-options', '"xor" and its "properties" option support 2-item tuples, i.e. ["id", "name"]', - [], + ['rules', 'my-rule', 'then', 'functionOptions', 'properties'], ), ], ], diff --git a/tsconfig.json b/tsconfig.json index 858e0c868..8f7094cec 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,8 @@ "baseUrl": ".", "paths": { "@stoplight/spectral-core": ["packages/core/src/index.ts"], + "@stoplight/spectral-core/ruleset": ["packages/core/src/ruleset/index.ts"], + "@stoplight/spectral-core/ruleset/validation": ["packages/core/src/ruleset/validation/index.ts"], "@stoplight/spectral-formats": ["packages/formats/src/index.ts"], "@stoplight/spectral-functions": ["packages/functions/src/index.ts"], "@stoplight/spectral-parsers": ["packages/parsers/src/index.ts"],