Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 95600551a7 | |||
| c18a8c1561 | |||
| 8ed588ca61 | |||
| edd0dd4763 | |||
| abf1d12e43 | |||
| a885713563 | |||
| d9b4f417f6 | |||
| eae39f92d6 | |||
| 2895f06074 | |||
| c1c16bc814 | |||
| 5885552192 | |||
| dc033296d7 | |||
| 03a871bc1a | |||
| 8aa15873b0 | |||
| 0d282cc930 | |||
| 581fc8e0c0 | |||
| 6f0bff8dc7 | |||
| 99c69e27ab | |||
| e490e0d844 | |||
| e026e82f65 | |||
| a1fb9ef650 |
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,246 +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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "boolean"
|
||||
},
|
||||
"details": {
|
||||
"path": "is_active",
|
||||
"schema": "schema1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "count",
|
||||
"schema": "additionalProperties_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "string"
|
||||
},
|
||||
"details": {
|
||||
"path": "group_a/0",
|
||||
"schema": "schema3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "string"
|
||||
},
|
||||
"details": {
|
||||
"path": "group_a/1",
|
||||
"schema": "schema3"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "invalid non-array type",
|
||||
"data": {
|
||||
"type": "my_type",
|
||||
"group_a": "field1"
|
||||
},
|
||||
"schema_id": "schema3",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "array"
|
||||
},
|
||||
"details": {
|
||||
"path": "group_a",
|
||||
"schema": "schema3"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -268,16 +268,6 @@
|
||||
"path": "",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "booleanSchema_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -156,26 +156,6 @@
|
||||
"path": "",
|
||||
"schema": "const_1_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "const_1_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "1",
|
||||
"schema": "const_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -233,16 +213,6 @@
|
||||
"path": "",
|
||||
"schema": "const_2_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "const_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -268,36 +238,6 @@
|
||||
"path": "",
|
||||
"schema": "const_2_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "const_2_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "1",
|
||||
"schema": "const_2_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "2",
|
||||
"schema": "const_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -534,16 +474,6 @@
|
||||
"path": "",
|
||||
"schema": "const_6_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "const_6_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -567,16 +497,6 @@
|
||||
"path": "",
|
||||
"schema": "const_6_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "const_6_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -630,16 +550,6 @@
|
||||
"path": "",
|
||||
"schema": "const_7_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "const_7_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -663,16 +573,6 @@
|
||||
"path": "",
|
||||
"schema": "const_7_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "const_7_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -72,8 +72,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "0"
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -268,23 +268,13 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
"limit": "1",
|
||||
"count": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "contains_3_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "contains_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -383,8 +373,8 @@
|
||||
{
|
||||
"code": "MULTIPLE_OF_VIOLATED",
|
||||
"values": {
|
||||
"value": "3",
|
||||
"multiple_of": "2"
|
||||
"multiple_of": "2",
|
||||
"value": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
@ -431,8 +421,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "0"
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -453,8 +443,8 @@
|
||||
{
|
||||
"code": "MULTIPLE_OF_VIOLATED",
|
||||
"values": {
|
||||
"multiple_of": "2",
|
||||
"value": "5"
|
||||
"value": "5",
|
||||
"multiple_of": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "1",
|
||||
@ -599,7 +589,7 @@
|
||||
},
|
||||
"tests": [
|
||||
{
|
||||
"description": "extra items cause failure",
|
||||
"description": "extra items do not cause failure",
|
||||
"data": [
|
||||
1,
|
||||
2
|
||||
@ -607,19 +597,7 @@
|
||||
"schema_id": "contains_8_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "1",
|
||||
"schema": "contains_8_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -62,8 +62,8 @@
|
||||
"code": "EDGE_MISSING",
|
||||
"values": {
|
||||
"parent_type": "org",
|
||||
"child_type": "user",
|
||||
"property_name": "missing_users"
|
||||
"property_name": "missing_users",
|
||||
"child_type": "user"
|
||||
},
|
||||
"details": {
|
||||
"path": "full.org/missing_users",
|
||||
@ -152,8 +152,8 @@
|
||||
"code": "EDGE_MISSING",
|
||||
"values": {
|
||||
"child_type": "child",
|
||||
"property_name": "children",
|
||||
"parent_type": "parent"
|
||||
"parent_type": "parent",
|
||||
"property_name": "children"
|
||||
},
|
||||
"details": {
|
||||
"path": "full.parent/children",
|
||||
@ -254,9 +254,9 @@
|
||||
{
|
||||
"code": "AMBIGUOUS_TYPE_RELATIONS",
|
||||
"values": {
|
||||
"parent_type": "invoice",
|
||||
"child_type": "activity",
|
||||
"property_name": "activities",
|
||||
"parent_type": "invoice"
|
||||
"property_name": "activities"
|
||||
},
|
||||
"details": {
|
||||
"path": "full.invoice/activities",
|
||||
@ -470,8 +470,8 @@
|
||||
{
|
||||
"code": "DATABASE_TYPE_PARSE_FAILED",
|
||||
"values": {
|
||||
"type": "failure",
|
||||
"reason": "invalid type: sequence, expected a string"
|
||||
"reason": "invalid type: sequence, expected a string",
|
||||
"type": "failure"
|
||||
},
|
||||
"details": {
|
||||
"context": "failure"
|
||||
|
||||
@ -65,8 +65,8 @@
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"required_property": "foo",
|
||||
"property_name": "bar"
|
||||
"property_name": "bar",
|
||||
"required_property": "foo"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -227,8 +227,8 @@
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"property_name": "quux",
|
||||
"required_property": "bar"
|
||||
"required_property": "bar",
|
||||
"property_name": "quux"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -362,8 +362,8 @@
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"required_property": "foo\rbar",
|
||||
"property_name": "foo\nbar"
|
||||
"property_name": "foo\nbar",
|
||||
"required_property": "foo\rbar"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -579,19 +579,7 @@
|
||||
"schema_id": "schema_schema1",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "schema_schema1"
|
||||
}
|
||||
}
|
||||
]
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -841,8 +829,8 @@
|
||||
{
|
||||
"code": "MIN_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"count": "2",
|
||||
"limit": "4"
|
||||
"limit": "4",
|
||||
"count": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
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": {
|
||||
"pattern": "^[a-z]{3}$",
|
||||
"value": "abcd"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -164,8 +164,8 @@
|
||||
{
|
||||
"code": "DYNAMIC_TYPE_RESOLUTION_FAILED",
|
||||
"values": {
|
||||
"discriminator": "kind",
|
||||
"pointer": "$kind.filter"
|
||||
"pointer": "$kind.filter",
|
||||
"discriminator": "kind"
|
||||
},
|
||||
"details": {
|
||||
"path": "filter",
|
||||
|
||||
@ -560,16 +560,6 @@
|
||||
"path": "",
|
||||
"schema": "enum_6_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "enum_6_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -593,16 +583,6 @@
|
||||
"path": "",
|
||||
"schema": "enum_6_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "enum_6_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -728,16 +708,6 @@
|
||||
"path": "",
|
||||
"schema": "enum_8_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "enum_8_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -761,16 +731,6 @@
|
||||
"path": "",
|
||||
"schema": "enum_8_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "enum_8_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -873,16 +833,6 @@
|
||||
"path": "",
|
||||
"schema": "enum_10_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "enum_10_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1007,16 +957,6 @@
|
||||
"path": "",
|
||||
"schema": "enum_12_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "enum_12_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -34,8 +34,8 @@
|
||||
{
|
||||
"code": "EXCLUSIVE_MAXIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "3",
|
||||
"limit": "3"
|
||||
"limit": "3",
|
||||
"value": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -34,8 +34,8 @@
|
||||
{
|
||||
"code": "EXCLUSIVE_MINIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "1.1",
|
||||
"limit": "1.1"
|
||||
"limit": "1.1",
|
||||
"value": "1.1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -56,8 +56,8 @@
|
||||
{
|
||||
"code": "EXCLUSIVE_MINIMUM_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1.1",
|
||||
"value": "0.6"
|
||||
"value": "0.6",
|
||||
"limit": "1.1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1623
fixtures/items.json
1623
fixtures/items.json
File diff suppressed because it is too large
Load Diff
@ -106,8 +106,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "2",
|
||||
"limit": "1"
|
||||
"limit": "1",
|
||||
"count": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -144,8 +144,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "2",
|
||||
"limit": "1"
|
||||
"limit": "1",
|
||||
"count": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -284,8 +284,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "4",
|
||||
"limit": "3"
|
||||
"limit": "3",
|
||||
"count": "4"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -7,8 +7,7 @@
|
||||
"name": "maxItems_0_0",
|
||||
"schemas": {
|
||||
"maxItems_0_0": {
|
||||
"maxItems": 2,
|
||||
"extensible": true
|
||||
"maxItems": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -53,8 +52,8 @@
|
||||
{
|
||||
"code": "MAX_ITEMS_VIOLATED",
|
||||
"values": {
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
"limit": "2",
|
||||
"count": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -83,8 +82,7 @@
|
||||
"name": "maxItems_1_0",
|
||||
"schemas": {
|
||||
"maxItems_1_0": {
|
||||
"maxItems": 2,
|
||||
"extensible": true
|
||||
"maxItems": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -117,8 +115,8 @@
|
||||
{
|
||||
"code": "MAX_ITEMS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "3"
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -138,8 +136,7 @@
|
||||
"name": "maxItems_2_0",
|
||||
"schemas": {
|
||||
"maxItems_2_0": {
|
||||
"maxItems": 2,
|
||||
"extensible": true
|
||||
"maxItems": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -161,8 +158,8 @@
|
||||
{
|
||||
"code": "MAX_ITEMS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "3"
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -43,8 +43,8 @@
|
||||
{
|
||||
"code": "MAX_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
"limit": "2",
|
||||
"count": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -109,8 +109,8 @@
|
||||
{
|
||||
"code": "MAX_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
"limit": "2",
|
||||
"count": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -139,8 +139,8 @@
|
||||
{
|
||||
"code": "MAX_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
"limit": "2",
|
||||
"count": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -190,8 +190,8 @@
|
||||
{
|
||||
"code": "MAX_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"count": "1",
|
||||
"limit": "0"
|
||||
"limit": "0",
|
||||
"count": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -234,8 +234,8 @@
|
||||
{
|
||||
"code": "MAX_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "3"
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -118,8 +118,8 @@
|
||||
{
|
||||
"code": "MAXIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "300.5",
|
||||
"limit": "300"
|
||||
"limit": "300",
|
||||
"value": "300.5"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -239,8 +239,8 @@
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"property_name": "trigger",
|
||||
"required_property": "base_dep"
|
||||
"required_property": "base_dep",
|
||||
"property_name": "trigger"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -264,8 +264,8 @@
|
||||
{
|
||||
"code": "DEPENDENCY_MISSING",
|
||||
"values": {
|
||||
"required_property": "child_dep",
|
||||
"property_name": "trigger"
|
||||
"property_name": "trigger",
|
||||
"required_property": "child_dep"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -1310,9 +1310,9 @@
|
||||
[
|
||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"JOIN agreego.\"organization\" t2 ON ",
|
||||
"JOIN agreego.\"user\" t3 ON ",
|
||||
"JOIN agreego.\"person\" t4 ON ",
|
||||
"LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" (\"first_name\" = 'LookupFirst'",
|
||||
" AND \"last_name\" = 'LookupLast'",
|
||||
@ -1463,12 +1463,18 @@
|
||||
[
|
||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"JOIN agreego.\"organization\" t2 ON ",
|
||||
"JOIN agreego.\"user\" t3 ON ",
|
||||
"JOIN agreego.\"person\" t4 ON ",
|
||||
"LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" t1.id = '{{uuid:data.id}}'",
|
||||
" OR (\"first_name\" = 'LookupFirst'",
|
||||
"UNION SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" (\"first_name\" = 'LookupFirst'",
|
||||
" AND \"last_name\" = 'LookupLast'",
|
||||
" AND \"date_of_birth\" = '{{timestamp}}'",
|
||||
" AND \"pronouns\" = 'they/them'))"
|
||||
@ -1616,12 +1622,18 @@
|
||||
[
|
||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"JOIN agreego.\"organization\" t2 ON ",
|
||||
"JOIN agreego.\"user\" t3 ON ",
|
||||
"JOIN agreego.\"person\" t4 ON ",
|
||||
"LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" t1.id = '{{uuid:data.id}}'",
|
||||
" OR (\"first_name\" = 'LookupFirst'",
|
||||
"UNION SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" (\"first_name\" = 'LookupFirst'",
|
||||
" AND \"last_name\" = 'LookupLast'",
|
||||
" AND \"date_of_birth\" = '{{timestamp}}'",
|
||||
" AND \"pronouns\" = 'they/them'))"
|
||||
@ -1759,9 +1771,9 @@
|
||||
[
|
||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"JOIN agreego.\"organization\" t2 ON ",
|
||||
"JOIN agreego.\"user\" t3 ON ",
|
||||
"JOIN agreego.\"person\" t4 ON ",
|
||||
"LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" t1.id = '{{uuid:mocks.0.id}}')"
|
||||
],
|
||||
@ -1882,9 +1894,9 @@
|
||||
[
|
||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"JOIN agreego.\"organization\" t2 ON ",
|
||||
"JOIN agreego.\"user\" t3 ON ",
|
||||
"JOIN agreego.\"person\" t4 ON ",
|
||||
"LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" t1.id = '123')"
|
||||
],
|
||||
@ -2221,10 +2233,14 @@
|
||||
[
|
||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"JOIN agreego.\"order\" t2 ON ",
|
||||
"LEFT JOIN agreego.\"order\" t2 ON t2.id = t1.id",
|
||||
"WHERE",
|
||||
" t1.id = 'abc'",
|
||||
" OR (\"id\" = 'abc'))"
|
||||
"UNION SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"LEFT JOIN agreego.\"order\" t2 ON t2.id = t1.id",
|
||||
"WHERE",
|
||||
" (\"id\" = 'abc'))"
|
||||
],
|
||||
[
|
||||
"INSERT INTO agreego.\"entity\" (",
|
||||
@ -3024,9 +3040,9 @@
|
||||
[
|
||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"JOIN agreego.\"organization\" t2 ON ",
|
||||
"JOIN agreego.\"user\" t3 ON ",
|
||||
"JOIN agreego.\"person\" t4 ON ",
|
||||
"LEFT JOIN agreego.\"organization\" t2 ON t2.id = t1.id",
|
||||
"LEFT JOIN agreego.\"user\" t3 ON t3.id = t1.id",
|
||||
"LEFT JOIN agreego.\"person\" t4 ON t4.id = t1.id",
|
||||
"WHERE",
|
||||
" t1.id = 'abc-archived')"
|
||||
],
|
||||
@ -3377,7 +3393,7 @@
|
||||
[
|
||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"JOIN agreego.\"order_line\" t2 ON ",
|
||||
"LEFT JOIN agreego.\"order_line\" t2 ON t2.id = t1.id",
|
||||
"WHERE",
|
||||
" t1.id = '{{uuid:data.lines.0.id}}')"
|
||||
],
|
||||
@ -3501,10 +3517,14 @@
|
||||
[
|
||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"JOIN agreego.\"invoice\" t2 ON ",
|
||||
"LEFT JOIN agreego.\"invoice\" t2 ON t2.id = t1.id",
|
||||
"WHERE",
|
||||
" t1.id = '{{uuid:data.id}}'",
|
||||
" OR (\"id\" = '{{uuid:data.id}}'))"
|
||||
"UNION SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"LEFT JOIN agreego.\"invoice\" t2 ON t2.id = t1.id",
|
||||
"WHERE",
|
||||
" (\"id\" = '{{uuid:data.id}}'))"
|
||||
],
|
||||
[
|
||||
"INSERT INTO agreego.\"entity\" (",
|
||||
@ -3618,7 +3638,7 @@
|
||||
[
|
||||
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
|
||||
"FROM agreego.\"entity\" t1",
|
||||
"JOIN agreego.\"account\" t2 ON ",
|
||||
"LEFT JOIN agreego.\"account\" t2 ON t2.id = t1.id",
|
||||
"WHERE",
|
||||
" t1.id = '{{uuid:data.id}}')"
|
||||
],
|
||||
|
||||
@ -169,8 +169,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "2"
|
||||
"limit": "2",
|
||||
"count": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -193,8 +193,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "1"
|
||||
"count": "1",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -218,8 +218,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "1"
|
||||
"count": "1",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -301,8 +301,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "1"
|
||||
"count": "1",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -357,8 +357,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "0",
|
||||
"limit": "2"
|
||||
"limit": "2",
|
||||
"count": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -407,8 +407,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "3"
|
||||
"count": "3",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -487,8 +487,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"count": "1",
|
||||
"limit": "3"
|
||||
"limit": "3",
|
||||
"count": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -538,8 +538,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "3",
|
||||
"count": "2"
|
||||
"count": "2",
|
||||
"limit": "3"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -549,8 +549,8 @@
|
||||
{
|
||||
"code": "CONTAINS_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "2"
|
||||
"count": "2",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -7,8 +7,7 @@
|
||||
"name": "minItems_0_0",
|
||||
"schemas": {
|
||||
"minItems_0_0": {
|
||||
"minItems": 1,
|
||||
"extensible": true
|
||||
"minItems": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -79,8 +78,7 @@
|
||||
"name": "minItems_1_0",
|
||||
"schemas": {
|
||||
"minItems_1_0": {
|
||||
"minItems": 1,
|
||||
"extensible": true
|
||||
"minItems": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,8 +43,8 @@
|
||||
{
|
||||
"code": "MIN_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"count": "1",
|
||||
"limit": "2"
|
||||
"limit": "2",
|
||||
"count": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -74,8 +74,8 @@
|
||||
{
|
||||
"code": "MIN_LENGTH_VIOLATED",
|
||||
"values": {
|
||||
"limit": "2",
|
||||
"count": "1"
|
||||
"count": "1",
|
||||
"limit": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -128,8 +128,8 @@
|
||||
{
|
||||
"code": "MIN_PROPERTIES_VIOLATED",
|
||||
"values": {
|
||||
"limit": "1",
|
||||
"count": "0"
|
||||
"count": "0",
|
||||
"limit": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -43,8 +43,8 @@
|
||||
{
|
||||
"code": "MINIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "0.6",
|
||||
"limit": "1.1"
|
||||
"limit": "1.1",
|
||||
"value": "0.6"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -100,8 +100,8 @@
|
||||
{
|
||||
"code": "MULTIPLE_OF_VIOLATED",
|
||||
"values": {
|
||||
"multiple_of": "1.5",
|
||||
"value": "35"
|
||||
"value": "35",
|
||||
"multiple_of": "1.5"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -407,16 +407,6 @@
|
||||
"path": "",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "not_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -610,16 +600,6 @@
|
||||
"path": "",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "not_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -156,8 +156,8 @@
|
||||
{
|
||||
"code": "MAXIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "60",
|
||||
"limit": "50"
|
||||
"limit": "50",
|
||||
"value": "60"
|
||||
},
|
||||
"details": {
|
||||
"path": "max",
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
{
|
||||
"code": "PATTERN_VIOLATED",
|
||||
"values": {
|
||||
"value": "abc",
|
||||
"pattern": "^a*$"
|
||||
},
|
||||
"details": {
|
||||
|
||||
@ -1,580 +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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "patternProperties_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "multiple invalid matches is invalid",
|
||||
"data": {
|
||||
"foo": "bar",
|
||||
"foooooo": "baz"
|
||||
},
|
||||
"schema_id": "patternProperties_0_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "patternProperties_0_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "foooooo",
|
||||
"schema": "patternProperties_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "extra"
|
||||
},
|
||||
"details": {
|
||||
"path": "extra",
|
||||
"schema": "patternProperties_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "a",
|
||||
"schema": "patternProperties_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "an invalid due to the other is invalid",
|
||||
"data": {
|
||||
"aaaa": 31
|
||||
},
|
||||
"schema_id": "patternProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "MAXIMUM_VIOLATED",
|
||||
"values": {
|
||||
"value": "31",
|
||||
"limit": "20"
|
||||
},
|
||||
"details": {
|
||||
"path": "aaaa",
|
||||
"schema": "patternProperties_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "an invalid due to both is invalid",
|
||||
"data": {
|
||||
"aaa": "foo",
|
||||
"aaaa": 31
|
||||
},
|
||||
"schema_id": "patternProperties_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "aaa",
|
||||
"schema": "patternProperties_1_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "MAXIMUM_VIOLATED",
|
||||
"values": {
|
||||
"limit": "20",
|
||||
"value": "31"
|
||||
},
|
||||
"details": {
|
||||
"path": "aaaa",
|
||||
"schema": "patternProperties_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "boolean"
|
||||
},
|
||||
"details": {
|
||||
"path": "a31b",
|
||||
"schema": "patternProperties_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "string"
|
||||
},
|
||||
"details": {
|
||||
"path": "a_X_3",
|
||||
"schema": "patternProperties_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "patternProperties_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "object with both properties is invalid",
|
||||
"data": {
|
||||
"foo": 1,
|
||||
"bar": 2
|
||||
},
|
||||
"schema_id": "patternProperties_3_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "bar",
|
||||
"schema": "patternProperties_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "foobar",
|
||||
"schema": "patternProperties_3_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "foo",
|
||||
"schema": "patternProperties_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -148,8 +148,8 @@
|
||||
{
|
||||
"code": "NO_FAMILY_MATCH",
|
||||
"values": {
|
||||
"discriminator": "type",
|
||||
"value": "alien"
|
||||
"value": "alien",
|
||||
"discriminator": "type"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
@ -284,8 +284,8 @@
|
||||
{
|
||||
"code": "NO_FAMILY_MATCH",
|
||||
"values": {
|
||||
"discriminator": "type",
|
||||
"value": "bot"
|
||||
"value": "bot",
|
||||
"discriminator": "type"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -1,324 +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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "integer"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "prefixItems_0_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "INVALID_TYPE",
|
||||
"values": {
|
||||
"expected": "string"
|
||||
},
|
||||
"details": {
|
||||
"path": "1",
|
||||
"schema": "prefixItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_ITEM_VIOLATION",
|
||||
"values": {
|
||||
"index": "2"
|
||||
},
|
||||
"details": {
|
||||
"path": "2",
|
||||
"schema": "prefixItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "0"
|
||||
},
|
||||
"details": {
|
||||
"path": "0",
|
||||
"schema": "prefixItems_0_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "1"
|
||||
},
|
||||
"details": {
|
||||
"path": "1",
|
||||
"schema": "prefixItems_0_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "length"
|
||||
},
|
||||
"details": {
|
||||
"path": "length",
|
||||
"schema": "prefixItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "1",
|
||||
"schema": "prefixItems_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -489,16 +489,6 @@
|
||||
"path": "constructor",
|
||||
"schema": "properties_4_0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"code": "STRICT_PROPERTY_VIOLATION",
|
||||
"values": {
|
||||
"property_name": "length"
|
||||
},
|
||||
"details": {
|
||||
"path": "constructor/length",
|
||||
"schema": "properties_4_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -141,7 +141,8 @@
|
||||
{
|
||||
"code": "PATTERN_VIOLATED",
|
||||
"values": {
|
||||
"pattern": "^a+$"
|
||||
"pattern": "^a+$",
|
||||
"value": "aaA"
|
||||
},
|
||||
"details": {
|
||||
"path": "",
|
||||
|
||||
@ -1293,8 +1293,8 @@
|
||||
" 'age', person_3.age",
|
||||
" )",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.organization organization_2 ON organization_2.id = entity_1.id",
|
||||
" JOIN agreego.person person_3 ON person_3.id = organization_2.id",
|
||||
" JOIN agreego.organization organization_2",
|
||||
" JOIN agreego.person person_3",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
"))))"
|
||||
@ -1336,15 +1336,15 @@
|
||||
" 'number', phone_number_8.number",
|
||||
" )",
|
||||
" FROM agreego.entity entity_7",
|
||||
" JOIN agreego.phone_number phone_number_8 ON phone_number_8.id = entity_7.id",
|
||||
" JOIN agreego.phone_number phone_number_8",
|
||||
" WHERE",
|
||||
" NOT entity_7.archived",
|
||||
" AND relationship_5.target_id = entity_7.id",
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_4",
|
||||
" JOIN agreego.relationship relationship_5 ON relationship_5.id = entity_4.id",
|
||||
" JOIN agreego.contact contact_6 ON contact_6.id = relationship_5.id",
|
||||
" JOIN agreego.relationship relationship_5",
|
||||
" JOIN agreego.contact contact_6",
|
||||
" WHERE",
|
||||
" NOT entity_4.archived",
|
||||
" AND relationship_5.target_type = 'phone_number'",
|
||||
@ -1366,15 +1366,15 @@
|
||||
" 'address', email_address_13.address",
|
||||
" )",
|
||||
" FROM agreego.entity entity_12",
|
||||
" JOIN agreego.email_address email_address_13 ON email_address_13.id = entity_12.id",
|
||||
" JOIN agreego.email_address email_address_13",
|
||||
" WHERE",
|
||||
" NOT entity_12.archived",
|
||||
" AND relationship_10.target_id = entity_12.id",
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_9",
|
||||
" JOIN agreego.relationship relationship_10 ON relationship_10.id = entity_9.id",
|
||||
" JOIN agreego.contact contact_11 ON contact_11.id = relationship_10.id",
|
||||
" JOIN agreego.relationship relationship_10",
|
||||
" JOIN agreego.contact contact_11",
|
||||
" WHERE",
|
||||
" NOT entity_9.archived",
|
||||
" AND relationship_10.target_type = 'email_address'",
|
||||
@ -1396,15 +1396,15 @@
|
||||
" 'city', address_18.city",
|
||||
" )",
|
||||
" FROM agreego.entity entity_17",
|
||||
" JOIN agreego.address address_18 ON address_18.id = entity_17.id",
|
||||
" JOIN agreego.address address_18",
|
||||
" WHERE",
|
||||
" NOT entity_17.archived",
|
||||
" AND relationship_15.target_id = entity_17.id",
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_14",
|
||||
" JOIN agreego.relationship relationship_15 ON relationship_15.id = entity_14.id",
|
||||
" JOIN agreego.contact contact_16 ON contact_16.id = relationship_15.id",
|
||||
" JOIN agreego.relationship relationship_15",
|
||||
" JOIN agreego.contact contact_16",
|
||||
" WHERE",
|
||||
" NOT entity_14.archived",
|
||||
" AND relationship_15.target_type = 'address'",
|
||||
@ -1427,7 +1427,7 @@
|
||||
" 'number', phone_number_23.number",
|
||||
" )",
|
||||
" FROM agreego.entity entity_22",
|
||||
" JOIN agreego.phone_number phone_number_23 ON phone_number_23.id = entity_22.id",
|
||||
" JOIN agreego.phone_number phone_number_23",
|
||||
" WHERE",
|
||||
" NOT entity_22.archived",
|
||||
" AND relationship_20.target_id = entity_22.id",
|
||||
@ -1441,7 +1441,7 @@
|
||||
" 'address', email_address_25.address",
|
||||
" )",
|
||||
" FROM agreego.entity entity_24",
|
||||
" JOIN agreego.email_address email_address_25 ON email_address_25.id = entity_24.id",
|
||||
" JOIN agreego.email_address email_address_25",
|
||||
" WHERE",
|
||||
" NOT entity_24.archived",
|
||||
" AND relationship_20.target_id = entity_24.id",
|
||||
@ -1455,7 +1455,7 @@
|
||||
" 'city', address_27.city",
|
||||
" )",
|
||||
" FROM agreego.entity entity_26",
|
||||
" JOIN agreego.address address_27 ON address_27.id = entity_26.id",
|
||||
" JOIN agreego.address address_27",
|
||||
" WHERE",
|
||||
" NOT entity_26.archived",
|
||||
" AND relationship_20.target_id = entity_26.id",
|
||||
@ -1464,16 +1464,16 @@
|
||||
" END",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_19",
|
||||
" JOIN agreego.relationship relationship_20 ON relationship_20.id = entity_19.id",
|
||||
" JOIN agreego.contact contact_21 ON contact_21.id = relationship_20.id",
|
||||
" JOIN agreego.relationship relationship_20",
|
||||
" JOIN agreego.contact contact_21",
|
||||
" WHERE",
|
||||
" NOT entity_19.archived",
|
||||
" AND relationship_20.source_id = entity_1.id",
|
||||
" )",
|
||||
" )",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.organization organization_2 ON organization_2.id = entity_1.id",
|
||||
" JOIN agreego.person person_3 ON person_3.id = organization_2.id",
|
||||
" JOIN agreego.organization organization_2",
|
||||
" JOIN agreego.person person_3",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
"))))"
|
||||
@ -1586,7 +1586,7 @@
|
||||
" 'number', phone_number_8.number",
|
||||
" )",
|
||||
" FROM agreego.entity entity_7",
|
||||
" JOIN agreego.phone_number phone_number_8 ON phone_number_8.id = entity_7.id",
|
||||
" JOIN agreego.phone_number phone_number_8",
|
||||
" WHERE",
|
||||
" NOT entity_7.archived",
|
||||
" AND phone_number_8.number ILIKE $32 #>> '{}'",
|
||||
@ -1594,8 +1594,8 @@
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_4",
|
||||
" JOIN agreego.relationship relationship_5 ON relationship_5.id = entity_4.id",
|
||||
" JOIN agreego.contact contact_6 ON contact_6.id = relationship_5.id",
|
||||
" JOIN agreego.relationship relationship_5",
|
||||
" JOIN agreego.contact contact_6",
|
||||
" WHERE",
|
||||
" NOT entity_4.archived",
|
||||
" AND relationship_5.target_type = 'phone_number'",
|
||||
@ -1617,15 +1617,15 @@
|
||||
" 'address', email_address_13.address",
|
||||
" )",
|
||||
" FROM agreego.entity entity_12",
|
||||
" JOIN agreego.email_address email_address_13 ON email_address_13.id = entity_12.id",
|
||||
" JOIN agreego.email_address email_address_13",
|
||||
" WHERE",
|
||||
" NOT entity_12.archived",
|
||||
" AND relationship_10.target_id = entity_12.id",
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_9",
|
||||
" JOIN agreego.relationship relationship_10 ON relationship_10.id = entity_9.id",
|
||||
" JOIN agreego.contact contact_11 ON contact_11.id = relationship_10.id",
|
||||
" JOIN agreego.relationship relationship_10",
|
||||
" JOIN agreego.contact contact_11",
|
||||
" WHERE",
|
||||
" NOT entity_9.archived",
|
||||
" AND relationship_10.target_type = 'email_address'",
|
||||
@ -1647,15 +1647,15 @@
|
||||
" 'city', address_18.city",
|
||||
" )",
|
||||
" FROM agreego.entity entity_17",
|
||||
" JOIN agreego.address address_18 ON address_18.id = entity_17.id",
|
||||
" JOIN agreego.address address_18",
|
||||
" WHERE",
|
||||
" NOT entity_17.archived",
|
||||
" AND relationship_15.target_id = entity_17.id",
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_14",
|
||||
" JOIN agreego.relationship relationship_15 ON relationship_15.id = entity_14.id",
|
||||
" JOIN agreego.contact contact_16 ON contact_16.id = relationship_15.id",
|
||||
" JOIN agreego.relationship relationship_15",
|
||||
" JOIN agreego.contact contact_16",
|
||||
" WHERE",
|
||||
" NOT entity_14.archived",
|
||||
" AND relationship_15.target_type = 'address'",
|
||||
@ -1678,7 +1678,7 @@
|
||||
" 'number', phone_number_23.number",
|
||||
" )",
|
||||
" FROM agreego.entity entity_22",
|
||||
" JOIN agreego.phone_number phone_number_23 ON phone_number_23.id = entity_22.id",
|
||||
" JOIN agreego.phone_number phone_number_23",
|
||||
" WHERE",
|
||||
" NOT entity_22.archived",
|
||||
" AND relationship_20.target_id = entity_22.id",
|
||||
@ -1692,7 +1692,7 @@
|
||||
" 'address', email_address_25.address",
|
||||
" )",
|
||||
" FROM agreego.entity entity_24",
|
||||
" JOIN agreego.email_address email_address_25 ON email_address_25.id = entity_24.id",
|
||||
" JOIN agreego.email_address email_address_25",
|
||||
" WHERE",
|
||||
" NOT entity_24.archived",
|
||||
" AND relationship_20.target_id = entity_24.id",
|
||||
@ -1706,7 +1706,7 @@
|
||||
" 'city', address_27.city",
|
||||
" )",
|
||||
" FROM agreego.entity entity_26",
|
||||
" JOIN agreego.address address_27 ON address_27.id = entity_26.id",
|
||||
" JOIN agreego.address address_27",
|
||||
" WHERE",
|
||||
" NOT entity_26.archived",
|
||||
" AND relationship_20.target_id = entity_26.id",
|
||||
@ -1715,8 +1715,8 @@
|
||||
" END",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_19",
|
||||
" JOIN agreego.relationship relationship_20 ON relationship_20.id = entity_19.id",
|
||||
" JOIN agreego.contact contact_21 ON contact_21.id = relationship_20.id",
|
||||
" JOIN agreego.relationship relationship_20",
|
||||
" JOIN agreego.contact contact_21",
|
||||
" WHERE",
|
||||
" NOT entity_19.archived",
|
||||
" AND contact_21.is_primary = ($11 #>> '{}')::BOOLEAN",
|
||||
@ -1724,8 +1724,8 @@
|
||||
" )",
|
||||
" )",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.organization organization_2 ON organization_2.id = entity_1.id",
|
||||
" JOIN agreego.person person_3 ON person_3.id = organization_2.id",
|
||||
" JOIN agreego.organization organization_2",
|
||||
" JOIN agreego.person person_3",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
" AND person_3.age = ($1 #>> '{}')::NUMERIC",
|
||||
@ -1787,15 +1787,15 @@
|
||||
" 'address', email_address_5.address",
|
||||
" )",
|
||||
" FROM agreego.entity entity_4",
|
||||
" JOIN agreego.email_address email_address_5 ON email_address_5.id = entity_4.id",
|
||||
" JOIN agreego.email_address email_address_5",
|
||||
" WHERE",
|
||||
" NOT entity_4.archived",
|
||||
" AND relationship_2.target_id = entity_4.id",
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.relationship relationship_2 ON relationship_2.id = entity_1.id",
|
||||
" JOIN agreego.contact contact_3 ON contact_3.id = relationship_2.id",
|
||||
" JOIN agreego.relationship relationship_2",
|
||||
" JOIN agreego.contact contact_3",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
" AND relationship_2.target_type = 'email_address'",
|
||||
@ -1832,8 +1832,8 @@
|
||||
" 'age', person_5.age",
|
||||
" )",
|
||||
" FROM agreego.entity entity_3",
|
||||
" JOIN agreego.organization organization_4 ON organization_4.id = entity_3.id",
|
||||
" JOIN agreego.person person_5 ON person_5.id = organization_4.id",
|
||||
" JOIN agreego.organization organization_4",
|
||||
" JOIN agreego.person person_5",
|
||||
" WHERE",
|
||||
" NOT entity_3.archived",
|
||||
" AND order_2.customer_id = person_5.id",
|
||||
@ -1849,14 +1849,14 @@
|
||||
" 'price', order_line_7.price",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_6",
|
||||
" JOIN agreego.order_line order_line_7 ON order_line_7.id = entity_6.id",
|
||||
" JOIN agreego.order_line order_line_7",
|
||||
" WHERE",
|
||||
" NOT entity_6.archived",
|
||||
" AND order_line_7.order_id = order_2.id",
|
||||
" )",
|
||||
" )",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.order order_2 ON order_2.id = entity_1.id",
|
||||
" JOIN agreego.order order_2",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
"))))"
|
||||
@ -1881,7 +1881,7 @@
|
||||
" 'name', organization_2.name",
|
||||
" )",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.organization organization_2 ON organization_2.id = entity_1.id",
|
||||
" JOIN agreego.organization organization_2",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
"))))"
|
||||
@ -1910,8 +1910,8 @@
|
||||
" 'role', bot_5.role",
|
||||
" )",
|
||||
" FROM agreego.entity entity_3",
|
||||
" JOIN agreego.organization organization_4 ON organization_4.id = entity_3.id",
|
||||
" JOIN agreego.bot bot_5 ON bot_5.id = organization_4.id",
|
||||
" JOIN agreego.organization organization_4",
|
||||
" JOIN agreego.bot bot_5",
|
||||
" WHERE",
|
||||
" NOT entity_3.archived",
|
||||
" AND entity_3.id = entity_1.id",
|
||||
@ -1925,7 +1925,7 @@
|
||||
" 'name', organization_7.name",
|
||||
" )",
|
||||
" FROM agreego.entity entity_6",
|
||||
" JOIN agreego.organization organization_7 ON organization_7.id = entity_6.id",
|
||||
" JOIN agreego.organization organization_7",
|
||||
" WHERE",
|
||||
" NOT entity_6.archived",
|
||||
" AND entity_6.id = entity_1.id",
|
||||
@ -1942,8 +1942,8 @@
|
||||
" 'age', person_10.age",
|
||||
" )",
|
||||
" FROM agreego.entity entity_8",
|
||||
" JOIN agreego.organization organization_9 ON organization_9.id = entity_8.id",
|
||||
" JOIN agreego.person person_10 ON person_10.id = organization_9.id",
|
||||
" JOIN agreego.organization organization_9",
|
||||
" JOIN agreego.person person_10",
|
||||
" WHERE",
|
||||
" NOT entity_8.archived",
|
||||
" AND entity_8.id = entity_1.id",
|
||||
@ -1951,7 +1951,7 @@
|
||||
" ELSE NULL",
|
||||
" END), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.organization organization_2 ON organization_2.id = entity_1.id",
|
||||
" JOIN agreego.organization organization_2",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
"))))"
|
||||
@ -1979,8 +1979,8 @@
|
||||
" 'token', bot_5.token",
|
||||
" )",
|
||||
" FROM agreego.entity entity_3",
|
||||
" JOIN agreego.organization organization_4 ON organization_4.id = entity_3.id",
|
||||
" JOIN agreego.bot bot_5 ON bot_5.id = organization_4.id",
|
||||
" JOIN agreego.organization organization_4",
|
||||
" JOIN agreego.bot bot_5",
|
||||
" WHERE",
|
||||
" NOT entity_3.archived",
|
||||
" AND entity_3.id = entity_1.id",
|
||||
@ -1996,8 +1996,8 @@
|
||||
" 'last_name', person_8.last_name",
|
||||
" )",
|
||||
" FROM agreego.entity entity_6",
|
||||
" JOIN agreego.organization organization_7 ON organization_7.id = entity_6.id",
|
||||
" JOIN agreego.person person_8 ON person_8.id = organization_7.id",
|
||||
" JOIN agreego.organization organization_7",
|
||||
" JOIN agreego.person person_8",
|
||||
" WHERE",
|
||||
" NOT entity_6.archived",
|
||||
" AND entity_6.id = entity_1.id",
|
||||
@ -2005,7 +2005,7 @@
|
||||
" ELSE NULL",
|
||||
" END",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.organization organization_2 ON organization_2.id = entity_1.id",
|
||||
" JOIN agreego.organization organization_2",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
"))))"
|
||||
@ -2049,15 +2049,15 @@
|
||||
" 'number', phone_number_10.number",
|
||||
" )",
|
||||
" FROM agreego.entity entity_9",
|
||||
" JOIN agreego.phone_number phone_number_10 ON phone_number_10.id = entity_9.id",
|
||||
" JOIN agreego.phone_number phone_number_10",
|
||||
" WHERE",
|
||||
" NOT entity_9.archived",
|
||||
" AND relationship_7.target_id = entity_9.id",
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_6",
|
||||
" JOIN agreego.relationship relationship_7 ON relationship_7.id = entity_6.id",
|
||||
" JOIN agreego.contact contact_8 ON contact_8.id = relationship_7.id",
|
||||
" JOIN agreego.relationship relationship_7",
|
||||
" JOIN agreego.contact contact_8",
|
||||
" WHERE",
|
||||
" NOT entity_6.archived",
|
||||
" AND relationship_7.target_type = 'phone_number'",
|
||||
@ -2079,15 +2079,15 @@
|
||||
" 'address', email_address_15.address",
|
||||
" )",
|
||||
" FROM agreego.entity entity_14",
|
||||
" JOIN agreego.email_address email_address_15 ON email_address_15.id = entity_14.id",
|
||||
" JOIN agreego.email_address email_address_15",
|
||||
" WHERE",
|
||||
" NOT entity_14.archived",
|
||||
" AND relationship_12.target_id = entity_14.id",
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_11",
|
||||
" JOIN agreego.relationship relationship_12 ON relationship_12.id = entity_11.id",
|
||||
" JOIN agreego.contact contact_13 ON contact_13.id = relationship_12.id",
|
||||
" JOIN agreego.relationship relationship_12",
|
||||
" JOIN agreego.contact contact_13",
|
||||
" WHERE",
|
||||
" NOT entity_11.archived",
|
||||
" AND relationship_12.target_type = 'email_address'",
|
||||
@ -2109,15 +2109,15 @@
|
||||
" 'city', address_20.city",
|
||||
" )",
|
||||
" FROM agreego.entity entity_19",
|
||||
" JOIN agreego.address address_20 ON address_20.id = entity_19.id",
|
||||
" JOIN agreego.address address_20",
|
||||
" WHERE",
|
||||
" NOT entity_19.archived",
|
||||
" AND relationship_17.target_id = entity_19.id",
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_16",
|
||||
" JOIN agreego.relationship relationship_17 ON relationship_17.id = entity_16.id",
|
||||
" JOIN agreego.contact contact_18 ON contact_18.id = relationship_17.id",
|
||||
" JOIN agreego.relationship relationship_17",
|
||||
" JOIN agreego.contact contact_18",
|
||||
" WHERE",
|
||||
" NOT entity_16.archived",
|
||||
" AND relationship_17.target_type = 'address'",
|
||||
@ -2140,7 +2140,7 @@
|
||||
" 'number', phone_number_25.number",
|
||||
" )",
|
||||
" FROM agreego.entity entity_24",
|
||||
" JOIN agreego.phone_number phone_number_25 ON phone_number_25.id = entity_24.id",
|
||||
" JOIN agreego.phone_number phone_number_25",
|
||||
" WHERE",
|
||||
" NOT entity_24.archived",
|
||||
" AND relationship_22.target_id = entity_24.id",
|
||||
@ -2154,7 +2154,7 @@
|
||||
" 'address', email_address_27.address",
|
||||
" )",
|
||||
" FROM agreego.entity entity_26",
|
||||
" JOIN agreego.email_address email_address_27 ON email_address_27.id = entity_26.id",
|
||||
" JOIN agreego.email_address email_address_27",
|
||||
" WHERE",
|
||||
" NOT entity_26.archived",
|
||||
" AND relationship_22.target_id = entity_26.id",
|
||||
@ -2168,7 +2168,7 @@
|
||||
" 'city', address_29.city",
|
||||
" )",
|
||||
" FROM agreego.entity entity_28",
|
||||
" JOIN agreego.address address_29 ON address_29.id = entity_28.id",
|
||||
" JOIN agreego.address address_29",
|
||||
" WHERE",
|
||||
" NOT entity_28.archived",
|
||||
" AND relationship_22.target_id = entity_28.id",
|
||||
@ -2177,16 +2177,16 @@
|
||||
" END",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_21",
|
||||
" JOIN agreego.relationship relationship_22 ON relationship_22.id = entity_21.id",
|
||||
" JOIN agreego.contact contact_23 ON contact_23.id = relationship_22.id",
|
||||
" JOIN agreego.relationship relationship_22",
|
||||
" JOIN agreego.contact contact_23",
|
||||
" WHERE",
|
||||
" NOT entity_21.archived",
|
||||
" AND relationship_22.source_id = entity_3.id",
|
||||
" )",
|
||||
" )",
|
||||
" FROM agreego.entity entity_3",
|
||||
" JOIN agreego.organization organization_4 ON organization_4.id = entity_3.id",
|
||||
" JOIN agreego.person person_5 ON person_5.id = organization_4.id",
|
||||
" JOIN agreego.organization organization_4",
|
||||
" JOIN agreego.person person_5",
|
||||
" WHERE",
|
||||
" NOT entity_3.archived",
|
||||
" AND entity_3.id = entity_1.id",
|
||||
@ -2194,7 +2194,7 @@
|
||||
" ELSE NULL",
|
||||
" END",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.organization organization_2 ON organization_2.id = entity_1.id",
|
||||
" JOIN agreego.organization organization_2",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
"))))"
|
||||
@ -2230,15 +2230,15 @@
|
||||
" 'age', person_5.age",
|
||||
" )",
|
||||
" FROM agreego.entity entity_3",
|
||||
" JOIN agreego.organization organization_4 ON organization_4.id = entity_3.id",
|
||||
" JOIN agreego.person person_5 ON person_5.id = organization_4.id",
|
||||
" JOIN agreego.organization organization_4",
|
||||
" JOIN agreego.person person_5",
|
||||
" WHERE",
|
||||
" NOT entity_3.archived",
|
||||
" AND order_2.customer_id = person_5.id",
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.order order_2 ON order_2.id = entity_1.id",
|
||||
" JOIN agreego.order order_2",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
"))))"
|
||||
@ -2273,7 +2273,7 @@
|
||||
" ELSE NULL",
|
||||
" END), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.widget widget_2 ON widget_2.id = entity_1.id",
|
||||
" JOIN agreego.widget widget_2",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
"))))"
|
||||
@ -2306,7 +2306,7 @@
|
||||
" 'price', invoice_line_4.price",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_3",
|
||||
" JOIN agreego.invoice_line invoice_line_4 ON invoice_line_4.id = entity_3.id",
|
||||
" JOIN agreego.invoice_line invoice_line_4",
|
||||
" WHERE",
|
||||
" NOT entity_3.archived",
|
||||
" AND invoice_line_4.invoice_id = invoice_2.id",
|
||||
@ -2317,7 +2317,7 @@
|
||||
" 'metadata_nested_lines', invoice_2.metadata_nested_lines",
|
||||
" )",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.invoice invoice_2 ON invoice_2.id = entity_1.id",
|
||||
" JOIN agreego.invoice invoice_2",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
"))))"
|
||||
@ -2344,7 +2344,7 @@
|
||||
" 'card_number', account_2.card_number",
|
||||
" )",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.account account_2 ON account_2.id = entity_1.id",
|
||||
" JOIN agreego.account account_2",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
"))))"
|
||||
@ -2381,8 +2381,8 @@
|
||||
" 'role', bot_7.role",
|
||||
" )",
|
||||
" FROM agreego.entity entity_5",
|
||||
" JOIN agreego.organization organization_6 ON organization_6.id = entity_5.id",
|
||||
" JOIN agreego.bot bot_7 ON bot_7.id = organization_6.id",
|
||||
" JOIN agreego.organization organization_6",
|
||||
" JOIN agreego.bot bot_7",
|
||||
" WHERE",
|
||||
" NOT entity_5.archived",
|
||||
" AND entity_5.id = entity_3.id",
|
||||
@ -2396,7 +2396,7 @@
|
||||
" 'name', organization_9.name",
|
||||
" )",
|
||||
" FROM agreego.entity entity_8",
|
||||
" JOIN agreego.organization organization_9 ON organization_9.id = entity_8.id",
|
||||
" JOIN agreego.organization organization_9",
|
||||
" WHERE",
|
||||
" NOT entity_8.archived",
|
||||
" AND entity_8.id = entity_3.id",
|
||||
@ -2413,8 +2413,8 @@
|
||||
" 'age', person_12.age",
|
||||
" )",
|
||||
" FROM agreego.entity entity_10",
|
||||
" JOIN agreego.organization organization_11 ON organization_11.id = entity_10.id",
|
||||
" JOIN agreego.person person_12 ON person_12.id = organization_11.id",
|
||||
" JOIN agreego.organization organization_11",
|
||||
" JOIN agreego.person person_12",
|
||||
" WHERE",
|
||||
" NOT entity_10.archived",
|
||||
" AND entity_10.id = entity_3.id",
|
||||
@ -2422,14 +2422,14 @@
|
||||
" ELSE NULL",
|
||||
" END",
|
||||
" FROM agreego.entity entity_3",
|
||||
" JOIN agreego.organization organization_4 ON organization_4.id = entity_3.id",
|
||||
" JOIN agreego.organization organization_4",
|
||||
" WHERE",
|
||||
" NOT entity_3.archived",
|
||||
" AND order_2.counterparty_id = entity_3.id",
|
||||
" )",
|
||||
" )), '[]'::jsonb)",
|
||||
" FROM agreego.entity entity_1",
|
||||
" JOIN agreego.order order_2 ON order_2.id = entity_1.id",
|
||||
" JOIN agreego.order order_2",
|
||||
" WHERE",
|
||||
" NOT entity_1.archived",
|
||||
" AND order_2.counterparty_type IN ('bot', 'organization', 'person')",
|
||||
|
||||
@ -316,536 +316,6 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_0_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[true, true] from items array is not valid",
|
||||
"data": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"schema_id": "uniqueItems_1_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_1_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "[true, true] from items array is not valid",
|
||||
"data": [
|
||||
true,
|
||||
true
|
||||
],
|
||||
"schema_id": "uniqueItems_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "UNIQUE_ITEMS_VIOLATED",
|
||||
"details": {
|
||||
"path": "",
|
||||
"schema": "uniqueItems_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "extra items are invalid even if unique",
|
||||
"data": [
|
||||
false,
|
||||
true,
|
||||
null
|
||||
],
|
||||
"schema_id": "uniqueItems_2_0",
|
||||
"action": "validate",
|
||||
"expect": {
|
||||
"success": false,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "2",
|
||||
"schema": "uniqueItems_2_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -1099,232 +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,
|
||||
"errors": [
|
||||
{
|
||||
"code": "FALSE_SCHEMA",
|
||||
"details": {
|
||||
"path": "2",
|
||||
"schema": "uniqueItems_5_0"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "extensible: true allows extra items in uniqueItems",
|
||||
"database": {
|
||||
|
||||
2
flows
2
flows
Submodule flows updated: 0d9bd8644e...89748a246e
@ -25,9 +25,9 @@ impl Schema {
|
||||
("identifier".to_string(), id.to_string()),
|
||||
])),
|
||||
details: ErrorDetails {
|
||||
path: Some(path.to_string()),
|
||||
schema: Some(root_id.to_string()),
|
||||
..Default::default()
|
||||
path: Some(path.to_string()),
|
||||
schema: Some(root_id.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
return;
|
||||
@ -84,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(
|
||||
@ -103,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");
|
||||
}
|
||||
@ -123,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");
|
||||
|
||||
@ -151,6 +151,7 @@ impl Schema {
|
||||
"number" => Some(vec!["number.condition".to_string()]),
|
||||
"boolean" => Some(vec!["boolean.condition".to_string()]),
|
||||
"object" => None, // Inline structures are ignored in Composed References
|
||||
"dict" => None, // Dynamic dictionary maps are ignored in Composed References
|
||||
"array" => {
|
||||
if let Some(items) = &schema.obj.items {
|
||||
return Self::resolve_filter_type(items, db);
|
||||
|
||||
@ -39,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
|
||||
@ -78,10 +66,10 @@ impl Schema {
|
||||
code: "MULTIPLE_INHERITANCE_PROHIBITED".to_string(),
|
||||
values: Some(HashMap::from([("types".to_string(), types.join(", "))])),
|
||||
details: ErrorDetails {
|
||||
path: Some(path.clone()),
|
||||
schema: Some(root_id.to_string()),
|
||||
..Default::default()
|
||||
}
|
||||
path: Some(path.clone()),
|
||||
schema: Some(root_id.to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -137,35 +125,21 @@ impl Schema {
|
||||
child.compile(db, root_id, format!("{}/{}", path, k), errors);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if let Some(child) = &self.obj.contains {
|
||||
child.compile(db, root_id, format!("{}/contains", path), errors);
|
||||
}
|
||||
|
||||
@ -81,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()) {
|
||||
@ -103,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());
|
||||
@ -119,7 +114,10 @@ fn resolve_in_place(
|
||||
if visited.contains(inc_name) {
|
||||
errors.push(Error {
|
||||
code: "CIRCULAR_INCLUDE_DETECTED".to_string(),
|
||||
values: Some(HashMap::from([("include".to_string(), inc_name.to_string())])),
|
||||
values: Some(HashMap::from([(
|
||||
"include".to_string(),
|
||||
inc_name.to_string(),
|
||||
)])),
|
||||
details: ErrorDetails {
|
||||
schema: Some(schema_id.to_string()),
|
||||
path: Some(path.to_string()),
|
||||
@ -156,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 {
|
||||
@ -218,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"
|
||||
@ -233,7 +218,10 @@ fn resolve_in_place(
|
||||
} else {
|
||||
errors.push(Error {
|
||||
code: "TRAIT_NOT_FOUND".to_string(),
|
||||
values: Some(HashMap::from([("include".to_string(), inc_name.to_string())])),
|
||||
values: Some(HashMap::from([(
|
||||
"include".to_string(),
|
||||
inc_name.to_string(),
|
||||
)])),
|
||||
details: ErrorDetails {
|
||||
schema: Some(schema_id.to_string()),
|
||||
path: Some(path.to_string()),
|
||||
@ -248,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()));
|
||||
@ -289,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,
|
||||
@ -316,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(
|
||||
|
||||
@ -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"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::database::action::Action;
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
#[serde(default)]
|
||||
@ -13,6 +14,11 @@ pub struct Page {
|
||||
pub sidebar: Option<Sidebar>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub actions: Option<IndexMap<String, Action>>,
|
||||
/// The personal-scope filter template ("one surface, two scopes"): the
|
||||
/// "mine" predicate the page merges into its filter when the app is in
|
||||
/// personal scope, e.g. {"reserved_by": "$me"}. Opaque to the engine.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub personal: Option<Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -744,9 +744,15 @@ impl Merger {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let where_clause = format!("WHERE {}", where_parts.join(" OR "));
|
||||
|
||||
let final_sql = format!("{} {}", fetch_sql_template, where_clause);
|
||||
let final_sql = if where_parts.len() == 1 {
|
||||
format!("{} WHERE {}", fetch_sql_template, where_parts[0])
|
||||
} else {
|
||||
where_parts
|
||||
.iter()
|
||||
.map(|p| format!("{} WHERE {}", fetch_sql_template, p))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" UNION ")
|
||||
};
|
||||
|
||||
let fetched = match self.db.query(&final_sql, None) {
|
||||
Ok(Value::Array(table)) => {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -179,14 +179,35 @@ impl SqlFormatter {
|
||||
}
|
||||
|
||||
fn format_query(&mut self, query: &Query) {
|
||||
match &*query.body {
|
||||
self.format_set_expr(&query.body);
|
||||
}
|
||||
|
||||
fn format_set_expr(&mut self, set_expr: &SetExpr) {
|
||||
match set_expr {
|
||||
SetExpr::Select(select) => self.format_select(select),
|
||||
SetExpr::Query(inner_query) => {
|
||||
self.push_str("(");
|
||||
self.format_query(inner_query);
|
||||
self.push_str(")");
|
||||
}
|
||||
_ => self.push_str(&query.to_string()),
|
||||
SetExpr::SetOperation { op, left, right, set_quantifier } => {
|
||||
self.format_set_expr(left);
|
||||
let op_str = match op {
|
||||
sqlparser::ast::SetOperator::Union => "UNION",
|
||||
sqlparser::ast::SetOperator::Intersect => "INTERSECT",
|
||||
sqlparser::ast::SetOperator::Except => "EXCEPT",
|
||||
_ => "UNION",
|
||||
};
|
||||
let quant_str = match set_quantifier {
|
||||
sqlparser::ast::SetQuantifier::All => " ALL",
|
||||
sqlparser::ast::SetQuantifier::Distinct => " DISTINCT",
|
||||
sqlparser::ast::SetQuantifier::None => "",
|
||||
_ => "",
|
||||
};
|
||||
self.push_line(&format!("{}{} ", op_str, quant_str));
|
||||
self.format_set_expr(right);
|
||||
}
|
||||
_ => self.push_str(&set_expr.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,20 +257,22 @@ impl SqlFormatter {
|
||||
}
|
||||
|
||||
fn format_join(&mut self, join: &Join) {
|
||||
let op = match &join.join_operator {
|
||||
let op_str = match &join.join_operator {
|
||||
JoinOperator::Inner(_) => "JOIN",
|
||||
JoinOperator::LeftOuter(_) => "LEFT JOIN",
|
||||
JoinOperator::Left(_) => "LEFT JOIN",
|
||||
JoinOperator::Right(_) => "RIGHT JOIN",
|
||||
_ => "JOIN",
|
||||
};
|
||||
self.push_str(&format!("{} {} ON ", op, join.relation));
|
||||
self.push_str(&format!("{} {}", op_str, join.relation));
|
||||
|
||||
match &join.join_operator {
|
||||
JoinOperator::Inner(JoinConstraint::On(expr)) => self.format_expr(expr),
|
||||
JoinOperator::LeftOuter(JoinConstraint::On(expr)) => self.format_expr(expr),
|
||||
JoinOperator::Join(JoinConstraint::On(expr)) => self.format_expr(expr),
|
||||
_ => {
|
||||
println!("FALLBACK JOIN OP: {:?}", join.join_operator);
|
||||
JoinOperator::Inner(JoinConstraint::On(expr))
|
||||
| JoinOperator::Left(JoinConstraint::On(expr))
|
||||
| JoinOperator::Right(JoinConstraint::On(expr)) => {
|
||||
self.push_str(" ON ");
|
||||
self.format_expr(expr);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -37,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,
|
||||
}
|
||||
|
||||
@ -99,42 +99,10 @@ impl<'a> ValidationContext<'a> {
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
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,5 +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;
|
||||
@ -16,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,
|
||||
@ -24,38 +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(),
|
||||
values: Some(HashMap::from([
|
||||
("property_name".to_string(), key.to_string()),
|
||||
])),
|
||||
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(),
|
||||
values: Some(HashMap::from([
|
||||
("index".to_string(), i.to_string()),
|
||||
])),
|
||||
path: item_path,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ 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;
|
||||
@ -43,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)? {
|
||||
|
||||
@ -211,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() {
|
||||
|
||||
@ -14,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()
|
||||
|
||||
@ -42,6 +42,7 @@ impl<'a> ValidationContext<'a> {
|
||||
code: "PATTERN_VIOLATED".to_string(),
|
||||
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(),
|
||||
});
|
||||
@ -54,6 +55,7 @@ impl<'a> ValidationContext<'a> {
|
||||
code: "PATTERN_VIOLATED".to_string(),
|
||||
values: Some(HashMap::from([
|
||||
("pattern".to_string(), pattern.to_string()),
|
||||
("value".to_string(), s.to_string()),
|
||||
])),
|
||||
path: self.path.to_string(),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user