Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e490e0d844 | |||
| e026e82f65 | |||
| a1fb9ef650 | |||
| 9900b3fc43 | |||
| 11d1f54bc8 | |||
| b0377e076e | |||
| d77765cb61 |
27
GEMINI.md
27
GEMINI.md
@ -47,7 +47,22 @@ The core execution engines natively enforce these boundaries:
|
||||
* **Merger**: Strictly bounded to the `Type` Realm. It is philosophically impossible and mathematically illegal to attempt to UPSERT an API endpoint.
|
||||
* **Queryer**: Routes recursively. Safely evaluates API boundary inputs directly from the `Punc` realm, while tracing underlying table targets back through the `Type` realm to physically compile SQL `SELECT` statements.
|
||||
|
||||
### Types of Types
|
||||
### Basic and Structural Types
|
||||
JSPG models data using a simplified subset of standard JSON Schema types, categorized into primitives and structural types:
|
||||
|
||||
* **Primitives**:
|
||||
* `string`: Standard string, supporting standard keywords (e.g., `pattern`, `minLength`, `maxLength`) and custom formats (`uuid`, `date-time`, `email`). Empty strings (`""`) are leniently treated as "present but unset".
|
||||
* `number` & `integer`: Numeric and integer values (e.g., supporting `minimum`, `maximum`).
|
||||
* `boolean`: Boolean `true` or `false` values.
|
||||
* `null`: Represents database `NULL` or unset fields.
|
||||
* **Structural Types**:
|
||||
* `object`: Represents a structured object with a fixed list of static `properties`. Objects are **strict by default** (raising `STRICT_PROPERTY_VIOLATION` for properties not defined in the schema) unless marked with `"extensible": true`.
|
||||
* `array`: A homogeneous, one-dimensional collection where every element is validated against the `items` schema. Positional/tuple array validation is not supported, and array strictness checks do not apply.
|
||||
* `dict`: A dynamic key-value map. It utilizes the `keys` keyword to validate key strings (typically via `pattern`) and the `items` keyword to validate the values. It completely replaces the legacy `additionalProperties` and `patternProperties` keywords. Extensibility is implicitly managed via dynamic keys, so strictness checking does not apply.
|
||||
|
||||
### Types of Types (Complex & Referential Types)
|
||||
Beyond basic primitives and structures, JSPG maps schemas to their storage and database-referential boundaries:
|
||||
|
||||
* **Table-Backed (Entity Types)**: Primarily defined in root `types` schemas. These represent physical Postgres tables.
|
||||
* They are implicitly registered in the Global Registry using their precise key name mapped from the database compilation phase.
|
||||
* The schema conceptually requires a `type` discriminator at runtime so the engine knows what physical variation to interact with.
|
||||
@ -162,9 +177,11 @@ It evaluates as an **Independent Declarative Rules Engine**. Every `Case` block
|
||||
```
|
||||
|
||||
### Strict by Default & Extensibility
|
||||
* **Strictness**: By default, any property not explicitly defined in the schema causes a validation error (effectively enforcing `additionalProperties: false` globally).
|
||||
* **Extensibility (`extensible: true`)**: To allow a free-for-all of undefined properties, schemas must explicitly declare `"extensible": true`.
|
||||
* **Structured Additional Properties**: If `additionalProperties: {...}` is defined as a schema, arbitrary keys are allowed so long as their values match the defined type constraint.
|
||||
* **Strictness**: Strictness is a first-class feature for object schemas. By default, any property present in the JSON instance that is not explicitly defined in the schema's `properties` (or inherited, etc.) causes a `STRICT_PROPERTY_VIOLATION` validation error.
|
||||
* **Extensibility (`extensible: true`)**: This keyword is valid **only** at the `type: "object"` level. By setting `"extensible": true`, you bypass the strictness checking on the object, allowing arbitrary undefined properties to pass.
|
||||
* **Type: dict and type: array**: These types are dynamic/homogeneous:
|
||||
* **`dict`**: Defined with `keys` and `items` schemas. Its keys and values are dynamic, so strictness checking does not apply. `"extensible"` is not applicable at the `dict` level.
|
||||
* **`array`**: Homogeneous collection of items matching the `items` schema. Validation is homogeneous, so strictness checking does not apply. `"extensible"` is not applicable at the `array` level (tuple-like `prefixItems` are removed).
|
||||
* **Inheritance Boundaries**: Strictness resets when crossing non-primitive `type` boundaries. A schema extending a strict parent remains strict unless it explicitly overrides with `"extensible": true`.
|
||||
|
||||
### Format Leniency for Empty Strings
|
||||
@ -206,7 +223,7 @@ Traits are reusable, non-generating schema fragments used to share properties an
|
||||
}
|
||||
```
|
||||
* **Resolution and Merging**: During `Database::new()`, includes are resolved and merged at the raw JSON level:
|
||||
* **`properties` / `patternProperties`**: Map keys from the host schema override/shadow included traits.
|
||||
* **`properties`**: Map keys from the host schema override/shadow included traits.
|
||||
* **`required` / `display`**: Lists are merged and deduped.
|
||||
* **`dependencies`**: Merged by combining and deduping lists.
|
||||
* **Scalars / Arrays / Items**: Host definitions completely override included traits.
|
||||
|
||||
@ -1,188 +0,0 @@
|
||||
[
|
||||
{
|
||||
"description": "additionalProperties validates properties not matched by properties",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "schema1",
|
||||
"schemas": {
|
||||
"schema1": {
|
||||
"properties": {
|
||||
"foo": {
|
||||
"type": "string"
|
||||
},
|
||||
"bar": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "defined properties are valid",
|
||||
"data": {
|
||||
"foo": "value",
|
||||
"bar": 123
|
||||
},
|
||||
"schema_id": "schema1",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "additional property matching schema is valid",
|
||||
"data": {
|
||||
"foo": "value",
|
||||
"is_active": true,
|
||||
"hidden": false
|
||||
},
|
||||
"schema_id": "schema1",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "additional property not matching schema is invalid",
|
||||
"data": {
|
||||
"foo": "value",
|
||||
"is_active": 1
|
||||
},
|
||||
"schema_id": "schema1",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "extensible: true with additionalProperties still validates structure",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "additionalProperties_1_0",
|
||||
"schemas": {
|
||||
"additionalProperties_1_0": {
|
||||
"properties": {
|
||||
"foo": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"extensible": true,
|
||||
"additionalProperties": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "additional property matching schema is valid",
|
||||
"data": {
|
||||
"foo": "hello",
|
||||
"count": 5,
|
||||
"age": 42
|
||||
},
|
||||
"schema_id": "additionalProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "additional property not matching schema is invalid despite extensible: true",
|
||||
"data": {
|
||||
"foo": "hello",
|
||||
"count": "five"
|
||||
},
|
||||
"schema_id": "additionalProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "complex additionalProperties with object and array items",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "schema3",
|
||||
"schemas": {
|
||||
"schema3": {
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "valid array of strings",
|
||||
"data": {
|
||||
"type": "my_type",
|
||||
"group_a": [
|
||||
"field1",
|
||||
"field2"
|
||||
],
|
||||
"group_b": [
|
||||
"field3"
|
||||
]
|
||||
},
|
||||
"schema_id": "schema3",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "invalid array of integers",
|
||||
"data": {
|
||||
"type": "my_type",
|
||||
"group_a": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
},
|
||||
"schema_id": "schema3",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "invalid non-array type",
|
||||
"data": {
|
||||
"type": "my_type",
|
||||
"group_a": "field1"
|
||||
},
|
||||
"schema_id": "schema3",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
590
fixtures/array.json
Normal file
590
fixtures/array.json
Normal file
@ -0,0 +1,590 @@
|
||||
[
|
||||
{
|
||||
"description": "array type without items allows any items",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "array_0_0",
|
||||
"schemas": {
|
||||
"array_0_0": {
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "empty array is valid",
|
||||
"data": [],
|
||||
"schema_id": "array_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "array with items is valid",
|
||||
"data": [
|
||||
1,
|
||||
"foo"
|
||||
],
|
||||
"schema_id": "array_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "array with arbitrary objects is valid since items is not constrained",
|
||||
"data": [
|
||||
{
|
||||
"extra_prop": 1
|
||||
}
|
||||
],
|
||||
"schema_id": "array_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "items with boolean schema (true)",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "array_1_0",
|
||||
"schemas": {
|
||||
"array_1_0": {
|
||||
"items": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "any array is valid",
|
||||
"data": [
|
||||
1,
|
||||
"foo",
|
||||
true
|
||||
],
|
||||
"schema_id": "array_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "items with boolean schema (false)",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "array_2_0",
|
||||
"schemas": {
|
||||
"array_2_0": {
|
||||
"items": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "empty array is valid",
|
||||
"data": [],
|
||||
"schema_id": "array_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "any non-empty array is invalid",
|
||||
"data": [
|
||||
1,
|
||||
"foo"
|
||||
],
|
||||
"schema_id": "array_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "array_2_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "1",
|
||||
"schema": "array_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "a schema given for items",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "array_3_0",
|
||||
"schemas": {
|
||||
"array_3_0": {
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "valid items",
|
||||
"data": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
"schema_id": "array_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "wrong type of items",
|
||||
"data": [
|
||||
1,
|
||||
"x"
|
||||
],
|
||||
"schema_id": "array_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "1",
|
||||
"schema": "array_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "non-arrays are invalid",
|
||||
"data": {
|
||||
"foo": "bar"
|
||||
},
|
||||
"schema_id": "array_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "foo"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "array_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "JavaScript pseudo-arrays are invalid",
|
||||
"data": {
|
||||
"0": "invalid",
|
||||
"length": 1
|
||||
},
|
||||
"schema_id": "array_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "array_3_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "length"
|
||||
},
|
||||
"details": {
|
||||
"path": "length",
|
||||
"schema": "array_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "primitive strings are valid since items is ignored on primitives",
|
||||
"data": "hello",
|
||||
"schema_id": "array_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "nested items",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "array_4_0",
|
||||
"schemas": {
|
||||
"array_4_0": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "valid nested array",
|
||||
"data": [
|
||||
[
|
||||
[
|
||||
[
|
||||
1
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
2
|
||||
],
|
||||
[
|
||||
3
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
[
|
||||
4
|
||||
],
|
||||
[
|
||||
5
|
||||
],
|
||||
[
|
||||
6
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"schema_id": "array_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "nested array with invalid type",
|
||||
"data": [
|
||||
[
|
||||
[
|
||||
[
|
||||
"1"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
2
|
||||
],
|
||||
[
|
||||
3
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
[
|
||||
4
|
||||
],
|
||||
[
|
||||
5
|
||||
],
|
||||
[
|
||||
6
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
"schema_id": "array_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "number"
|
||||
},
|
||||
"details": {
|
||||
"path": "0/0/0/0",
|
||||
"schema": "array_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "not deep enough",
|
||||
"data": [
|
||||
[
|
||||
[
|
||||
1
|
||||
],
|
||||
[
|
||||
2
|
||||
],
|
||||
[
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
4
|
||||
],
|
||||
[
|
||||
5
|
||||
],
|
||||
[
|
||||
6
|
||||
]
|
||||
]
|
||||
],
|
||||
"schema_id": "array_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "array"
|
||||
},
|
||||
"details": {
|
||||
"path": "0/0/0",
|
||||
"schema": "array_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "array"
|
||||
},
|
||||
"details": {
|
||||
"path": "0/1/0",
|
||||
"schema": "array_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "array"
|
||||
},
|
||||
"details": {
|
||||
"path": "0/2/0",
|
||||
"schema": "array_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "array"
|
||||
},
|
||||
"details": {
|
||||
"path": "1/0/0",
|
||||
"schema": "array_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "array"
|
||||
},
|
||||
"details": {
|
||||
"path": "1/1/0",
|
||||
"schema": "array_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "array"
|
||||
},
|
||||
"details": {
|
||||
"path": "1/2/0",
|
||||
"schema": "array_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "items with null instance elements",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "array_5_0",
|
||||
"schemas": {
|
||||
"array_5_0": {
|
||||
"items": {
|
||||
"type": "null"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "allows null elements",
|
||||
"data": [
|
||||
null
|
||||
],
|
||||
"schema_id": "array_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "array: items extensible",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "array_6_0",
|
||||
"schemas": {
|
||||
"array_6_0": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"extensible": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "array with items is valid (items explicitly allowed to be anything extensible)",
|
||||
"data": [
|
||||
1,
|
||||
"foo",
|
||||
{}
|
||||
],
|
||||
"schema_id": "array_6_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "array: items strict",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "array_7_0",
|
||||
"schemas": {
|
||||
"array_7_0": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"extensible": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "array with strict object items is valid",
|
||||
"data": [
|
||||
{}
|
||||
],
|
||||
"schema_id": "array_7_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "array with invalid strict object items (extra property)",
|
||||
"data": [
|
||||
{
|
||||
"extra": 1
|
||||
}
|
||||
],
|
||||
"schema_id": "array_7_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "extra"
|
||||
},
|
||||
"details": {
|
||||
"path": "0/extra",
|
||||
"schema": "array_7_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -120,7 +120,16 @@
|
||||
"schema_id": "booleanSchema_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -129,7 +138,16 @@
|
||||
"schema_id": "booleanSchema_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -138,7 +156,16 @@
|
||||
"schema_id": "booleanSchema_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -147,7 +174,16 @@
|
||||
"schema_id": "booleanSchema_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -156,7 +192,16 @@
|
||||
"schema_id": "booleanSchema_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -167,7 +212,26 @@
|
||||
"schema_id": "booleanSchema_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "foo"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -176,7 +240,16 @@
|
||||
"schema_id": "booleanSchema_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -187,7 +260,16 @@
|
||||
"schema_id": "booleanSchema_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -196,7 +278,16 @@
|
||||
"schema_id": "booleanSchema_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -277,20 +277,32 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "amount_1"
|
||||
},
|
||||
"details": {
|
||||
"path": "amount_1"
|
||||
"path": "amount_1",
|
||||
"schema": "parallel_rules"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "amount_2"
|
||||
},
|
||||
"details": {
|
||||
"path": "amount_2"
|
||||
"path": "amount_2",
|
||||
"schema": "parallel_rules"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "cvv"
|
||||
},
|
||||
"details": {
|
||||
"path": "cvv"
|
||||
"path": "cvv",
|
||||
"schema": "parallel_rules"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -309,8 +321,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "cvv"
|
||||
},
|
||||
"details": {
|
||||
"path": "cvv"
|
||||
"path": "cvv",
|
||||
"schema": "parallel_rules"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -362,8 +378,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "unconditional"
|
||||
},
|
||||
"details": {
|
||||
"path": "unconditional"
|
||||
"path": "unconditional",
|
||||
"schema": "missing_when"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -29,7 +29,19 @@
|
||||
"schema_id": "const_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(2)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -38,7 +50,19 @@
|
||||
"schema_id": "const_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(2)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -97,7 +121,19 @@
|
||||
"schema_id": "const_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Object {\"foo\": String(\"bar\"), \"baz\": String(\"bax\")}"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -109,7 +145,19 @@
|
||||
"schema_id": "const_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Object {\"foo\": String(\"bar\"), \"baz\": String(\"bax\")}"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -154,7 +202,19 @@
|
||||
"schema_id": "const_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Array [Object {\"foo\": String(\"bar\")}]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -167,7 +227,19 @@
|
||||
"schema_id": "const_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Array [Object {\"foo\": String(\"bar\")}]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -202,7 +274,19 @@
|
||||
"schema_id": "const_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Null"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -237,7 +321,19 @@
|
||||
"schema_id": "const_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Bool(false)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -246,7 +342,19 @@
|
||||
"schema_id": "const_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Bool(false)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -281,7 +389,19 @@
|
||||
"schema_id": "const_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Bool(true)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -290,7 +410,19 @@
|
||||
"schema_id": "const_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Bool(true)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -331,7 +463,19 @@
|
||||
"schema_id": "const_6_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Array [Bool(false)]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_6_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -342,7 +486,19 @@
|
||||
"schema_id": "const_6_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Array [Bool(false)]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_6_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -383,7 +539,19 @@
|
||||
"schema_id": "const_7_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Array [Bool(true)]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_7_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -394,7 +562,19 @@
|
||||
"schema_id": "const_7_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Array [Bool(true)]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_7_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -435,7 +615,29 @@
|
||||
"schema_id": "const_8_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Object {\"a\": Bool(false)}"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_8_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "a"
|
||||
},
|
||||
"details": {
|
||||
"path": "a",
|
||||
"schema": "const_8_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -446,7 +648,29 @@
|
||||
"schema_id": "const_8_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Object {\"a\": Bool(false)}"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_8_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "a"
|
||||
},
|
||||
"details": {
|
||||
"path": "a",
|
||||
"schema": "const_8_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -487,7 +711,29 @@
|
||||
"schema_id": "const_9_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Object {\"a\": Bool(true)}"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_9_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "a"
|
||||
},
|
||||
"details": {
|
||||
"path": "a",
|
||||
"schema": "const_9_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -498,7 +744,29 @@
|
||||
"schema_id": "const_9_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Object {\"a\": Bool(true)}"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_9_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "a"
|
||||
},
|
||||
"details": {
|
||||
"path": "a",
|
||||
"schema": "const_9_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -524,7 +792,19 @@
|
||||
"schema_id": "const_10_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(0)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_10_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -551,7 +831,19 @@
|
||||
"schema_id": "const_10_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(0)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_10_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -560,7 +852,19 @@
|
||||
"schema_id": "const_10_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(0)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_10_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -569,7 +873,19 @@
|
||||
"schema_id": "const_10_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(0)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_10_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -595,7 +911,19 @@
|
||||
"schema_id": "const_11_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(1)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_11_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -648,7 +976,19 @@
|
||||
"schema_id": "const_12_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(-2)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_12_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -666,7 +1006,19 @@
|
||||
"schema_id": "const_12_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(-2)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_12_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -675,7 +1027,19 @@
|
||||
"schema_id": "const_12_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(-2)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_12_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -710,7 +1074,19 @@
|
||||
"schema_id": "const_13_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(9007199254740992)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_13_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -728,7 +1104,19 @@
|
||||
"schema_id": "const_13_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Number(9007199254740992)"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_13_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -763,7 +1151,19 @@
|
||||
"schema_id": "const_14_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "String(\"hello\\0there\")"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_14_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -776,7 +1176,7 @@
|
||||
"name": "const_15_0",
|
||||
"schemas": {
|
||||
"const_15_0": {
|
||||
"const": "\u03bc",
|
||||
"const": "μ",
|
||||
"$comment": "U+03BC"
|
||||
}
|
||||
}
|
||||
@ -786,7 +1186,7 @@
|
||||
"tests": [
|
||||
{
|
||||
"description": "character uses the same codepoint",
|
||||
"data": "\u03bc",
|
||||
"data": "μ",
|
||||
"comment": "U+03BC",
|
||||
"schema_id": "const_15_0",
|
||||
"action": "validate",
|
||||
@ -796,12 +1196,24 @@
|
||||
},
|
||||
{
|
||||
"description": "character looks the same but uses a different codepoint",
|
||||
"data": "\u00b5",
|
||||
"data": "µ",
|
||||
"comment": "U+00B5",
|
||||
"schema_id": "const_15_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "String(\"μ\")"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_15_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -814,7 +1226,7 @@
|
||||
"name": "const_16_0",
|
||||
"schemas": {
|
||||
"const_16_0": {
|
||||
"const": "\u00e4",
|
||||
"const": "ä",
|
||||
"$comment": "U+00E4"
|
||||
}
|
||||
}
|
||||
@ -824,7 +1236,7 @@
|
||||
"tests": [
|
||||
{
|
||||
"description": "character uses the same codepoint",
|
||||
"data": "\u00e4",
|
||||
"data": "ä",
|
||||
"comment": "U+00E4",
|
||||
"schema_id": "const_16_0",
|
||||
"action": "validate",
|
||||
@ -834,12 +1246,24 @@
|
||||
},
|
||||
{
|
||||
"description": "character looks the same but uses combining marks",
|
||||
"data": "a\u0308",
|
||||
"data": "ä",
|
||||
"comment": "a, U+0308",
|
||||
"schema_id": "const_16_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "String(\"ä\")"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_16_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -871,7 +1295,19 @@
|
||||
"schema_id": "const_17_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "Object {\"a\": Number(1)}"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "const_17_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -67,7 +67,20 @@
|
||||
"schema_id": "contains_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "contains_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -76,7 +89,20 @@
|
||||
"schema_id": "contains_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "contains_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -146,7 +172,20 @@
|
||||
"schema_id": "contains_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "contains_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -183,7 +222,20 @@
|
||||
"schema_id": "contains_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "contains_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -211,7 +263,20 @@
|
||||
"schema_id": "contains_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "contains_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -220,7 +285,20 @@
|
||||
"schema_id": "contains_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "contains_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -264,7 +342,20 @@
|
||||
"schema_id": "contains_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "contains_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -277,7 +368,31 @@
|
||||
"schema_id": "contains_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MULTIPLE_OF_VIOLATED",
|
||||
"values": {
|
||||
"multiple_of": "2",
|
||||
"value": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "contains_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "MULTIPLE_OF_VIOLATED",
|
||||
"values": {
|
||||
"value": "9",
|
||||
"multiple_of": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "2",
|
||||
"schema": "contains_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -301,7 +416,42 @@
|
||||
"schema_id": "contains_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "contains_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "MULTIPLE_OF_VIOLATED",
|
||||
"values": {
|
||||
"multiple_of": "2",
|
||||
"value": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "contains_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "MULTIPLE_OF_VIOLATED",
|
||||
"values": {
|
||||
"multiple_of": "2",
|
||||
"value": "5"
|
||||
},
|
||||
"details": {
|
||||
"path": "1",
|
||||
"schema": "contains_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -341,7 +491,20 @@
|
||||
"schema_id": "contains_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "contains_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -426,7 +589,7 @@
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "extra items cause failure",
|
||||
"description": "extra items do not cause failure",
|
||||
"data": [
|
||||
1,
|
||||
2
|
||||
@ -434,7 +597,7 @@
|
||||
"schema_id": "contains_8_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -59,7 +59,16 @@
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "EDGE_MISSING"
|
||||
"code": "EDGE_MISSING",
|
||||
"values": {
|
||||
"parent_type": "org",
|
||||
"child_type": "user",
|
||||
"property_name": "missing_users"
|
||||
},
|
||||
"details": {
|
||||
"path": "full.org/missing_users",
|
||||
"schema": "full.org"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -140,7 +149,16 @@
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "EDGE_MISSING"
|
||||
"code": "EDGE_MISSING",
|
||||
"values": {
|
||||
"property_name": "children",
|
||||
"parent_type": "parent",
|
||||
"child_type": "child"
|
||||
},
|
||||
"details": {
|
||||
"path": "full.parent/children",
|
||||
"schema": "full.parent"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -235,16 +253,45 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "AMBIGUOUS_TYPE_RELATIONS",
|
||||
"values": {
|
||||
"child_type": "activity",
|
||||
"property_name": "activities",
|
||||
"parent_type": "invoice"
|
||||
},
|
||||
"details": {
|
||||
"path": "full.invoice/activities",
|
||||
"cause": "Multiple conflicting constraints found matching prefixes",
|
||||
"context": [
|
||||
{
|
||||
"constraint": "fk_activity_invoice_1"
|
||||
"id": "33333333-3333-3333-3333-333333333333",
|
||||
"type": "relation",
|
||||
"constraint": "fk_activity_invoice_1",
|
||||
"source_type": "activity",
|
||||
"source_columns": [
|
||||
"invoice_id_1"
|
||||
],
|
||||
"destination_type": "invoice",
|
||||
"destination_columns": [
|
||||
"id"
|
||||
],
|
||||
"prefix": null
|
||||
},
|
||||
{
|
||||
"constraint": "fk_activity_invoice_2"
|
||||
"id": "44444444-4444-4444-4444-444444444444",
|
||||
"type": "relation",
|
||||
"constraint": "fk_activity_invoice_2",
|
||||
"source_type": "activity",
|
||||
"source_columns": [
|
||||
"invoice_id_2"
|
||||
],
|
||||
"destination_type": "invoice",
|
||||
"destination_columns": [
|
||||
"id"
|
||||
],
|
||||
"prefix": null
|
||||
}
|
||||
]
|
||||
],
|
||||
"schema": "full.invoice"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -342,16 +389,45 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "AMBIGUOUS_TYPE_RELATIONS",
|
||||
"values": {
|
||||
"property_name": "ambiguous_edge",
|
||||
"child_type": "junction",
|
||||
"parent_type": "actor"
|
||||
},
|
||||
"details": {
|
||||
"path": "full.actor/ambiguous_edge",
|
||||
"cause": "Multiple conflicting constraints found matching prefixes",
|
||||
"context": [
|
||||
{
|
||||
"constraint": "fk_junction_source_actor"
|
||||
"id": "33333333-3333-3333-3333-333333333333",
|
||||
"type": "relation",
|
||||
"constraint": "fk_junction_source_actor",
|
||||
"source_type": "junction",
|
||||
"source_columns": [
|
||||
"source_id"
|
||||
],
|
||||
"destination_type": "actor",
|
||||
"destination_columns": [
|
||||
"id"
|
||||
],
|
||||
"prefix": "source"
|
||||
},
|
||||
{
|
||||
"constraint": "fk_junction_target_actor"
|
||||
"id": "44444444-4444-4444-4444-444444444444",
|
||||
"type": "relation",
|
||||
"constraint": "fk_junction_target_actor",
|
||||
"source_type": "junction",
|
||||
"source_columns": [
|
||||
"target_id"
|
||||
],
|
||||
"destination_type": "actor",
|
||||
"destination_columns": [
|
||||
"id"
|
||||
],
|
||||
"prefix": "target"
|
||||
}
|
||||
]
|
||||
],
|
||||
"schema": "full.actor"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -392,7 +468,14 @@
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "DATABASE_TYPE_PARSE_FAILED"
|
||||
"code": "DATABASE_TYPE_PARSE_FAILED",
|
||||
"values": {
|
||||
"type": "failure",
|
||||
"reason": "invalid type: sequence, expected a string"
|
||||
},
|
||||
"details": {
|
||||
"context": "failure"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -60,7 +60,20 @@
|
||||
"schema_id": "schema1",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"required_property": "foo",
|
||||
"property_name": "bar"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "schema1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -209,7 +222,20 @@
|
||||
"schema_id": "schema3",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"required_property": "bar",
|
||||
"property_name": "quux"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "schema3"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -221,7 +247,20 @@
|
||||
"schema_id": "schema3",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"property_name": "quux",
|
||||
"required_property": "foo"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "schema3"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -232,7 +271,31 @@
|
||||
"schema_id": "schema3",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"required_property": "foo",
|
||||
"property_name": "quux"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "schema3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"required_property": "bar",
|
||||
"property_name": "quux"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "schema3"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -294,7 +357,20 @@
|
||||
"schema_id": "schema4",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"required_property": "foo\rbar",
|
||||
"property_name": "foo\nbar"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "schema4"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -305,7 +381,20 @@
|
||||
"schema_id": "schema4",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"required_property": "foo'bar",
|
||||
"property_name": "foo\"bar"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "schema4"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -409,7 +498,19 @@
|
||||
"schema_id": "schema_schema1",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "schema_schema1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -421,7 +522,19 @@
|
||||
"schema_id": "schema_schema1",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "schema_schema1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -433,7 +546,29 @@
|
||||
"schema_id": "schema_schema1",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "schema_schema1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "schema_schema1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -444,12 +579,7 @@
|
||||
"schema_id": "schema_schema1",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION"
|
||||
}
|
||||
]
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -559,7 +689,16 @@
|
||||
"schema_id": "schema_schema3",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "schema_schema3"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -571,7 +710,16 @@
|
||||
"schema_id": "schema_schema3",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "schema_schema3"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -642,7 +790,29 @@
|
||||
"schema_id": "schema_schema4",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "foo\"bar"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\"bar",
|
||||
"schema": "schema_schema4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "foo'bar"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo'bar",
|
||||
"schema": "schema_schema4"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -654,7 +824,20 @@
|
||||
"schema_id": "schema_schema4",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MIN_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"count": "2",
|
||||
"limit": "4"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "schema_schema4"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -665,7 +848,29 @@
|
||||
"schema_id": "schema_schema4",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "foo\"bar"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\"bar",
|
||||
"schema": "schema_schema4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "foo'bar"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo'bar",
|
||||
"schema": "schema_schema4"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -704,7 +909,19 @@
|
||||
"schema_id": "schema_schema5",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "foo"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "schema_schema5"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -718,7 +935,14 @@
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION"
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "bar"
|
||||
},
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "schema_schema5"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -732,7 +956,19 @@
|
||||
"schema_id": "schema_schema5",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "foo"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "schema_schema5"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
284
fixtures/dict.json
Normal file
284
fixtures/dict.json
Normal file
@ -0,0 +1,284 @@
|
||||
[
|
||||
{
|
||||
"description": "basic dict type validation",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "dict_basic",
|
||||
"schemas": {
|
||||
"dict_basic": {
|
||||
"type": "dict"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "valid empty dict",
|
||||
"data": {},
|
||||
"schema_id": "dict_basic",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "valid simple dict",
|
||||
"data": {
|
||||
"key1": "value1",
|
||||
"key2": 123,
|
||||
"key3": true
|
||||
},
|
||||
"schema_id": "dict_basic",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "invalid type - array is not dict",
|
||||
"data": [
|
||||
"a",
|
||||
"b"
|
||||
],
|
||||
"schema_id": "dict_basic",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "dict"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "dict_basic"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "invalid type - string is not dict",
|
||||
"data": "not a dict",
|
||||
"schema_id": "dict_basic",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "dict"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "dict_basic"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "dict keys validation",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "dict_keys",
|
||||
"schemas": {
|
||||
"dict_keys": {
|
||||
"type": "dict",
|
||||
"keys": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z]{3}$"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "valid 3-letter lowercase keys",
|
||||
"data": {
|
||||
"abc": 1,
|
||||
"xyz": "test"
|
||||
},
|
||||
"schema_id": "dict_keys",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "invalid key format",
|
||||
"data": {
|
||||
"abc": 1,
|
||||
"abcd": 2
|
||||
},
|
||||
"schema_id": "dict_keys",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "PATTERN_VIOLATED",
|
||||
"values": {
|
||||
"value": "abcd",
|
||||
"pattern": "^[a-z]{3}$"
|
||||
},
|
||||
"details": {
|
||||
"path": "keys/abcd",
|
||||
"schema": "dict_keys"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "dict items (values) validation",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "dict_items",
|
||||
"schemas": {
|
||||
"dict_items": {
|
||||
"type": "dict",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "valid integer values",
|
||||
"data": {
|
||||
"a": 1,
|
||||
"b": 100
|
||||
},
|
||||
"schema_id": "dict_items",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "invalid value type",
|
||||
"data": {
|
||||
"a": 1,
|
||||
"b": "string value"
|
||||
},
|
||||
"schema_id": "dict_items",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "b",
|
||||
"schema": "dict_items"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "dict keys and items validation combined",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "dict_combined",
|
||||
"schemas": {
|
||||
"dict_combined": {
|
||||
"type": "dict",
|
||||
"keys": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]+$"
|
||||
},
|
||||
"items": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "valid numeric keys and boolean values",
|
||||
"data": {
|
||||
"123": true,
|
||||
"456": false
|
||||
},
|
||||
"schema_id": "dict_combined",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "invalid key and valid value",
|
||||
"data": {
|
||||
"123": true,
|
||||
"abc": false
|
||||
},
|
||||
"schema_id": "dict_combined",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "PATTERN_VIOLATED",
|
||||
"values": {
|
||||
"pattern": "^[0-9]+$",
|
||||
"value": "abc"
|
||||
},
|
||||
"details": {
|
||||
"path": "keys/abc",
|
||||
"schema": "dict_combined"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "valid key and invalid value",
|
||||
"data": {
|
||||
"123": "not a boolean"
|
||||
},
|
||||
"schema_id": "dict_combined",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "boolean"
|
||||
},
|
||||
"details": {
|
||||
"path": "123",
|
||||
"schema": "dict_combined"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -41,9 +41,15 @@
|
||||
"conditions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"new": { "type": "$kind.filter" },
|
||||
"old": { "type": "$kind.filter" },
|
||||
"complete": { "type": "$kind.filter" }
|
||||
"new": {
|
||||
"type": "$kind.filter"
|
||||
},
|
||||
"old": {
|
||||
"type": "$kind.filter"
|
||||
},
|
||||
"complete": {
|
||||
"type": "$kind.filter"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -82,8 +88,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "filter/age"
|
||||
"path": "filter/age",
|
||||
"schema": "search"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -118,14 +128,22 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "DYNAMIC_TYPE_RESOLUTION_FAILED",
|
||||
"values": {
|
||||
"pointer": "unknown.filter"
|
||||
},
|
||||
"details": {
|
||||
"path": "filter"
|
||||
"path": "filter",
|
||||
"schema": "search"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "weight"
|
||||
},
|
||||
"details": {
|
||||
"path": "filter/weight"
|
||||
"path": "filter/weight",
|
||||
"schema": "search"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -145,14 +163,23 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "DYNAMIC_TYPE_RESOLUTION_FAILED",
|
||||
"values": {
|
||||
"pointer": "$kind.filter",
|
||||
"discriminator": "kind"
|
||||
},
|
||||
"details": {
|
||||
"path": "filter"
|
||||
"path": "filter",
|
||||
"schema": "search"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "weight"
|
||||
},
|
||||
"details": {
|
||||
"path": "filter/weight"
|
||||
"path": "filter/weight",
|
||||
"schema": "search"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -191,8 +218,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "conditions/new/age"
|
||||
"path": "conditions/new/age",
|
||||
"schema": "search"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -200,5 +231,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
]
|
||||
@ -146,8 +146,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "String(\"value\")"
|
||||
},
|
||||
"details": {
|
||||
"path": "con"
|
||||
"path": "con",
|
||||
"schema": "emptyString_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -33,7 +33,19 @@
|
||||
"schema_id": "enum_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Number(1), Number(2), Number(3)]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -79,7 +91,19 @@
|
||||
"schema_id": "enum_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Number(6), String(\"foo\"), Array [], Bool(true), Object {\"foo\": Number(12)}]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -90,7 +114,19 @@
|
||||
"schema_id": "enum_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Number(6), String(\"foo\"), Array [], Bool(true), Object {\"foo\": Number(12)}]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -113,7 +149,29 @@
|
||||
"schema_id": "enum_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Number(6), String(\"foo\"), Array [], Bool(true), Object {\"foo\": Number(12)}]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_1_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "boo"
|
||||
},
|
||||
"details": {
|
||||
"path": "boo",
|
||||
"schema": "enum_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -160,7 +218,19 @@
|
||||
"schema_id": "enum_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Number(6), Null]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -216,7 +286,19 @@
|
||||
"schema_id": "enum_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[String(\"foo\")]"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "enum_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -228,7 +310,19 @@
|
||||
"schema_id": "enum_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[String(\"bar\")]"
|
||||
},
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "enum_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -250,7 +344,19 @@
|
||||
"schema_id": "enum_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "bar"
|
||||
},
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "enum_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -259,7 +365,19 @@
|
||||
"schema_id": "enum_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "bar"
|
||||
},
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "enum_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -306,7 +424,19 @@
|
||||
"schema_id": "enum_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[String(\"foo\\nbar\"), String(\"foo\\rbar\")]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -343,7 +473,19 @@
|
||||
"schema_id": "enum_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Bool(false)]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -352,7 +494,19 @@
|
||||
"schema_id": "enum_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Bool(false)]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -395,7 +549,19 @@
|
||||
"schema_id": "enum_6_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Array [Bool(false)]]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_6_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -406,7 +572,19 @@
|
||||
"schema_id": "enum_6_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Array [Bool(false)]]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_6_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -443,7 +621,19 @@
|
||||
"schema_id": "enum_7_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Bool(true)]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_7_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -452,7 +642,19 @@
|
||||
"schema_id": "enum_7_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Bool(true)]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_7_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -495,7 +697,19 @@
|
||||
"schema_id": "enum_8_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Array [Bool(true)]]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_8_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -506,7 +720,19 @@
|
||||
"schema_id": "enum_8_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Array [Bool(true)]]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_8_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -534,7 +760,19 @@
|
||||
"schema_id": "enum_9_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Number(0)]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_9_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -584,7 +822,19 @@
|
||||
"schema_id": "enum_10_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Array [Number(0)]]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_10_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -634,7 +884,19 @@
|
||||
"schema_id": "enum_11_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Number(1)]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_11_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -684,7 +946,19 @@
|
||||
"schema_id": "enum_12_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Array [Number(1)]]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_12_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -743,7 +1017,19 @@
|
||||
"schema_id": "enum_13_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[String(\"hello\\0there\")]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_13_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -777,7 +1063,19 @@
|
||||
"schema_id": "enum_14_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[Object {\"foo\": Number(1)}]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "enum_14_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -29,7 +29,20 @@
|
||||
"schema_id": "exclusiveMaximum_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "EXCLUSIVE_MAXIMUM_VIOLATED",
|
||||
"values": {
|
||||
"limit": "3",
|
||||
"value": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "exclusiveMaximum_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -38,7 +51,20 @@
|
||||
"schema_id": "exclusiveMaximum_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "EXCLUSIVE_MAXIMUM_VIOLATED",
|
||||
"values": {
|
||||
"limit": "3",
|
||||
"value": "3.5"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "exclusiveMaximum_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -29,7 +29,20 @@
|
||||
"schema_id": "exclusiveMinimum_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "EXCLUSIVE_MINIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "1.1",
|
||||
"limit": "1.1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "exclusiveMinimum_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -38,7 +51,20 @@
|
||||
"schema_id": "exclusiveMinimum_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "EXCLUSIVE_MINIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "0.6",
|
||||
"limit": "1.1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "exclusiveMinimum_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
3892
fixtures/format.json
3892
fixtures/format.json
File diff suppressed because it is too large
Load Diff
1038
fixtures/items.json
1038
fixtures/items.json
File diff suppressed because it is too large
Load Diff
@ -65,7 +65,20 @@
|
||||
"schema_id": "maxContains_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxContains_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -88,7 +101,20 @@
|
||||
"schema_id": "maxContains_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxContains_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -113,7 +139,20 @@
|
||||
"schema_id": "maxContains_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "2",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxContains_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -157,7 +196,20 @@
|
||||
"schema_id": "maxContains_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "2",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxContains_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -188,7 +240,20 @@
|
||||
"schema_id": "maxContains_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxContains_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -214,7 +279,20 @@
|
||||
"schema_id": "maxContains_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "3",
|
||||
"count": "4"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxContains_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -7,8 +7,7 @@
|
||||
"name": "maxItems_0_0",
|
||||
"schemas": {
|
||||
"maxItems_0_0": {
|
||||
"maxItems": 2,
|
||||
"extensible": true
|
||||
"maxItems": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -48,7 +47,20 @@
|
||||
"schema_id": "maxItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_ITEMS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -70,8 +82,7 @@
|
||||
"name": "maxItems_1_0",
|
||||
"schemas": {
|
||||
"maxItems_1_0": {
|
||||
"maxItems": 2,
|
||||
"extensible": true
|
||||
"maxItems": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,7 +110,20 @@
|
||||
"schema_id": "maxItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_ITEMS_VIOLATED",
|
||||
"values": {
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxItems_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -112,8 +136,7 @@
|
||||
"name": "maxItems_2_0",
|
||||
"schemas": {
|
||||
"maxItems_2_0": {
|
||||
"maxItems": 2,
|
||||
"extensible": true
|
||||
"maxItems": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -130,7 +153,20 @@
|
||||
"schema_id": "maxItems_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_ITEMS_VIOLATED",
|
||||
"values": {
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxItems_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -38,7 +38,20 @@
|
||||
"schema_id": "maxLength_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxLength_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -52,7 +65,7 @@
|
||||
},
|
||||
{
|
||||
"description": "two graphemes is long enough",
|
||||
"data": "\ud83d\udca9\ud83d\udca9",
|
||||
"data": "💩💩",
|
||||
"schema_id": "maxLength_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
@ -91,7 +104,20 @@
|
||||
"schema_id": "maxLength_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxLength_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -48,7 +48,20 @@
|
||||
"schema_id": "maxProperties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxProperties_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -121,7 +134,20 @@
|
||||
"schema_id": "maxProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxProperties_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -159,7 +185,20 @@
|
||||
"schema_id": "maxProperties_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"count": "1",
|
||||
"limit": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxProperties_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -190,7 +229,20 @@
|
||||
"schema_id": "maxProperties_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maxProperties_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -38,7 +38,20 @@
|
||||
"schema_id": "maximum_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAXIMUM_VIOLATED",
|
||||
"values": {
|
||||
"limit": "3",
|
||||
"value": "3.5"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maximum_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -100,7 +113,20 @@
|
||||
"schema_id": "maximum_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAXIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "300.5",
|
||||
"limit": "300"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "maximum_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -56,8 +56,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "string"
|
||||
},
|
||||
"details": {
|
||||
"path": "base_prop"
|
||||
"path": "base_prop",
|
||||
"schema": "merge_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -127,8 +131,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "a"
|
||||
},
|
||||
"details": {
|
||||
"path": "a"
|
||||
"path": "a",
|
||||
"schema": "merge_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -146,8 +154,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "b"
|
||||
},
|
||||
"details": {
|
||||
"path": "b"
|
||||
"path": "b",
|
||||
"schema": "merge_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -226,8 +238,13 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"required_property": "base_dep",
|
||||
"property_name": "trigger"
|
||||
},
|
||||
"details": {
|
||||
"path": ""
|
||||
"path": "",
|
||||
"schema": "merge_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -246,8 +263,13 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"required_property": "child_dep",
|
||||
"property_name": "trigger"
|
||||
},
|
||||
"details": {
|
||||
"path": ""
|
||||
"path": "",
|
||||
"schema": "merge_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -62,7 +62,20 @@
|
||||
"schema_id": "minContains_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -73,7 +86,20 @@
|
||||
"schema_id": "minContains_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -138,7 +164,20 @@
|
||||
"schema_id": "minContains_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -149,7 +188,20 @@
|
||||
"schema_id": "minContains_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "1",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -161,7 +213,20 @@
|
||||
"schema_id": "minContains_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -231,7 +296,20 @@
|
||||
"schema_id": "minContains_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "1",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -274,7 +352,20 @@
|
||||
"schema_id": "minContains_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -285,7 +376,20 @@
|
||||
"schema_id": "minContains_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -298,7 +402,20 @@
|
||||
"schema_id": "minContains_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -341,7 +458,20 @@
|
||||
"schema_id": "minContains_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -352,7 +482,20 @@
|
||||
"schema_id": "minContains_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "1",
|
||||
"limit": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -365,7 +508,20 @@
|
||||
"schema_id": "minContains_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "3",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -377,7 +533,31 @@
|
||||
"schema_id": "minContains_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "3",
|
||||
"count": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_5_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -472,7 +652,20 @@
|
||||
"schema_id": "minContains_7_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "2",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minContains_7_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -7,8 +7,7 @@
|
||||
"name": "minItems_0_0",
|
||||
"schemas": {
|
||||
"minItems_0_0": {
|
||||
"minItems": 1,
|
||||
"extensible": true
|
||||
"minItems": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -44,7 +43,20 @@
|
||||
"schema_id": "minItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MIN_ITEMS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -66,8 +78,7 @@
|
||||
"name": "minItems_1_0",
|
||||
"schemas": {
|
||||
"minItems_1_0": {
|
||||
"minItems": 1,
|
||||
"extensible": true
|
||||
"minItems": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -92,7 +103,20 @@
|
||||
"schema_id": "minItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MIN_ITEMS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minItems_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -38,7 +38,20 @@
|
||||
"schema_id": "minLength_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MIN_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minLength_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -52,11 +65,24 @@
|
||||
},
|
||||
{
|
||||
"description": "one grapheme is not long enough",
|
||||
"data": "\ud83d\udca9",
|
||||
"data": "💩",
|
||||
"schema_id": "minLength_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MIN_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"count": "1",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minLength_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -91,7 +117,20 @@
|
||||
"schema_id": "minLength_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MIN_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"count": "1",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minLength_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -44,7 +44,20 @@
|
||||
"schema_id": "minProperties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MIN_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minProperties_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -110,7 +123,20 @@
|
||||
"schema_id": "minProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MIN_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minProperties_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -38,7 +38,20 @@
|
||||
"schema_id": "minimum_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MINIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "0.6",
|
||||
"limit": "1.1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minimum_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -109,7 +122,20 @@
|
||||
"schema_id": "minimum_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MINIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "-2.0001",
|
||||
"limit": "-2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minimum_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -118,7 +144,20 @@
|
||||
"schema_id": "minimum_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MINIMUM_VIOLATED",
|
||||
"values": {
|
||||
"limit": "-2",
|
||||
"value": "-3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "minimum_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -29,7 +29,20 @@
|
||||
"schema_id": "multipleOf_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MULTIPLE_OF_VIOLATED",
|
||||
"values": {
|
||||
"value": "7",
|
||||
"multiple_of": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "multipleOf_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -82,7 +95,20 @@
|
||||
"schema_id": "multipleOf_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MULTIPLE_OF_VIOLATED",
|
||||
"values": {
|
||||
"multiple_of": "1.5",
|
||||
"value": "35"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "multipleOf_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -117,7 +143,20 @@
|
||||
"schema_id": "multipleOf_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MULTIPLE_OF_VIOLATED",
|
||||
"values": {
|
||||
"value": "0.00751",
|
||||
"multiple_of": "0.0001"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "multipleOf_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -131,7 +170,7 @@
|
||||
"schemas": {
|
||||
"multipleOf_3_0": {
|
||||
"type": "integer",
|
||||
"multipleOf": 1e-08
|
||||
"multipleOf": 1e-8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,7 +31,16 @@
|
||||
"schema_id": "not_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -71,7 +80,16 @@
|
||||
"schema_id": "not_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -80,7 +98,16 @@
|
||||
"schema_id": "not_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -136,7 +163,16 @@
|
||||
"schema_id": "not_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -169,7 +205,26 @@
|
||||
"schema_id": "not_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "not_3_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "bar"
|
||||
},
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "not_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -204,7 +259,16 @@
|
||||
"schema_id": "not_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -213,7 +277,16 @@
|
||||
"schema_id": "not_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -222,7 +295,16 @@
|
||||
"schema_id": "not_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -231,7 +313,16 @@
|
||||
"schema_id": "not_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -240,7 +331,16 @@
|
||||
"schema_id": "not_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -251,7 +351,26 @@
|
||||
"schema_id": "not_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "foo"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -260,7 +379,16 @@
|
||||
"schema_id": "not_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -271,7 +399,16 @@
|
||||
"schema_id": "not_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -280,7 +417,16 @@
|
||||
"schema_id": "not_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -306,7 +452,16 @@
|
||||
"schema_id": "not_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -315,7 +470,16 @@
|
||||
"schema_id": "not_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -324,7 +488,16 @@
|
||||
"schema_id": "not_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -333,7 +506,16 @@
|
||||
"schema_id": "not_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -342,7 +524,16 @@
|
||||
"schema_id": "not_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -353,7 +544,26 @@
|
||||
"schema_id": "not_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "foo"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -362,7 +572,16 @@
|
||||
"schema_id": "not_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -373,7 +592,16 @@
|
||||
"schema_id": "not_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -382,7 +610,16 @@
|
||||
"schema_id": "not_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -574,7 +811,19 @@
|
||||
"schema_id": "not_9_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "foo"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "not_9_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -647,7 +896,19 @@
|
||||
"schema_id": "not_11_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "foo"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "not_11_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -55,7 +55,19 @@
|
||||
},
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "a"
|
||||
},
|
||||
"details": {
|
||||
"path": "a",
|
||||
"schema": "child_type"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -68,7 +80,19 @@
|
||||
},
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "c"
|
||||
},
|
||||
"details": {
|
||||
"path": "c",
|
||||
"schema": "child_type"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -127,7 +151,20 @@
|
||||
},
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAXIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "60",
|
||||
"limit": "50"
|
||||
},
|
||||
"details": {
|
||||
"path": "max",
|
||||
"schema": "custom_budget"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -205,7 +242,19 @@
|
||||
},
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "inv/amount",
|
||||
"schema": "request"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -127,8 +127,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "string"
|
||||
},
|
||||
"details": {
|
||||
"path": "primitives/1"
|
||||
"path": "primitives/1",
|
||||
"schema": "hybrid_pathing"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -153,14 +157,22 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "name"
|
||||
},
|
||||
"details": {
|
||||
"path": "ad_hoc_objects/1/name"
|
||||
"path": "ad_hoc_objects/1/name",
|
||||
"schema": "hybrid_pathing"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "age"
|
||||
},
|
||||
"details": {
|
||||
"path": "ad_hoc_objects/1/age"
|
||||
"path": "ad_hoc_objects/1/age",
|
||||
"schema": "hybrid_pathing"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -187,8 +199,13 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "MINIMUM_VIOLATED",
|
||||
"values": {
|
||||
"limit": "10",
|
||||
"value": "5"
|
||||
},
|
||||
"details": {
|
||||
"path": "entities/entity-beta/value"
|
||||
"path": "entities/entity-beta/value",
|
||||
"schema": "hybrid_pathing"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -220,8 +237,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "boolean"
|
||||
},
|
||||
"details": {
|
||||
"path": "deep_entities/parent-omega/nested/child-beta/flag"
|
||||
"path": "deep_entities/parent-omega/nested/child-beta/flag",
|
||||
"schema": "hybrid_pathing"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -275,8 +296,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "NO_ONEOF_MATCH",
|
||||
"values": {
|
||||
"primitive": "boolean"
|
||||
},
|
||||
"details": {
|
||||
"path": "metadata_bubbles/2"
|
||||
"path": "metadata_bubbles/2",
|
||||
"schema": "ad_hoc_pathing"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -293,16 +318,22 @@
|
||||
"type": "relation",
|
||||
"constraint": "fk_family_pathing_table_families_widget",
|
||||
"source_type": "widget",
|
||||
"source_columns": ["family_pathing_id"],
|
||||
"source_columns": [
|
||||
"family_pathing_id"
|
||||
],
|
||||
"destination_type": "family_pathing",
|
||||
"destination_columns": ["id"],
|
||||
"destination_columns": [
|
||||
"id"
|
||||
],
|
||||
"prefix": "table_families"
|
||||
}
|
||||
],
|
||||
"types": [
|
||||
{
|
||||
"name": "widget",
|
||||
"hierarchy": ["widget"],
|
||||
"hierarchy": [
|
||||
"widget"
|
||||
],
|
||||
"variations": [
|
||||
"widget"
|
||||
],
|
||||
@ -348,7 +379,9 @@
|
||||
},
|
||||
{
|
||||
"name": "family_pathing",
|
||||
"hierarchy": ["family_pathing"],
|
||||
"hierarchy": [
|
||||
"family_pathing"
|
||||
],
|
||||
"schemas": {
|
||||
"family_pathing": {
|
||||
"type": "object",
|
||||
@ -398,26 +431,42 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "table_families/widget-2/amount"
|
||||
"path": "table_families/widget-2/amount",
|
||||
"schema": "family_pathing"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "nested_metric"
|
||||
},
|
||||
"details": {
|
||||
"path": "table_families/widget-2/details/nested_metric"
|
||||
"path": "table_families/widget-2/details/nested_metric",
|
||||
"schema": "family_pathing"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "stray_child"
|
||||
},
|
||||
"details": {
|
||||
"path": "table_families/widget-2/details/stray_child"
|
||||
"path": "table_families/widget-2/details/stray_child",
|
||||
"schema": "family_pathing"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "unexpected_root_prop"
|
||||
},
|
||||
"details": {
|
||||
"path": "table_families/widget-2/unexpected_root_prop"
|
||||
"path": "table_families/widget-2/unexpected_root_prop",
|
||||
"schema": "family_pathing"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -29,7 +29,20 @@
|
||||
"schema_id": "pattern_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "PATTERN_VIOLATED",
|
||||
"values": {
|
||||
"pattern": "^a*$",
|
||||
"value": "abc"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "pattern_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -1,423 +0,0 @@
|
||||
[
|
||||
{
|
||||
"description": "patternProperties validates properties matching a regex",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "patternProperties_0_0",
|
||||
"schemas": {
|
||||
"patternProperties_0_0": {
|
||||
"patternProperties": {
|
||||
"f.*o": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"items": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "a single valid match is valid",
|
||||
"data": {
|
||||
"foo": 1
|
||||
},
|
||||
"schema_id": "patternProperties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "multiple valid matches is valid",
|
||||
"data": {
|
||||
"foo": 1,
|
||||
"foooooo": 2
|
||||
},
|
||||
"schema_id": "patternProperties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "a single invalid match is invalid",
|
||||
"data": {
|
||||
"foo": "bar",
|
||||
"fooooo": 2
|
||||
},
|
||||
"schema_id": "patternProperties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "multiple invalid matches is invalid",
|
||||
"data": {
|
||||
"foo": "bar",
|
||||
"foooooo": "baz"
|
||||
},
|
||||
"schema_id": "patternProperties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "ignores arrays",
|
||||
"data": [
|
||||
"foo"
|
||||
],
|
||||
"schema_id": "patternProperties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "ignores strings",
|
||||
"data": "foo",
|
||||
"schema_id": "patternProperties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "ignores other non-objects",
|
||||
"data": 12,
|
||||
"schema_id": "patternProperties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "extra property not matching pattern is INVALID (strict by default)",
|
||||
"data": {
|
||||
"foo": 1,
|
||||
"extra": 2
|
||||
},
|
||||
"schema_id": "patternProperties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "multiple simultaneous patternProperties are validated",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "patternProperties_1_0",
|
||||
"schemas": {
|
||||
"patternProperties_1_0": {
|
||||
"patternProperties": {
|
||||
"a*": {
|
||||
"type": "integer"
|
||||
},
|
||||
"aaa*": {
|
||||
"maximum": 20
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "a single valid match is valid",
|
||||
"data": {
|
||||
"a": 21
|
||||
},
|
||||
"schema_id": "patternProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "a simultaneous match is valid",
|
||||
"data": {
|
||||
"aaaa": 18
|
||||
},
|
||||
"schema_id": "patternProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "multiple matches is valid",
|
||||
"data": {
|
||||
"a": 21,
|
||||
"aaaa": 18
|
||||
},
|
||||
"schema_id": "patternProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "an invalid due to one is invalid",
|
||||
"data": {
|
||||
"a": "bar"
|
||||
},
|
||||
"schema_id": "patternProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "an invalid due to the other is invalid",
|
||||
"data": {
|
||||
"aaaa": 31
|
||||
},
|
||||
"schema_id": "patternProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "an invalid due to both is invalid",
|
||||
"data": {
|
||||
"aaa": "foo",
|
||||
"aaaa": 31
|
||||
},
|
||||
"schema_id": "patternProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "regexes are not anchored by default and are case sensitive",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "patternProperties_2_0",
|
||||
"schemas": {
|
||||
"patternProperties_2_0": {
|
||||
"patternProperties": {
|
||||
"[0-9]{2,}": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"X_": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"extensible": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "non recognized members are ignored",
|
||||
"data": {
|
||||
"answer 1": "42"
|
||||
},
|
||||
"schema_id": "patternProperties_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "recognized members are accounted for",
|
||||
"data": {
|
||||
"a31b": null
|
||||
},
|
||||
"schema_id": "patternProperties_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "regexes are case sensitive",
|
||||
"data": {
|
||||
"a_x_3": 3
|
||||
},
|
||||
"schema_id": "patternProperties_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "regexes are case sensitive, 2",
|
||||
"data": {
|
||||
"a_X_3": 3
|
||||
},
|
||||
"schema_id": "patternProperties_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "patternProperties with boolean schemas",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "patternProperties_3_0",
|
||||
"schemas": {
|
||||
"patternProperties_3_0": {
|
||||
"patternProperties": {
|
||||
"f.*": true,
|
||||
"b.*": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "object with property matching schema true is valid",
|
||||
"data": {
|
||||
"foo": 1
|
||||
},
|
||||
"schema_id": "patternProperties_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "object with property matching schema false is invalid",
|
||||
"data": {
|
||||
"bar": 2
|
||||
},
|
||||
"schema_id": "patternProperties_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "object with both properties is invalid",
|
||||
"data": {
|
||||
"foo": 1,
|
||||
"bar": 2
|
||||
},
|
||||
"schema_id": "patternProperties_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "object with a property matching both true and false is invalid",
|
||||
"data": {
|
||||
"foobar": 1
|
||||
},
|
||||
"schema_id": "patternProperties_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "empty object is valid",
|
||||
"data": {},
|
||||
"schema_id": "patternProperties_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "patternProperties with null valued instance properties",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "patternProperties_4_0",
|
||||
"schemas": {
|
||||
"patternProperties_4_0": {
|
||||
"patternProperties": {
|
||||
"^.*bar$": {
|
||||
"type": "null"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "allows null values",
|
||||
"data": {
|
||||
"foobar": null
|
||||
},
|
||||
"schema_id": "patternProperties_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "extensible: true allows extra properties NOT matching pattern",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "patternProperties_5_0",
|
||||
"schemas": {
|
||||
"patternProperties_5_0": {
|
||||
"patternProperties": {
|
||||
"f.*o": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"extensible": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "extra property not matching pattern is valid",
|
||||
"data": {
|
||||
"bar": 1
|
||||
},
|
||||
"schema_id": "patternProperties_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "property matching pattern MUST still be valid",
|
||||
"data": {
|
||||
"foo": "invalid string"
|
||||
},
|
||||
"schema_id": "patternProperties_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -123,8 +123,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "MISSING_TYPE",
|
||||
"values": {
|
||||
"discriminator": "type"
|
||||
},
|
||||
"details": {
|
||||
"path": ""
|
||||
"path": "",
|
||||
"schema": "family_entity"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -143,8 +147,13 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "NO_FAMILY_MATCH",
|
||||
"values": {
|
||||
"discriminator": "type",
|
||||
"value": "alien"
|
||||
},
|
||||
"details": {
|
||||
"path": ""
|
||||
"path": "",
|
||||
"schema": "family_entity"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -274,8 +283,13 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "NO_FAMILY_MATCH",
|
||||
"values": {
|
||||
"discriminator": "type",
|
||||
"value": "bot"
|
||||
},
|
||||
"details": {
|
||||
"path": ""
|
||||
"path": "",
|
||||
"schema": "family_light_org"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -397,8 +411,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "super_amount"
|
||||
"path": "super_amount",
|
||||
"schema": "family_stock_widget"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -509,8 +527,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "MISSING_TYPE",
|
||||
"values": {
|
||||
"discriminator": "type"
|
||||
},
|
||||
"details": {
|
||||
"path": ""
|
||||
"path": "",
|
||||
"schema": "oneOf_union"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -530,8 +552,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "age"
|
||||
"path": "age",
|
||||
"schema": "oneOf_union"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -564,8 +590,13 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "NO_ONEOF_MATCH",
|
||||
"values": {
|
||||
"value": "alien",
|
||||
"discriminator": "type"
|
||||
},
|
||||
"details": {
|
||||
"path": ""
|
||||
"path": "",
|
||||
"schema": "oneOf_union"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -643,8 +674,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "invoice_id"
|
||||
"path": "invoice_id",
|
||||
"schema": "oneOf_bubble"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -736,7 +771,8 @@
|
||||
{
|
||||
"code": "MISSING_KIND",
|
||||
"details": {
|
||||
"path": ""
|
||||
"path": "",
|
||||
"schema": "stock_widget_validation"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -768,8 +804,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "kind"
|
||||
},
|
||||
"details": {
|
||||
"path": "kind"
|
||||
"path": "kind",
|
||||
"schema": "projected_widget_validation"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -866,8 +906,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "amount"
|
||||
"path": "amount",
|
||||
"schema": "family_panel"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -886,8 +930,13 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "NO_FAMILY_MATCH",
|
||||
"values": {
|
||||
"value": "unknown_panel",
|
||||
"discriminator": "kind"
|
||||
},
|
||||
"details": {
|
||||
"path": ""
|
||||
"path": "",
|
||||
"schema": "family_panel"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -1,249 +0,0 @@
|
||||
[
|
||||
{
|
||||
"description": "a schema given for prefixItems",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "prefixItems_0_0",
|
||||
"schemas": {
|
||||
"prefixItems_0_0": {
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "correct types",
|
||||
"data": [
|
||||
1,
|
||||
"foo"
|
||||
],
|
||||
"schema_id": "prefixItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "wrong types",
|
||||
"data": [
|
||||
"foo",
|
||||
1
|
||||
],
|
||||
"schema_id": "prefixItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "incomplete array of items",
|
||||
"data": [
|
||||
1
|
||||
],
|
||||
"schema_id": "prefixItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "array with additional items (invalid due to strictness)",
|
||||
"data": [
|
||||
1,
|
||||
"foo",
|
||||
true
|
||||
],
|
||||
"schema_id": "prefixItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "empty array",
|
||||
"data": [],
|
||||
"schema_id": "prefixItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "JavaScript pseudo-array is valid (invalid due to strict object validation)",
|
||||
"data": {
|
||||
"0": "invalid",
|
||||
"1": "valid",
|
||||
"length": 2
|
||||
},
|
||||
"schema_id": "prefixItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "prefixItems with boolean schemas",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "prefixItems_1_0",
|
||||
"schemas": {
|
||||
"prefixItems_1_0": {
|
||||
"prefixItems": [
|
||||
true,
|
||||
false
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "array with one item is valid",
|
||||
"data": [
|
||||
1
|
||||
],
|
||||
"schema_id": "prefixItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "array with two items is invalid",
|
||||
"data": [
|
||||
1,
|
||||
"foo"
|
||||
],
|
||||
"schema_id": "prefixItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "empty array is valid",
|
||||
"data": [],
|
||||
"schema_id": "prefixItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "additional items are allowed by default",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "prefixItems_2_0",
|
||||
"schemas": {
|
||||
"prefixItems_2_0": {
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": "integer"
|
||||
}
|
||||
],
|
||||
"extensible": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "only the first item is validated",
|
||||
"data": [
|
||||
1,
|
||||
"foo",
|
||||
false
|
||||
],
|
||||
"schema_id": "prefixItems_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "prefixItems with null instance elements",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "prefixItems_3_0",
|
||||
"schemas": {
|
||||
"prefixItems_3_0": {
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "allows null elements",
|
||||
"data": [
|
||||
null
|
||||
],
|
||||
"schema_id": "prefixItems_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "extensible: true allows extra items with prefixItems",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "prefixItems_4_0",
|
||||
"schemas": {
|
||||
"prefixItems_4_0": {
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": "integer"
|
||||
}
|
||||
],
|
||||
"extensible": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "extra item is valid",
|
||||
"data": [
|
||||
1,
|
||||
"foo"
|
||||
],
|
||||
"schema_id": "prefixItems_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
@ -42,7 +42,19 @@
|
||||
"schema_id": "properties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "string"
|
||||
},
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "properties_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -54,7 +66,29 @@
|
||||
"schema_id": "properties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "properties_0_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "string"
|
||||
},
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "properties_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -132,7 +166,16 @@
|
||||
"schema_id": "properties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "properties_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -144,7 +187,16 @@
|
||||
"schema_id": "properties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "properties_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -212,7 +264,69 @@
|
||||
"schema_id": "properties_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "number"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\nbar",
|
||||
"schema": "properties_2_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "number"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\"bar",
|
||||
"schema": "properties_2_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "number"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\\bar",
|
||||
"schema": "properties_2_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "number"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\rbar",
|
||||
"schema": "properties_2_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "number"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\tbar",
|
||||
"schema": "properties_2_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "number"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\fbar",
|
||||
"schema": "properties_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -314,7 +428,19 @@
|
||||
"schema_id": "properties_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "number"
|
||||
},
|
||||
"details": {
|
||||
"path": "__proto__",
|
||||
"schema": "properties_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -327,7 +453,19 @@
|
||||
"schema_id": "properties_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "string"
|
||||
},
|
||||
"details": {
|
||||
"path": "toString/length",
|
||||
"schema": "properties_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -340,7 +478,19 @@
|
||||
"schema_id": "properties_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "number"
|
||||
},
|
||||
"details": {
|
||||
"path": "constructor",
|
||||
"schema": "properties_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -422,7 +572,19 @@
|
||||
"schema_id": "properties_6_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "extra"
|
||||
},
|
||||
"details": {
|
||||
"path": "extra",
|
||||
"schema": "properties_6_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -461,7 +623,19 @@
|
||||
"schema_id": "properties_7_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "extra"
|
||||
},
|
||||
"details": {
|
||||
"path": "nested/extra",
|
||||
"schema": "properties_7_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -582,7 +756,19 @@
|
||||
"schema_id": "properties_10_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "extra"
|
||||
},
|
||||
"details": {
|
||||
"path": "nested/extra",
|
||||
"schema": "properties_10_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -626,7 +812,19 @@
|
||||
"schema_id": "properties_11_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "extra"
|
||||
},
|
||||
"details": {
|
||||
"path": "list/0/extra",
|
||||
"schema": "properties_11_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -38,7 +38,20 @@
|
||||
"schema_id": "propertyNames_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"limit": "3",
|
||||
"count": "6"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "propertyNames_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -123,7 +136,20 @@
|
||||
"schema_id": "propertyNames_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "PATTERN_VIOLATED",
|
||||
"values": {
|
||||
"pattern": "^a+$",
|
||||
"value": "aaA"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "propertyNames_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -199,7 +225,16 @@
|
||||
"schema_id": "propertyNames_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "propertyNames_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -250,7 +285,19 @@
|
||||
"schema_id": "propertyNames_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CONST_VIOLATED",
|
||||
"values": {
|
||||
"expected": "String(\"foo\")"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "propertyNames_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -316,7 +363,19 @@
|
||||
"schema_id": "propertyNames_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "ENUM_MISMATCH",
|
||||
"values": {
|
||||
"expected": "[String(\"foo\"), String(\"bar\")]"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "propertyNames_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -367,7 +426,20 @@
|
||||
"schema_id": "propertyNames_6_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"count": "6",
|
||||
"limit": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "propertyNames_6_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -39,7 +39,19 @@
|
||||
"schema_id": "required_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "foo"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "required_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -194,7 +206,49 @@
|
||||
"schema_id": "required_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "foo\\bar"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\\bar",
|
||||
"schema": "required_3_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "foo\rbar"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\rbar",
|
||||
"schema": "required_3_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "foo\tbar"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\tbar",
|
||||
"schema": "required_3_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "foo\fbar"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo\fbar",
|
||||
"schema": "required_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -244,7 +298,39 @@
|
||||
"schema_id": "required_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "__proto__"
|
||||
},
|
||||
"details": {
|
||||
"path": "__proto__",
|
||||
"schema": "required_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "toString"
|
||||
},
|
||||
"details": {
|
||||
"path": "toString",
|
||||
"schema": "required_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "constructor"
|
||||
},
|
||||
"details": {
|
||||
"path": "constructor",
|
||||
"schema": "required_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -255,7 +341,29 @@
|
||||
"schema_id": "required_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "toString"
|
||||
},
|
||||
"details": {
|
||||
"path": "toString",
|
||||
"schema": "required_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "constructor"
|
||||
},
|
||||
"details": {
|
||||
"path": "constructor",
|
||||
"schema": "required_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -268,7 +376,29 @@
|
||||
"schema_id": "required_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "__proto__"
|
||||
},
|
||||
"details": {
|
||||
"path": "__proto__",
|
||||
"schema": "required_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "constructor"
|
||||
},
|
||||
"details": {
|
||||
"path": "constructor",
|
||||
"schema": "required_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -281,7 +411,29 @@
|
||||
"schema_id": "required_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "__proto__"
|
||||
},
|
||||
"details": {
|
||||
"path": "__proto__",
|
||||
"schema": "required_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "toString"
|
||||
},
|
||||
"details": {
|
||||
"path": "toString",
|
||||
"schema": "required_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -8,27 +8,46 @@
|
||||
"schemas": {
|
||||
"full.person": {
|
||||
"type": "object",
|
||||
"include": ["emailable", "phonable"],
|
||||
"include": [
|
||||
"emailable",
|
||||
"phonable"
|
||||
],
|
||||
"properties": {
|
||||
"name": { "type": "string" }
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name"]
|
||||
"required": [
|
||||
"name"
|
||||
]
|
||||
}
|
||||
},
|
||||
"traits": {
|
||||
"emailable": {
|
||||
"properties": {
|
||||
"email": { "type": "string" }
|
||||
"email": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["email"],
|
||||
"display": ["email"]
|
||||
"required": [
|
||||
"email"
|
||||
],
|
||||
"display": [
|
||||
"email"
|
||||
]
|
||||
},
|
||||
"phonable": {
|
||||
"properties": {
|
||||
"phone": { "type": "string" }
|
||||
"phone": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["phone"],
|
||||
"display": ["phone"]
|
||||
"required": [
|
||||
"phone"
|
||||
],
|
||||
"display": [
|
||||
"phone"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,8 +80,12 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"values": {
|
||||
"field_name": "email"
|
||||
},
|
||||
"details": {
|
||||
"path": "email"
|
||||
"path": "email",
|
||||
"schema": "full.person"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -79,7 +102,9 @@
|
||||
"schemas": {
|
||||
"full.person": {
|
||||
"type": "object",
|
||||
"include": ["emailable"],
|
||||
"include": [
|
||||
"emailable"
|
||||
],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
@ -91,7 +116,9 @@
|
||||
"traits": {
|
||||
"emailable": {
|
||||
"properties": {
|
||||
"email": { "type": "string" }
|
||||
"email": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -111,8 +138,13 @@
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAX_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"count": "26",
|
||||
"limit": "5"
|
||||
},
|
||||
"details": {
|
||||
"path": "email"
|
||||
"path": "email",
|
||||
"schema": "full.person"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -129,7 +161,9 @@
|
||||
"schemas": {
|
||||
"full.person": {
|
||||
"type": "object",
|
||||
"include": ["nonexistent_trait"]
|
||||
"include": [
|
||||
"nonexistent_trait"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -143,7 +177,14 @@
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "TRAIT_NOT_FOUND"
|
||||
"code": "TRAIT_NOT_FOUND",
|
||||
"values": {
|
||||
"include": "nonexistent_trait"
|
||||
},
|
||||
"details": {
|
||||
"path": "full.person",
|
||||
"schema": "full.person"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -159,15 +200,21 @@
|
||||
"schemas": {
|
||||
"full.person": {
|
||||
"type": "object",
|
||||
"include": ["trait_a"]
|
||||
"include": [
|
||||
"trait_a"
|
||||
]
|
||||
}
|
||||
},
|
||||
"traits": {
|
||||
"trait_a": {
|
||||
"include": ["trait_b"]
|
||||
"include": [
|
||||
"trait_b"
|
||||
]
|
||||
},
|
||||
"trait_b": {
|
||||
"include": ["trait_a"]
|
||||
"include": [
|
||||
"trait_a"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -181,11 +228,18 @@
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "CIRCULAR_INCLUDE_DETECTED"
|
||||
"code": "CIRCULAR_INCLUDE_DETECTED",
|
||||
"values": {
|
||||
"include": "trait_a"
|
||||
},
|
||||
"details": {
|
||||
"path": "full.person/include/trait_a/include/trait_b",
|
||||
"schema": "full.person"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@ -36,7 +36,16 @@
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -49,7 +58,16 @@
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -62,7 +80,16 @@
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -112,7 +139,16 @@
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -144,7 +180,16 @@
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -162,7 +207,16 @@
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -210,7 +264,16 @@
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -242,447 +305,16 @@
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "non-unique array of more than two arrays is invalid",
|
||||
"data": [
|
||||
[
|
||||
"foo"
|
||||
],
|
||||
[
|
||||
"bar"
|
||||
],
|
||||
[
|
||||
"foo"
|
||||
]
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "1 and true are unique",
|
||||
"data": [
|
||||
1,
|
||||
true
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "0 and false are unique",
|
||||
"data": [
|
||||
0,
|
||||
false
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[1] and [true] are unique",
|
||||
"data": [
|
||||
[
|
||||
1
|
||||
],
|
||||
[
|
||||
true
|
||||
]
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[0] and [false] are unique",
|
||||
"data": [
|
||||
[
|
||||
0
|
||||
],
|
||||
[
|
||||
false
|
||||
]
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "nested [1] and [true] are unique",
|
||||
"data": [
|
||||
[
|
||||
[
|
||||
1
|
||||
],
|
||||
"foo"
|
||||
],
|
||||
[
|
||||
[
|
||||
true
|
||||
],
|
||||
"foo"
|
||||
]
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "nested [0] and [false] are unique",
|
||||
"data": [
|
||||
[
|
||||
[
|
||||
0
|
||||
],
|
||||
"foo"
|
||||
],
|
||||
[
|
||||
[
|
||||
false
|
||||
],
|
||||
"foo"
|
||||
]
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "unique heterogeneous types are valid",
|
||||
"data": [
|
||||
{},
|
||||
[
|
||||
1
|
||||
],
|
||||
true,
|
||||
null,
|
||||
1,
|
||||
"{}"
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "non-unique heterogeneous types are invalid",
|
||||
"data": [
|
||||
{},
|
||||
[
|
||||
1
|
||||
],
|
||||
true,
|
||||
null,
|
||||
{},
|
||||
1
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "different objects are unique",
|
||||
"data": [
|
||||
{
|
||||
"a": 1,
|
||||
"b": 2
|
||||
},
|
||||
{
|
||||
"a": 2,
|
||||
"b": 1
|
||||
}
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "objects are non-unique despite key order",
|
||||
"data": [
|
||||
{
|
||||
"a": 1,
|
||||
"b": 2
|
||||
},
|
||||
{
|
||||
"b": 2,
|
||||
"a": 1
|
||||
}
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "{\"a\": false} and {\"a\": 0} are unique",
|
||||
"data": [
|
||||
{
|
||||
"a": false
|
||||
},
|
||||
{
|
||||
"a": 0
|
||||
}
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "{\"a\": true} and {\"a\": 1} are unique",
|
||||
"data": [
|
||||
{
|
||||
"a": true
|
||||
},
|
||||
{
|
||||
"a": 1
|
||||
}
|
||||
],
|
||||
"schema_id": "uniqueItems_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "uniqueItems with an array of items",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "uniqueItems_1_0",
|
||||
"schemas": {
|
||||
"uniqueItems_1_0": {
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"uniqueItems": true,
|
||||
"extensible": true
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_0_0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "[false, true] from items array is valid",
|
||||
"data": [
|
||||
false,
|
||||
true
|
||||
],
|
||||
"schema_id": "uniqueItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[true, false] from items array is valid",
|
||||
"data": [
|
||||
true,
|
||||
false
|
||||
],
|
||||
"schema_id": "uniqueItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[false, false] from items array is not valid",
|
||||
"data": [
|
||||
false,
|
||||
false
|
||||
],
|
||||
"schema_id": "uniqueItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[true, true] from items array is not valid",
|
||||
"data": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"schema_id": "uniqueItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "unique array extended from [false, true] is valid",
|
||||
"data": [
|
||||
false,
|
||||
true,
|
||||
"foo",
|
||||
"bar"
|
||||
],
|
||||
"schema_id": "uniqueItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "unique array extended from [true, false] is valid",
|
||||
"data": [
|
||||
true,
|
||||
false,
|
||||
"foo",
|
||||
"bar"
|
||||
],
|
||||
"schema_id": "uniqueItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "non-unique array extended from [false, true] is not valid",
|
||||
"data": [
|
||||
false,
|
||||
true,
|
||||
"foo",
|
||||
"foo"
|
||||
],
|
||||
"schema_id": "uniqueItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "non-unique array extended from [true, false] is not valid",
|
||||
"data": [
|
||||
true,
|
||||
false,
|
||||
"foo",
|
||||
"foo"
|
||||
],
|
||||
"schema_id": "uniqueItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "uniqueItems with an array of items and additionalItems=false",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "uniqueItems_2_0",
|
||||
"schemas": {
|
||||
"uniqueItems_2_0": {
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"uniqueItems": true,
|
||||
"items": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "[false, true] from items array is valid",
|
||||
"data": [
|
||||
false,
|
||||
true
|
||||
],
|
||||
"schema_id": "uniqueItems_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[true, false] from items array is valid",
|
||||
"data": [
|
||||
true,
|
||||
false
|
||||
],
|
||||
"schema_id": "uniqueItems_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[false, false] from items array is not valid",
|
||||
"data": [
|
||||
false,
|
||||
false
|
||||
],
|
||||
"schema_id": "uniqueItems_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[true, true] from items array is not valid",
|
||||
"data": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"schema_id": "uniqueItems_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "extra items are invalid even if unique",
|
||||
"data": [
|
||||
false,
|
||||
true,
|
||||
null
|
||||
],
|
||||
"schema_id": "uniqueItems_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -937,223 +569,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "uniqueItems=false with an array of items",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "uniqueItems_4_0",
|
||||
"schemas": {
|
||||
"uniqueItems_4_0": {
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"uniqueItems": false,
|
||||
"extensible": true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "[false, true] from items array is valid",
|
||||
"data": [
|
||||
false,
|
||||
true
|
||||
],
|
||||
"schema_id": "uniqueItems_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[true, false] from items array is valid",
|
||||
"data": [
|
||||
true,
|
||||
false
|
||||
],
|
||||
"schema_id": "uniqueItems_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[false, false] from items array is valid",
|
||||
"data": [
|
||||
false,
|
||||
false
|
||||
],
|
||||
"schema_id": "uniqueItems_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[true, true] from items array is valid",
|
||||
"data": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"schema_id": "uniqueItems_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "unique array extended from [false, true] is valid",
|
||||
"data": [
|
||||
false,
|
||||
true,
|
||||
"foo",
|
||||
"bar"
|
||||
],
|
||||
"schema_id": "uniqueItems_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "unique array extended from [true, false] is valid",
|
||||
"data": [
|
||||
true,
|
||||
false,
|
||||
"foo",
|
||||
"bar"
|
||||
],
|
||||
"schema_id": "uniqueItems_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "non-unique array extended from [false, true] is valid",
|
||||
"data": [
|
||||
false,
|
||||
true,
|
||||
"foo",
|
||||
"foo"
|
||||
],
|
||||
"schema_id": "uniqueItems_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "non-unique array extended from [true, false] is valid",
|
||||
"data": [
|
||||
true,
|
||||
false,
|
||||
"foo",
|
||||
"foo"
|
||||
],
|
||||
"schema_id": "uniqueItems_4_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "uniqueItems=false with an array of items and additionalItems=false",
|
||||
"database": {
|
||||
"types": [
|
||||
{
|
||||
"name": "uniqueItems_5_0",
|
||||
"schemas": {
|
||||
"uniqueItems_5_0": {
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"uniqueItems": false,
|
||||
"items": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "[false, true] from items array is valid",
|
||||
"data": [
|
||||
false,
|
||||
true
|
||||
],
|
||||
"schema_id": "uniqueItems_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[true, false] from items array is valid",
|
||||
"data": [
|
||||
true,
|
||||
false
|
||||
],
|
||||
"schema_id": "uniqueItems_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[false, false] from items array is valid",
|
||||
"data": [
|
||||
false,
|
||||
false
|
||||
],
|
||||
"schema_id": "uniqueItems_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[true, true] from items array is valid",
|
||||
"data": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"schema_id": "uniqueItems_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "extra items are invalid even if unique",
|
||||
"data": [
|
||||
false,
|
||||
true,
|
||||
null
|
||||
],
|
||||
"schema_id": "uniqueItems_5_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "extensible: true allows extra items in uniqueItems",
|
||||
"database": {
|
||||
@ -1179,7 +594,16 @@
|
||||
"schema_id": "uniqueItems_6_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_6_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
use crate::database::schema::Schema;
|
||||
#[allow(unused_imports)]
|
||||
use crate::drop::{Error, ErrorDetails};
|
||||
#[allow(unused_imports)]
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
impl Schema {
|
||||
@ -8,21 +12,22 @@ impl Schema {
|
||||
field_name: &str,
|
||||
root_id: &str,
|
||||
path: &str,
|
||||
errors: &mut Vec<crate::drop::Error>,
|
||||
errors: &mut Vec<Error>,
|
||||
) {
|
||||
#[cfg(not(test))]
|
||||
for c in id.chars() {
|
||||
if !c.is_ascii_lowercase() && !c.is_ascii_digit() && c != '_' && c != '.' && c != '$' {
|
||||
errors.push(crate::drop::Error {
|
||||
errors.push(Error {
|
||||
code: "INVALID_IDENTIFIER".to_string(),
|
||||
message: format!(
|
||||
"Invalid character '{}' in JSON Schema '{}' property: '{}'. Identifiers must exclusively contain [a-z0-9_.$]",
|
||||
c, field_name, id
|
||||
),
|
||||
details: crate::drop::ErrorDetails {
|
||||
path: Some(path.to_string()),
|
||||
schema: Some(root_id.to_string()),
|
||||
..Default::default()
|
||||
values: Some(HashMap::from([
|
||||
("character".to_string(), c.to_string()),
|
||||
("field_name".to_string(), field_name.to_string()),
|
||||
("identifier".to_string(), id.to_string()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
path: Some(path.to_string()),
|
||||
schema: Some(root_id.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
return;
|
||||
@ -35,7 +40,7 @@ impl Schema {
|
||||
root_id: &str,
|
||||
path: String,
|
||||
to_insert: &mut Vec<(String, Arc<Schema>)>,
|
||||
errors: &mut Vec<crate::drop::Error>,
|
||||
errors: &mut Vec<Error>,
|
||||
) {
|
||||
if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &schema_arc.obj.type_ {
|
||||
if t == "array" {
|
||||
@ -70,7 +75,7 @@ impl Schema {
|
||||
root_id: &str,
|
||||
path: String,
|
||||
to_insert: &mut Vec<(String, Arc<Schema>)>,
|
||||
errors: &mut Vec<crate::drop::Error>,
|
||||
errors: &mut Vec<Error>,
|
||||
) {
|
||||
if let Some(props) = &schema_arc.obj.properties {
|
||||
for (k, v) in props.iter() {
|
||||
@ -79,13 +84,6 @@ impl Schema {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(pattern_props) = &schema_arc.obj.pattern_properties {
|
||||
for (k, v) in pattern_props.iter() {
|
||||
let next_path = format!("{}/{}", path, k);
|
||||
Self::collect_schemas(v, root_id, next_path, to_insert, errors);
|
||||
}
|
||||
}
|
||||
|
||||
let mut map_arr = |arr: &Vec<Arc<Schema>>, sub: &str| {
|
||||
for (i, v) in arr.iter().enumerate() {
|
||||
Self::collect_schemas(
|
||||
@ -98,10 +96,6 @@ impl Schema {
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(arr) = &schema_arc.obj.prefix_items {
|
||||
map_arr(arr, "prefixItems");
|
||||
}
|
||||
|
||||
if let Some(arr) = &schema_arc.obj.one_of {
|
||||
map_arr(arr, "oneOf");
|
||||
}
|
||||
@ -118,11 +112,6 @@ impl Schema {
|
||||
}
|
||||
};
|
||||
|
||||
map_opt(
|
||||
&schema_arc.obj.additional_properties,
|
||||
false,
|
||||
"additionalProperties",
|
||||
);
|
||||
map_opt(&schema_arc.obj.items, true, "items");
|
||||
map_opt(&schema_arc.obj.not, false, "not");
|
||||
map_opt(&schema_arc.obj.contains, false, "contains");
|
||||
|
||||
@ -5,7 +5,9 @@ pub mod filter;
|
||||
pub mod polymorphism;
|
||||
|
||||
use crate::database::schema::Schema;
|
||||
use crate::drop::{Error, ErrorDetails};
|
||||
use indexmap::IndexMap;
|
||||
use std::collections::HashMap;
|
||||
|
||||
impl Schema {
|
||||
pub fn compile(
|
||||
@ -13,7 +15,7 @@ impl Schema {
|
||||
db: &crate::database::Database,
|
||||
root_id: &str,
|
||||
path: String,
|
||||
errors: &mut Vec<crate::drop::Error>,
|
||||
errors: &mut Vec<Error>,
|
||||
) {
|
||||
if self.obj.compiled_properties.get().is_some() {
|
||||
return;
|
||||
@ -37,18 +39,6 @@ impl Schema {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(pattern_props) = &self.obj.pattern_properties {
|
||||
let mut compiled = Vec::new();
|
||||
for (k, v) in pattern_props {
|
||||
if let Ok(re) = regex::Regex::new(k) {
|
||||
compiled.push((crate::database::object::CompiledRegex(re), v.clone()));
|
||||
}
|
||||
}
|
||||
if !compiled.is_empty() {
|
||||
let _ = self.obj.compiled_pattern_properties.set(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
let mut props = IndexMap::new();
|
||||
|
||||
// 1. Resolve INHERITANCE dependencies first
|
||||
@ -72,17 +62,14 @@ impl Schema {
|
||||
}
|
||||
|
||||
if custom_type_count > 1 {
|
||||
errors.push(crate::drop::Error {
|
||||
errors.push(Error {
|
||||
code: "MULTIPLE_INHERITANCE_PROHIBITED".to_string(),
|
||||
message: format!(
|
||||
"Schema attempts to extend multiple custom object pointers in its type array {:?}. Use 'oneOf' for polymorphism and tagged unions.",
|
||||
types
|
||||
),
|
||||
details: crate::drop::ErrorDetails {
|
||||
path: Some(path.clone()),
|
||||
schema: Some(root_id.to_string()),
|
||||
..Default::default()
|
||||
}
|
||||
values: Some(HashMap::from([("types".to_string(), types.join(", "))])),
|
||||
details: ErrorDetails {
|
||||
path: Some(path.clone()),
|
||||
schema: Some(root_id.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -141,29 +128,13 @@ impl Schema {
|
||||
if let Some(items) = &self.obj.items {
|
||||
items.compile(db, root_id, format!("{}/items", path), errors);
|
||||
}
|
||||
if let Some(pattern_props) = &self.obj.pattern_properties {
|
||||
for (k, child) in pattern_props {
|
||||
child.compile(db, root_id, format!("{}/{}", path, k), errors);
|
||||
}
|
||||
}
|
||||
if let Some(additional_props) = &self.obj.additional_properties {
|
||||
additional_props.compile(
|
||||
db,
|
||||
root_id,
|
||||
format!("{}/additionalProperties", path),
|
||||
errors,
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(one_of) = &self.obj.one_of {
|
||||
for (i, child) in one_of.iter().enumerate() {
|
||||
child.compile(db, root_id, format!("{}/oneOf/{}", path, i), errors);
|
||||
}
|
||||
}
|
||||
if let Some(arr) = &self.obj.prefix_items {
|
||||
for (i, child) in arr.iter().enumerate() {
|
||||
child.compile(db, root_id, format!("{}/prefixItems/{}", path, i), errors);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(child) = &self.obj.not {
|
||||
child.compile(db, root_id, format!("{}/not", path), errors);
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
use crate::drop::{Error, ErrorDetails};
|
||||
use indexmap::IndexSet;
|
||||
use std::collections::HashMap;
|
||||
use crate::database::schema::Schema;
|
||||
|
||||
impl Schema {
|
||||
@ -7,7 +9,7 @@ impl Schema {
|
||||
db: &crate::database::Database,
|
||||
root_id: &str,
|
||||
path: &str,
|
||||
errors: &mut Vec<crate::drop::Error>,
|
||||
errors: &mut Vec<Error>,
|
||||
) {
|
||||
let mut options = indexmap::IndexMap::new();
|
||||
let strategy: &str;
|
||||
@ -118,16 +120,16 @@ impl Schema {
|
||||
};
|
||||
|
||||
if strategy.is_empty() {
|
||||
errors.push(crate::drop::Error {
|
||||
code: "AMBIGUOUS_POLYMORPHISM".to_string(),
|
||||
message: format!("oneOf boundaries must map mathematically unique 'type' or 'kind' discriminators, or strictly contain disjoint primitive types."),
|
||||
details: crate::drop::ErrorDetails {
|
||||
path: Some(path.to_string()),
|
||||
schema: Some(root_id.to_string()),
|
||||
..Default::default()
|
||||
}
|
||||
});
|
||||
return;
|
||||
errors.push(Error {
|
||||
code: "AMBIGUOUS_POLYMORPHISM".to_string(),
|
||||
values: None,
|
||||
details: ErrorDetails {
|
||||
path: Some(path.to_string()),
|
||||
schema: Some(root_id.to_string()),
|
||||
..Default::default()
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
for (i, c) in one_of.iter().enumerate() {
|
||||
@ -140,15 +142,15 @@ impl Schema {
|
||||
|
||||
if let Some(val) = c.obj.get_discriminator_value(&strategy, &child_id) {
|
||||
if options.contains_key(&val) {
|
||||
errors.push(crate::drop::Error {
|
||||
errors.push(Error {
|
||||
code: "POLYMORPHIC_COLLISION".to_string(),
|
||||
message: format!("Polymorphic boundary defines multiple candidates mapped to the identical discriminator value '{}'.", val),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([("value".to_string(), val.to_string())])),
|
||||
details: ErrorDetails {
|
||||
path: Some(path.to_string()),
|
||||
schema: Some(root_id.to_string()),
|
||||
..Default::default()
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use crate::drop::{Error, ErrorDetails};
|
||||
use serde_json::Value;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub fn compose(val: &mut Value, errors: &mut Vec<crate::drop::Error>) -> Result<(), String> {
|
||||
pub fn compose(val: &mut Value, errors: &mut Vec<Error>) {
|
||||
let mut traits = HashMap::new();
|
||||
let mut schemas = HashMap::new();
|
||||
|
||||
@ -56,15 +57,13 @@ pub fn compose(val: &mut Value, errors: &mut Vec<crate::drop::Error>) -> Result<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resolve_in_place(
|
||||
current: &mut Value,
|
||||
traits: &HashMap<String, Value>,
|
||||
schemas: &HashMap<String, Value>,
|
||||
errors: &mut Vec<crate::drop::Error>,
|
||||
errors: &mut Vec<Error>,
|
||||
schema_id: &str,
|
||||
path: &str,
|
||||
visited: &mut HashSet<String>,
|
||||
@ -82,7 +81,6 @@ fn resolve_in_place(
|
||||
let mut merged_required = HashSet::new();
|
||||
let mut merged_display = HashSet::new();
|
||||
let mut merged_dependencies = serde_json::Map::new();
|
||||
let mut merged_pattern_props = serde_json::Map::new();
|
||||
|
||||
// Read current values first to let host override included properties
|
||||
if let Some(req) = current.get("required").and_then(|v| v.as_array()) {
|
||||
@ -104,11 +102,7 @@ fn resolve_in_place(
|
||||
merged_dependencies.insert(k.clone(), v.clone());
|
||||
}
|
||||
}
|
||||
if let Some(pat_props) = current.get("patternProperties").and_then(|v| v.as_object()) {
|
||||
for (k, v) in pat_props {
|
||||
merged_pattern_props.insert(k.clone(), v.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(props) = current.get("properties").and_then(|v| v.as_object()) {
|
||||
for (k, v) in props {
|
||||
merged_props.insert(k.clone(), v.clone());
|
||||
@ -118,10 +112,13 @@ fn resolve_in_place(
|
||||
for inc in include_arr {
|
||||
if let Some(inc_name) = inc.as_str() {
|
||||
if visited.contains(inc_name) {
|
||||
errors.push(crate::drop::Error {
|
||||
errors.push(Error {
|
||||
code: "CIRCULAR_INCLUDE_DETECTED".to_string(),
|
||||
message: format!("Circular inclusion detected for '{}'", inc_name),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([(
|
||||
"include".to_string(),
|
||||
inc_name.to_string(),
|
||||
)])),
|
||||
details: ErrorDetails {
|
||||
schema: Some(schema_id.to_string()),
|
||||
path: Some(path.to_string()),
|
||||
..Default::default()
|
||||
@ -157,18 +154,6 @@ fn resolve_in_place(
|
||||
}
|
||||
}
|
||||
|
||||
// Merge patternProperties (host overrides trait)
|
||||
if let Some(target_pat_props) = resolved_target
|
||||
.get("patternProperties")
|
||||
.and_then(|v| v.as_object())
|
||||
{
|
||||
for (k, v) in target_pat_props {
|
||||
if !merged_pattern_props.contains_key(k) {
|
||||
merged_pattern_props.insert(k.clone(), v.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge required
|
||||
if let Some(target_req) = resolved_target.get("required").and_then(|v| v.as_array()) {
|
||||
for r in target_req {
|
||||
@ -219,7 +204,6 @@ fn resolve_in_place(
|
||||
if let Some(obj) = current.as_object_mut() {
|
||||
for (k, v) in resolved_target.as_object().unwrap() {
|
||||
if k != "properties"
|
||||
&& k != "patternProperties"
|
||||
&& k != "required"
|
||||
&& k != "display"
|
||||
&& k != "dependencies"
|
||||
@ -232,10 +216,13 @@ fn resolve_in_place(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errors.push(crate::drop::Error {
|
||||
errors.push(Error {
|
||||
code: "TRAIT_NOT_FOUND".to_string(),
|
||||
message: format!("Trait or schema '{}' not found for inclusion", inc_name),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([(
|
||||
"include".to_string(),
|
||||
inc_name.to_string(),
|
||||
)])),
|
||||
details: ErrorDetails {
|
||||
schema: Some(schema_id.to_string()),
|
||||
path: Some(path.to_string()),
|
||||
..Default::default()
|
||||
@ -249,12 +236,7 @@ fn resolve_in_place(
|
||||
if !merged_props.is_empty() {
|
||||
obj.insert("properties".to_string(), Value::Object(merged_props));
|
||||
}
|
||||
if !merged_pattern_props.is_empty() {
|
||||
obj.insert(
|
||||
"patternProperties".to_string(),
|
||||
Value::Object(merged_pattern_props),
|
||||
);
|
||||
}
|
||||
|
||||
if !merged_required.is_empty() {
|
||||
let mut req_vec: Vec<Value> = merged_required.into_iter().map(Value::String).collect();
|
||||
req_vec.sort_by(|a, b| a.as_str().unwrap().cmp(b.as_str().unwrap()));
|
||||
@ -290,22 +272,7 @@ fn resolve_in_place(
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(pat_props) = obj
|
||||
.get_mut("patternProperties")
|
||||
.and_then(|v| v.as_object_mut())
|
||||
{
|
||||
for (k, v) in pat_props {
|
||||
resolve_in_place(
|
||||
v,
|
||||
traits,
|
||||
schemas,
|
||||
errors,
|
||||
schema_id,
|
||||
&format!("{}/{}", path, k),
|
||||
visited,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(items) = obj.get_mut("items") {
|
||||
resolve_in_place(
|
||||
items,
|
||||
@ -317,30 +284,6 @@ fn resolve_in_place(
|
||||
visited,
|
||||
);
|
||||
}
|
||||
if let Some(prefix_items) = obj.get_mut("prefixItems").and_then(|v| v.as_array_mut()) {
|
||||
for (i, v) in prefix_items.iter_mut().enumerate() {
|
||||
resolve_in_place(
|
||||
v,
|
||||
traits,
|
||||
schemas,
|
||||
errors,
|
||||
schema_id,
|
||||
&format!("{}/prefixItems/{}", path, i),
|
||||
visited,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(additional_props) = obj.get_mut("additionalProperties") {
|
||||
resolve_in_place(
|
||||
additional_props,
|
||||
traits,
|
||||
schemas,
|
||||
errors,
|
||||
schema_id,
|
||||
&format!("{}/additionalProperties", path),
|
||||
visited,
|
||||
);
|
||||
}
|
||||
if let Some(one_of) = obj.get_mut("oneOf").and_then(|v| v.as_array_mut()) {
|
||||
for (i, v) in one_of.iter_mut().enumerate() {
|
||||
resolve_in_place(
|
||||
|
||||
@ -28,6 +28,8 @@ use serde_json::Value;
|
||||
use indexmap::IndexMap;
|
||||
use std::sync::Arc;
|
||||
use r#type::Type;
|
||||
use std::collections::HashMap;
|
||||
use crate::drop::{Drop, Error, ErrorDetails};
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
pub struct Database {
|
||||
@ -57,13 +59,7 @@ impl Database {
|
||||
|
||||
let mut errors = Vec::new();
|
||||
|
||||
if let Err(e) = compose::compose(&mut val, &mut errors) {
|
||||
errors.push(crate::drop::Error {
|
||||
code: "COMPOSE_FAILED".to_string(),
|
||||
message: format!("Fatal error during trait composition: {}", e),
|
||||
details: crate::drop::ErrorDetails::default(),
|
||||
});
|
||||
}
|
||||
compose::compose(&mut val, &mut errors);
|
||||
|
||||
if let serde_json::Value::Object(mut map) = val {
|
||||
if let Some(serde_json::Value::Array(arr)) = map.remove("enums") {
|
||||
@ -78,10 +74,13 @@ impl Database {
|
||||
db.enums.insert(def.name.clone(), def);
|
||||
}
|
||||
Err(e) => {
|
||||
errors.push(crate::drop::Error {
|
||||
errors.push(Error {
|
||||
code: "DATABASE_ENUM_PARSE_FAILED".to_string(),
|
||||
message: format!("Failed to parse database enum '{}': {}", name, e),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([
|
||||
("enum".to_string(), name.clone()),
|
||||
("reason".to_string(), e.to_string()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
context: Some(serde_json::json!(name)),
|
||||
..Default::default()
|
||||
},
|
||||
@ -103,10 +102,13 @@ impl Database {
|
||||
db.types.insert(def.name.clone(), def);
|
||||
}
|
||||
Err(e) => {
|
||||
errors.push(crate::drop::Error {
|
||||
errors.push(Error {
|
||||
code: "DATABASE_TYPE_PARSE_FAILED".to_string(),
|
||||
message: format!("Failed to parse database type '{}': {}", name, e),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([
|
||||
("type".to_string(), name.clone()),
|
||||
("reason".to_string(), e.to_string()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
context: Some(serde_json::json!(name)),
|
||||
..Default::default()
|
||||
},
|
||||
@ -132,10 +134,13 @@ impl Database {
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
errors.push(crate::drop::Error {
|
||||
errors.push(Error {
|
||||
code: "DATABASE_RELATION_PARSE_FAILED".to_string(),
|
||||
message: format!("Failed to parse database relation '{}': {}", constraint, e),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([
|
||||
("relation".to_string(), constraint.clone()),
|
||||
("reason".to_string(), e.to_string()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
context: Some(serde_json::json!(constraint)),
|
||||
..Default::default()
|
||||
},
|
||||
@ -157,10 +162,13 @@ impl Database {
|
||||
db.puncs.insert(def.name.clone(), def);
|
||||
}
|
||||
Err(e) => {
|
||||
errors.push(crate::drop::Error {
|
||||
errors.push(Error {
|
||||
code: "DATABASE_PUNC_PARSE_FAILED".to_string(),
|
||||
message: format!("Failed to parse database punc '{}': {}", name, e),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([
|
||||
("punc".to_string(), name.clone()),
|
||||
("reason".to_string(), e.to_string()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
context: Some(serde_json::json!(name)),
|
||||
..Default::default()
|
||||
},
|
||||
@ -173,9 +181,9 @@ impl Database {
|
||||
|
||||
db.compile(&mut errors);
|
||||
let drop = if errors.is_empty() {
|
||||
crate::drop::Drop::success()
|
||||
Drop::success()
|
||||
} else {
|
||||
crate::drop::Drop::with_errors(errors)
|
||||
Drop::with_errors(errors)
|
||||
};
|
||||
(db, drop)
|
||||
}
|
||||
@ -443,7 +451,7 @@ impl Database {
|
||||
|
||||
// Abort relation discovery early if no hierarchical inheritance match was found
|
||||
if matching_rels.is_empty() {
|
||||
let mut details = crate::drop::ErrorDetails {
|
||||
let mut details = ErrorDetails {
|
||||
path: Some(path.to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
@ -451,12 +459,13 @@ impl Database {
|
||||
details.schema = Some(sid.to_string());
|
||||
}
|
||||
|
||||
errors.push(crate::drop::Error {
|
||||
errors.push(Error {
|
||||
code: "EDGE_MISSING".to_string(),
|
||||
message: format!(
|
||||
"No database relation exists between '{}' and '{}' for property '{}'",
|
||||
parent_type, child_type, prop_name
|
||||
),
|
||||
values: Some(HashMap::from([
|
||||
("parent_type".to_string(), parent_type.to_string()),
|
||||
("child_type".to_string(), child_type.to_string()),
|
||||
("property_name".to_string(), prop_name.to_string()),
|
||||
])),
|
||||
details,
|
||||
});
|
||||
return None;
|
||||
@ -542,7 +551,7 @@ impl Database {
|
||||
// we must abort rather than silently guessing. Returning None prevents arbitrary SQL generation
|
||||
// and forces a clean structural error for the architect.
|
||||
if !resolved {
|
||||
let mut details = crate::drop::ErrorDetails {
|
||||
let mut details = ErrorDetails {
|
||||
path: Some(path.to_string()),
|
||||
context: serde_json::to_value(&matching_rels).ok(),
|
||||
cause: Some("Multiple conflicting constraints found matching prefixes".to_string()),
|
||||
@ -552,12 +561,13 @@ impl Database {
|
||||
details.schema = Some(sid.to_string());
|
||||
}
|
||||
|
||||
errors.push(crate::drop::Error {
|
||||
errors.push(Error {
|
||||
code: "AMBIGUOUS_TYPE_RELATIONS".to_string(),
|
||||
message: format!(
|
||||
"Ambiguous database relation between '{}' and '{}' for property '{}'",
|
||||
parent_type, child_type, prop_name
|
||||
),
|
||||
values: Some(HashMap::from([
|
||||
("parent_type".to_string(), parent_type.to_string()),
|
||||
("child_type".to_string(), child_type.to_string()),
|
||||
("property_name".to_string(), prop_name.to_string()),
|
||||
])),
|
||||
details,
|
||||
});
|
||||
return None;
|
||||
|
||||
@ -32,12 +32,10 @@ pub struct SchemaObject {
|
||||
// Object Keywords
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub properties: Option<IndexMap<String, Arc<Schema>>>,
|
||||
#[serde(rename = "patternProperties")]
|
||||
#[serde(rename = "keys")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub pattern_properties: Option<IndexMap<String, Arc<Schema>>>,
|
||||
#[serde(rename = "additionalProperties")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub additional_properties: Option<Arc<Schema>>,
|
||||
pub keys: Option<Arc<Schema>>,
|
||||
|
||||
#[serde(rename = "family")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub family: Option<String>,
|
||||
@ -53,9 +51,6 @@ pub struct SchemaObject {
|
||||
#[serde(rename = "items")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub items: Option<Arc<Schema>>,
|
||||
#[serde(rename = "prefixItems")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub prefix_items: Option<Vec<Arc<Schema>>>,
|
||||
|
||||
// String Validation
|
||||
#[serde(rename = "minLength")]
|
||||
@ -189,8 +184,6 @@ pub struct SchemaObject {
|
||||
pub compiled_format: OnceLock<CompiledFormat>,
|
||||
#[serde(skip)]
|
||||
pub compiled_pattern: OnceLock<CompiledRegex>,
|
||||
#[serde(skip)]
|
||||
pub compiled_pattern_properties: OnceLock<Vec<(CompiledRegex, Arc<Schema>)>>,
|
||||
}
|
||||
|
||||
/// Represents a compiled format validator
|
||||
@ -263,7 +256,7 @@ where
|
||||
pub fn is_primitive_type(t: &str) -> bool {
|
||||
matches!(
|
||||
t,
|
||||
"string" | "number" | "integer" | "boolean" | "object" | "array" | "null"
|
||||
"string" | "number" | "integer" | "boolean" | "object" | "array" | "null" | "dict"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -26,12 +26,10 @@ impl Schema {
|
||||
/// Returns true if the schema acts purely as a type pointer (composition without overriding constraints)
|
||||
pub fn is_proxy(&self) -> bool {
|
||||
self.obj.properties.is_none()
|
||||
&& self.obj.pattern_properties.is_none()
|
||||
&& self.obj.additional_properties.is_none()
|
||||
&& self.obj.keys.is_none()
|
||||
&& self.obj.required.is_none()
|
||||
&& self.obj.dependencies.is_none()
|
||||
&& self.obj.items.is_none()
|
||||
&& self.obj.prefix_items.is_none()
|
||||
&& self.obj.contains.is_none()
|
||||
&& self.obj.format.is_none()
|
||||
&& self.obj.enum_.is_none()
|
||||
@ -68,12 +66,10 @@ impl<'de> Deserialize<'de> for Schema {
|
||||
// restrict additional properties natively
|
||||
let is_empty = obj.type_.is_none()
|
||||
&& obj.properties.is_none()
|
||||
&& obj.pattern_properties.is_none()
|
||||
&& obj.additional_properties.is_none()
|
||||
&& obj.keys.is_none()
|
||||
&& obj.required.is_none()
|
||||
&& obj.dependencies.is_none()
|
||||
&& obj.items.is_none()
|
||||
&& obj.prefix_items.is_none()
|
||||
&& obj.contains.is_none()
|
||||
&& obj.format.is_none()
|
||||
&& obj.enum_.is_none()
|
||||
|
||||
@ -57,10 +57,13 @@ impl Drop {
|
||||
}
|
||||
}
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct Error {
|
||||
pub code: String,
|
||||
pub message: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub values: Option<HashMap<String, String>>,
|
||||
pub details: ErrorDetails,
|
||||
}
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ lazy_static::lazy_static! {
|
||||
fn jspg_failure() -> JsonB {
|
||||
let error = crate::drop::Error {
|
||||
code: "ENGINE_NOT_INITIALIZED".to_string(),
|
||||
message: "JSPG extension has not been initialized via jspg_setup".to_string(),
|
||||
values: None,
|
||||
details: crate::drop::ErrorDetails {
|
||||
path: None,
|
||||
cause: None,
|
||||
|
||||
@ -5,7 +5,9 @@ pub mod cache;
|
||||
|
||||
use crate::database::Database;
|
||||
use crate::database::r#type::Type;
|
||||
use crate::drop::{Drop, Error, ErrorDetails};
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct Merger {
|
||||
@ -21,20 +23,22 @@ impl Merger {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn merge(&self, schema_id: &str, data: Value) -> crate::drop::Drop {
|
||||
pub fn merge(&self, schema_id: &str, data: Value) -> Drop {
|
||||
let mut notifications_queue = Vec::new();
|
||||
|
||||
let target_schema = match self.db.schemas.get(schema_id) {
|
||||
Some(s) => Arc::clone(&s),
|
||||
None => {
|
||||
return crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
code: "MERGE_FAILED".to_string(),
|
||||
message: format!("Unknown schema_id: {}", schema_id),
|
||||
details: crate::drop::ErrorDetails {
|
||||
return Drop::with_errors(vec![Error {
|
||||
code: "SCHEMA_NOT_FOUND".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("schema".to_string(), schema_id.to_string()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
path: None,
|
||||
cause: None,
|
||||
context: Some(data),
|
||||
schema: None,
|
||||
schema: Some(schema_id.to_string()),
|
||||
},
|
||||
}]);
|
||||
}
|
||||
@ -72,10 +76,12 @@ impl Merger {
|
||||
}
|
||||
}
|
||||
|
||||
return crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
return Drop::with_errors(vec![Error {
|
||||
code: final_code,
|
||||
message: final_message,
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([
|
||||
("error".to_string(), final_message),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
path: None,
|
||||
cause: final_cause,
|
||||
context: None,
|
||||
@ -88,10 +94,12 @@ impl Merger {
|
||||
// Execute the globally collected, pre-ordered notifications last!
|
||||
for notify_sql in notifications_queue {
|
||||
if let Err(e) = self.db.execute(¬ify_sql, None) {
|
||||
return crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
return Drop::with_errors(vec![Error {
|
||||
code: "MERGE_FAILED".to_string(),
|
||||
message: format!("Executor Error in pre-ordered notify: {:?}", e),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([
|
||||
("error".to_string(), e.to_string()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
path: None,
|
||||
cause: None,
|
||||
context: None,
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
use crate::database::Database;
|
||||
use crate::drop::{Drop, Error, ErrorDetails};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub mod compiler;
|
||||
@ -22,17 +24,19 @@ impl Queryer {
|
||||
&self,
|
||||
schema_id: &str,
|
||||
filter: Option<&serde_json::Value>,
|
||||
) -> crate::drop::Drop {
|
||||
) -> Drop {
|
||||
let filters_map = filter.and_then(|f| f.as_object());
|
||||
|
||||
// 1. Process filters into structured $op keys and linear values
|
||||
let (filter_keys, args) = match self.parse_filter_entries(filters_map) {
|
||||
Ok(res) => res,
|
||||
Err(msg) => {
|
||||
return crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
return Drop::with_errors(vec![Error {
|
||||
code: "FILTER_PARSE_FAILED".to_string(),
|
||||
message: msg.clone(),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([
|
||||
("error".to_string(), msg.clone()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
path: None, // filters apply to the root query
|
||||
cause: Some(msg),
|
||||
context: filter.cloned(),
|
||||
@ -134,10 +138,12 @@ impl Queryer {
|
||||
.insert(cache_key.to_string(), compiled_sql.clone());
|
||||
Ok(compiled_sql)
|
||||
}
|
||||
Err(e) => Err(crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
Err(e) => Err(Drop::with_errors(vec![Error {
|
||||
code: "QUERY_COMPILATION_FAILED".to_string(),
|
||||
message: e.clone(),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([
|
||||
("error".to_string(), e.clone()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
path: None,
|
||||
cause: Some(e),
|
||||
context: None,
|
||||
@ -152,29 +158,33 @@ impl Queryer {
|
||||
schema_id: &str,
|
||||
sql: &str,
|
||||
args: Vec<serde_json::Value>,
|
||||
) -> crate::drop::Drop {
|
||||
) -> Drop {
|
||||
match self.db.query(sql, Some(args)) {
|
||||
Ok(serde_json::Value::Array(table)) => {
|
||||
if table.is_empty() {
|
||||
crate::drop::Drop::success_with_val(serde_json::Value::Null)
|
||||
Drop::success_with_val(serde_json::Value::Null)
|
||||
} else {
|
||||
crate::drop::Drop::success_with_val(table.first().unwrap().clone())
|
||||
Drop::success_with_val(table.first().unwrap().clone())
|
||||
}
|
||||
}
|
||||
Ok(other) => crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
Ok(other) => Drop::with_errors(vec![Error {
|
||||
code: "QUERY_FAILED".to_string(),
|
||||
message: format!("Expected array from generic query, got: {:?}", other),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([
|
||||
("error".to_string(), format!("Expected array from generic query, got: {:?}", other)),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
path: None,
|
||||
cause: Some(format!("Expected array, got {}", other)),
|
||||
context: Some(serde_json::json!([sql])),
|
||||
schema: Some(schema_id.to_string()),
|
||||
},
|
||||
}]),
|
||||
Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
Err(e) => Drop::with_errors(vec![Error {
|
||||
code: "QUERY_FAILED".to_string(),
|
||||
message: format!("SPI error in queryer: {}", e),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([
|
||||
("error".to_string(), e.to_string()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
path: None,
|
||||
cause: Some(format!("SPI error in queryer: {}", e)),
|
||||
context: Some(serde_json::json!([sql])),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,6 @@ fn test_library_api() {
|
||||
"type": "drop",
|
||||
"errors": [{
|
||||
"code": "ENGINE_NOT_INITIALIZED",
|
||||
"message": "JSPG extension has not been initialized via jspg_setup",
|
||||
"details": {}
|
||||
}]
|
||||
})
|
||||
@ -250,7 +249,9 @@ fn test_library_api() {
|
||||
"errors": [
|
||||
{
|
||||
"code": "REQUIRED_FIELD_MISSING",
|
||||
"message": "Missing name",
|
||||
"values": {
|
||||
"field_name": "name"
|
||||
},
|
||||
"details": {
|
||||
"path": "name",
|
||||
"schema": "source_schema"
|
||||
@ -258,7 +259,9 @@ fn test_library_api() {
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"message": "Unexpected property 'wrong'",
|
||||
"values": {
|
||||
"property_name": "wrong"
|
||||
},
|
||||
"details": {
|
||||
"path": "wrong",
|
||||
"schema": "source_schema"
|
||||
|
||||
@ -86,7 +86,7 @@ pub fn run_test_case(path: &str, suite_idx: usize, case_idx: usize) -> Result<()
|
||||
let error_messages: Vec<String> = drop
|
||||
.errors
|
||||
.iter()
|
||||
.map(|e| format!("Error {} at path {}: {}", e.code, e.details.path.as_deref().unwrap_or("/"), e.message))
|
||||
.map(|e| format!("Error {} at path {}: {:?}", e.code, e.details.path.as_deref().unwrap_or("/"), e.values))
|
||||
.collect();
|
||||
failures.push(format!(
|
||||
"[{}] Cannot run '{}' test '{}': System Setup Compilation structurally failed:\n{}",
|
||||
@ -107,7 +107,7 @@ pub fn run_test_case(path: &str, suite_idx: usize, case_idx: usize) -> Result<()
|
||||
|
||||
match test.action.as_str() {
|
||||
"compile" => {
|
||||
let result = test.run_compile(db);
|
||||
let result = test.run_compile(db, path, suite_idx, case_idx);
|
||||
if let Err(e) = result {
|
||||
println!("TEST COMPILE ERROR FOR '{}': {}", test.description, e);
|
||||
failures.push(format!(
|
||||
@ -117,7 +117,7 @@ pub fn run_test_case(path: &str, suite_idx: usize, case_idx: usize) -> Result<()
|
||||
}
|
||||
}
|
||||
"validate" => {
|
||||
let result = test.run_validate(db_unwrapped.unwrap());
|
||||
let result = test.run_validate(db_unwrapped.unwrap(), path, suite_idx, case_idx);
|
||||
if let Err(e) = result {
|
||||
println!("TEST VALIDATE ERROR FOR '{}': {}", test.description, e);
|
||||
failures.push(format!(
|
||||
@ -205,6 +205,25 @@ pub fn canonicalize_with_map(s: &str, uuid_map: &HashMap<String, String>, gen_ma
|
||||
ts_re.replace_all(&s1, "{{timestamp}}").to_string()
|
||||
}
|
||||
|
||||
pub fn update_validation_fixture(path: &str, suite_idx: usize, case_idx: usize, errors: &[crate::drop::Error]) {
|
||||
let content = fs::read_to_string(path).unwrap();
|
||||
let mut file_data: Value = serde_json::from_str(&content).unwrap();
|
||||
|
||||
if let Some(expect) = file_data[suite_idx]["tests"][case_idx].get_mut("expect") {
|
||||
if let Some(obj) = expect.as_object_mut() {
|
||||
if errors.is_empty() {
|
||||
obj.remove("errors");
|
||||
} else {
|
||||
let serialized_errors = serde_json::to_value(errors).unwrap();
|
||||
obj.insert("errors".to_string(), serialized_errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let formatted_json = serde_json::to_string_pretty(&file_data).unwrap();
|
||||
fs::write(path, formatted_json).unwrap();
|
||||
}
|
||||
|
||||
pub fn update_sql_fixture(path: &str, suite_idx: usize, case_idx: usize, queries: &[String]) {
|
||||
use crate::tests::formatter::SqlFormatter;
|
||||
let content = fs::read_to_string(path).unwrap();
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
use super::expect::Expect;
|
||||
use crate::database::Database;
|
||||
use crate::tests::runner::update_validation_fixture;
|
||||
use crate::validator::Validator;
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@ -38,6 +41,9 @@ impl Case {
|
||||
pub fn run_compile(
|
||||
&self,
|
||||
db_res: &Result<Arc<Database>, crate::drop::Drop>,
|
||||
path: &str,
|
||||
suite_idx: usize,
|
||||
case_idx: usize,
|
||||
) -> Result<(), String> {
|
||||
let expect = match &self.expect {
|
||||
Some(e) => e,
|
||||
@ -49,6 +55,10 @@ impl Case {
|
||||
Err(d) => d.clone(),
|
||||
};
|
||||
|
||||
if env::var("UPDATE_EXPECT").is_ok() {
|
||||
update_validation_fixture(path, suite_idx, case_idx, &result.errors);
|
||||
}
|
||||
|
||||
expect.assert_drop(&result)?;
|
||||
|
||||
if let Ok(db) = db_res {
|
||||
@ -58,16 +68,16 @@ impl Case {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_validate(&self, db: Arc<Database>) -> Result<(), String> {
|
||||
use crate::validator::Validator;
|
||||
|
||||
pub fn run_validate(&self, db: Arc<Database>, path: &str, suite_idx: usize, case_idx: usize) -> Result<(), String> {
|
||||
let validator = Validator::new(db);
|
||||
|
||||
let schema_id = &self.schema_id;
|
||||
|
||||
let test_data = self.data.clone().unwrap_or(Value::Null);
|
||||
let result = validator.validate(schema_id, &test_data);
|
||||
|
||||
if env::var("UPDATE_EXPECT").is_ok() {
|
||||
update_validation_fixture(path, suite_idx, case_idx, &result.errors);
|
||||
}
|
||||
|
||||
if let Some(expect) = &self.expect {
|
||||
expect.assert_drop(&result)?;
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use super::Expect;
|
||||
use serde_json::Value;
|
||||
|
||||
impl Expect {
|
||||
pub fn assert_drop(&self, drop: &crate::drop::Drop) -> Result<(), String> {
|
||||
@ -14,14 +15,14 @@ impl Expect {
|
||||
|
||||
if !self.success {
|
||||
if let Some(expected_errors) = &self.errors {
|
||||
let actual_values: Vec<serde_json::Value> = drop.errors
|
||||
let actual_values: Vec<Value> = drop.errors
|
||||
.iter()
|
||||
.map(|e| serde_json::to_value(e).unwrap())
|
||||
.collect();
|
||||
|
||||
if expected_errors.len() != actual_values.len() {
|
||||
return Err(format!(
|
||||
"Expected {} errors, but got {}.\nExpected subset: {:?}\nActual full errors: {:?}",
|
||||
"Expected {} errors, but got {}.\nExpected: {:?}\nActual full errors: {:?}",
|
||||
expected_errors.len(),
|
||||
actual_values.len(),
|
||||
expected_errors,
|
||||
@ -31,17 +32,15 @@ impl Expect {
|
||||
|
||||
for (i, expected_val) in expected_errors.iter().enumerate() {
|
||||
let mut matched = false;
|
||||
|
||||
for actual_val in &actual_values {
|
||||
if subset_match(expected_val, actual_val) {
|
||||
if expected_val == actual_val {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !matched {
|
||||
return Err(format!(
|
||||
"Expected error {} was not found in actual errors.\nExpected subset: {}\nActual full errors: {:?}",
|
||||
"Expected error {} was not found in actual errors.\nExpected: {}\nActual full errors: {:?}",
|
||||
i,
|
||||
serde_json::to_string_pretty(expected_val).unwrap(),
|
||||
drop.errors,
|
||||
@ -54,35 +53,3 @@ impl Expect {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to check if `expected` is a structural subset of `actual`
|
||||
fn subset_match(expected: &serde_json::Value, actual: &serde_json::Value) -> bool {
|
||||
match (expected, actual) {
|
||||
(serde_json::Value::Object(exp_map), serde_json::Value::Object(act_map)) => {
|
||||
for (k, v) in exp_map {
|
||||
if let Some(act_v) = act_map.get(k) {
|
||||
if !subset_match(v, act_v) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
(serde_json::Value::Array(exp_arr), serde_json::Value::Array(act_arr)) => {
|
||||
// Basic check: array sizes and elements must match exactly in order
|
||||
if exp_arr.len() != act_arr.len() {
|
||||
return false;
|
||||
}
|
||||
for (e, a) in exp_arr.iter().zip(act_arr.iter()) {
|
||||
if !subset_match(e, a) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
// For primitives, exact match
|
||||
(e, a) => e == a,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
pub struct ValidationError {
|
||||
pub code: String,
|
||||
pub message: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub values: Option<HashMap<String, String>>,
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use std::collections::HashSet;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub mod context;
|
||||
pub mod error;
|
||||
@ -13,6 +13,7 @@ use crate::database::Database;
|
||||
use crate::validator::rules::util::is_integer;
|
||||
use serde_json::Value;
|
||||
use std::sync::Arc;
|
||||
use crate::drop::{Drop, Error, ErrorDetails};
|
||||
|
||||
pub struct Validator {
|
||||
pub db: Arc<Database>,
|
||||
@ -36,6 +37,7 @@ impl Validator {
|
||||
"number" => val.is_number(),
|
||||
"integer" => is_integer(val),
|
||||
"object" => val.is_object(),
|
||||
"dict" => val.is_object(),
|
||||
"array" => val.is_array(),
|
||||
_ => true,
|
||||
}
|
||||
@ -57,15 +59,15 @@ impl Validator {
|
||||
match ctx.validate_scoped() {
|
||||
Ok(result) => {
|
||||
if result.is_valid() {
|
||||
crate::drop::Drop::success()
|
||||
Drop::success()
|
||||
} else {
|
||||
let errors: Vec<crate::drop::Error> = result
|
||||
let errors: Vec<Error> = result
|
||||
.errors
|
||||
.into_iter()
|
||||
.map(|e| crate::drop::Error {
|
||||
.map(|e| Error {
|
||||
code: e.code,
|
||||
message: e.message,
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: e.values,
|
||||
details: ErrorDetails {
|
||||
path: Some(e.path),
|
||||
cause: None,
|
||||
context: None,
|
||||
@ -73,13 +75,13 @@ impl Validator {
|
||||
},
|
||||
})
|
||||
.collect();
|
||||
crate::drop::Drop::with_errors(errors)
|
||||
Drop::with_errors(errors)
|
||||
}
|
||||
}
|
||||
Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
Err(e) => Drop::with_errors(vec![Error {
|
||||
code: e.code,
|
||||
message: e.message,
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: e.values,
|
||||
details: ErrorDetails {
|
||||
path: Some(e.path),
|
||||
cause: None,
|
||||
context: None,
|
||||
@ -88,10 +90,12 @@ impl Validator {
|
||||
}]),
|
||||
}
|
||||
} else {
|
||||
crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
Drop::with_errors(vec![Error {
|
||||
code: "SCHEMA_NOT_FOUND".to_string(),
|
||||
message: format!("Schema {} not found", schema_id),
|
||||
details: crate::drop::ErrorDetails {
|
||||
values: Some(HashMap::from([
|
||||
("schema".to_string(), schema_id.to_string()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
path: Some("/".to_string()),
|
||||
cause: None,
|
||||
context: None,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use std::collections::HashSet;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use serde_json::Value;
|
||||
|
||||
@ -17,8 +17,11 @@ impl<'a> ValidationContext<'a> {
|
||||
&& (arr.len() as f64) < min
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "MIN_ITEMS".to_string(),
|
||||
message: "Too few items".to_string(),
|
||||
code: "MIN_ITEMS_VIOLATED".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("count".to_string(), arr.len().to_string()),
|
||||
("limit".to_string(), min.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -26,8 +29,11 @@ impl<'a> ValidationContext<'a> {
|
||||
&& (arr.len() as f64) > max
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "MAX_ITEMS".to_string(),
|
||||
message: "Too many items".to_string(),
|
||||
code: "MAX_ITEMS_VIOLATED".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("count".to_string(), arr.len().to_string()),
|
||||
("limit".to_string(), max.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -38,7 +44,7 @@ impl<'a> ValidationContext<'a> {
|
||||
if seen.contains(&item) {
|
||||
result.errors.push(ValidationError {
|
||||
code: "UNIQUE_ITEMS_VIOLATED".to_string(),
|
||||
message: "Array has duplicate items".to_string(),
|
||||
values: None,
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
break;
|
||||
@ -71,7 +77,10 @@ impl<'a> ValidationContext<'a> {
|
||||
if _match_count < min {
|
||||
result.errors.push(ValidationError {
|
||||
code: "CONTAINS_VIOLATED".to_string(),
|
||||
message: format!("Contains matches {} < min {}", _match_count, min),
|
||||
values: Some(HashMap::from([
|
||||
("count".to_string(), _match_count.to_string()),
|
||||
("limit".to_string(), min.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -80,49 +89,20 @@ impl<'a> ValidationContext<'a> {
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "CONTAINS_VIOLATED".to_string(),
|
||||
message: format!("Contains matches {} > max {}", _match_count, max),
|
||||
values: Some(HashMap::from([
|
||||
("count".to_string(), _match_count.to_string()),
|
||||
("limit".to_string(), max.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let len = arr.len();
|
||||
let mut validation_index = 0;
|
||||
|
||||
if let Some(ref prefix) = self.schema.prefix_items {
|
||||
for (i, sub_schema) in prefix.iter().enumerate() {
|
||||
if i < len {
|
||||
if let Some(child_instance) = arr.get(i) {
|
||||
let mut item_path = self.join_path(&i.to_string());
|
||||
let is_topological = sub_schema.obj.requires_uuid_path(self.db);
|
||||
if is_topological {
|
||||
if let Some(obj) = child_instance.as_object() {
|
||||
if let Some(id_str) = obj.get("id").and_then(|v| v.as_str()) {
|
||||
item_path = self.join_path(id_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
let derived = self.derive(
|
||||
sub_schema,
|
||||
child_instance,
|
||||
&item_path,
|
||||
HashSet::new(),
|
||||
self.extensible,
|
||||
false,
|
||||
Some(self.instance),
|
||||
);
|
||||
let item_res = derived.validate()?;
|
||||
result.merge(item_res);
|
||||
result.evaluated_indices.insert(i);
|
||||
validation_index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref items_schema) = self.schema.items {
|
||||
let is_topological = items_schema.obj.requires_uuid_path(self.db);
|
||||
for i in validation_index..len {
|
||||
for i in 0..len {
|
||||
if let Some(child_instance) = arr.get(i) {
|
||||
let mut item_path = self.join_path(&i.to_string());
|
||||
if is_topological {
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::validator::Validator;
|
||||
use crate::validator::context::ValidationContext;
|
||||
use crate::validator::error::ValidationError;
|
||||
@ -17,7 +19,9 @@ impl<'a> ValidationContext<'a> {
|
||||
if !Validator::check_type(t, current) {
|
||||
result.errors.push(ValidationError {
|
||||
code: "INVALID_TYPE".to_string(),
|
||||
message: format!("Expected type '{}'", t),
|
||||
values: Some(HashMap::from([
|
||||
("expected".to_string(), t.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -33,7 +37,9 @@ impl<'a> ValidationContext<'a> {
|
||||
if !valid {
|
||||
result.errors.push(ValidationError {
|
||||
code: "INVALID_TYPE".to_string(),
|
||||
message: format!("Expected one of types {:?}", types),
|
||||
values: Some(HashMap::from([
|
||||
("expected".to_string(), format!("{:?}", types)),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -45,7 +51,9 @@ impl<'a> ValidationContext<'a> {
|
||||
if !equals(current, const_val) {
|
||||
result.errors.push(ValidationError {
|
||||
code: "CONST_VIOLATED".to_string(),
|
||||
message: "Value does not match const".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("expected".to_string(), format!("{:?}", const_val)),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
} else if let Some(obj) = current.as_object() {
|
||||
@ -66,7 +74,9 @@ impl<'a> ValidationContext<'a> {
|
||||
if !found {
|
||||
result.errors.push(ValidationError {
|
||||
code: "ENUM_MISMATCH".to_string(),
|
||||
message: "Value is not in enum".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("expected".to_string(), format!("{:?}", enum_vals)),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
} else if let Some(obj) = current.as_object() {
|
||||
|
||||
76
src/validator/rules/dict.rs
Normal file
76
src/validator/rules/dict.rs
Normal file
@ -0,0 +1,76 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::validator::context::ValidationContext;
|
||||
use crate::validator::error::ValidationError;
|
||||
use crate::validator::result::ValidationResult;
|
||||
|
||||
impl<'a> ValidationContext<'a> {
|
||||
pub(crate) fn validate_dict(
|
||||
&self,
|
||||
result: &mut ValidationResult,
|
||||
) -> Result<bool, ValidationError> {
|
||||
let current = self.instance;
|
||||
if let Some(obj) = current.as_object() {
|
||||
let is_dict = match &self.schema.type_ {
|
||||
Some(crate::database::object::SchemaTypeOrArray::Single(t)) => t == "dict",
|
||||
Some(crate::database::object::SchemaTypeOrArray::Multiple(types)) => types.contains(&"dict".to_string()),
|
||||
None => false,
|
||||
};
|
||||
|
||||
if is_dict {
|
||||
// Mark all keys as evaluated since a dictionary's keys are all dynamic parameters, not structured properties
|
||||
result.evaluated_keys.extend(obj.keys().cloned());
|
||||
|
||||
// Validate keys
|
||||
if let Some(ref keys_schema) = self.schema.keys {
|
||||
for key in obj.keys() {
|
||||
let _new_path = self.join_path(&format!("keys/{}", key));
|
||||
let val_str = Value::String(key.to_string());
|
||||
|
||||
let ctx = self.derive(
|
||||
keys_schema,
|
||||
&val_str,
|
||||
&_new_path,
|
||||
HashSet::new(),
|
||||
self.extensible,
|
||||
self.reporter,
|
||||
None,
|
||||
);
|
||||
|
||||
result.merge(ctx.validate()?);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate items (values)
|
||||
if let Some(ref items_schema) = self.schema.items {
|
||||
for (key, child_instance) in obj {
|
||||
let new_path = self.join_path(key);
|
||||
let is_ref = match &items_schema.type_ {
|
||||
Some(crate::database::object::SchemaTypeOrArray::Single(ref_t)) => {
|
||||
!crate::database::object::is_primitive_type(ref_t)
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
let next_extensible = if is_ref { false } else { self.extensible };
|
||||
|
||||
let derived = self.derive(
|
||||
items_schema,
|
||||
child_instance,
|
||||
&new_path,
|
||||
HashSet::new(),
|
||||
next_extensible,
|
||||
false,
|
||||
Some(self.instance),
|
||||
);
|
||||
let item_res = derived.validate()?;
|
||||
result.merge(item_res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::database::object::{is_primitive_type, SchemaTypeOrArray};
|
||||
use crate::database::schema::Schema;
|
||||
use crate::validator::context::ValidationContext;
|
||||
use crate::validator::error::ValidationError;
|
||||
use crate::validator::result::ValidationResult;
|
||||
@ -14,6 +18,49 @@ impl<'a> ValidationContext<'a> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub(crate) fn schema_expects_primitive(&self, schema: &Schema, primitive: &str) -> bool {
|
||||
match &schema.type_ {
|
||||
None => true, // Any type is allowed
|
||||
Some(SchemaTypeOrArray::Single(t)) => {
|
||||
if t == primitive {
|
||||
true
|
||||
} else if !is_primitive_type(t) {
|
||||
if primitive == "object" {
|
||||
true
|
||||
} else {
|
||||
// Custom type - resolve recursively
|
||||
if let Some(parent) = self.db.schemas.get(t) {
|
||||
self.schema_expects_primitive(parent, primitive)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
Some(SchemaTypeOrArray::Multiple(types)) => {
|
||||
types.iter().any(|t| {
|
||||
if t == primitive {
|
||||
true
|
||||
} else if !is_primitive_type(t) {
|
||||
if primitive == "object" {
|
||||
true
|
||||
} else {
|
||||
if let Some(parent) = self.db.schemas.get(t) {
|
||||
self.schema_expects_primitive(parent, primitive)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn validate_strictness(
|
||||
&self,
|
||||
result: &mut ValidationResult,
|
||||
@ -22,34 +69,18 @@ impl<'a> ValidationContext<'a> {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
if let Some(obj) = self.instance.as_object() {
|
||||
for key in obj.keys() {
|
||||
if !result.evaluated_keys.contains(key) && !self.overrides.contains(key) {
|
||||
result.errors.push(ValidationError {
|
||||
code: "STRICT_PROPERTY_VIOLATION".to_string(),
|
||||
message: format!("Unexpected property '{}'", key),
|
||||
path: self.join_path(key),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(arr) = self.instance.as_array() {
|
||||
for i in 0..arr.len() {
|
||||
if !result.evaluated_indices.contains(&i) {
|
||||
let mut item_path = self.join_path(&i.to_string());
|
||||
if let Some(child_instance) = arr.get(i) {
|
||||
if let Some(obj) = child_instance.as_object() {
|
||||
if let Some(id_str) = obj.get("id").and_then(|v| v.as_str()) {
|
||||
item_path = self.join_path(id_str);
|
||||
}
|
||||
}
|
||||
if self.schema_expects_primitive(self.schema, "object") || self.schema_expects_primitive(self.schema, "dict") {
|
||||
if let Some(obj) = self.instance.as_object() {
|
||||
for key in obj.keys() {
|
||||
if !result.evaluated_keys.contains(key) && !self.overrides.contains(key) {
|
||||
result.errors.push(ValidationError {
|
||||
code: "STRICT_PROPERTY_VIOLATION".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("property_name".to_string(), key.to_string()),
|
||||
])),
|
||||
path: self.join_path(key),
|
||||
});
|
||||
}
|
||||
result.errors.push(ValidationError {
|
||||
code: "STRICT_ITEM_VIOLATION".to_string(),
|
||||
message: format!("Unexpected item at index {}", i),
|
||||
path: item_path,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::validator::context::ValidationContext;
|
||||
use crate::validator::error::ValidationError;
|
||||
use crate::validator::result::ValidationResult;
|
||||
@ -19,7 +21,10 @@ impl<'a> ValidationContext<'a> {
|
||||
if should && let Err(e) = f(current) {
|
||||
result.errors.push(ValidationError {
|
||||
code: "FORMAT_MISMATCH".to_string(),
|
||||
message: format!("Format error: {}", e),
|
||||
values: Some(HashMap::from([
|
||||
("format".to_string(), self.schema.format.clone().unwrap_or_default()),
|
||||
("error".to_string(), e.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -30,7 +35,9 @@ impl<'a> ValidationContext<'a> {
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "FORMAT_MISMATCH".to_string(),
|
||||
message: "Format regex mismatch".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("format".to_string(), self.schema.format.clone().unwrap_or_default()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
use crate::validator::context::ValidationContext;
|
||||
use crate::validator::error::ValidationError;
|
||||
use crate::validator::result::ValidationResult;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub mod array;
|
||||
pub mod cases;
|
||||
pub mod core;
|
||||
pub mod dict;
|
||||
pub mod extensible;
|
||||
pub mod format;
|
||||
pub mod not;
|
||||
@ -42,6 +44,7 @@ impl<'a> ValidationContext<'a> {
|
||||
// Complex Structures
|
||||
self.validate_object(&mut result)?;
|
||||
self.validate_array(&mut result)?;
|
||||
self.validate_dict(&mut result)?;
|
||||
|
||||
// Multipliers & Conditionals
|
||||
if !self.validate_one_of(&mut result)? {
|
||||
@ -61,7 +64,9 @@ impl<'a> ValidationContext<'a> {
|
||||
if self.depth > 100 {
|
||||
Err(ValidationError {
|
||||
code: "RECURSION_LIMIT_EXCEEDED".to_string(),
|
||||
message: "Recursion limit exceeded".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("limit".to_string(), 100.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
})
|
||||
} else {
|
||||
@ -73,7 +78,7 @@ impl<'a> ValidationContext<'a> {
|
||||
if self.schema.always_fail {
|
||||
result.errors.push(ValidationError {
|
||||
code: "FALSE_SCHEMA".to_string(),
|
||||
message: "Schema is false".to_string(),
|
||||
values: None,
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
// Short-circuit
|
||||
|
||||
@ -13,7 +13,7 @@ impl<'a> ValidationContext<'a> {
|
||||
if sub_res.is_valid() {
|
||||
result.errors.push(ValidationError {
|
||||
code: "NOT_VIOLATED".to_string(),
|
||||
message: "Matched 'not' schema".to_string(),
|
||||
values: None,
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::validator::context::ValidationContext;
|
||||
use crate::validator::error::ValidationError;
|
||||
use crate::validator::result::ValidationResult;
|
||||
@ -14,7 +16,10 @@ impl<'a> ValidationContext<'a> {
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "MINIMUM_VIOLATED".to_string(),
|
||||
message: format!("Value {} < min {}", num, min),
|
||||
values: Some(HashMap::from([
|
||||
("value".to_string(), num.to_string()),
|
||||
("limit".to_string(), min.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -23,7 +28,10 @@ impl<'a> ValidationContext<'a> {
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "MAXIMUM_VIOLATED".to_string(),
|
||||
message: format!("Value {} > max {}", num, max),
|
||||
values: Some(HashMap::from([
|
||||
("value".to_string(), num.to_string()),
|
||||
("limit".to_string(), max.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -32,7 +40,10 @@ impl<'a> ValidationContext<'a> {
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "EXCLUSIVE_MINIMUM_VIOLATED".to_string(),
|
||||
message: format!("Value {} <= ex_min {}", num, ex_min),
|
||||
values: Some(HashMap::from([
|
||||
("value".to_string(), num.to_string()),
|
||||
("limit".to_string(), ex_min.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -41,7 +52,10 @@ impl<'a> ValidationContext<'a> {
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "EXCLUSIVE_MAXIMUM_VIOLATED".to_string(),
|
||||
message: format!("Value {} >= ex_max {}", num, ex_max),
|
||||
values: Some(HashMap::from([
|
||||
("value".to_string(), num.to_string()),
|
||||
("limit".to_string(), ex_max.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -50,7 +64,10 @@ impl<'a> ValidationContext<'a> {
|
||||
if (val - val.round()).abs() > f64::EPSILON {
|
||||
result.errors.push(ValidationError {
|
||||
code: "MULTIPLE_OF_VIOLATED".to_string(),
|
||||
message: format!("Value {} not multiple of {}", num, multiple_of),
|
||||
values: Some(HashMap::from([
|
||||
("value".to_string(), num.to_string()),
|
||||
("multiple_of".to_string(), multiple_of.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use std::collections::HashSet;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use serde_json::Value;
|
||||
|
||||
@ -38,10 +38,9 @@ impl<'a> ValidationContext<'a> {
|
||||
} else {
|
||||
result.errors.push(ValidationError {
|
||||
code: "CONST_VIOLATED".to_string(), // Aligning with original const override errors natively
|
||||
message: format!(
|
||||
"Type '{}' is not a valid descendant for this entity bound schema",
|
||||
type_str
|
||||
),
|
||||
values: Some(HashMap::from([
|
||||
("value".to_string(), type_str.to_string()),
|
||||
])),
|
||||
path: self.join_path("type"),
|
||||
});
|
||||
}
|
||||
@ -50,10 +49,9 @@ impl<'a> ValidationContext<'a> {
|
||||
// Because it's a global entity target, the payload must structurally provide a discriminator natively
|
||||
result.errors.push(ValidationError {
|
||||
code: "MISSING_TYPE".to_string(),
|
||||
message: format!(
|
||||
"Schema mechanically requires type discrimination '{}'",
|
||||
expected_type
|
||||
),
|
||||
values: Some(HashMap::from([
|
||||
("expected".to_string(), expected_type.to_string()),
|
||||
])),
|
||||
path: self.path.clone(), // Empty boundary
|
||||
});
|
||||
}
|
||||
@ -70,8 +68,7 @@ impl<'a> ValidationContext<'a> {
|
||||
if obj.get("kind").is_none() {
|
||||
result.errors.push(ValidationError {
|
||||
code: "MISSING_KIND".to_string(),
|
||||
message: "Schema mechanically requires horizontal kind discrimination"
|
||||
.to_string(),
|
||||
values: None,
|
||||
path: self.path.clone(),
|
||||
});
|
||||
} else {
|
||||
@ -106,8 +103,11 @@ impl<'a> ValidationContext<'a> {
|
||||
&& (obj.len() as f64) < min
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "MIN_PROPERTIES".to_string(),
|
||||
message: "Too few properties".to_string(),
|
||||
code: "MIN_PROPERTIES_VIOLATED".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("count".to_string(), obj.len().to_string()),
|
||||
("limit".to_string(), min.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -116,8 +116,11 @@ impl<'a> ValidationContext<'a> {
|
||||
&& (obj.len() as f64) > max
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "MAX_PROPERTIES".to_string(),
|
||||
message: "Too many properties".to_string(),
|
||||
code: "MAX_PROPERTIES_VIOLATED".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("count".to_string(), obj.len().to_string()),
|
||||
("limit".to_string(), max.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -128,13 +131,17 @@ impl<'a> ValidationContext<'a> {
|
||||
if field == "type" {
|
||||
result.errors.push(ValidationError {
|
||||
code: "MISSING_TYPE".to_string(),
|
||||
message: "Missing type discriminator".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("field_name".to_string(), "type".to_string()),
|
||||
])),
|
||||
path: self.join_path(field),
|
||||
});
|
||||
} else {
|
||||
result.errors.push(ValidationError {
|
||||
code: "REQUIRED_FIELD_MISSING".to_string(),
|
||||
message: format!("Missing {}", field),
|
||||
values: Some(HashMap::from([
|
||||
("field_name".to_string(), field.to_string()),
|
||||
])),
|
||||
path: self.join_path(field),
|
||||
});
|
||||
}
|
||||
@ -151,7 +158,10 @@ impl<'a> ValidationContext<'a> {
|
||||
if !obj.contains_key(req_prop) {
|
||||
result.errors.push(ValidationError {
|
||||
code: "DEPENDENCY_MISSING".to_string(),
|
||||
message: format!("Property '{}' requires property '{}'", prop, req_prop),
|
||||
values: Some(HashMap::from([
|
||||
("property_name".to_string(), prop.to_string()),
|
||||
("required_property".to_string(), req_prop.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -201,80 +211,8 @@ impl<'a> ValidationContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(compiled_pp) = self.schema.compiled_pattern_properties.get() {
|
||||
for (compiled_re, sub_schema) in compiled_pp {
|
||||
for (key, child_instance) in obj {
|
||||
if compiled_re.0.is_match(key) {
|
||||
let new_path = self.join_path(key);
|
||||
let is_ref = match &sub_schema.type_ {
|
||||
Some(crate::database::object::SchemaTypeOrArray::Single(t)) => {
|
||||
!crate::database::object::is_primitive_type(t)
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
let next_extensible = if is_ref { false } else { self.extensible };
|
||||
|
||||
let derived = self.derive(
|
||||
sub_schema,
|
||||
child_instance,
|
||||
&new_path,
|
||||
HashSet::new(),
|
||||
next_extensible,
|
||||
false,
|
||||
Some(self.instance),
|
||||
);
|
||||
let item_res = derived.validate()?;
|
||||
result.merge(item_res);
|
||||
result.evaluated_keys.insert(key.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref additional_schema) = self.schema.additional_properties {
|
||||
for (key, child_instance) in obj {
|
||||
let mut locally_matched = false;
|
||||
if let Some(props) = &self.schema.properties
|
||||
&& props.contains_key(&key.to_string())
|
||||
{
|
||||
locally_matched = true;
|
||||
}
|
||||
if !locally_matched
|
||||
&& let Some(compiled_pp) = self.schema.compiled_pattern_properties.get()
|
||||
{
|
||||
for (compiled_re, _) in compiled_pp {
|
||||
if compiled_re.0.is_match(key) {
|
||||
locally_matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !locally_matched {
|
||||
let new_path = self.join_path(key);
|
||||
let is_ref = match &additional_schema.type_ {
|
||||
Some(crate::database::object::SchemaTypeOrArray::Single(t)) => {
|
||||
!crate::database::object::is_primitive_type(t)
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
let next_extensible = if is_ref { false } else { self.extensible };
|
||||
|
||||
let derived = self.derive(
|
||||
additional_schema,
|
||||
child_instance,
|
||||
&new_path,
|
||||
HashSet::new(),
|
||||
next_extensible,
|
||||
false,
|
||||
Some(self.instance),
|
||||
);
|
||||
let item_res = derived.validate()?;
|
||||
result.merge(item_res);
|
||||
result.evaluated_keys.insert(key.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref property_names) = self.schema.property_names {
|
||||
for key in obj.keys() {
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::validator::context::ValidationContext;
|
||||
use crate::validator::error::ValidationError;
|
||||
use crate::validator::result::ValidationResult;
|
||||
@ -12,7 +14,6 @@ impl<'a> ValidationContext<'a> {
|
||||
let conflicts = self.schema.type_.is_some()
|
||||
|| self.schema.properties.is_some()
|
||||
|| self.schema.required.is_some()
|
||||
|| self.schema.additional_properties.is_some()
|
||||
|| self.schema.items.is_some()
|
||||
|| self.schema.cases.is_some()
|
||||
|| self.schema.one_of.is_some()
|
||||
@ -22,7 +23,7 @@ impl<'a> ValidationContext<'a> {
|
||||
if conflicts {
|
||||
result.errors.push(ValidationError {
|
||||
code: "INVALID_SCHEMA".to_string(),
|
||||
message: "family must be used exclusively without other constraints".to_string(),
|
||||
values: None,
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
return Ok(false);
|
||||
@ -35,7 +36,7 @@ impl<'a> ValidationContext<'a> {
|
||||
} else {
|
||||
result.errors.push(ValidationError {
|
||||
code: "UNCOMPILED_FAMILY".to_string(),
|
||||
message: "Encountered family block that could not be mapped to deterministic options during db schema compilation.".to_string(),
|
||||
values: None,
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
return Ok(false);
|
||||
@ -55,7 +56,7 @@ impl<'a> ValidationContext<'a> {
|
||||
} else {
|
||||
result.errors.push(ValidationError {
|
||||
code: "UNCOMPILED_ONEOF".to_string(),
|
||||
message: "Encountered oneOf block that could not be mapped to deterministic compiled options natively.".to_string(),
|
||||
values: None,
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
return Ok(false);
|
||||
@ -109,10 +110,9 @@ impl<'a> ValidationContext<'a> {
|
||||
} else {
|
||||
result.errors.push(ValidationError {
|
||||
code: "MISSING_COMPILED_SCHEMA".to_string(),
|
||||
message: format!(
|
||||
"Polymorphic router target '{}' does not exist in the database schemas map",
|
||||
target_id
|
||||
),
|
||||
values: Some(HashMap::from([
|
||||
("target_id".to_string(), target_id.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
return Ok(false);
|
||||
@ -132,10 +132,9 @@ impl<'a> ValidationContext<'a> {
|
||||
} else {
|
||||
result.errors.push(ValidationError {
|
||||
code: "MISSING_COMPILED_SCHEMA".to_string(),
|
||||
message: format!(
|
||||
"Polymorphic index target '{}' does not exist in the local oneOf array",
|
||||
idx
|
||||
),
|
||||
values: Some(HashMap::from([
|
||||
("index".to_string(), idx.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
return Ok(false);
|
||||
@ -144,10 +143,15 @@ impl<'a> ValidationContext<'a> {
|
||||
return Ok(false);
|
||||
}
|
||||
} else {
|
||||
let disc_msg = if let Some(d) = self.schema.compiled_discriminator.get() {
|
||||
format!("discriminator {}='{}'", d, val)
|
||||
let values = if let Some(d) = self.schema.compiled_discriminator.get() {
|
||||
Some(HashMap::from([
|
||||
("discriminator".to_string(), d.to_string()),
|
||||
("value".to_string(), val.to_string()),
|
||||
]))
|
||||
} else {
|
||||
format!("structural JSON base primitive '{}'", val)
|
||||
Some(HashMap::from([
|
||||
("primitive".to_string(), val.to_string()),
|
||||
]))
|
||||
};
|
||||
result.errors.push(ValidationError {
|
||||
code: if self.schema.family.is_some() {
|
||||
@ -155,10 +159,7 @@ impl<'a> ValidationContext<'a> {
|
||||
} else {
|
||||
"NO_ONEOF_MATCH".to_string()
|
||||
},
|
||||
message: format!(
|
||||
"Payload matched no candidate boundaries based on its {}",
|
||||
disc_msg
|
||||
),
|
||||
values,
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
return Ok(false);
|
||||
@ -167,10 +168,9 @@ impl<'a> ValidationContext<'a> {
|
||||
if let Some(d) = self.schema.compiled_discriminator.get() {
|
||||
result.errors.push(ValidationError {
|
||||
code: "MISSING_TYPE".to_string(),
|
||||
message: format!(
|
||||
"Missing explicit '{}' discriminator. Unable to resolve polymorphic boundaries",
|
||||
d
|
||||
),
|
||||
values: Some(HashMap::from([
|
||||
("discriminator".to_string(), d.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::validator::context::ValidationContext;
|
||||
use crate::validator::error::ValidationError;
|
||||
use crate::validator::result::ValidationResult;
|
||||
@ -15,7 +17,10 @@ impl<'a> ValidationContext<'a> {
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "MIN_LENGTH_VIOLATED".to_string(),
|
||||
message: format!("Length < min {}", min),
|
||||
values: Some(HashMap::from([
|
||||
("count".to_string(), s.chars().count().to_string()),
|
||||
("limit".to_string(), min.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -24,7 +29,10 @@ impl<'a> ValidationContext<'a> {
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "MAX_LENGTH_VIOLATED".to_string(),
|
||||
message: format!("Length > max {}", max),
|
||||
values: Some(HashMap::from([
|
||||
("count".to_string(), s.chars().count().to_string()),
|
||||
("limit".to_string(), max.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -32,7 +40,10 @@ impl<'a> ValidationContext<'a> {
|
||||
if !compiled_re.0.is_match(s) {
|
||||
result.errors.push(ValidationError {
|
||||
code: "PATTERN_VIOLATED".to_string(),
|
||||
message: format!("Pattern mismatch {:?}", self.schema.pattern),
|
||||
values: Some(HashMap::from([
|
||||
("pattern".to_string(), self.schema.pattern.clone().unwrap_or_default()),
|
||||
("value".to_string(), s.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
@ -42,7 +53,10 @@ impl<'a> ValidationContext<'a> {
|
||||
{
|
||||
result.errors.push(ValidationError {
|
||||
code: "PATTERN_VIOLATED".to_string(),
|
||||
message: format!("Pattern mismatch {}", pattern),
|
||||
values: Some(HashMap::from([
|
||||
("pattern".to_string(), pattern.to_string()),
|
||||
("value".to_string(), s.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
use crate::database::object::{is_primitive_type, SchemaTypeOrArray};
|
||||
use crate::validator::context::ValidationContext;
|
||||
use crate::validator::error::ValidationError;
|
||||
use crate::validator::result::ValidationResult;
|
||||
use std::collections::HashMap;
|
||||
|
||||
impl<'a> ValidationContext<'a> {
|
||||
pub(crate) fn validate_type(
|
||||
@ -24,19 +26,19 @@ impl<'a> ValidationContext<'a> {
|
||||
|
||||
let mut custom_types = Vec::new();
|
||||
match &self.schema.type_ {
|
||||
Some(crate::database::object::SchemaTypeOrArray::Single(t)) => {
|
||||
if !crate::database::object::is_primitive_type(t) {
|
||||
Some(SchemaTypeOrArray::Single(t)) => {
|
||||
if !is_primitive_type(t) {
|
||||
custom_types.push(t.clone());
|
||||
}
|
||||
}
|
||||
Some(crate::database::object::SchemaTypeOrArray::Multiple(arr)) => {
|
||||
Some(SchemaTypeOrArray::Multiple(arr)) => {
|
||||
if arr.contains(&payload_primitive.to_string())
|
||||
|| (payload_primitive == "integer" && arr.contains(&"number".to_string()))
|
||||
{
|
||||
// It natively matched a primitive in the array options, skip forcing custom proxy fallback
|
||||
} else {
|
||||
for t in arr {
|
||||
if !crate::database::object::is_primitive_type(t) {
|
||||
if !is_primitive_type(t) {
|
||||
custom_types.push(t.clone());
|
||||
}
|
||||
}
|
||||
@ -51,7 +53,7 @@ impl<'a> ValidationContext<'a> {
|
||||
// 1. DYNAMIC TYPE (Composition)
|
||||
if t.starts_with('$') {
|
||||
let parts: Vec<&str> = t.split('.').collect();
|
||||
let var_name = &parts[0][1..]; // Remove the $ prefix
|
||||
let var_name = parts[0].trim_start_matches('$');
|
||||
let suffix = if parts.len() > 1 {
|
||||
format!(".{}", parts[1..].join("."))
|
||||
} else {
|
||||
@ -74,10 +76,10 @@ impl<'a> ValidationContext<'a> {
|
||||
if !resolved {
|
||||
result.errors.push(ValidationError {
|
||||
code: "DYNAMIC_TYPE_RESOLUTION_FAILED".to_string(),
|
||||
message: format!(
|
||||
"Dynamic type pointer '{}' could not resolve discriminator property '{}' on parent instance",
|
||||
t, var_name
|
||||
),
|
||||
values: Some(HashMap::from([
|
||||
("pointer".to_string(), t.clone()),
|
||||
("discriminator".to_string(), var_name.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
continue;
|
||||
@ -107,28 +109,25 @@ impl<'a> ValidationContext<'a> {
|
||||
if t.starts_with('$') {
|
||||
result.errors.push(ValidationError {
|
||||
code: "DYNAMIC_TYPE_RESOLUTION_FAILED".to_string(),
|
||||
message: format!(
|
||||
"Resolved dynamic type pointer '{}' was not found in schema registry",
|
||||
target_id
|
||||
),
|
||||
values: Some(HashMap::from([
|
||||
("pointer".to_string(), target_id.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
} else if self.schema.is_proxy() {
|
||||
result.errors.push(ValidationError {
|
||||
code: "PROXY_TYPE_RESOLUTION_FAILED".to_string(),
|
||||
message: format!(
|
||||
"Composed proxy entity pointer '{}' was not found in schema registry",
|
||||
target_id
|
||||
),
|
||||
values: Some(HashMap::from([
|
||||
("pointer".to_string(), target_id.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
} else {
|
||||
result.errors.push(ValidationError {
|
||||
code: "INHERITANCE_RESOLUTION_FAILED".to_string(),
|
||||
message: format!(
|
||||
"Inherited entity pointer '{}' was not found in schema registry",
|
||||
target_id
|
||||
),
|
||||
values: Some(HashMap::from([
|
||||
("pointer".to_string(), target_id.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user