Skip to content

Commit 6097122

Browse files
committed
publish: bump version to v10.1.0
1 parent a90ec68 commit 6097122

File tree

10 files changed

+97
-67
lines changed

10 files changed

+97
-67
lines changed

README.md

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ console.log(titleNode.evaluationPath); // #/properties/image/properties/title
114114
console.log(titleNode.schemaLocation); // #/properties/image/properties/title
115115
```
116116

117-
- `evaluationPath` refers to the path in schema and is extended by `$ref`, e.g. if image is defined on `$defs`: `#/properties/image/$ref/properties/title`
118-
- `schemaLocation` refers to the absolute path within the schema and will not change, e.g. `#/$defs/properties/title`
117+
- `evaluationPath` refers to the path in schema and is extended by `$ref`, e.g. if image is defined on `$defs`: `#/properties/image/$ref/properties/title`
118+
- `schemaLocation` refers to the absolute path within the schema and will not change, e.g. `#/$defs/properties/title`
119119

120120
</details>
121121

@@ -163,17 +163,17 @@ _json-schema-library_ fully supports all core features of draft versions draft-0
163163

164164
Draft support is defined by running a validator against the official [json-schema-test-suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite).
165165

166-
- Test results for _json-schema-library_ can be inspected in [github actions](https://github.com/sagold/json-schema-library/actions/workflows/ci.yaml)
167-
- A comparison to other validators is listed on [json-schema-benchmark](https://github.com/sagold/json-schema-benchmark)
166+
- Test results for _json-schema-library_ can be inspected in [github actions](https://github.com/sagold/json-schema-library/actions/workflows/ci.yaml)
167+
- A comparison to other validators is listed on [json-schema-benchmark](https://github.com/sagold/json-schema-benchmark)
168168

169169
Please note that these benchmarks refer to validation only. _json-schema-library_ offers tooling outside of validation and strives to be as spec-compliant as possible.
170170

171171
</details>
172172

173173
<details><summary>Overview format validation support</summary>
174174

175-
- **`❌ unsupported formats`** iri, iri-reference, idn-hostname
176-
- **`✅ supported formats`**: date, date-time, date, duration, ecmascript-regex, email, hostname, idn-email, ipv4, ipv6, json-pointer, regex, relative-json-pointer, time, unknown, uri-reference, uri-template, uri, uuid
175+
- **`❌ unsupported formats`** iri, iri-reference, idn-hostname
176+
- **`✅ supported formats`**: date, date-time, date, duration, ecmascript-regex, email, hostname, idn-email, ipv4, ipv6, json-pointer, regex, relative-json-pointer, time, unknown, uri-reference, uri-template, uri, uuid
177177

178178
</details>
179179

@@ -631,9 +631,9 @@ expect(node.schema).to.deep.equal({
631631

632632
All returned json-errors have a data property with the following properties
633633

634-
- `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
635-
- `schema` the JSON Schema of the last resolved location and the source of the error
636-
- `value` the data value at this location that could not be resolved
634+
- `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
635+
- `schema` the JSON Schema of the last resolved location and the source of the error
636+
- `value` the data value at this location that could not be resolved
637637

638638
```ts
639639
const { error } = schemaNode.getNode("/list/1");
@@ -921,10 +921,10 @@ _json-schema-library_ uses the concept of **drafts** to support different versio
921921

922922
Each **draft** describes how a schema should be parsed, validated, and interpreted. Drafts can also be extended or modified to change or enhance behavior, such as:
923923

924-
- Replacing or adding new keywords (`oneOf`, `if/then`, custom ones, etc.)
925-
- Defining or overriding format validators (`format: "email"`, etc.)
926-
- Customizing or localizing error messages
927-
- Tweaking how schema nodes behave during parsing or resolution
924+
- Replacing or adding new keywords (`oneOf`, `if/then`, custom ones, etc.)
925+
- Defining or overriding format validators (`format: "email"`, etc.)
926+
- Customizing or localizing error messages
927+
- Tweaking how schema nodes behave during parsing or resolution
928928

929929
Out of the box, the library exports all compliant JSON Schema drafts:
930930

@@ -1123,10 +1123,10 @@ console.assert(valid, errors.at(0)?.message);
11231123

11241124
**Keywords** hold the main logic for JSON Schema functionality. Each `Keyword` corresponds to a JSON Schema keyword like `properties`, `prefixItems`, `oneOf`, etc and offers implementations to `parse`, `validate`, `resolve` and `reduce`. Note that support for each implementation is optional, dependending on the feature requirements. The main properties of a `Keyword`:
11251125

1126-
- a `Keyword` is only processed if the specified `keyword` is available as property on the JSON Schema
1127-
- an optional `order` property may be added as order of keyword execution is sometimes important (`additionalItems` last, `$ref` evaluation first)
1128-
- the list of keywords is unique by property-value `keyword`
1129-
- for a given function `addX`, a function `X` must be present
1126+
- a `Keyword` is only processed if the specified `keyword` is available as property on the JSON Schema
1127+
- an optional `order` property may be added as order of keyword execution is sometimes important (`additionalItems` last, `$ref` evaluation first)
1128+
- the list of keywords is unique by property-value `keyword`
1129+
- for a given function `addX`, a function `X` must be present
11301130

11311131
```ts
11321132
type Keyword = {
@@ -1294,6 +1294,11 @@ assert.deepEqual(errors[0].message, "Custom error 2");
12941294

12951295
## Breaking Changes
12961296

1297+
### v10.1.0
1298+
1299+
- replaced `node.additionalItems` by `node.items` for drafts below 2020-12
1300+
- fixed `additionalItems` behaviour to be ignored when `schema.items` is not an array
1301+
12971302
### v10.0.0
12981303

12991304
> This update involves some significant changes in how you work with the library, so please carefully review the migration guide and adjust your implementation accordingly.
@@ -1304,8 +1309,8 @@ The new implementation revolves around compiling schemas into a **SchemaNode** t
13041309

13051310
#### Key Changes:
13061311

1307-
- **Compile Schema**: The `compileSchema` function now replaces the previous Draft-Class approach.
1308-
- **SchemaNode Representation**: All schemas are now represented as `SchemaNode`, which holds the schema and provides an easier way to work with them.
1312+
- **Compile Schema**: The `compileSchema` function now replaces the previous Draft-Class approach.
1313+
- **SchemaNode Representation**: All schemas are now represented as `SchemaNode`, which holds the schema and provides an easier way to work with them.
13091314

13101315
#### Breaking Changes:
13111316

@@ -1321,14 +1326,14 @@ const node = compileSchema(schema);
13211326

13221327
**Changed Methods**:
13231328

1324-
- `draft.createSchemaOf(schema)``node.createSchema(schema)`
1325-
- `draft.each(data, callback)``const nodes = node.toDataNodes(data)`
1326-
- `draft.eachSchema(callback)``const nodes = node.toSchemaNodes()`
1327-
- `draft.getChildSchemaSelection(property)``node.getChildSelection(property)`
1328-
- `draft.getNode(options)``node.getNode(pointer, data, options)`
1329-
- `draft.getTemplate(inputData)``node.getData(inputData)`
1330-
- `draft.isValid(data)``node.validate(data).valid`
1331-
- `draft.step(property, data)``node.getNodeChild(property, data)`
1329+
- `draft.createSchemaOf(schema)``node.createSchema(schema)`
1330+
- `draft.each(data, callback)``const nodes = node.toDataNodes(data)`
1331+
- `draft.eachSchema(callback)``const nodes = node.toSchemaNodes()`
1332+
- `draft.getChildSchemaSelection(property)``node.getChildSelection(property)`
1333+
- `draft.getNode(options)``node.getNode(pointer, data, options)`
1334+
- `draft.getTemplate(inputData)``node.getData(inputData)`
1335+
- `draft.isValid(data)``node.validate(data).valid`
1336+
- `draft.step(property, data)``node.getNodeChild(property, data)`
13321337

13331338
**Renamed Properties**: `templateDefaultOptions``getDataDefaultOptions`
13341339

@@ -1354,28 +1359,28 @@ compileSchema(schema, {
13541359

13551360
**breaking changes**:
13561361

1357-
- _getSchema_ signature changed in favour of an options object. Instead of `draft.getNode(pointer, data)` arguments have to be passed as an object `draft.getNode({ pointer, data })`. This removes setting unwanted optional arguments and keeps the api more stable in the future (e.g. `withSchemaWarning` option)
1358-
- _JsonError_ now must expose `pointer`, `schema` and `value` consistently on data property
1362+
- _getSchema_ signature changed in favour of an options object. Instead of `draft.getNode(pointer, data)` arguments have to be passed as an object `draft.getNode({ pointer, data })`. This removes setting unwanted optional arguments and keeps the api more stable in the future (e.g. `withSchemaWarning` option)
1363+
- _JsonError_ now must expose `pointer`, `schema` and `value` consistently on data property
13591364

13601365
**updates**
13611366

1362-
- _getSchema_ consistently returns errors and can return errors for empty schema using `withSchemaWarning` option
1367+
- _getSchema_ consistently returns errors and can return errors for empty schema using `withSchemaWarning` option
13631368

13641369
### v8.0.0
13651370

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

1368-
- Renamed `JSONError` to `JsonError` and `JSONSchema` to `JsonSchema`
1369-
- `getData` only adds required properties. Behaviour can be changed by [getData default options](#getData-default-options)
1370-
- Internal schema property `oneOfSchema` has been replaced by `schema.getOneOfOrigin()`
1371-
- Changed `unique-items-error` to point to error for duplicated item and changed data-properties
1372-
- Removed `SchemaService` as it was no longer used nor tested
1373+
- Renamed `JSONError` to `JsonError` and `JSONSchema` to `JsonSchema`
1374+
- `getData` only adds required properties. Behaviour can be changed by [getData default options](#getData-default-options)
1375+
- Internal schema property `oneOfSchema` has been replaced by `schema.getOneOfOrigin()`
1376+
- Changed `unique-items-error` to point to error for duplicated item and changed data-properties
1377+
- Removed `SchemaService` as it was no longer used nor tested
13731378

13741379
<details><summary>Exposed new helper functions</summary>
13751380

1376-
- `mergeSchema` - Merges to two json schema
1377-
- `reduceNode` - Reduce schema by merging dynamic constructs into a static json schema omitting those properties
1378-
- `isDynamicSchema` - Returns true if the passed schema contains dynamic properties (_if_, _dependencies_, _allOf_, etc)
1379-
- `resolveDynamicSchema` - Resolves all dynamic schema definitions for the given input data and returns the resulting JSON Schema without any dynamic schema definitions.
1381+
- `mergeSchema` - Merges to two json schema
1382+
- `reduceNode` - Reduce schema by merging dynamic constructs into a static json schema omitting those properties
1383+
- `isDynamicSchema` - Returns true if the passed schema contains dynamic properties (_if_, _dependencies_, _allOf_, etc)
1384+
- `resolveDynamicSchema` - Resolves all dynamic schema definitions for the given input data and returns the resulting JSON Schema without any dynamic schema definitions.
13801385

13811386
</details>

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/module/src/draft2019-09/keywords/additionalItems.js

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,23 @@ export const additionalItemsKeyword = {
66
keyword: "additionalItems",
77
order: -10,
88
parse: parseAdditionalItems,
9-
addResolve: (node) => node.additionalItems != null,
9+
addResolve: (node) => node.items != null,
1010
resolve: additionalItemsResolver,
11-
addValidate: ({ schema }) => schema.additionalItems != null &&
12-
schema.additionalItems !== true &&
13-
schema.items != null &&
14-
!isObject(schema.items),
11+
addValidate: ({ schema }) => schema.additionalItems != null && schema.additionalItems !== true && Array.isArray(schema.items),
1512
validate: validateAdditionalItems
1613
};
1714
// must come as last resolver
1815
export function parseAdditionalItems(node) {
1916
const { schema, evaluationPath, schemaLocation } = node;
20-
if (isObject(schema.additionalItems) || schema.additionalItems === true) {
21-
node.additionalItems = node.compileSchema(schema.additionalItems, `${evaluationPath}/additionalItems`, `${schemaLocation}/additionalItems`);
17+
if ((isObject(schema.additionalItems) || schema.additionalItems === true) && Array.isArray(schema.items)) {
18+
node.items = node.compileSchema(schema.additionalItems, `${evaluationPath}/additionalItems`, `${schemaLocation}/additionalItems`);
2219
}
2320
}
2421
function additionalItemsResolver({ node, key, data }) {
2522
if (Array.isArray(data)) {
2623
// @attention: items, etc should already have been tried
2724
const value = getValue(data, key);
28-
const { node: childNode, error } = node.additionalItems.reduceNode(value);
25+
const { node: childNode, error } = node.items.reduceNode(value);
2926
return childNode !== null && childNode !== void 0 ? childNode : error;
3027
}
3128
}
@@ -43,8 +40,8 @@ function validateAdditionalItems({ node, data, pointer, path }) {
4340
const errors = [];
4441
for (let i = startIndex; i < data.length; i += 1) {
4542
const item = data[i];
46-
if (node.additionalItems) {
47-
const validationResult = validateNode(node.additionalItems, item, `${pointer}/${i}`, path);
43+
if (node.items) {
44+
const validationResult = validateNode(node.items, item, `${pointer}/${i}`, path);
4845
validationResult && errors.push(...validationResult);
4946
}
5047
else if (schema.additionalItems === false) {

dist/module/src/draft2019-09/keywords/items.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ export const itemsKeyword = {
1010
validate: validateItems
1111
};
1212
function itemsResolver({ node, key }) {
13+
var _a;
14+
if ((_a = node.prefixItems) === null || _a === void 0 ? void 0 : _a[key]) {
15+
return node.prefixItems[key];
16+
}
1317
if (node.items) {
1418
return node.items;
1519
}
16-
if (node.prefixItems[key]) {
17-
return node.prefixItems[key];
18-
}
1920
}
2021
export function parseItems(node) {
2122
const { schema, evaluationPath } = node;

dist/module/src/draft2019-09/methods/getChildSelection.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,12 @@ export function getChildSelection(node, property) {
2020
return error;
2121
}
2222
// array.items[] exceeded (or undefined), but additionalItems specified
23-
if (node.additionalItems && node.items == null) {
23+
if (node.schema.additionalItems) {
2424
// we fallback to a string if no schema is defined - might be subject for configuration
25-
// @ts-expect-error boolean schema
26-
if (node.additionalItems.schema === true) {
25+
if (node.schema.additionalItems === true) {
2726
return [node.compileSchema({ type: "string" })];
2827
}
29-
return [node.additionalItems.resolveRef()];
28+
return [node.items.resolveRef()];
3029
}
3130
// array.items[] exceeded
3231
if (node.prefixItems && node.prefixItems.length <= +property) {

dist/module/src/draft2019-09/methods/getData.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,10 @@ const TYPE = {
232232
// when there are no array-items are defined
233233
if (schema.items == null) {
234234
// => all items are additionalItems
235-
if (node.additionalItems) {
235+
if (node.items) {
236236
const itemCount = Math.max(minItems, d.length);
237237
for (let i = 0; i < itemCount; i += 1) {
238-
d[i] = node.additionalItems.getData(d[i], opts);
238+
d[i] = node.items.getData(d[i], opts);
239239
}
240240
}
241241
return d || [];
@@ -246,7 +246,7 @@ const TYPE = {
246246
// build defined set of items
247247
const length = Math.max(minItems !== null && minItems !== void 0 ? minItems : 0, node.prefixItems.length);
248248
for (let i = 0; i < length; i += 1) {
249-
const childNode = (_b = node.prefixItems[i]) !== null && _b !== void 0 ? _b : node.additionalItems;
249+
const childNode = (_b = node.prefixItems[i]) !== null && _b !== void 0 ? _b : node.items;
250250
if ((childNode && canResolveRef(childNode, opts)) || input[i] !== undefined) {
251251
const result = childNode.getData(d[i] == null ? template[i] : d[i], opts);
252252
if (result !== undefined) {
@@ -261,8 +261,7 @@ const TYPE = {
261261
return d;
262262
}
263263
// build data from items-definition
264-
// @ts-expect-error asd
265-
if ((node.items && canResolveRef(node.items, opts)) || (data === null || data === void 0 ? void 0 : data.length) > 0) {
264+
if ((node.items && canResolveRef(node.items, opts)) || (Array.isArray(data) && (data === null || data === void 0 ? void 0 : data.length) > 0)) {
266265
// @attention this should disable cache or break intended behaviour as we reset it after loop
267266
// intention: reset cache after each property. last call will add counters
268267
const cache = { ...opts.cache };

dist/module/src/mergeNode.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ export function mergeNode(a, b, ...omit) {
7777
resolvers: a.resolvers.concat(b.resolvers).filter(removeDuplicates).sort(sortCb),
7878
reducers: a.reducers.concat(b.reducers).filter(removeDuplicates).sort(sortCb),
7979
validators: a.validators.concat(b.validators).filter(removeDuplicates).sort(sortCb),
80-
additionalItems: mergeNode(a.additionalItems, b.additionalItems),
8180
additionalProperties: mergeNode(a.additionalProperties, b.additionalProperties),
8281
contains: mergeNode(a.contains, b.contains),
8382
if: mergeNode(a.if, b.if),

dist/module/src/methods/toSchemaNodes.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ export function toSchemaNodes(node, nodeList = []) {
1515
}
1616
nodeList.push(node);
1717
eachProperty(nodeList, node.$defs);
18-
node.additionalItems && toSchemaNodes(node.additionalItems, nodeList);
1918
node.additionalProperties && toSchemaNodes(node.additionalProperties, nodeList);
2019
eachItem(nodeList, node.allOf);
2120
eachItem(nodeList, node.anyOf);

dist/src/SchemaNode.d.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ export interface SchemaNode extends SchemaNodeMethodsType {
7575
$id?: string;
7676
$defs?: Record<string, SchemaNode>;
7777
$ref?: string;
78-
/** only used for draft <= 2019-09 */
79-
additionalItems?: SchemaNode;
8078
additionalProperties?: SchemaNode;
8179
allOf?: SchemaNode[];
8280
anyOf?: SchemaNode[];
@@ -85,7 +83,40 @@ export interface SchemaNode extends SchemaNodeMethodsType {
8583
dependentSchemas?: Record<string, SchemaNode | boolean>;
8684
else?: SchemaNode;
8785
if?: SchemaNode;
86+
/**
87+
* # Items-array schema - for all drafts
88+
*
89+
* - for drafts prior 2020-12 `schema.items[]`-schema stored as `node.prefixItems`
90+
*
91+
* Validation succeeds if each element of the instance validates against the schema at the
92+
* same position, if any.
93+
*
94+
* The `prefixItems` keyword restricts a number of items from the start of an array instance
95+
* to validate against the given sequence of subschemas, where the item at a given index in
96+
* the array instance is evaluated against the subschema at the given index in the `prefixItems`
97+
* array, if any. Array items outside the range described by the `prefixItems` keyword is
98+
* evaluated against the items keyword, if present.
99+
*
100+
* [Docs](https://www.learnjsonschema.com/2020-12/applicator/prefixitems/)
101+
* | [Examples](https://json-schema.org/understanding-json-schema/reference/array#tupleValidation)
102+
*/
88103
prefixItems?: SchemaNode[];
104+
/**
105+
* # Items-object schema for additional array item - for all drafts
106+
*
107+
* - for drafts prior 2020-12 `schema.additionalItems` object-schema stored as `node.items`
108+
*
109+
* Validation succeeds if each element of the instance not covered by `prefixItems` validates
110+
* against this schema.
111+
*
112+
* The items keyword restricts array instance items not described by the sibling `prefixItems`
113+
* keyword (if any), to validate against the given subschema. Whetherthis keyword was evaluated
114+
* against any item of the array instance is reported using annotations.
115+
*
116+
* [Docs](https://www.learnjsonschema.com/2020-12/applicator/items/)
117+
* | [Examples](https://json-schema.org/understanding-json-schema/reference/array#items)
118+
* | [AdditionalItems Specification](https://json-schema.org/draft/2019-09/draft-handrews-json-schema-02#additionalItems)
119+
*/
89120
items?: SchemaNode;
90121
not?: SchemaNode;
91122
oneOf?: SchemaNode[];

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "json-schema-library",
3-
"version": "10.0.0",
3+
"version": "10.1.0",
44
"description": "Customizable and hackable json-validator and json-schema utilities for traversal, data generation and validation",
55
"module": "dist/module/index.js",
66
"types": "dist/index.d.ts",

0 commit comments

Comments
 (0)