Skip to content

Commit c5bd2c2

Browse files
author
Sascha Goldhofer
committed
change!: getSchema signature and return errors consistently
- docs: update upcoming breaking changes - chore: update dist - fix: return oneOf error in reduceSchema - change!: errors to always contain schema and value data - change: getSchema to return error when a schema cannot be resolved - fix: getSchema pointer and return type - fix: createSchemaOf to return undefined for missing data
1 parent 656d2e5 commit c5bd2c2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+987
-389
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
## Changelog
22

3-
### 8.0.0
3+
### v9.0.0
4+
5+
- [Breaking] error data to always contain `schema` and `value`
6+
- [Breaking] getSchema arguments changed to options-object
7+
- [Add] withSchemaWarning option for getSchema to always return an error fpr undefined schema
8+
9+
### v8.0.0
410

511
- [Breaking] renamed `JSON` types and variables to `Json`
612
- [Breaking] remove `oneOfSchema` helper property in favor of `getOneOfOrigin()` non-enumerable function

README.md

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -357,12 +357,28 @@ expect(calls).to.deep.equal([
357357

358358
### getSchema
359359

360-
`getSchema` retrieves the json-schema of a specific location in data. The location in data is given by a _json-pointer_. In many cases the schema can be retrieved without passing the actual data, but in situations where the schema is dynamic (e.g., in _oneOf_, _dependencies_, etc.), the data is required or will return a _JsonError_ if the location cannot be found.
360+
`getSchema` retrieves the json-schema of a specific location in data. The location in data is given by a _json-pointer_. In many cases the json-schema can be retrieved without passing any data, but in situations where the schema is dynamic (for example in _oneOf_, _dependencies_, etc.), the data is required or will return a _JsonError_ if the location cannot be found.
361361

362362
```ts
363363
const jsonSchema = new Draft07(mySchema);
364-
let schemaOfName: JsonSchema | JsonError;
365-
schemaOfName = jsonSchema.getSchema("/list/1/name", myData);
364+
let schemaOfName: JsonSchema | JsonError | undefined;
365+
schemaOfName = jsonSchema.getSchema({ pointer: "/list/1/name", data: myData });
366+
```
367+
368+
**Note** that `getSchema` will return `undefined` for paths that lead to valid properties, but miss a schema definition. For example:
369+
370+
```ts
371+
const jsonSchema = new Draft07({ type: "object" });
372+
let schemaOfName = jsonSchema.getSchema({ pointer: "/name" });
373+
console.log(schemaOfName); // undefined
374+
```
375+
376+
In case this is unwanted behaviour, use the `withSchemaWarning` option to return a json-error with code `schema-warning` instead:
377+
378+
```ts
379+
const jsonSchema = new Draft07({ type: "object" });
380+
let schemaOfName = jsonSchema.getSchema({ pointer: "/name", withSchemaWarning: true });
381+
console.log(schemaOfName); // { type: "error", code: "schema-warning" }
366382
```
367383

368384
<details><summary>Example</summary>
@@ -404,9 +420,12 @@ const mySchema = {
404420
};
405421

406422
const jsonSchema = new Draft07(mySchema);
407-
let schemaOfItem: JsonSchema | JsonError;
408-
schemaOfItem = jsonSchema.getSchema("/list/1", {
409-
list: [{ description: "..." }, { name: "my-item" }]
423+
let schemaOfItem: JsonSchema | JsonError | undefined;
424+
schemaOfItem = jsonSchema.getSchema({
425+
pointer: "/list/1",
426+
data: {
427+
list: [{ description: "..." }, { name: "my-item" }]
428+
}
410429
});
411430

412431
expect(schemaOfItem).to.deep.equal({
@@ -423,6 +442,23 @@ expect(schemaOfItem).to.deep.equal({
423442

424443
</details>
425444

445+
<details><summary>Evaluating errors</summary>
446+
447+
All returned json-errors have a data property with the following properties
448+
449+
- `pointer` json-pointer to the location where the error occured. In case of omitted data, this is the last json-schema location that could be resolved
450+
- `schema` the json-schema of the last resolved location and the source of the error
451+
- `value` the data value at this location that could not be resolved
452+
453+
```ts
454+
const schema = jsonSchema.getSchema({ pointer: "/list/1" });
455+
if (isJsonError(schema)) {
456+
console.log(Object.keys(schema.data)); // [pointer, schema, value]
457+
}
458+
```
459+
460+
</details>
461+
426462
<details><summary>About JsonPointer</summary>
427463

428464
**[Json-Pointer](https://tools.ietf.org/html/rfc6901)** defines a string syntax for identifying a specific value within a Json document and is [supported by Json-Schema](https://json-schema.org/understanding-json-schema/structuring.html). Given a Json document, it behaves similar to a [lodash path](https://lodash.com/docs/4.17.5#get) (`a[0].b.c`), which follows JS-syntax, but instead uses `/` separators (e.g., `a/0/b/c`). In the end, you describe a path into the Json data to a specific point.
@@ -919,6 +955,17 @@ const error: JsonError = createError("EnumError", { data: { pointer: "#/location
919955

920956
## Breaking Changes
921957

958+
### v9.0.0
959+
960+
**breaking changes**:
961+
962+
- _getSchema_ signature changed in favor of an options object. Instead of `draft.getSchema(pointer, data)` arguments have to be passed as an object `draft.getSchema({ pointer, data })`. This removes setting unwanted optional arguments and keeps the api more stable in the future (e.g. `withSchemaWarning` option)
963+
- _JsonError_ now must expose `pointer`, `schema` and `value` consistently on data property
964+
965+
**updates**
966+
967+
- _getSchema_ consistently returns errors and can return errors for empty schema using `withSchemaWarning` option
968+
922969
### v8.0.0
923970

924971
With version `v8.0.0`, _getTemplate_ was improved to better support optional properties and utilize existing core logic, making it more reliable. Breaking changes:

dist/index.d.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ resolveOneOf, resolveOneOfFuzzy, resolveRef, resolveRefMerge, settings, validate
3636
import { DraftConfig } from "./lib/draft";
3737
import { EachCallback } from "./lib/each";
3838
import { EachSchemaCallback } from "./lib/eachSchema";
39-
import { ErrorData, CreateError } from "./lib/utils/createCustomError";
40-
import { JsonSchema, JsonPointer, JsonError, JsonValidator, JsonTypeValidator } from "./lib/types";
39+
import { CreateError } from "./lib/utils/createCustomError";
40+
import { GetSchemaOptions } from "./lib/getSchema";
41+
import { JsonSchema, JsonPointer, JsonError, JsonValidator, JsonTypeValidator, ErrorData } from "./lib/types";
4142
import { JSType } from "./lib/getTypeOf";
42-
export type { CreateError, DraftConfig, EachCallback, EachSchemaCallback, ErrorData, JsonError, JsonPointer, JsonSchema, JsonTypeValidator, JsonValidator, JSType };
43+
export type { CreateError, DraftConfig, EachCallback, EachSchemaCallback, ErrorData, GetSchemaOptions, JsonError, JsonPointer, JsonSchema, JsonTypeValidator, JsonValidator, JSType };

dist/jsonSchemaLibrary.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/lib/createSchemaOf.d.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,5 @@ import { JsonSchema } from "./types";
22
/**
33
* Create a simple json schema for the given input data
44
* @param data - data to get json schema for
5-
* @return schema
65
*/
7-
export default function createSchemaOf(data: any): JsonSchema;
6+
export default function createSchemaOf(data: unknown): JsonSchema | undefined;

dist/lib/draft/index.d.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import addRemoteSchema from "../addRemoteSchema";
22
import compileSchema from "../compileSchema";
33
import createSchemaOf from "../createSchemaOf";
44
import getChildSchemaSelection from "../getChildSchemaSelection";
5-
import getSchema from "../getSchema";
5+
import getSchema, { GetSchemaOptions } from "../getSchema";
66
import getTemplate, { TemplateOptions } from "../getTemplate";
77
import isValid from "../isValid";
88
import resolveRef from "../resolveRef.strict";
@@ -83,16 +83,27 @@ export declare class Draft {
8383
getChildSchemaSelection(property: string | number, schema?: JsonSchema): JsonError | JsonSchema[];
8484
/**
8585
* Returns the json-schema of a data-json-pointer.
86+
*
87+
* To resolve dynamic schema where the type of json-schema is evaluated by
88+
* its value, a data object has to be passed in options.
89+
*
90+
* Per default this function will return `undefined` for valid properties that
91+
* do not have a defined schema. Use the option `withSchemaWarning: true` to
92+
* receive an error with `code: schema-warning` containing the location of its
93+
* last evaluated json-schema.
94+
*
8695
* Notes
87-
* - Uses draft.step to walk through data and schema
96+
* - uses draft.step to walk through data and schema
8897
*
98+
* @param draft
8999
* @param pointer - json pointer in data to get the json schema for
90-
* @param [data] - the data object, which includes the json pointers value. This is optional, as
100+
* @param [options.data] - the data object, which includes the json pointers value. This is optional, as
91101
* long as no oneOf, anyOf, etc statement is part of the pointers schema
92-
* @param [schema] - the json schema to iterate. Defaults to draft.rootSchema
93-
* @return json schema object of the json-pointer or an error
102+
* @param [options.schema] - the json schema to iterate. Defaults to draft.rootSchema
103+
* @param [options.withSchemaWarning] - if true returns an error instead of `undefined` for valid properties missing a schema definition
104+
* @return resolved json-schema object of requested json-pointer location
94105
*/
95-
getSchema(pointer?: JsonPointer, data?: any, schema?: JsonSchema): JsonSchema | JsonError;
106+
getSchema(options?: GetSchemaOptions): JsonSchema | JsonError | undefined;
96107
/**
97108
* Create data object matching the given schema
98109
*

dist/lib/getSchema.d.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,31 @@
11
import { JsonSchema, JsonPointer } from "./types";
22
import { Draft } from "./draft";
3+
export type GetSchemaOptions = {
4+
pointer?: JsonPointer;
5+
data?: unknown;
6+
schema?: JsonSchema;
7+
withSchemaWarning?: boolean;
8+
};
39
/**
410
* Returns the json-schema of a data-json-pointer.
511
*
6-
* Notes
7-
* - Uses draft.step to walk through data and schema
12+
* To resolve dynamic schema where the type of json-schema is evaluated by
13+
* its value, a data object has to be passed in options.
14+
*
15+
* Per default this function will return `undefined` for valid properties that
16+
* do not have a defined schema. Use the option `withSchemaWarning: true` to
17+
* receive an error with `code: schema-warning` containing the location of its
18+
* last evaluated json-schema.
19+
*
20+
* Notes
21+
* - uses draft.step to walk through data and schema
822
*
923
* @param draft
1024
* @param pointer - json pointer in data to get the json schema for
11-
* @param [data] - the data object, which includes the json pointers value. This is optional, as
25+
* @param [options.data] - the data object, which includes the json pointers value. This is optional, as
1226
* long as no oneOf, anyOf, etc statement is part of the pointers schema
13-
* @param [schema] - the json schema to iterate. Defaults to draft.rootSchema
14-
* @return json schema object of the json-pointer or an error
27+
* @param [options.schema] - the json schema to iterate. Defaults to draft.rootSchema
28+
* @param [options.withSchemaWarning] - if true returns an error instead of `undefined` for valid properties missing a schema definition
29+
* @return resolved json-schema object of requested json-pointer location or json-error
1530
*/
16-
export default function getSchema(draft: Draft, pointer: JsonPointer, data?: unknown, schema?: JsonSchema): JsonSchema;
31+
export default function getSchema(draft: Draft, options?: GetSchemaOptions): JsonSchema;

dist/lib/reduceSchema.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { JsonSchema } from "./types";
1+
import { JsonSchema, JsonPointer } from "./types";
22
import { Draft } from "./draft";
33
/**
44
* reduces json schema by merging dynamic constructs like if-then-else,
@@ -8,4 +8,4 @@ import { Draft } from "./draft";
88
* @returns input schema reduced by dynamic schema definitions for the given
99
* input data
1010
*/
11-
export declare function reduceSchema(draft: Draft, schema: JsonSchema, data: unknown): JsonSchema;
11+
export declare function reduceSchema(draft: Draft, schema: JsonSchema, data: unknown, pointer: JsonPointer): JsonSchema;

dist/lib/resolveDynamicSchema.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { JsonSchema } from "./types";
1+
import { JsonPointer, JsonSchema } from "./types";
22
import { Draft } from "./draft";
33
import { JsonData } from "@sagold/json-pointer";
44
export declare function isDynamicSchema(schema: JsonData): boolean;
@@ -18,4 +18,4 @@ export declare function isDynamicSchema(schema: JsonData): boolean;
1818
* @returns static schema from resolved dynamic schema definitions for this
1919
* specific input data
2020
*/
21-
export declare function resolveDynamicSchema(draft: Draft, schema: JsonSchema, data: unknown): Record<string, unknown>;
21+
export declare function resolveDynamicSchema(draft: Draft, schema: JsonSchema, data: unknown, pointer: JsonPointer): Record<string, unknown>;

dist/lib/types.d.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@ export type JsonSchema = {
33
[p: string]: any;
44
};
55
export type JsonPointer = string;
6-
export type JsonError = {
6+
export type ErrorData<T extends Record<string, unknown> = {
7+
[p: string]: unknown;
8+
}> = T & {
9+
pointer: string;
10+
schema: JsonSchema;
11+
value: unknown;
12+
};
13+
export type JsonError<T extends ErrorData = ErrorData> = {
714
type: "error";
815
name: string;
916
code: string;
1017
message: string;
11-
data?: {
12-
[p: string]: any;
13-
};
14-
[p: string]: any;
18+
data: T;
19+
[p: string]: unknown;
1520
};
1621
/**
1722
* ts type guard for json error

0 commit comments

Comments
 (0)