Compare commits

..

26 Commits

Author SHA1 Message Date
9900b3fc43 version: 1.0.163 2026-06-23 17:48:11 -04:00
11d1f54bc8 Merge branch 'main' of gitea-ssh.thoughtpatterns.ai:cellular/jspg 2026-06-23 17:47:32 -04:00
b0377e076e drop error improvements across the board for localization 2026-06-23 17:47:19 -04:00
d77765cb61 jspg error refactoring checkpoint 2026-06-23 17:03:27 -04:00
10e388421d version: 1.0.162 2026-06-19 15:35:01 -04:00
7f666e0ece Revert "queryer: NULL-tolerant bound for optional single-family forward relations"
This reverts commit 94477b677d.
2026-06-19 15:34:24 -04:00
98a9719509 Revert "queryer: don't emit a parent type-bound for reified-relationship properties"
This reverts commit c97e5d75b3.
2026-06-19 15:34:23 -04:00
0509995589 version: 1.0.161 2026-06-19 11:08:52 -04:00
c97e5d75b3 queryer: don't emit a parent type-bound for reified-relationship properties
A SINGLE reified-relationship property (e.g. invoice.counterparty,
person.primary_contact — a property whose type is a relationship
subtype) is hydrated by a correlated subquery that joins the
relationship table and correlates source_id/target_id = parent.id; its
discriminators (the relationship subtype and the target's type CASE)
are constrained INSIDE that subquery.

For such a property the resolved edge is a REVERSE traversal
(forward = false) over a generic relationship FK
(fk_relationship_source_entity, destination = entity). compile_
polymorphic_bounds then took the `!edge.forward` branch with
poly_col = destination_columns[1] = "type" and
table_to_alias = "entity", which resolves to the PARENT's entity alias
— emitting a bound like `entity_1.type = 'counterparty'` into the
parent WHERE. No parent row has that type, so EVERY parent was dropped
(e.g. get_invoice returned null for an existing invoice whose
counterparty edge was absent).

Array reified traversals (contacts, occupancies) never hit this: an
array property has no bound_type_name. Only the single form did, and it
was previously unexercised.

Fix: in compile_polymorphic_bounds, skip the bound when the property's
resolved type is itself a relationship (type_def.relationship) — there
is no parent-row discriminator column to bound.

Test: new queryer case (person.primary_contact, type=contact) asserts
the parent WHERE has no spurious entity.type bound while the subquery
keeps its discriminator + source_id correlation. Full suite green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:03:13 -04:00
94477b677d queryer: NULL-tolerant bound for optional single-family forward relations
An OPTIONAL forward polymorphic relation declared via `family` (e.g.
order.counterparty / invoice.counterparty) had its auto-generated type
bound `{alias}.{disc} IN (variations)` emitted into the PARENT row's
WHERE. When the relation is absent (NULL discriminator) the parent row
was wrongly excluded — a counterparty-less order/invoice returned
nothing instead of the row with `counterparty: null`.

Fix: in `compile_polymorphic_bounds`, make the forward-FK bound
NULL-tolerant (`(… IN (…) OR …_type IS NULL)`), gated on
`!r#type.relationship`:
  - real entities get NULL-tolerance (the relation is an optional
    attribute; an absent one must not drop the row — the inner CASE
    already resolves it to NULL);
  - edge entities (`relationship == true`, e.g. `contact`) keep the
    bound EXACT, because there source_type/target_type *partition*
    typed sub-collections (phone_numbers vs email_addresses) and a NULL
    endpoint belongs to no partition.

Note: the `oneOf` path was already correct — it emits no parent bound
(resolves via CASE … ELSE NULL), so cross-family optional relations
already hydrate NULL-safely. Added a fixture case documenting that.

Tests (fixtures/queryer.json): case 15 (entity → NULL-tolerant),
cases 3/5/10 (contact edges → exact, unchanged), new case 16
(oneOf cross-family → no bound). Full suite green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 10:22:29 -04:00
fb25224d22 version: 1.0.160 2026-06-18 20:31:49 -04:00
01368305de fixed missing schema ids in validation results 2026-06-18 20:31:35 -04:00
9e362f2168 version: 1.0.159 2026-06-15 16:44:04 -04:00
9fffc7707f Merge branch 'main' of gitea-ssh.thoughtpatterns.ai:cellular/jspg 2026-06-15 16:42:13 -04:00
c5d652c6fd fixed merger ordering issue 2026-06-15 16:41:59 -04:00
d2cdd680ed insert fix checkpoint 2026-06-15 16:18:44 -04:00
6f1c0d7ee9 version: 1.0.158 2026-06-12 22:11:14 -04:00
25bbf2b564 merger: generate entity and changelog ids with uuid v7
Switch the two UUID generation sites in the merger from v4 to time-ordered
v7, and swap the uuid crate feature flag from v4 to v7 accordingly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 22:11:09 -04:00
c8cc4cbde8 version: 1.0.157 2026-06-11 20:40:36 -04:00
5af2399e3b fixed issue with filter generation where filters or conditions are used internally 2026-06-11 20:40:27 -04:00
1d56bae9a5 version: 1.0.156 2026-06-11 17:37:43 -04:00
813e9ff3c2 more executor reverts 2026-06-11 17:37:34 -04:00
7e28eb2645 added kind to merge notifications, re-instated sql pattern matching 2026-06-11 17:26:07 -04:00
5133283795 checkpoint for re-enabling SQL pattern matching 2026-06-11 15:25:21 -04:00
d41209e7c1 version: 1.0.155 2026-06-11 12:19:31 -04:00
03c60f5156 fix: remove trigger, origin and redundant type properties from notification payload 2026-06-11 12:19:25 -04:00
79 changed files with 10467 additions and 2019 deletions

View File

@ -16,7 +16,7 @@ url = "2.5.8"
fluent-uri = "0.3.2"
idna = "1.1.0"
percent-encoding = "2.3.2"
uuid = { version = "1.20.0", features = ["v4", "serde"] }
uuid = { version = "1.20.0", features = ["v7", "serde"] }
chrono = { version = "0.4.43", features = ["serde"] }
json-pointer = "0.3.4"
indexmap = { version = "2.13.0", features = ["serde"] }

View File

@ -175,6 +175,7 @@ In the Punc architecture, filters are automatically synthesized, strongly-typed
* **Conditions**: A condition schema is the contract defining the mathematical operations allowed on a primitive field. For example, a `string.condition` allows `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$of` (IN), and `$nof` (NOT IN).
* **Enum Conditions**: When JSPG synthesizes an enum, it dynamically generates an `<enum>.condition` (e.g., `address_kind.condition`). This strongly-typed condition perfectly mirrors the operations of a `string.condition`, but strictly limits the arrays and inputs of `$eq`, `$ne`, `$of`, and `$nof` to the exact variations defined by that Enum. This context ensures that UI generators know exactly when to render `<Select>` dropdowns instead of generic `<Text>` boxes.
* **Pre-compiled Condition and Filter Mapping**: To prevent redundant double-wrapping of search structures, any schema property whose type is already a `.condition` or `.filter` type (such as `"string.condition"` or `"$kind.filter"`) maps directly to itself during filter synthesis rather than receiving a redundant `.filter` suffix.
* **Filters**: A filter schema (e.g., `person.filter`) is an object containing condition properties used to filter entities. It natively supports structural composition:
* **Inherited Properties**: Filters automatically inherit all valid database columns from their base type schema, immediately converting them to their respective `.condition` schemas.
* **Relational Proxies**: If a table has a foreign key to another table, the filter automatically generates a proxy property pointing to the related entity's filter (e.g., the `person` filter automatically gains an `organization` property that points to `organization.filter`), allowing infinitely deep nested queries natively.

View File

@ -58,7 +58,19 @@
"schema_id": "schema1",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "boolean"
},
"details": {
"path": "is_active",
"schema": "schema1"
}
}
]
}
}
]
@ -108,7 +120,19 @@
"schema_id": "additionalProperties_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "count",
"schema": "additionalProperties_1_0"
}
}
]
}
}
]
@ -168,7 +192,29 @@
"schema_id": "schema3",
"action": "validate",
"expect": {
"success": false
"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"
}
}
]
}
},
{
@ -180,7 +226,19 @@
"schema_id": "schema3",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "array"
},
"details": {
"path": "group_a",
"schema": "schema3"
}
}
]
}
}
]

View File

@ -120,7 +120,16 @@
"schema_id": "booleanSchema_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "booleanSchema_1_0"
}
}
]
}
},
{
@ -129,7 +138,16 @@
"schema_id": "booleanSchema_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "booleanSchema_1_0"
}
}
]
}
},
{
@ -138,7 +156,16 @@
"schema_id": "booleanSchema_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "booleanSchema_1_0"
}
}
]
}
},
{
@ -147,7 +174,16 @@
"schema_id": "booleanSchema_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "booleanSchema_1_0"
}
}
]
}
},
{
@ -156,7 +192,16 @@
"schema_id": "booleanSchema_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "booleanSchema_1_0"
}
}
]
}
},
{
@ -167,7 +212,26 @@
"schema_id": "booleanSchema_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "booleanSchema_1_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "foo",
"schema": "booleanSchema_1_0"
}
}
]
}
},
{
@ -176,7 +240,16 @@
"schema_id": "booleanSchema_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "booleanSchema_1_0"
}
}
]
}
},
{
@ -187,7 +260,26 @@
"schema_id": "booleanSchema_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "booleanSchema_1_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "booleanSchema_1_0"
}
}
]
}
},
{
@ -196,7 +288,16 @@
"schema_id": "booleanSchema_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "booleanSchema_1_0"
}
}
]
}
}
]

View File

@ -277,20 +277,32 @@
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "amount_1"
},
"details": {
"path": "amount_1"
"path": "amount_1",
"schema": "parallel_rules"
}
},
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "amount_2"
},
"details": {
"path": "amount_2"
"path": "amount_2",
"schema": "parallel_rules"
}
},
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "cvv"
},
"details": {
"path": "cvv"
"path": "cvv",
"schema": "parallel_rules"
}
}
]
@ -309,8 +321,12 @@
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "cvv"
},
"details": {
"path": "cvv"
"path": "cvv",
"schema": "parallel_rules"
}
}
]
@ -362,8 +378,12 @@
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "unconditional"
},
"details": {
"path": "unconditional"
"path": "unconditional",
"schema": "missing_when"
}
}
]

View File

@ -29,7 +29,19 @@
"schema_id": "const_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(2)"
},
"details": {
"path": "",
"schema": "const_0_0"
}
}
]
}
},
{
@ -38,7 +50,19 @@
"schema_id": "const_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(2)"
},
"details": {
"path": "",
"schema": "const_0_0"
}
}
]
}
}
]
@ -97,7 +121,19 @@
"schema_id": "const_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Object {\"foo\": String(\"bar\"), \"baz\": String(\"bax\")}"
},
"details": {
"path": "",
"schema": "const_1_0"
}
}
]
}
},
{
@ -109,7 +145,39 @@
"schema_id": "const_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Object {\"foo\": String(\"bar\"), \"baz\": String(\"bax\")}"
},
"details": {
"path": "",
"schema": "const_1_0"
}
},
{
"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"
}
}
]
}
}
]
@ -154,7 +222,29 @@
"schema_id": "const_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Array [Object {\"foo\": String(\"bar\")}]"
},
"details": {
"path": "",
"schema": "const_2_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "const_2_0"
}
}
]
}
},
{
@ -167,7 +257,49 @@
"schema_id": "const_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Array [Object {\"foo\": String(\"bar\")}]"
},
"details": {
"path": "",
"schema": "const_2_0"
}
},
{
"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"
}
}
]
}
}
]
@ -202,7 +334,19 @@
"schema_id": "const_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Null"
},
"details": {
"path": "",
"schema": "const_3_0"
}
}
]
}
}
]
@ -237,7 +381,19 @@
"schema_id": "const_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Bool(false)"
},
"details": {
"path": "",
"schema": "const_4_0"
}
}
]
}
},
{
@ -246,7 +402,19 @@
"schema_id": "const_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Bool(false)"
},
"details": {
"path": "",
"schema": "const_4_0"
}
}
]
}
}
]
@ -281,7 +449,19 @@
"schema_id": "const_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Bool(true)"
},
"details": {
"path": "",
"schema": "const_5_0"
}
}
]
}
},
{
@ -290,7 +470,19 @@
"schema_id": "const_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Bool(true)"
},
"details": {
"path": "",
"schema": "const_5_0"
}
}
]
}
}
]
@ -331,7 +523,29 @@
"schema_id": "const_6_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Array [Bool(false)]"
},
"details": {
"path": "",
"schema": "const_6_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "const_6_0"
}
}
]
}
},
{
@ -342,7 +556,29 @@
"schema_id": "const_6_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Array [Bool(false)]"
},
"details": {
"path": "",
"schema": "const_6_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "const_6_0"
}
}
]
}
}
]
@ -383,7 +619,29 @@
"schema_id": "const_7_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Array [Bool(true)]"
},
"details": {
"path": "",
"schema": "const_7_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "const_7_0"
}
}
]
}
},
{
@ -394,7 +652,29 @@
"schema_id": "const_7_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Array [Bool(true)]"
},
"details": {
"path": "",
"schema": "const_7_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "const_7_0"
}
}
]
}
}
]
@ -435,7 +715,29 @@
"schema_id": "const_8_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Object {\"a\": Bool(false)}"
},
"details": {
"path": "",
"schema": "const_8_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "a"
},
"details": {
"path": "a",
"schema": "const_8_0"
}
}
]
}
},
{
@ -446,7 +748,29 @@
"schema_id": "const_8_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Object {\"a\": Bool(false)}"
},
"details": {
"path": "",
"schema": "const_8_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "a"
},
"details": {
"path": "a",
"schema": "const_8_0"
}
}
]
}
}
]
@ -487,7 +811,29 @@
"schema_id": "const_9_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Object {\"a\": Bool(true)}"
},
"details": {
"path": "",
"schema": "const_9_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "a"
},
"details": {
"path": "a",
"schema": "const_9_0"
}
}
]
}
},
{
@ -498,7 +844,29 @@
"schema_id": "const_9_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Object {\"a\": Bool(true)}"
},
"details": {
"path": "",
"schema": "const_9_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "a"
},
"details": {
"path": "a",
"schema": "const_9_0"
}
}
]
}
}
]
@ -524,7 +892,19 @@
"schema_id": "const_10_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(0)"
},
"details": {
"path": "",
"schema": "const_10_0"
}
}
]
}
},
{
@ -551,7 +931,19 @@
"schema_id": "const_10_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(0)"
},
"details": {
"path": "",
"schema": "const_10_0"
}
}
]
}
},
{
@ -560,7 +952,19 @@
"schema_id": "const_10_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(0)"
},
"details": {
"path": "",
"schema": "const_10_0"
}
}
]
}
},
{
@ -569,7 +973,19 @@
"schema_id": "const_10_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(0)"
},
"details": {
"path": "",
"schema": "const_10_0"
}
}
]
}
}
]
@ -595,7 +1011,19 @@
"schema_id": "const_11_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(1)"
},
"details": {
"path": "",
"schema": "const_11_0"
}
}
]
}
},
{
@ -648,7 +1076,19 @@
"schema_id": "const_12_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(-2)"
},
"details": {
"path": "",
"schema": "const_12_0"
}
}
]
}
},
{
@ -666,7 +1106,19 @@
"schema_id": "const_12_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(-2)"
},
"details": {
"path": "",
"schema": "const_12_0"
}
}
]
}
},
{
@ -675,7 +1127,19 @@
"schema_id": "const_12_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(-2)"
},
"details": {
"path": "",
"schema": "const_12_0"
}
}
]
}
}
]
@ -710,7 +1174,19 @@
"schema_id": "const_13_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(9007199254740992)"
},
"details": {
"path": "",
"schema": "const_13_0"
}
}
]
}
},
{
@ -728,7 +1204,19 @@
"schema_id": "const_13_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Number(9007199254740992)"
},
"details": {
"path": "",
"schema": "const_13_0"
}
}
]
}
}
]
@ -763,7 +1251,19 @@
"schema_id": "const_14_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "String(\"hello\\0there\")"
},
"details": {
"path": "",
"schema": "const_14_0"
}
}
]
}
}
]
@ -776,7 +1276,7 @@
"name": "const_15_0",
"schemas": {
"const_15_0": {
"const": "\u03bc",
"const": "μ",
"$comment": "U+03BC"
}
}
@ -786,7 +1286,7 @@
"tests": [
{
"description": "character uses the same codepoint",
"data": "\u03bc",
"data": "μ",
"comment": "U+03BC",
"schema_id": "const_15_0",
"action": "validate",
@ -796,12 +1296,24 @@
},
{
"description": "character looks the same but uses a different codepoint",
"data": "\u00b5",
"data": "µ",
"comment": "U+00B5",
"schema_id": "const_15_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "String(\"μ\")"
},
"details": {
"path": "",
"schema": "const_15_0"
}
}
]
}
}
]
@ -814,7 +1326,7 @@
"name": "const_16_0",
"schemas": {
"const_16_0": {
"const": "\u00e4",
"const": "ä",
"$comment": "U+00E4"
}
}
@ -824,7 +1336,7 @@
"tests": [
{
"description": "character uses the same codepoint",
"data": "\u00e4",
"data": "ä",
"comment": "U+00E4",
"schema_id": "const_16_0",
"action": "validate",
@ -834,12 +1346,24 @@
},
{
"description": "character looks the same but uses combining marks",
"data": "a\u0308",
"data": "ä",
"comment": "a, U+0308",
"schema_id": "const_16_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "String(\"ä\")"
},
"details": {
"path": "",
"schema": "const_16_0"
}
}
]
}
}
]
@ -871,7 +1395,19 @@
"schema_id": "const_17_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "Object {\"a\": Number(1)}"
},
"details": {
"path": "",
"schema": "const_17_0"
}
}
]
}
},
{

View File

@ -67,7 +67,20 @@
"schema_id": "contains_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "1",
"count": "0"
},
"details": {
"path": "",
"schema": "contains_0_0"
}
}
]
}
},
{
@ -76,7 +89,20 @@
"schema_id": "contains_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "0",
"limit": "1"
},
"details": {
"path": "",
"schema": "contains_0_0"
}
}
]
}
},
{
@ -146,7 +172,20 @@
"schema_id": "contains_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "0",
"limit": "1"
},
"details": {
"path": "",
"schema": "contains_1_0"
}
}
]
}
}
]
@ -183,7 +222,20 @@
"schema_id": "contains_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "1",
"count": "0"
},
"details": {
"path": "",
"schema": "contains_2_0"
}
}
]
}
}
]
@ -211,7 +263,30 @@
"schema_id": "contains_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "0",
"limit": "1"
},
"details": {
"path": "",
"schema": "contains_3_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "contains_3_0"
}
}
]
}
},
{
@ -220,7 +295,20 @@
"schema_id": "contains_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "0",
"limit": "1"
},
"details": {
"path": "",
"schema": "contains_3_0"
}
}
]
}
},
{
@ -264,7 +352,20 @@
"schema_id": "contains_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "1",
"count": "0"
},
"details": {
"path": "",
"schema": "contains_4_0"
}
}
]
}
},
{
@ -277,7 +378,31 @@
"schema_id": "contains_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MULTIPLE_OF_VIOLATED",
"values": {
"value": "3",
"multiple_of": "2"
},
"details": {
"path": "0",
"schema": "contains_4_0"
}
},
{
"code": "MULTIPLE_OF_VIOLATED",
"values": {
"multiple_of": "2",
"value": "9"
},
"details": {
"path": "2",
"schema": "contains_4_0"
}
}
]
}
},
{
@ -301,7 +426,42 @@
"schema_id": "contains_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "1",
"count": "0"
},
"details": {
"path": "",
"schema": "contains_4_0"
}
},
{
"code": "MULTIPLE_OF_VIOLATED",
"values": {
"multiple_of": "2",
"value": "1"
},
"details": {
"path": "0",
"schema": "contains_4_0"
}
},
{
"code": "MULTIPLE_OF_VIOLATED",
"values": {
"multiple_of": "2",
"value": "5"
},
"details": {
"path": "1",
"schema": "contains_4_0"
}
}
]
}
}
]
@ -341,7 +501,20 @@
"schema_id": "contains_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "0",
"limit": "1"
},
"details": {
"path": "",
"schema": "contains_5_0"
}
}
]
}
}
]
@ -434,7 +607,19 @@
"schema_id": "contains_8_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "1"
},
"details": {
"path": "1",
"schema": "contains_8_0"
}
}
]
}
},
{

View File

@ -59,7 +59,16 @@
"success": false,
"errors": [
{
"code": "EDGE_MISSING"
"code": "EDGE_MISSING",
"values": {
"parent_type": "org",
"child_type": "user",
"property_name": "missing_users"
},
"details": {
"path": "full.org/missing_users",
"schema": "full.org"
}
}
]
}
@ -140,7 +149,16 @@
"success": false,
"errors": [
{
"code": "EDGE_MISSING"
"code": "EDGE_MISSING",
"values": {
"child_type": "child",
"property_name": "children",
"parent_type": "parent"
},
"details": {
"path": "full.parent/children",
"schema": "full.parent"
}
}
]
}
@ -235,16 +253,45 @@
"errors": [
{
"code": "AMBIGUOUS_TYPE_RELATIONS",
"values": {
"child_type": "activity",
"property_name": "activities",
"parent_type": "invoice"
},
"details": {
"path": "full.invoice/activities",
"cause": "Multiple conflicting constraints found matching prefixes",
"context": [
{
"constraint": "fk_activity_invoice_1"
"id": "33333333-3333-3333-3333-333333333333",
"type": "relation",
"constraint": "fk_activity_invoice_1",
"source_type": "activity",
"source_columns": [
"invoice_id_1"
],
"destination_type": "invoice",
"destination_columns": [
"id"
],
"prefix": null
},
{
"constraint": "fk_activity_invoice_2"
"id": "44444444-4444-4444-4444-444444444444",
"type": "relation",
"constraint": "fk_activity_invoice_2",
"source_type": "activity",
"source_columns": [
"invoice_id_2"
],
"destination_type": "invoice",
"destination_columns": [
"id"
],
"prefix": null
}
]
],
"schema": "full.invoice"
}
}
]
@ -342,16 +389,45 @@
"errors": [
{
"code": "AMBIGUOUS_TYPE_RELATIONS",
"values": {
"parent_type": "actor",
"child_type": "junction",
"property_name": "ambiguous_edge"
},
"details": {
"path": "full.actor/ambiguous_edge",
"cause": "Multiple conflicting constraints found matching prefixes",
"context": [
{
"constraint": "fk_junction_source_actor"
"id": "33333333-3333-3333-3333-333333333333",
"type": "relation",
"constraint": "fk_junction_source_actor",
"source_type": "junction",
"source_columns": [
"source_id"
],
"destination_type": "actor",
"destination_columns": [
"id"
],
"prefix": "source"
},
{
"constraint": "fk_junction_target_actor"
"id": "44444444-4444-4444-4444-444444444444",
"type": "relation",
"constraint": "fk_junction_target_actor",
"source_type": "junction",
"source_columns": [
"target_id"
],
"destination_type": "actor",
"destination_columns": [
"id"
],
"prefix": "target"
}
]
],
"schema": "full.actor"
}
}
]
@ -392,7 +468,14 @@
"success": false,
"errors": [
{
"code": "DATABASE_TYPE_PARSE_FAILED"
"code": "DATABASE_TYPE_PARSE_FAILED",
"values": {
"type": "failure",
"reason": "invalid type: sequence, expected a string"
},
"details": {
"context": "failure"
}
}
]
}
@ -791,8 +874,8 @@
}
},
"hierarchy": [
"invoice",
"entity"
"entity",
"invoice"
],
"fields": [
"id",
@ -867,8 +950,8 @@
}
},
"hierarchy": [
"invoice_line",
"entity"
"entity",
"invoice_line"
],
"fields": [
"id",

View File

@ -60,7 +60,20 @@
"schema_id": "schema1",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "DEPENDENCY_MISSING",
"values": {
"required_property": "foo",
"property_name": "bar"
},
"details": {
"path": "",
"schema": "schema1"
}
}
]
}
},
{
@ -209,7 +222,20 @@
"schema_id": "schema3",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "DEPENDENCY_MISSING",
"values": {
"property_name": "quux",
"required_property": "bar"
},
"details": {
"path": "",
"schema": "schema3"
}
}
]
}
},
{
@ -221,7 +247,20 @@
"schema_id": "schema3",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "DEPENDENCY_MISSING",
"values": {
"property_name": "quux",
"required_property": "foo"
},
"details": {
"path": "",
"schema": "schema3"
}
}
]
}
},
{
@ -232,7 +271,31 @@
"schema_id": "schema3",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "DEPENDENCY_MISSING",
"values": {
"property_name": "quux",
"required_property": "foo"
},
"details": {
"path": "",
"schema": "schema3"
}
},
{
"code": "DEPENDENCY_MISSING",
"values": {
"property_name": "quux",
"required_property": "bar"
},
"details": {
"path": "",
"schema": "schema3"
}
}
]
}
}
]
@ -294,7 +357,20 @@
"schema_id": "schema4",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "DEPENDENCY_MISSING",
"values": {
"required_property": "foo\rbar",
"property_name": "foo\nbar"
},
"details": {
"path": "",
"schema": "schema4"
}
}
]
}
},
{
@ -305,7 +381,20 @@
"schema_id": "schema4",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "DEPENDENCY_MISSING",
"values": {
"required_property": "foo'bar",
"property_name": "foo\"bar"
},
"details": {
"path": "",
"schema": "schema4"
}
}
]
}
}
]
@ -409,7 +498,19 @@
"schema_id": "schema_schema1",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "foo",
"schema": "schema_schema1"
}
}
]
}
},
{
@ -421,7 +522,19 @@
"schema_id": "schema_schema1",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "bar",
"schema": "schema_schema1"
}
}
]
}
},
{
@ -433,7 +546,29 @@
"schema_id": "schema_schema1",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "foo",
"schema": "schema_schema1"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "bar",
"schema": "schema_schema1"
}
}
]
}
},
{
@ -447,7 +582,14 @@
"success": false,
"errors": [
{
"code": "STRICT_ITEM_VIOLATION"
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "schema_schema1"
}
}
]
}
@ -559,7 +701,16 @@
"schema_id": "schema_schema3",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "",
"schema": "schema_schema3"
}
}
]
}
},
{
@ -571,7 +722,16 @@
"schema_id": "schema_schema3",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "",
"schema": "schema_schema3"
}
}
]
}
},
{
@ -642,7 +802,29 @@
"schema_id": "schema_schema4",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "foo\"bar"
},
"details": {
"path": "foo\"bar",
"schema": "schema_schema4"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo'bar"
},
"details": {
"path": "foo'bar",
"schema": "schema_schema4"
}
}
]
}
},
{
@ -654,7 +836,20 @@
"schema_id": "schema_schema4",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MIN_PROPERTIES_VIOLATED",
"values": {
"count": "2",
"limit": "4"
},
"details": {
"path": "",
"schema": "schema_schema4"
}
}
]
}
},
{
@ -665,7 +860,29 @@
"schema_id": "schema_schema4",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "foo\"bar"
},
"details": {
"path": "foo\"bar",
"schema": "schema_schema4"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo'bar"
},
"details": {
"path": "foo'bar",
"schema": "schema_schema4"
}
}
]
}
}
]
@ -704,7 +921,19 @@
"schema_id": "schema_schema5",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "foo",
"schema": "schema_schema5"
}
}
]
}
},
{
@ -718,7 +947,14 @@
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION"
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "bar"
},
"details": {
"path": "bar",
"schema": "schema_schema5"
}
}
]
}
@ -732,7 +968,19 @@
"schema_id": "schema_schema5",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "foo",
"schema": "schema_schema5"
}
}
]
}
},
{

View File

@ -41,9 +41,15 @@
"conditions": {
"type": "object",
"properties": {
"new": { "type": "$kind.filter" },
"old": { "type": "$kind.filter" },
"complete": { "type": "$kind.filter" }
"new": {
"type": "$kind.filter"
},
"old": {
"type": "$kind.filter"
},
"complete": {
"type": "$kind.filter"
}
}
}
}
@ -82,8 +88,12 @@
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "filter/age"
"path": "filter/age",
"schema": "search"
}
}
]
@ -118,14 +128,22 @@
"errors": [
{
"code": "DYNAMIC_TYPE_RESOLUTION_FAILED",
"values": {
"pointer": "unknown.filter"
},
"details": {
"path": "filter"
"path": "filter",
"schema": "search"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "weight"
},
"details": {
"path": "filter/weight"
"path": "filter/weight",
"schema": "search"
}
}
]
@ -145,14 +163,23 @@
"errors": [
{
"code": "DYNAMIC_TYPE_RESOLUTION_FAILED",
"values": {
"discriminator": "kind",
"pointer": "$kind.filter"
},
"details": {
"path": "filter"
"path": "filter",
"schema": "search"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "weight"
},
"details": {
"path": "filter/weight"
"path": "filter/weight",
"schema": "search"
}
}
]
@ -191,8 +218,12 @@
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "conditions/new/age"
"path": "conditions/new/age",
"schema": "search"
}
}
]
@ -200,5 +231,4 @@
}
]
}
]
]

View File

@ -146,8 +146,12 @@
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "String(\"value\")"
},
"details": {
"path": "con"
"path": "con",
"schema": "emptyString_0_0"
}
}
]

View File

@ -33,7 +33,19 @@
"schema_id": "enum_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Number(1), Number(2), Number(3)]"
},
"details": {
"path": "",
"schema": "enum_0_0"
}
}
]
}
}
]
@ -79,7 +91,19 @@
"schema_id": "enum_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Number(6), String(\"foo\"), Array [], Bool(true), Object {\"foo\": Number(12)}]"
},
"details": {
"path": "",
"schema": "enum_1_0"
}
}
]
}
},
{
@ -90,7 +114,19 @@
"schema_id": "enum_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Number(6), String(\"foo\"), Array [], Bool(true), Object {\"foo\": Number(12)}]"
},
"details": {
"path": "",
"schema": "enum_1_0"
}
}
]
}
},
{
@ -113,7 +149,29 @@
"schema_id": "enum_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Number(6), String(\"foo\"), Array [], Bool(true), Object {\"foo\": Number(12)}]"
},
"details": {
"path": "",
"schema": "enum_1_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "boo"
},
"details": {
"path": "boo",
"schema": "enum_1_0"
}
}
]
}
}
]
@ -160,7 +218,19 @@
"schema_id": "enum_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Number(6), Null]"
},
"details": {
"path": "",
"schema": "enum_2_0"
}
}
]
}
}
]
@ -216,7 +286,19 @@
"schema_id": "enum_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[String(\"foo\")]"
},
"details": {
"path": "foo",
"schema": "enum_3_0"
}
}
]
}
},
{
@ -228,7 +310,19 @@
"schema_id": "enum_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[String(\"bar\")]"
},
"details": {
"path": "bar",
"schema": "enum_3_0"
}
}
]
}
},
{
@ -250,7 +344,19 @@
"schema_id": "enum_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "bar"
},
"details": {
"path": "bar",
"schema": "enum_3_0"
}
}
]
}
},
{
@ -259,7 +365,19 @@
"schema_id": "enum_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "bar"
},
"details": {
"path": "bar",
"schema": "enum_3_0"
}
}
]
}
}
]
@ -306,7 +424,19 @@
"schema_id": "enum_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[String(\"foo\\nbar\"), String(\"foo\\rbar\")]"
},
"details": {
"path": "",
"schema": "enum_4_0"
}
}
]
}
}
]
@ -343,7 +473,19 @@
"schema_id": "enum_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Bool(false)]"
},
"details": {
"path": "",
"schema": "enum_5_0"
}
}
]
}
},
{
@ -352,7 +494,19 @@
"schema_id": "enum_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Bool(false)]"
},
"details": {
"path": "",
"schema": "enum_5_0"
}
}
]
}
}
]
@ -395,7 +549,29 @@
"schema_id": "enum_6_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Array [Bool(false)]]"
},
"details": {
"path": "",
"schema": "enum_6_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "enum_6_0"
}
}
]
}
},
{
@ -406,7 +582,29 @@
"schema_id": "enum_6_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Array [Bool(false)]]"
},
"details": {
"path": "",
"schema": "enum_6_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "enum_6_0"
}
}
]
}
}
]
@ -443,7 +641,19 @@
"schema_id": "enum_7_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Bool(true)]"
},
"details": {
"path": "",
"schema": "enum_7_0"
}
}
]
}
},
{
@ -452,7 +662,19 @@
"schema_id": "enum_7_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Bool(true)]"
},
"details": {
"path": "",
"schema": "enum_7_0"
}
}
]
}
}
]
@ -495,7 +717,29 @@
"schema_id": "enum_8_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Array [Bool(true)]]"
},
"details": {
"path": "",
"schema": "enum_8_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "enum_8_0"
}
}
]
}
},
{
@ -506,7 +750,29 @@
"schema_id": "enum_8_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Array [Bool(true)]]"
},
"details": {
"path": "",
"schema": "enum_8_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "enum_8_0"
}
}
]
}
}
]
@ -534,7 +800,19 @@
"schema_id": "enum_9_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Number(0)]"
},
"details": {
"path": "",
"schema": "enum_9_0"
}
}
]
}
},
{
@ -584,7 +862,29 @@
"schema_id": "enum_10_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Array [Number(0)]]"
},
"details": {
"path": "",
"schema": "enum_10_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "enum_10_0"
}
}
]
}
},
{
@ -634,7 +934,19 @@
"schema_id": "enum_11_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Number(1)]"
},
"details": {
"path": "",
"schema": "enum_11_0"
}
}
]
}
},
{
@ -684,7 +996,29 @@
"schema_id": "enum_12_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Array [Number(1)]]"
},
"details": {
"path": "",
"schema": "enum_12_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "enum_12_0"
}
}
]
}
},
{
@ -743,7 +1077,19 @@
"schema_id": "enum_13_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[String(\"hello\\0there\")]"
},
"details": {
"path": "",
"schema": "enum_13_0"
}
}
]
}
}
]
@ -777,7 +1123,19 @@
"schema_id": "enum_14_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[Object {\"foo\": Number(1)}]"
},
"details": {
"path": "",
"schema": "enum_14_0"
}
}
]
}
},
{

View File

@ -29,7 +29,20 @@
"schema_id": "exclusiveMaximum_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "EXCLUSIVE_MAXIMUM_VIOLATED",
"values": {
"value": "3",
"limit": "3"
},
"details": {
"path": "",
"schema": "exclusiveMaximum_0_0"
}
}
]
}
},
{
@ -38,7 +51,20 @@
"schema_id": "exclusiveMaximum_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "EXCLUSIVE_MAXIMUM_VIOLATED",
"values": {
"value": "3.5",
"limit": "3"
},
"details": {
"path": "",
"schema": "exclusiveMaximum_0_0"
}
}
]
}
},
{

View File

@ -29,7 +29,20 @@
"schema_id": "exclusiveMinimum_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "EXCLUSIVE_MINIMUM_VIOLATED",
"values": {
"value": "1.1",
"limit": "1.1"
},
"details": {
"path": "",
"schema": "exclusiveMinimum_0_0"
}
}
]
}
},
{
@ -38,7 +51,20 @@
"schema_id": "exclusiveMinimum_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "EXCLUSIVE_MINIMUM_VIOLATED",
"values": {
"limit": "1.1",
"value": "0.6"
},
"details": {
"path": "",
"schema": "exclusiveMinimum_0_0"
}
}
]
}
},
{

View File

@ -466,7 +466,7 @@
},
"filter": {
"type": [
"$kind.filter.filter",
"$kind.filter",
"null"
]
},

File diff suppressed because it is too large Load Diff

View File

@ -110,8 +110,8 @@
}
},
"hierarchy": [
"activity",
"entity"
"entity",
"activity"
],
"variations": [
"activity",
@ -166,9 +166,9 @@
}
},
"hierarchy": [
"invoice",
"entity",
"activity",
"entity"
"invoice"
],
"variations": [
"invoice"
@ -237,8 +237,8 @@
}
},
"hierarchy": [
"attachment",
"entity"
"entity",
"attachment"
],
"variations": [
"attachment"

View File

@ -38,7 +38,19 @@
"schema_id": "items_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "1",
"schema": "items_0_0"
}
}
]
}
},
{
@ -49,7 +61,19 @@
"schema_id": "items_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "foo",
"schema": "items_0_0"
}
}
]
}
},
{
@ -61,7 +85,29 @@
"schema_id": "items_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "0"
},
"details": {
"path": "0",
"schema": "items_0_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "length"
},
"details": {
"path": "length",
"schema": "items_0_0"
}
}
]
}
}
]
@ -130,7 +176,30 @@
"schema_id": "items_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "0",
"schema": "items_2_0"
}
},
{
"code": "FALSE_SCHEMA",
"details": {
"path": "1",
"schema": "items_2_0"
}
},
{
"code": "FALSE_SCHEMA",
"details": {
"path": "2",
"schema": "items_2_0"
}
}
]
}
},
{
@ -230,7 +299,69 @@
"schema_id": "items_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "0/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "0/1/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "1/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "1/1/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "2/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "2/1/foo",
"schema": "items_3_0"
}
}
]
}
},
{
@ -272,7 +403,76 @@
"schema_id": "items_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "0/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "0/1/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "1/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "1/1/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "2/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "2/1/foo",
"schema": "items_3_0"
}
},
{
"code": "FALSE_SCHEMA",
"details": {
"path": "3",
"schema": "items_3_0"
}
}
]
}
},
{
@ -309,7 +509,76 @@
"schema_id": "items_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "0/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "0/1/foo",
"schema": "items_3_0"
}
},
{
"code": "FALSE_SCHEMA",
"details": {
"path": "0/2",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "1/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "1/1/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "2/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "2/1/foo",
"schema": "items_3_0"
}
}
]
}
},
{
@ -338,7 +607,69 @@
"schema_id": "items_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "array"
},
"details": {
"path": "0",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "1/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "1/1/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "2/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "2/1/foo",
"schema": "items_3_0"
}
}
]
}
},
{
@ -370,7 +701,69 @@
"schema_id": "items_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "foo"
},
"details": {
"path": "0/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "0/1/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "1/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "1/1/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "2/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "2/1/foo",
"schema": "items_3_0"
}
}
]
}
},
{
@ -390,7 +783,29 @@
"schema_id": "items_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "0/0/foo",
"schema": "items_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "1/0/foo",
"schema": "items_3_0"
}
}
]
}
}
]
@ -495,7 +910,19 @@
"schema_id": "items_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "number"
},
"details": {
"path": "0/0/0/0",
"schema": "items_4_0"
}
}
]
}
},
{
@ -527,7 +954,69 @@
"schema_id": "items_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "array"
},
"details": {
"path": "0/0/0",
"schema": "items_4_0"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "array"
},
"details": {
"path": "0/1/0",
"schema": "items_4_0"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "array"
},
"details": {
"path": "0/2/0",
"schema": "items_4_0"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "array"
},
"details": {
"path": "1/0/0",
"schema": "items_4_0"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "array"
},
"details": {
"path": "1/1/0",
"schema": "items_4_0"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "array"
},
"details": {
"path": "1/2/0",
"schema": "items_4_0"
}
}
]
}
}
]
@ -608,7 +1097,16 @@
"schema_id": "items_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "3",
"schema": "items_5_0"
}
}
]
}
}
]
@ -648,7 +1146,20 @@
"schema_id": "items_6_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MINIMUM_VIOLATED",
"values": {
"limit": "5",
"value": "3"
},
"details": {
"path": "0",
"schema": "items_6_0"
}
}
]
}
},
{
@ -709,7 +1220,19 @@
"schema_id": "items_7_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "1",
"schema": "items_7_0"
}
}
]
}
}
]
@ -742,7 +1265,23 @@
"schema_id": "items_8_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "1",
"schema": "items_8_0"
}
},
{
"code": "FALSE_SCHEMA",
"details": {
"path": "2",
"schema": "items_8_0"
}
}
]
}
},
{
@ -812,7 +1351,16 @@
"schema_id": "items_10_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "0",
"schema": "items_10_0"
}
}
]
}
}
]
@ -855,7 +1403,20 @@
"schema_id": "items_11_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MINIMUM_VIOLATED",
"values": {
"limit": "5",
"value": "4"
},
"details": {
"path": "0",
"schema": "items_11_0"
}
}
]
}
}
]
@ -932,7 +1493,19 @@
"schema_id": "items_13_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "items_13_0"
}
}
]
}
}
]
@ -1030,7 +1603,19 @@
"schema_id": "items_15_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "extra"
},
"details": {
"path": "0/extra",
"schema": "items_15_0"
}
}
]
}
}
]

View File

@ -65,7 +65,20 @@
"schema_id": "maxContains_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "0",
"limit": "1"
},
"details": {
"path": "",
"schema": "maxContains_1_0"
}
}
]
}
},
{
@ -88,7 +101,20 @@
"schema_id": "maxContains_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "2",
"limit": "1"
},
"details": {
"path": "",
"schema": "maxContains_1_0"
}
}
]
}
},
{
@ -113,7 +139,20 @@
"schema_id": "maxContains_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "2",
"limit": "1"
},
"details": {
"path": "",
"schema": "maxContains_1_0"
}
}
]
}
}
]
@ -157,7 +196,20 @@
"schema_id": "maxContains_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "2",
"limit": "1"
},
"details": {
"path": "",
"schema": "maxContains_2_0"
}
}
]
}
}
]
@ -188,7 +240,20 @@
"schema_id": "maxContains_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "0",
"limit": "1"
},
"details": {
"path": "",
"schema": "maxContains_3_0"
}
}
]
}
},
{
@ -214,7 +279,20 @@
"schema_id": "maxContains_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "4",
"limit": "3"
},
"details": {
"path": "",
"schema": "maxContains_3_0"
}
}
]
}
}
]

View File

@ -48,7 +48,20 @@
"schema_id": "maxItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAX_ITEMS_VIOLATED",
"values": {
"count": "3",
"limit": "2"
},
"details": {
"path": "",
"schema": "maxItems_0_0"
}
}
]
}
},
{
@ -99,7 +112,20 @@
"schema_id": "maxItems_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAX_ITEMS_VIOLATED",
"values": {
"limit": "2",
"count": "3"
},
"details": {
"path": "",
"schema": "maxItems_1_0"
}
}
]
}
}
]
@ -130,7 +156,20 @@
"schema_id": "maxItems_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAX_ITEMS_VIOLATED",
"values": {
"limit": "2",
"count": "3"
},
"details": {
"path": "",
"schema": "maxItems_2_0"
}
}
]
}
}
]

View File

@ -38,7 +38,20 @@
"schema_id": "maxLength_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAX_LENGTH_VIOLATED",
"values": {
"count": "3",
"limit": "2"
},
"details": {
"path": "",
"schema": "maxLength_0_0"
}
}
]
}
},
{
@ -52,7 +65,7 @@
},
{
"description": "two graphemes is long enough",
"data": "\ud83d\udca9\ud83d\udca9",
"data": "💩💩",
"schema_id": "maxLength_0_0",
"action": "validate",
"expect": {
@ -91,7 +104,20 @@
"schema_id": "maxLength_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAX_LENGTH_VIOLATED",
"values": {
"count": "3",
"limit": "2"
},
"details": {
"path": "",
"schema": "maxLength_1_0"
}
}
]
}
}
]

View File

@ -48,7 +48,20 @@
"schema_id": "maxProperties_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAX_PROPERTIES_VIOLATED",
"values": {
"count": "3",
"limit": "2"
},
"details": {
"path": "",
"schema": "maxProperties_0_0"
}
}
]
}
},
{
@ -121,7 +134,20 @@
"schema_id": "maxProperties_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAX_PROPERTIES_VIOLATED",
"values": {
"count": "3",
"limit": "2"
},
"details": {
"path": "",
"schema": "maxProperties_1_0"
}
}
]
}
}
]
@ -159,7 +185,20 @@
"schema_id": "maxProperties_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAX_PROPERTIES_VIOLATED",
"values": {
"count": "1",
"limit": "0"
},
"details": {
"path": "",
"schema": "maxProperties_2_0"
}
}
]
}
}
]
@ -190,7 +229,20 @@
"schema_id": "maxProperties_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAX_PROPERTIES_VIOLATED",
"values": {
"limit": "2",
"count": "3"
},
"details": {
"path": "",
"schema": "maxProperties_3_0"
}
}
]
}
},
{

View File

@ -38,7 +38,20 @@
"schema_id": "maximum_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAXIMUM_VIOLATED",
"values": {
"value": "3.5",
"limit": "3"
},
"details": {
"path": "",
"schema": "maximum_0_0"
}
}
]
}
},
{
@ -100,7 +113,20 @@
"schema_id": "maximum_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAXIMUM_VIOLATED",
"values": {
"value": "300.5",
"limit": "300"
},
"details": {
"path": "",
"schema": "maximum_1_0"
}
}
]
}
}
]

View File

@ -56,8 +56,12 @@
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "string"
},
"details": {
"path": "base_prop"
"path": "base_prop",
"schema": "merge_0_0"
}
}
]
@ -127,8 +131,12 @@
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "a"
},
"details": {
"path": "a"
"path": "a",
"schema": "merge_1_0"
}
}
]
@ -146,8 +154,12 @@
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "b"
},
"details": {
"path": "b"
"path": "b",
"schema": "merge_1_0"
}
}
]
@ -226,8 +238,13 @@
"errors": [
{
"code": "DEPENDENCY_MISSING",
"values": {
"property_name": "trigger",
"required_property": "base_dep"
},
"details": {
"path": ""
"path": "",
"schema": "merge_2_0"
}
}
]
@ -246,8 +263,13 @@
"errors": [
{
"code": "DEPENDENCY_MISSING",
"values": {
"required_property": "child_dep",
"property_name": "trigger"
},
"details": {
"path": ""
"path": "",
"schema": "merge_2_0"
}
}
]

View File

@ -219,8 +219,8 @@
}
},
"hierarchy": [
"organization",
"entity"
"entity",
"organization"
],
"fields": [
"id",
@ -262,9 +262,9 @@
}
},
"hierarchy": [
"user",
"entity",
"organization",
"entity"
"user"
],
"fields": [
"id",
@ -359,10 +359,10 @@
}
},
"hierarchy": [
"person",
"user",
"entity",
"organization",
"entity"
"user",
"person"
],
"fields": [
"id",
@ -445,8 +445,8 @@
}
},
"hierarchy": [
"order",
"entity"
"entity",
"order"
],
"fields": [
"id",
@ -504,8 +504,8 @@
}
},
"hierarchy": [
"order_line",
"entity"
"entity",
"order_line"
],
"fields": [
"id",
@ -548,8 +548,8 @@
"name": "relationship",
"relationship": true,
"hierarchy": [
"relationship",
"entity"
"entity",
"relationship"
],
"fields": [
"source_id",
@ -611,9 +611,9 @@
"name": "contact",
"relationship": true,
"hierarchy": [
"contact",
"entity",
"relationship",
"entity"
"contact"
],
"fields": [
"is_primary",
@ -683,8 +683,8 @@
{
"name": "phone_number",
"hierarchy": [
"phone_number",
"entity"
"entity",
"phone_number"
],
"fields": [
"number",
@ -741,8 +741,8 @@
{
"name": "email_address",
"hierarchy": [
"email_address",
"entity"
"entity",
"email_address"
],
"fields": [
"address",
@ -834,8 +834,8 @@
}
},
"hierarchy": [
"attachment",
"entity"
"entity",
"attachment"
],
"fields": [
"id",
@ -887,8 +887,8 @@
{
"name": "account",
"hierarchy": [
"account",
"entity"
"entity",
"account"
],
"fields": [
"id",
@ -1031,8 +1031,8 @@
}
},
"hierarchy": [
"invoice",
"entity"
"entity",
"invoice"
],
"fields": [
"id",
@ -1107,8 +1107,8 @@
}
},
"hierarchy": [
"invoice_line",
"entity"
"entity",
"invoice_line"
],
"fields": [
"id",
@ -1260,6 +1260,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"first_name\": \"IncompleteFirst\",",
" \"last_name\": \"IncompleteLast\",",
@ -1308,10 +1309,10 @@
"sql": [
[
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
"FROM agreego.\"person\" t1",
"JOIN agreego.\"user\" t2 ON ",
"JOIN agreego.\"organization\" t3 ON ",
"JOIN agreego.\"entity\" t4 ON ",
"FROM agreego.\"entity\" t1",
"JOIN agreego.\"organization\" t2 ON ",
"JOIN agreego.\"user\" t3 ON ",
"JOIN agreego.\"person\" t4 ON ",
"WHERE",
" (\"first_name\" = 'LookupFirst'",
" AND \"last_name\" = 'LookupLast'",
@ -1319,17 +1320,62 @@
" AND \"pronouns\" = 'they/them'))"
],
[
"UPDATE agreego.\"person\" SET",
" contact_id = 'abc-contact'",
"WHERE",
" id = '{{uuid:mocks.0.id}}'"
"INSERT INTO agreego.\"entity\" (",
" \"created_at\",",
" \"created_by\",",
" \"id\",",
" \"modified_at\",",
" \"modified_by\",",
" \"type\"",
")",
"VALUES (",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000',",
" '{{uuid:generated_0}}',",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000',",
" 'person'",
")"
],
[
"UPDATE agreego.\"entity\" SET",
" modified_at = '{{timestamp}}',",
" modified_by = '00000000-0000-0000-0000-000000000000'",
"WHERE",
" id = '{{uuid:mocks.0.id}}'"
"INSERT INTO agreego.\"organization\" (",
" \"id\",",
" \"type\"",
")",
"VALUES (",
" '{{uuid:generated_0}}',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"user\" (",
" \"id\",",
" \"type\"",
")",
"VALUES (",
" '{{uuid:generated_0}}',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"person\" (",
" \"contact_id\",",
" \"date_of_birth\",",
" \"first_name\",",
" \"id\",",
" \"last_name\",",
" \"pronouns\",",
" \"type\"",
")",
"VALUES (",
" 'abc-contact',",
" '{{timestamp}}',",
" 'LookupFirst',",
" '{{uuid:generated_0}}',",
" 'LookupLast',",
" 'they/them',",
" 'person'",
")"
],
[
"INSERT INTO agreego.change (",
@ -1342,39 +1388,45 @@
" \"modified_by\"",
")",
"VALUES (",
" NULL,",
" '{",
" \"contact_id\": \"old-contact\"",
" }',",
" '{",
" \"first_name\": \"LookupFirst\",",
" \"last_name\": \"LookupLast\",",
" \"date_of_birth\": \"{{timestamp}}\",",
" \"pronouns\": \"they/them\",",
" \"contact_id\": \"abc-contact\",",
" \"type\": \"person\"",
" }',",
" '{{uuid:mocks.0.id}}',",
" '{{uuid:generated_0}}',",
" 'update',",
" '{{uuid:generated_1}}',",
" 'create',",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000'",
")"
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"id\": \"{{uuid:mocks.0.id}}\",",
" \"type\": \"person\",",
" \"first_name\": \"LookupFirst\",",
" \"last_name\": \"LookupLast\",",
" \"date_of_birth\": \"{{timestamp}}\",",
" \"pronouns\": \"they/them\",",
" \"contact_id\": \"abc-contact\",",
" \"id\": \"{{uuid:generated_0}}\",",
" \"type\": \"person\",",
" \"created_by\": \"00000000-0000-0000-0000-000000000000\",",
" \"created_at\": \"{{timestamp}}\",",
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
" \"modified_at\": \"{{timestamp}}\"",
" },",
" \"new\": {",
" \"first_name\": \"LookupFirst\",",
" \"last_name\": \"LookupLast\",",
" \"date_of_birth\": \"{{timestamp}}\",",
" \"pronouns\": \"they/them\",",
" \"contact_id\": \"abc-contact\",",
" \"type\": \"person\"",
" },",
" \"old\": {",
" \"contact_id\": \"old-contact\"",
" }",
"}'))"
]
@ -1410,10 +1462,10 @@
"sql": [
[
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
"FROM agreego.\"person\" t1",
"JOIN agreego.\"user\" t2 ON ",
"JOIN agreego.\"organization\" t3 ON ",
"JOIN agreego.\"entity\" t4 ON ",
"FROM agreego.\"entity\" t1",
"JOIN agreego.\"organization\" t2 ON ",
"JOIN agreego.\"user\" t3 ON ",
"JOIN agreego.\"person\" t4 ON ",
"WHERE",
" t1.id = '{{uuid:data.id}}'",
" OR (\"first_name\" = 'LookupFirst'",
@ -1422,17 +1474,62 @@
" AND \"pronouns\" = 'they/them'))"
],
[
"UPDATE agreego.\"person\" SET",
" contact_id = 'abc-contact'",
"WHERE",
" id = '{{uuid:mocks.0.id}}'"
"INSERT INTO agreego.\"entity\" (",
" \"created_at\",",
" \"created_by\",",
" \"id\",",
" \"modified_at\",",
" \"modified_by\",",
" \"type\"",
")",
"VALUES (",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000',",
" '{{uuid:data.id}}',",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000',",
" 'person'",
")"
],
[
"UPDATE agreego.\"entity\" SET",
" modified_at = '{{timestamp}}',",
" modified_by = '00000000-0000-0000-0000-000000000000'",
"WHERE",
" id = '{{uuid:mocks.0.id}}'"
"INSERT INTO agreego.\"organization\" (",
" \"id\",",
" \"type\"",
")",
"VALUES (",
" '{{uuid:data.id}}',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"user\" (",
" \"id\",",
" \"type\"",
")",
"VALUES (",
" '{{uuid:data.id}}',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"person\" (",
" \"contact_id\",",
" \"date_of_birth\",",
" \"first_name\",",
" \"id\",",
" \"last_name\",",
" \"pronouns\",",
" \"type\"",
")",
"VALUES (",
" 'abc-contact',",
" '{{timestamp}}',",
" 'LookupFirst',",
" '{{uuid:data.id}}',",
" 'LookupLast',",
" 'they/them',",
" 'person'",
")"
],
[
"INSERT INTO agreego.change (",
@ -1445,41 +1542,46 @@
" \"modified_by\"",
")",
"VALUES (",
" NULL,",
" '{",
" \"contact_id\": \"old-contact\"",
" }',",
" '{",
" \"first_name\": \"LookupFirst\",",
" \"last_name\": \"LookupLast\",",
" \"date_of_birth\": \"{{timestamp}}\",",
" \"pronouns\": \"they/them\",",
" \"contact_id\": \"abc-contact\",",
" \"type\": \"person\"",
" }',",
" '{{uuid:mocks.0.id}}',",
" '{{uuid:data.id}}',",
" '{{uuid:generated_0}}',",
" 'update',",
" 'create',",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000'",
")"
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"id\": \"{{uuid:mocks.0.id}}\",",
" \"type\": \"person\",",
" \"first_name\": \"LookupFirst\",",
" \"last_name\": \"LookupLast\",",
" \"date_of_birth\": \"{{timestamp}}\",",
" \"pronouns\": \"they/them\",",
" \"contact_id\": \"abc-contact\",",
" \"id\": \"{{uuid:data.id}}\",",
" \"type\": \"person\",",
" \"created_by\": \"00000000-0000-0000-0000-000000000000\",",
" \"created_at\": \"{{timestamp}}\",",
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
" \"modified_at\": \"{{timestamp}}\"",
" },",
" \"new\": {",
" \"first_name\": \"LookupFirst\",",
" \"last_name\": \"LookupLast\",",
" \"date_of_birth\": \"{{timestamp}}\",",
" \"pronouns\": \"they/them\",",
" \"contact_id\": \"abc-contact\",",
" \"type\": \"person\"",
" },",
" \"old\": {",
" \"contact_id\": \"old-contact\"",
" },",
" \"replaces\": \"{{uuid:data.id}}\"",
" }",
"}'))"
]
]
@ -1513,10 +1615,10 @@
"sql": [
[
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
"FROM agreego.\"person\" t1",
"JOIN agreego.\"user\" t2 ON ",
"JOIN agreego.\"organization\" t3 ON ",
"JOIN agreego.\"entity\" t4 ON ",
"FROM agreego.\"entity\" t1",
"JOIN agreego.\"organization\" t2 ON ",
"JOIN agreego.\"user\" t3 ON ",
"JOIN agreego.\"person\" t4 ON ",
"WHERE",
" t1.id = '{{uuid:data.id}}'",
" OR (\"first_name\" = 'LookupFirst'",
@ -1525,22 +1627,109 @@
" AND \"pronouns\" = 'they/them'))"
],
[
"(SELECT pg_notify('entity', '{",
" \"complete\": {",
" \"id\": \"{{uuid:mocks.0.id}}\",",
" \"type\": \"person\",",
"INSERT INTO agreego.\"entity\" (",
" \"created_at\",",
" \"created_by\",",
" \"id\",",
" \"modified_at\",",
" \"modified_by\",",
" \"type\"",
")",
"VALUES (",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000',",
" '{{uuid:data.id}}',",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"organization\" (",
" \"id\",",
" \"type\"",
")",
"VALUES (",
" '{{uuid:data.id}}',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"user\" (",
" \"id\",",
" \"type\"",
")",
"VALUES (",
" '{{uuid:data.id}}',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"person\" (",
" \"date_of_birth\",",
" \"first_name\",",
" \"id\",",
" \"last_name\",",
" \"pronouns\",",
" \"type\"",
")",
"VALUES (",
" '{{timestamp}}',",
" 'LookupFirst',",
" '{{uuid:data.id}}',",
" 'LookupLast',",
" 'they/them',",
" 'person'",
")"
],
[
"INSERT INTO agreego.change (",
" \"old\",",
" \"new\",",
" \"entity_id\",",
" \"id\",",
" \"kind\",",
" \"modified_at\",",
" \"modified_by\"",
")",
"VALUES (",
" NULL,",
" '{",
" \"first_name\": \"LookupFirst\",",
" \"last_name\": \"LookupLast\",",
" \"date_of_birth\": \"{{timestamp}}\",",
" \"pronouns\": \"they/them\",",
" \"contact_id\": \"old-contact\",",
" \"type\": \"person\"",
" }',",
" '{{uuid:data.id}}',",
" '{{uuid:generated_0}}',",
" 'create',",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000'",
")"
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"first_name\": \"LookupFirst\",",
" \"last_name\": \"LookupLast\",",
" \"date_of_birth\": \"{{timestamp}}\",",
" \"pronouns\": \"they/them\",",
" \"id\": \"{{uuid:data.id}}\",",
" \"type\": \"person\",",
" \"created_by\": \"00000000-0000-0000-0000-000000000000\",",
" \"created_at\": \"{{timestamp}}\",",
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
" \"modified_at\": \"{{timestamp}}\"",
" },",
" \"new\": {",
" \"first_name\": \"LookupFirst\",",
" \"last_name\": \"LookupLast\",",
" \"date_of_birth\": \"{{timestamp}}\",",
" \"pronouns\": \"they/them\",",
" \"type\": \"person\"",
" },",
" \"replaces\": \"{{uuid:data.id}}\"",
" }",
"}'))"
]
]
@ -1569,26 +1758,64 @@
"sql": [
[
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
"FROM agreego.\"person\" t1",
"JOIN agreego.\"user\" t2 ON ",
"JOIN agreego.\"organization\" t3 ON ",
"JOIN agreego.\"entity\" t4 ON ",
"FROM agreego.\"entity\" t1",
"JOIN agreego.\"organization\" t2 ON ",
"JOIN agreego.\"user\" t3 ON ",
"JOIN agreego.\"person\" t4 ON ",
"WHERE",
" t1.id = '{{uuid:mocks.0.id}}')"
],
[
"UPDATE agreego.\"person\" SET",
" first_name = 'NewFirst',",
" last_name = 'NewLast'",
"WHERE",
" id = '{{uuid:mocks.0.id}}'"
"INSERT INTO agreego.\"entity\" (",
" \"created_at\",",
" \"created_by\",",
" \"id\",",
" \"modified_at\",",
" \"modified_by\",",
" \"type\"",
")",
"VALUES (",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000',",
" '{{uuid:mocks.0.id}}',",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000',",
" 'person'",
")"
],
[
"UPDATE agreego.\"entity\" SET",
" modified_at = '{{timestamp}}',",
" modified_by = '00000000-0000-0000-0000-000000000000'",
"WHERE",
" id = '{{uuid:mocks.0.id}}'"
"INSERT INTO agreego.\"organization\" (",
" \"id\",",
" \"type\"",
")",
"VALUES (",
" '{{uuid:mocks.0.id}}',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"user\" (",
" \"id\",",
" \"type\"",
")",
"VALUES (",
" '{{uuid:mocks.0.id}}',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"person\" (",
" \"first_name\",",
" \"id\",",
" \"last_name\",",
" \"type\"",
")",
"VALUES (",
" 'NewFirst',",
" '{{uuid:mocks.0.id}}',",
" 'NewLast',",
" 'person'",
")"
],
[
"INSERT INTO agreego.change (",
@ -1601,10 +1828,7 @@
" \"modified_by\"",
")",
"VALUES (",
" '{",
" \"first_name\": \"OldFirst\",",
" \"last_name\": \"OldLast\"",
" }',",
" NULL,",
" '{",
" \"first_name\": \"NewFirst\",",
" \"last_name\": \"NewLast\",",
@ -1612,18 +1836,21 @@
" }',",
" '{{uuid:mocks.0.id}}',",
" '{{uuid:generated_0}}',",
" 'update',",
" 'create',",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000'",
")"
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"id\": \"{{uuid:mocks.0.id}}\",",
" \"type\": \"person\",",
" \"first_name\": \"NewFirst\",",
" \"last_name\": \"NewLast\",",
" \"id\": \"{{uuid:mocks.0.id}}\",",
" \"type\": \"person\",",
" \"created_by\": \"00000000-0000-0000-0000-000000000000\",",
" \"created_at\": \"{{timestamp}}\",",
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
" \"modified_at\": \"{{timestamp}}\"",
" },",
@ -1631,10 +1858,6 @@
" \"first_name\": \"NewFirst\",",
" \"last_name\": \"NewLast\",",
" \"type\": \"person\"",
" },",
" \"old\": {",
" \"first_name\": \"OldFirst\",",
" \"last_name\": \"OldLast\"",
" }",
"}'))"
]
@ -1658,10 +1881,10 @@
"sql": [
[
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
"FROM agreego.\"person\" t1",
"JOIN agreego.\"user\" t2 ON ",
"JOIN agreego.\"organization\" t3 ON ",
"JOIN agreego.\"entity\" t4 ON ",
"FROM agreego.\"entity\" t1",
"JOIN agreego.\"organization\" t2 ON ",
"JOIN agreego.\"user\" t3 ON ",
"JOIN agreego.\"person\" t4 ON ",
"WHERE",
" t1.id = '123')"
],
@ -1749,6 +1972,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"first_name\": \"John\",",
" \"last_name\": \"Doe\",",
@ -1930,6 +2154,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"total\": 100.0,",
" \"id\": \"{{uuid:generated_3}}\",",
@ -1949,6 +2174,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"first_name\": \"Bob\",",
" \"last_name\": \"Smith\",",
@ -1994,8 +2220,8 @@
"sql": [
[
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
"FROM agreego.\"order\" t1",
"JOIN agreego.\"entity\" t2 ON ",
"FROM agreego.\"entity\" t1",
"JOIN agreego.\"order\" t2 ON ",
"WHERE",
" t1.id = 'abc'",
" OR (\"id\" = 'abc'))"
@ -2114,6 +2340,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"total\": 99.0,",
" \"id\": \"abc\",",
@ -2131,6 +2358,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"product\": \"Widget\",",
" \"price\": 99.0,",
@ -2619,6 +2847,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"first_name\": \"Relation\",",
" \"last_name\": \"Test\",",
@ -2638,6 +2867,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"is_primary\": true,",
" \"source_id\": \"{{uuid:generated_0}}\",",
@ -2663,6 +2893,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"number\": \"555-0001\",",
" \"id\": \"{{uuid:generated_1}}\",",
@ -2680,6 +2911,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"is_primary\": false,",
" \"source_id\": \"{{uuid:generated_0}}\",",
@ -2705,6 +2937,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"address\": \"test@example.com\",",
" \"id\": \"{{uuid:generated_5}}\",",
@ -2722,6 +2955,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"is_primary\": false,",
" \"source_id\": \"{{uuid:generated_0}}\",",
@ -2747,6 +2981,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"address\": \"test2@example.com\",",
" \"id\": \"{{uuid:generated_9}}\",",
@ -2788,20 +3023,62 @@
"sql": [
[
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*) || to_jsonb(t3.*) || to_jsonb(t4.*)",
"FROM agreego.\"person\" t1",
"JOIN agreego.\"user\" t2 ON ",
"JOIN agreego.\"organization\" t3 ON ",
"JOIN agreego.\"entity\" t4 ON ",
"FROM agreego.\"entity\" t1",
"JOIN agreego.\"organization\" t2 ON ",
"JOIN agreego.\"user\" t3 ON ",
"JOIN agreego.\"person\" t4 ON ",
"WHERE",
" t1.id = 'abc-archived')"
],
[
"UPDATE agreego.\"entity\" SET",
" archived = true,",
" modified_at = '{{timestamp}}',",
" modified_by = '00000000-0000-0000-0000-000000000000'",
"WHERE",
" id = 'abc-archived'"
"INSERT INTO agreego.\"entity\" (",
" \"archived\",",
" \"created_at\",",
" \"created_by\",",
" \"id\",",
" \"modified_at\",",
" \"modified_by\",",
" \"type\"",
")",
"VALUES (",
" true,",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000',",
" 'abc-archived',",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"organization\" (",
" \"id\",",
" \"type\"",
")",
"VALUES (",
" 'abc-archived',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"user\" (",
" \"id\",",
" \"type\"",
")",
"VALUES (",
" 'abc-archived',",
" 'person'",
")"
],
[
"INSERT INTO agreego.\"person\" (",
" \"id\",",
" \"type\"",
")",
"VALUES (",
" 'abc-archived',",
" 'person'",
")"
],
[
"INSERT INTO agreego.change (",
@ -2814,37 +3091,33 @@
" \"modified_by\"",
")",
"VALUES (",
" '{",
" \"archived\": false",
" }',",
" NULL,",
" '{",
" \"archived\": true,",
" \"type\": \"person\"",
" }',",
" 'abc-archived',",
" '{{uuid:generated_0}}',",
" 'delete',",
" 'create',",
" '{{timestamp}}',",
" '00000000-0000-0000-0000-000000000000'",
")"
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"archived\": true,",
" \"id\": \"abc-archived\",",
" \"type\": \"person\",",
" \"first_name\": \"ArchivedFirst\",",
" \"last_name\": \"ArchivedLast\",",
" \"archived\": true,",
" \"created_by\": \"00000000-0000-0000-0000-000000000000\",",
" \"created_at\": \"{{timestamp}}\",",
" \"modified_by\": \"00000000-0000-0000-0000-000000000000\",",
" \"modified_at\": \"{{timestamp}}\"",
" },",
" \"new\": {",
" \"archived\": true,",
" \"type\": \"person\"",
" },",
" \"old\": {",
" \"archived\": false",
" }",
"}'))"
]
@ -2943,6 +3216,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"flags\": [",
" \"urgent\",",
@ -3058,6 +3332,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"product\": \"Widget\",",
" \"price\": 99.0,",
@ -3101,8 +3376,8 @@
"sql": [
[
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
"FROM agreego.\"order_line\" t1",
"JOIN agreego.\"entity\" t2 ON ",
"FROM agreego.\"entity\" t1",
"JOIN agreego.\"order_line\" t2 ON ",
"WHERE",
" t1.id = '{{uuid:data.lines.0.id}}')"
],
@ -3167,6 +3442,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"product\": \"Widget\",",
" \"price\": 99.0,",
@ -3224,8 +3500,8 @@
"sql": [
[
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
"FROM agreego.\"invoice\" t1",
"JOIN agreego.\"entity\" t2 ON ",
"FROM agreego.\"entity\" t1",
"JOIN agreego.\"invoice\" t2 ON ",
"WHERE",
" t1.id = '{{uuid:data.id}}'",
" OR (\"id\" = '{{uuid:data.id}}'))"
@ -3341,8 +3617,8 @@
"sql": [
[
"(SELECT to_jsonb(t1.*) || to_jsonb(t2.*)",
"FROM agreego.\"account\" t1",
"JOIN agreego.\"entity\" t2 ON ",
"FROM agreego.\"entity\" t1",
"JOIN agreego.\"account\" t2 ON ",
"WHERE",
" t1.id = '{{uuid:data.id}}')"
],
@ -3404,6 +3680,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"kind\": \"checking\",",
" \"routing_number\": \"123456789\",",
@ -3698,6 +3975,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"organization_id\": \"parent-org-id\",",
" \"id\": \"{{uuid:generated_3}}\",",
@ -3717,6 +3995,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"first_name\": \"Const\",",
" \"last_name\": \"Person\",",
@ -3738,6 +4017,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"order_id\": \"{{uuid:generated_3}}\",",
" \"id\": \"{{uuid:generated_4}}\",",
@ -3757,6 +4037,7 @@
],
[
"(SELECT pg_notify('entity', '{",
" \"kind\": \"create\",",
" \"complete\": {",
" \"organization_id\": \"explicit-org-id\",",
" \"order_id\": \"{{uuid:generated_3}}\",",

View File

@ -62,7 +62,20 @@
"schema_id": "minContains_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "0",
"limit": "1"
},
"details": {
"path": "",
"schema": "minContains_1_0"
}
}
]
}
},
{
@ -73,7 +86,20 @@
"schema_id": "minContains_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "0",
"limit": "1"
},
"details": {
"path": "",
"schema": "minContains_1_0"
}
}
]
}
},
{
@ -138,7 +164,20 @@
"schema_id": "minContains_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "0",
"limit": "2"
},
"details": {
"path": "",
"schema": "minContains_2_0"
}
}
]
}
},
{
@ -149,7 +188,20 @@
"schema_id": "minContains_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "2",
"count": "1"
},
"details": {
"path": "",
"schema": "minContains_2_0"
}
}
]
}
},
{
@ -161,7 +213,20 @@
"schema_id": "minContains_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "2",
"count": "1"
},
"details": {
"path": "",
"schema": "minContains_2_0"
}
}
]
}
},
{
@ -231,7 +296,20 @@
"schema_id": "minContains_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "2",
"count": "1"
},
"details": {
"path": "",
"schema": "minContains_3_0"
}
}
]
}
},
{
@ -274,7 +352,20 @@
"schema_id": "minContains_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "0",
"limit": "2"
},
"details": {
"path": "",
"schema": "minContains_4_0"
}
}
]
}
},
{
@ -285,7 +376,20 @@
"schema_id": "minContains_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "1",
"limit": "2"
},
"details": {
"path": "",
"schema": "minContains_4_0"
}
}
]
}
},
{
@ -298,7 +402,20 @@
"schema_id": "minContains_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "2",
"count": "3"
},
"details": {
"path": "",
"schema": "minContains_4_0"
}
}
]
}
},
{
@ -341,7 +458,20 @@
"schema_id": "minContains_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "3",
"count": "0"
},
"details": {
"path": "",
"schema": "minContains_5_0"
}
}
]
}
},
{
@ -352,7 +482,20 @@
"schema_id": "minContains_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"count": "1",
"limit": "3"
},
"details": {
"path": "",
"schema": "minContains_5_0"
}
}
]
}
},
{
@ -365,7 +508,20 @@
"schema_id": "minContains_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "1",
"count": "3"
},
"details": {
"path": "",
"schema": "minContains_5_0"
}
}
]
}
},
{
@ -377,7 +533,31 @@
"schema_id": "minContains_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "3",
"count": "2"
},
"details": {
"path": "",
"schema": "minContains_5_0"
}
},
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "1",
"count": "2"
},
"details": {
"path": "",
"schema": "minContains_5_0"
}
}
]
}
}
]
@ -472,7 +652,20 @@
"schema_id": "minContains_7_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONTAINS_VIOLATED",
"values": {
"limit": "1",
"count": "2"
},
"details": {
"path": "",
"schema": "minContains_7_0"
}
}
]
}
}
]

View File

@ -44,7 +44,20 @@
"schema_id": "minItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MIN_ITEMS_VIOLATED",
"values": {
"count": "0",
"limit": "1"
},
"details": {
"path": "",
"schema": "minItems_0_0"
}
}
]
}
},
{
@ -92,7 +105,20 @@
"schema_id": "minItems_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MIN_ITEMS_VIOLATED",
"values": {
"limit": "1",
"count": "0"
},
"details": {
"path": "",
"schema": "minItems_1_0"
}
}
]
}
}
]

View File

@ -38,7 +38,20 @@
"schema_id": "minLength_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MIN_LENGTH_VIOLATED",
"values": {
"count": "1",
"limit": "2"
},
"details": {
"path": "",
"schema": "minLength_0_0"
}
}
]
}
},
{
@ -52,11 +65,24 @@
},
{
"description": "one grapheme is not long enough",
"data": "\ud83d\udca9",
"data": "💩",
"schema_id": "minLength_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MIN_LENGTH_VIOLATED",
"values": {
"limit": "2",
"count": "1"
},
"details": {
"path": "",
"schema": "minLength_0_0"
}
}
]
}
}
]
@ -91,7 +117,20 @@
"schema_id": "minLength_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MIN_LENGTH_VIOLATED",
"values": {
"count": "1",
"limit": "2"
},
"details": {
"path": "",
"schema": "minLength_1_0"
}
}
]
}
}
]

View File

@ -44,7 +44,20 @@
"schema_id": "minProperties_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MIN_PROPERTIES_VIOLATED",
"values": {
"count": "0",
"limit": "1"
},
"details": {
"path": "",
"schema": "minProperties_0_0"
}
}
]
}
},
{
@ -110,7 +123,20 @@
"schema_id": "minProperties_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MIN_PROPERTIES_VIOLATED",
"values": {
"limit": "1",
"count": "0"
},
"details": {
"path": "",
"schema": "minProperties_1_0"
}
}
]
}
}
]

View File

@ -38,7 +38,20 @@
"schema_id": "minimum_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MINIMUM_VIOLATED",
"values": {
"value": "0.6",
"limit": "1.1"
},
"details": {
"path": "",
"schema": "minimum_0_0"
}
}
]
}
},
{
@ -109,7 +122,20 @@
"schema_id": "minimum_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MINIMUM_VIOLATED",
"values": {
"limit": "-2",
"value": "-2.0001"
},
"details": {
"path": "",
"schema": "minimum_1_0"
}
}
]
}
},
{
@ -118,7 +144,20 @@
"schema_id": "minimum_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MINIMUM_VIOLATED",
"values": {
"limit": "-2",
"value": "-3"
},
"details": {
"path": "",
"schema": "minimum_1_0"
}
}
]
}
},
{

View File

@ -29,7 +29,20 @@
"schema_id": "multipleOf_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MULTIPLE_OF_VIOLATED",
"values": {
"value": "7",
"multiple_of": "2"
},
"details": {
"path": "",
"schema": "multipleOf_0_0"
}
}
]
}
},
{
@ -82,7 +95,20 @@
"schema_id": "multipleOf_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MULTIPLE_OF_VIOLATED",
"values": {
"multiple_of": "1.5",
"value": "35"
},
"details": {
"path": "",
"schema": "multipleOf_1_0"
}
}
]
}
}
]
@ -117,7 +143,20 @@
"schema_id": "multipleOf_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MULTIPLE_OF_VIOLATED",
"values": {
"multiple_of": "0.0001",
"value": "0.00751"
},
"details": {
"path": "",
"schema": "multipleOf_2_0"
}
}
]
}
}
]
@ -131,7 +170,7 @@
"schemas": {
"multipleOf_3_0": {
"type": "integer",
"multipleOf": 1e-08
"multipleOf": 1e-8
}
}
}

View File

@ -31,7 +31,16 @@
"schema_id": "not_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_0_0"
}
}
]
}
}
]
@ -71,7 +80,16 @@
"schema_id": "not_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_1_0"
}
}
]
}
},
{
@ -80,7 +98,16 @@
"schema_id": "not_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_1_0"
}
}
]
}
}
]
@ -136,7 +163,16 @@
"schema_id": "not_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_2_0"
}
}
]
}
}
]
@ -169,7 +205,26 @@
"schema_id": "not_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "foo",
"schema": "not_3_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "bar"
},
"details": {
"path": "bar",
"schema": "not_3_0"
}
}
]
}
},
{
@ -204,7 +259,16 @@
"schema_id": "not_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_4_0"
}
}
]
}
},
{
@ -213,7 +277,16 @@
"schema_id": "not_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_4_0"
}
}
]
}
},
{
@ -222,7 +295,16 @@
"schema_id": "not_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_4_0"
}
}
]
}
},
{
@ -231,7 +313,16 @@
"schema_id": "not_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_4_0"
}
}
]
}
},
{
@ -240,7 +331,16 @@
"schema_id": "not_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_4_0"
}
}
]
}
},
{
@ -251,7 +351,26 @@
"schema_id": "not_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_4_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "foo",
"schema": "not_4_0"
}
}
]
}
},
{
@ -260,7 +379,16 @@
"schema_id": "not_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_4_0"
}
}
]
}
},
{
@ -271,7 +399,26 @@
"schema_id": "not_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_4_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "not_4_0"
}
}
]
}
},
{
@ -280,7 +427,16 @@
"schema_id": "not_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_4_0"
}
}
]
}
}
]
@ -306,7 +462,16 @@
"schema_id": "not_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_5_0"
}
}
]
}
},
{
@ -315,7 +480,16 @@
"schema_id": "not_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_5_0"
}
}
]
}
},
{
@ -324,7 +498,16 @@
"schema_id": "not_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_5_0"
}
}
]
}
},
{
@ -333,7 +516,16 @@
"schema_id": "not_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_5_0"
}
}
]
}
},
{
@ -342,7 +534,16 @@
"schema_id": "not_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_5_0"
}
}
]
}
},
{
@ -353,7 +554,26 @@
"schema_id": "not_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_5_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "foo",
"schema": "not_5_0"
}
}
]
}
},
{
@ -362,7 +582,16 @@
"schema_id": "not_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_5_0"
}
}
]
}
},
{
@ -373,7 +602,26 @@
"schema_id": "not_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_5_0"
}
},
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "0"
},
"details": {
"path": "0",
"schema": "not_5_0"
}
}
]
}
},
{
@ -382,7 +630,16 @@
"schema_id": "not_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "NOT_VIOLATED",
"details": {
"path": "",
"schema": "not_5_0"
}
}
]
}
}
]
@ -574,7 +831,19 @@
"schema_id": "not_9_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "foo",
"schema": "not_9_0"
}
}
]
}
}
]
@ -647,7 +916,19 @@
"schema_id": "not_11_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "foo"
},
"details": {
"path": "foo",
"schema": "not_11_0"
}
}
]
}
},
{

View File

@ -55,7 +55,19 @@
},
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "a"
},
"details": {
"path": "a",
"schema": "child_type"
}
}
]
}
},
{
@ -68,7 +80,19 @@
},
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "c"
},
"details": {
"path": "c",
"schema": "child_type"
}
}
]
}
}
]
@ -127,7 +151,20 @@
},
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAXIMUM_VIOLATED",
"values": {
"value": "60",
"limit": "50"
},
"details": {
"path": "max",
"schema": "custom_budget"
}
}
]
}
}
]
@ -205,7 +242,19 @@
},
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "inv/amount",
"schema": "request"
}
}
]
}
}
]

View File

@ -127,8 +127,12 @@
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "string"
},
"details": {
"path": "primitives/1"
"path": "primitives/1",
"schema": "hybrid_pathing"
}
}
]
@ -153,14 +157,22 @@
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "name"
},
"details": {
"path": "ad_hoc_objects/1/name"
"path": "ad_hoc_objects/1/name",
"schema": "hybrid_pathing"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "age"
},
"details": {
"path": "ad_hoc_objects/1/age"
"path": "ad_hoc_objects/1/age",
"schema": "hybrid_pathing"
}
}
]
@ -187,8 +199,13 @@
"errors": [
{
"code": "MINIMUM_VIOLATED",
"values": {
"limit": "10",
"value": "5"
},
"details": {
"path": "entities/entity-beta/value"
"path": "entities/entity-beta/value",
"schema": "hybrid_pathing"
}
}
]
@ -220,8 +237,12 @@
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "boolean"
},
"details": {
"path": "deep_entities/parent-omega/nested/child-beta/flag"
"path": "deep_entities/parent-omega/nested/child-beta/flag",
"schema": "hybrid_pathing"
}
}
]
@ -275,8 +296,12 @@
"errors": [
{
"code": "NO_ONEOF_MATCH",
"values": {
"primitive": "boolean"
},
"details": {
"path": "metadata_bubbles/2"
"path": "metadata_bubbles/2",
"schema": "ad_hoc_pathing"
}
}
]
@ -293,16 +318,22 @@
"type": "relation",
"constraint": "fk_family_pathing_table_families_widget",
"source_type": "widget",
"source_columns": ["family_pathing_id"],
"source_columns": [
"family_pathing_id"
],
"destination_type": "family_pathing",
"destination_columns": ["id"],
"destination_columns": [
"id"
],
"prefix": "table_families"
}
],
"types": [
{
"name": "widget",
"hierarchy": ["widget"],
"hierarchy": [
"widget"
],
"variations": [
"widget"
],
@ -348,7 +379,9 @@
},
{
"name": "family_pathing",
"hierarchy": ["family_pathing"],
"hierarchy": [
"family_pathing"
],
"schemas": {
"family_pathing": {
"type": "object",
@ -398,26 +431,42 @@
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "table_families/widget-2/amount"
"path": "table_families/widget-2/amount",
"schema": "family_pathing"
}
},
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "nested_metric"
},
"details": {
"path": "table_families/widget-2/details/nested_metric"
"path": "table_families/widget-2/details/nested_metric",
"schema": "family_pathing"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "stray_child"
},
"details": {
"path": "table_families/widget-2/details/stray_child"
"path": "table_families/widget-2/details/stray_child",
"schema": "family_pathing"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "unexpected_root_prop"
},
"details": {
"path": "table_families/widget-2/unexpected_root_prop"
"path": "table_families/widget-2/unexpected_root_prop",
"schema": "family_pathing"
}
}
]

View File

@ -29,7 +29,19 @@
"schema_id": "pattern_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "PATTERN_VIOLATED",
"values": {
"pattern": "^a*$"
},
"details": {
"path": "",
"schema": "pattern_0_0"
}
}
]
}
},
{

View File

@ -51,7 +51,19 @@
"schema_id": "patternProperties_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "foo",
"schema": "patternProperties_0_0"
}
}
]
}
},
{
@ -63,7 +75,29 @@
"schema_id": "patternProperties_0_0",
"action": "validate",
"expect": {
"success": false
"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"
}
}
]
}
},
{
@ -104,7 +138,19 @@
"schema_id": "patternProperties_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "extra"
},
"details": {
"path": "extra",
"schema": "patternProperties_0_0"
}
}
]
}
}
]
@ -173,7 +219,19 @@
"schema_id": "patternProperties_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "a",
"schema": "patternProperties_1_0"
}
}
]
}
},
{
@ -184,7 +242,20 @@
"schema_id": "patternProperties_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAXIMUM_VIOLATED",
"values": {
"value": "31",
"limit": "20"
},
"details": {
"path": "aaaa",
"schema": "patternProperties_1_0"
}
}
]
}
},
{
@ -196,7 +267,30 @@
"schema_id": "patternProperties_1_0",
"action": "validate",
"expect": {
"success": false
"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"
}
}
]
}
}
]
@ -243,7 +337,19 @@
"schema_id": "patternProperties_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "boolean"
},
"details": {
"path": "a31b",
"schema": "patternProperties_2_0"
}
}
]
}
},
{
@ -265,7 +371,19 @@
"schema_id": "patternProperties_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "string"
},
"details": {
"path": "a_X_3",
"schema": "patternProperties_2_0"
}
}
]
}
}
]
@ -307,7 +425,16 @@
"schema_id": "patternProperties_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "bar",
"schema": "patternProperties_3_0"
}
}
]
}
},
{
@ -319,7 +446,16 @@
"schema_id": "patternProperties_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "bar",
"schema": "patternProperties_3_0"
}
}
]
}
},
{
@ -330,7 +466,16 @@
"schema_id": "patternProperties_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "foobar",
"schema": "patternProperties_3_0"
}
}
]
}
},
{
@ -415,7 +560,19 @@
"schema_id": "patternProperties_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "foo",
"schema": "patternProperties_5_0"
}
}
]
}
}
]

View File

@ -123,8 +123,12 @@
"errors": [
{
"code": "MISSING_TYPE",
"values": {
"discriminator": "type"
},
"details": {
"path": ""
"path": "",
"schema": "family_entity"
}
}
]
@ -143,8 +147,13 @@
"errors": [
{
"code": "NO_FAMILY_MATCH",
"values": {
"discriminator": "type",
"value": "alien"
},
"details": {
"path": ""
"path": "",
"schema": "family_entity"
}
}
]
@ -274,8 +283,13 @@
"errors": [
{
"code": "NO_FAMILY_MATCH",
"values": {
"discriminator": "type",
"value": "bot"
},
"details": {
"path": ""
"path": "",
"schema": "family_light_org"
}
}
]
@ -397,8 +411,12 @@
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "super_amount"
"path": "super_amount",
"schema": "family_stock_widget"
}
}
]
@ -509,8 +527,12 @@
"errors": [
{
"code": "MISSING_TYPE",
"values": {
"discriminator": "type"
},
"details": {
"path": ""
"path": "",
"schema": "oneOf_union"
}
}
]
@ -530,8 +552,12 @@
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "age"
"path": "age",
"schema": "oneOf_union"
}
}
]
@ -564,8 +590,13 @@
"errors": [
{
"code": "NO_ONEOF_MATCH",
"values": {
"value": "alien",
"discriminator": "type"
},
"details": {
"path": ""
"path": "",
"schema": "oneOf_union"
}
}
]
@ -643,8 +674,12 @@
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "invoice_id"
"path": "invoice_id",
"schema": "oneOf_bubble"
}
}
]
@ -736,7 +771,8 @@
{
"code": "MISSING_KIND",
"details": {
"path": ""
"path": "",
"schema": "stock_widget_validation"
}
}
]
@ -768,8 +804,12 @@
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "kind"
},
"details": {
"path": "kind"
"path": "kind",
"schema": "projected_widget_validation"
}
}
]
@ -866,8 +906,12 @@
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "amount"
"path": "amount",
"schema": "family_panel"
}
}
]
@ -886,8 +930,13 @@
"errors": [
{
"code": "NO_FAMILY_MATCH",
"values": {
"value": "unknown_panel",
"discriminator": "kind"
},
"details": {
"path": ""
"path": "",
"schema": "family_panel"
}
}
]

View File

@ -42,7 +42,29 @@
"schema_id": "prefixItems_0_0",
"action": "validate",
"expect": {
"success": false
"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"
}
}
]
}
},
{
@ -66,7 +88,19 @@
"schema_id": "prefixItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_ITEM_VIOLATION",
"values": {
"index": "2"
},
"details": {
"path": "2",
"schema": "prefixItems_0_0"
}
}
]
}
},
{
@ -88,7 +122,39 @@
"schema_id": "prefixItems_0_0",
"action": "validate",
"expect": {
"success": false
"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"
}
}
]
}
}
]
@ -131,7 +197,16 @@
"schema_id": "prefixItems_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "1",
"schema": "prefixItems_1_0"
}
}
]
}
},
{

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,19 @@
"schema_id": "properties_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "string"
},
"details": {
"path": "bar",
"schema": "properties_0_0"
}
}
]
}
},
{
@ -54,7 +66,29 @@
"schema_id": "properties_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "integer"
},
"details": {
"path": "foo",
"schema": "properties_0_0"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "string"
},
"details": {
"path": "bar",
"schema": "properties_0_0"
}
}
]
}
},
{
@ -132,7 +166,16 @@
"schema_id": "properties_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "bar",
"schema": "properties_1_0"
}
}
]
}
},
{
@ -144,7 +187,16 @@
"schema_id": "properties_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "bar",
"schema": "properties_1_0"
}
}
]
}
}
]
@ -212,7 +264,69 @@
"schema_id": "properties_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "number"
},
"details": {
"path": "foo\nbar",
"schema": "properties_2_0"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "number"
},
"details": {
"path": "foo\"bar",
"schema": "properties_2_0"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "number"
},
"details": {
"path": "foo\\bar",
"schema": "properties_2_0"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "number"
},
"details": {
"path": "foo\rbar",
"schema": "properties_2_0"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "number"
},
"details": {
"path": "foo\tbar",
"schema": "properties_2_0"
}
},
{
"code": "INVALID_TYPE",
"values": {
"expected": "number"
},
"details": {
"path": "foo\fbar",
"schema": "properties_2_0"
}
}
]
}
}
]
@ -314,7 +428,19 @@
"schema_id": "properties_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "number"
},
"details": {
"path": "__proto__",
"schema": "properties_4_0"
}
}
]
}
},
{
@ -327,7 +453,19 @@
"schema_id": "properties_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "string"
},
"details": {
"path": "toString/length",
"schema": "properties_4_0"
}
}
]
}
},
{
@ -340,7 +478,29 @@
"schema_id": "properties_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"values": {
"expected": "number"
},
"details": {
"path": "constructor",
"schema": "properties_4_0"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "length"
},
"details": {
"path": "constructor/length",
"schema": "properties_4_0"
}
}
]
}
},
{
@ -422,7 +582,19 @@
"schema_id": "properties_6_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "extra"
},
"details": {
"path": "extra",
"schema": "properties_6_0"
}
}
]
}
}
]
@ -461,7 +633,19 @@
"schema_id": "properties_7_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "extra"
},
"details": {
"path": "nested/extra",
"schema": "properties_7_0"
}
}
]
}
}
]
@ -582,7 +766,19 @@
"schema_id": "properties_10_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "extra"
},
"details": {
"path": "nested/extra",
"schema": "properties_10_0"
}
}
]
}
}
]
@ -626,7 +822,19 @@
"schema_id": "properties_11_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"values": {
"property_name": "extra"
},
"details": {
"path": "list/0/extra",
"schema": "properties_11_0"
}
}
]
}
}
]

View File

@ -38,7 +38,20 @@
"schema_id": "propertyNames_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAX_LENGTH_VIOLATED",
"values": {
"count": "6",
"limit": "3"
},
"details": {
"path": "",
"schema": "propertyNames_0_0"
}
}
]
}
},
{
@ -123,7 +136,19 @@
"schema_id": "propertyNames_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "PATTERN_VIOLATED",
"values": {
"pattern": "^a+$"
},
"details": {
"path": "",
"schema": "propertyNames_1_0"
}
}
]
}
},
{
@ -199,7 +224,16 @@
"schema_id": "propertyNames_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "",
"schema": "propertyNames_3_0"
}
}
]
}
},
{
@ -250,7 +284,19 @@
"schema_id": "propertyNames_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "CONST_VIOLATED",
"values": {
"expected": "String(\"foo\")"
},
"details": {
"path": "",
"schema": "propertyNames_4_0"
}
}
]
}
},
{
@ -316,7 +362,19 @@
"schema_id": "propertyNames_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "ENUM_MISMATCH",
"values": {
"expected": "[String(\"foo\"), String(\"bar\")]"
},
"details": {
"path": "",
"schema": "propertyNames_5_0"
}
}
]
}
},
{
@ -367,7 +425,20 @@
"schema_id": "propertyNames_6_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "MAX_LENGTH_VIOLATED",
"values": {
"limit": "3",
"count": "6"
},
"details": {
"path": "",
"schema": "propertyNames_6_0"
}
}
]
}
}
]

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,19 @@
"schema_id": "required_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "foo"
},
"details": {
"path": "foo",
"schema": "required_0_0"
}
}
]
}
},
{
@ -194,7 +206,49 @@
"schema_id": "required_3_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "foo\\bar"
},
"details": {
"path": "foo\\bar",
"schema": "required_3_0"
}
},
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "foo\rbar"
},
"details": {
"path": "foo\rbar",
"schema": "required_3_0"
}
},
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "foo\tbar"
},
"details": {
"path": "foo\tbar",
"schema": "required_3_0"
}
},
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "foo\fbar"
},
"details": {
"path": "foo\fbar",
"schema": "required_3_0"
}
}
]
}
}
]
@ -244,7 +298,39 @@
"schema_id": "required_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "__proto__"
},
"details": {
"path": "__proto__",
"schema": "required_4_0"
}
},
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "toString"
},
"details": {
"path": "toString",
"schema": "required_4_0"
}
},
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "constructor"
},
"details": {
"path": "constructor",
"schema": "required_4_0"
}
}
]
}
},
{
@ -255,7 +341,29 @@
"schema_id": "required_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "toString"
},
"details": {
"path": "toString",
"schema": "required_4_0"
}
},
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "constructor"
},
"details": {
"path": "constructor",
"schema": "required_4_0"
}
}
]
}
},
{
@ -268,7 +376,29 @@
"schema_id": "required_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "__proto__"
},
"details": {
"path": "__proto__",
"schema": "required_4_0"
}
},
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "constructor"
},
"details": {
"path": "constructor",
"schema": "required_4_0"
}
}
]
}
},
{
@ -281,7 +411,29 @@
"schema_id": "required_4_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "__proto__"
},
"details": {
"path": "__proto__",
"schema": "required_4_0"
}
},
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "toString"
},
"details": {
"path": "toString",
"schema": "required_4_0"
}
}
]
}
},
{

View File

@ -8,27 +8,46 @@
"schemas": {
"full.person": {
"type": "object",
"include": ["emailable", "phonable"],
"include": [
"emailable",
"phonable"
],
"properties": {
"name": { "type": "string" }
"name": {
"type": "string"
}
},
"required": ["name"]
"required": [
"name"
]
}
},
"traits": {
"emailable": {
"properties": {
"email": { "type": "string" }
"email": {
"type": "string"
}
},
"required": ["email"],
"display": ["email"]
"required": [
"email"
],
"display": [
"email"
]
},
"phonable": {
"properties": {
"phone": { "type": "string" }
"phone": {
"type": "string"
}
},
"required": ["phone"],
"display": ["phone"]
"required": [
"phone"
],
"display": [
"phone"
]
}
}
}
@ -61,8 +80,12 @@
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"values": {
"field_name": "email"
},
"details": {
"path": "email"
"path": "email",
"schema": "full.person"
}
}
]
@ -79,7 +102,9 @@
"schemas": {
"full.person": {
"type": "object",
"include": ["emailable"],
"include": [
"emailable"
],
"properties": {
"email": {
"type": "string",
@ -91,7 +116,9 @@
"traits": {
"emailable": {
"properties": {
"email": { "type": "string" }
"email": {
"type": "string"
}
}
}
}
@ -111,8 +138,13 @@
"errors": [
{
"code": "MAX_LENGTH_VIOLATED",
"values": {
"limit": "5",
"count": "26"
},
"details": {
"path": "email"
"path": "email",
"schema": "full.person"
}
}
]
@ -129,7 +161,9 @@
"schemas": {
"full.person": {
"type": "object",
"include": ["nonexistent_trait"]
"include": [
"nonexistent_trait"
]
}
}
}
@ -143,7 +177,14 @@
"success": false,
"errors": [
{
"code": "TRAIT_NOT_FOUND"
"code": "TRAIT_NOT_FOUND",
"values": {
"include": "nonexistent_trait"
},
"details": {
"path": "full.person",
"schema": "full.person"
}
}
]
}
@ -159,15 +200,21 @@
"schemas": {
"full.person": {
"type": "object",
"include": ["trait_a"]
"include": [
"trait_a"
]
}
},
"traits": {
"trait_a": {
"include": ["trait_b"]
"include": [
"trait_b"
]
},
"trait_b": {
"include": ["trait_a"]
"include": [
"trait_a"
]
}
}
}
@ -181,11 +228,18 @@
"success": false,
"errors": [
{
"code": "CIRCULAR_INCLUDE_DETECTED"
"code": "CIRCULAR_INCLUDE_DETECTED",
"values": {
"include": "trait_a"
},
"details": {
"path": "full.person/include/trait_a/include/trait_b",
"schema": "full.person"
}
}
]
}
}
]
}
]
]

View File

@ -36,7 +36,16 @@
"schema_id": "uniqueItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_0_0"
}
}
]
}
},
{
@ -49,7 +58,16 @@
"schema_id": "uniqueItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_0_0"
}
}
]
}
},
{
@ -62,7 +80,16 @@
"schema_id": "uniqueItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_0_0"
}
}
]
}
},
{
@ -112,7 +139,16 @@
"schema_id": "uniqueItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_0_0"
}
}
]
}
},
{
@ -144,7 +180,16 @@
"schema_id": "uniqueItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_0_0"
}
}
]
}
},
{
@ -162,7 +207,16 @@
"schema_id": "uniqueItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_0_0"
}
}
]
}
},
{
@ -210,7 +264,16 @@
"schema_id": "uniqueItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_0_0"
}
}
]
}
},
{
@ -242,7 +305,16 @@
"schema_id": "uniqueItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_0_0"
}
}
]
}
},
{
@ -261,7 +333,16 @@
"schema_id": "uniqueItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_0_0"
}
}
]
}
},
{
@ -397,7 +478,16 @@
"schema_id": "uniqueItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_0_0"
}
}
]
}
},
{
@ -433,7 +523,16 @@
"schema_id": "uniqueItems_0_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_0_0"
}
}
]
}
},
{
@ -527,7 +626,16 @@
"schema_id": "uniqueItems_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_1_0"
}
}
]
}
},
{
@ -539,7 +647,16 @@
"schema_id": "uniqueItems_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_1_0"
}
}
]
}
},
{
@ -581,7 +698,16 @@
"schema_id": "uniqueItems_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_1_0"
}
}
]
}
},
{
@ -595,7 +721,16 @@
"schema_id": "uniqueItems_1_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_1_0"
}
}
]
}
}
]
@ -657,7 +792,16 @@
"schema_id": "uniqueItems_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_2_0"
}
}
]
}
},
{
@ -669,7 +813,16 @@
"schema_id": "uniqueItems_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_2_0"
}
}
]
}
},
{
@ -682,7 +835,16 @@
"schema_id": "uniqueItems_2_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "2",
"schema": "uniqueItems_2_0"
}
}
]
}
}
]
@ -1149,7 +1311,16 @@
"schema_id": "uniqueItems_5_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "FALSE_SCHEMA",
"details": {
"path": "2",
"schema": "uniqueItems_5_0"
}
}
]
}
}
]
@ -1179,7 +1350,16 @@
"schema_id": "uniqueItems_6_0",
"action": "validate",
"expect": {
"success": false
"success": false,
"errors": [
{
"code": "UNIQUE_ITEMS_VIOLATED",
"details": {
"path": "",
"schema": "uniqueItems_6_0"
}
}
]
}
},
{

View File

@ -1,4 +1,8 @@
use crate::database::schema::Schema;
#[allow(unused_imports)]
use crate::drop::{Error, ErrorDetails};
#[allow(unused_imports)]
use std::collections::HashMap;
use std::sync::Arc;
impl Schema {
@ -8,18 +12,19 @@ impl Schema {
field_name: &str,
root_id: &str,
path: &str,
errors: &mut Vec<crate::drop::Error>,
errors: &mut Vec<Error>,
) {
#[cfg(not(test))]
for c in id.chars() {
if !c.is_ascii_lowercase() && !c.is_ascii_digit() && c != '_' && c != '.' && c != '$' {
errors.push(crate::drop::Error {
errors.push(Error {
code: "INVALID_IDENTIFIER".to_string(),
message: format!(
"Invalid character '{}' in JSON Schema '{}' property: '{}'. Identifiers must exclusively contain [a-z0-9_.$]",
c, field_name, id
),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("character".to_string(), c.to_string()),
("field_name".to_string(), field_name.to_string()),
("identifier".to_string(), id.to_string()),
])),
details: ErrorDetails {
path: Some(path.to_string()),
schema: Some(root_id.to_string()),
..Default::default()
@ -35,7 +40,7 @@ impl Schema {
root_id: &str,
path: String,
to_insert: &mut Vec<(String, Arc<Schema>)>,
errors: &mut Vec<crate::drop::Error>,
errors: &mut Vec<Error>,
) {
if let Some(crate::database::object::SchemaTypeOrArray::Single(t)) = &schema_arc.obj.type_ {
if t == "array" {
@ -70,7 +75,7 @@ impl Schema {
root_id: &str,
path: String,
to_insert: &mut Vec<(String, Arc<Schema>)>,
errors: &mut Vec<crate::drop::Error>,
errors: &mut Vec<Error>,
) {
if let Some(props) = &schema_arc.obj.properties {
for (k, v) in props.iter() {

View File

@ -159,7 +159,9 @@ impl Schema {
},
"null" => None,
custom => {
if db.enums.contains_key(custom) {
if custom.ends_with(".condition") || custom.ends_with(".filter") {
Some(vec![custom.to_string()])
} else if db.enums.contains_key(custom) {
Some(vec![format!("{}.condition", custom)])
} else {
// Assume anything else is a Relational cross-boundary that already has its own .filter dynamically built

View File

@ -5,7 +5,9 @@ pub mod filter;
pub mod polymorphism;
use crate::database::schema::Schema;
use crate::drop::{Error, ErrorDetails};
use indexmap::IndexMap;
use std::collections::HashMap;
impl Schema {
pub fn compile(
@ -13,7 +15,7 @@ impl Schema {
db: &crate::database::Database,
root_id: &str,
path: String,
errors: &mut Vec<crate::drop::Error>,
errors: &mut Vec<Error>,
) {
if self.obj.compiled_properties.get().is_some() {
return;
@ -72,13 +74,10 @@ impl Schema {
}
if custom_type_count > 1 {
errors.push(crate::drop::Error {
errors.push(Error {
code: "MULTIPLE_INHERITANCE_PROHIBITED".to_string(),
message: format!(
"Schema attempts to extend multiple custom object pointers in its type array {:?}. Use 'oneOf' for polymorphism and tagged unions.",
types
),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([("types".to_string(), types.join(", "))])),
details: ErrorDetails {
path: Some(path.clone()),
schema: Some(root_id.to_string()),
..Default::default()

View File

@ -1,4 +1,6 @@
use crate::drop::{Error, ErrorDetails};
use indexmap::IndexSet;
use std::collections::HashMap;
use crate::database::schema::Schema;
impl Schema {
@ -7,7 +9,7 @@ impl Schema {
db: &crate::database::Database,
root_id: &str,
path: &str,
errors: &mut Vec<crate::drop::Error>,
errors: &mut Vec<Error>,
) {
let mut options = indexmap::IndexMap::new();
let strategy: &str;
@ -118,16 +120,16 @@ impl Schema {
};
if strategy.is_empty() {
errors.push(crate::drop::Error {
code: "AMBIGUOUS_POLYMORPHISM".to_string(),
message: format!("oneOf boundaries must map mathematically unique 'type' or 'kind' discriminators, or strictly contain disjoint primitive types."),
details: crate::drop::ErrorDetails {
path: Some(path.to_string()),
schema: Some(root_id.to_string()),
..Default::default()
}
});
return;
errors.push(Error {
code: "AMBIGUOUS_POLYMORPHISM".to_string(),
values: None,
details: ErrorDetails {
path: Some(path.to_string()),
schema: Some(root_id.to_string()),
..Default::default()
}
});
return;
}
for (i, c) in one_of.iter().enumerate() {
@ -140,15 +142,15 @@ impl Schema {
if let Some(val) = c.obj.get_discriminator_value(&strategy, &child_id) {
if options.contains_key(&val) {
errors.push(crate::drop::Error {
errors.push(Error {
code: "POLYMORPHIC_COLLISION".to_string(),
message: format!("Polymorphic boundary defines multiple candidates mapped to the identical discriminator value '{}'.", val),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([("value".to_string(), val.to_string())])),
details: ErrorDetails {
path: Some(path.to_string()),
schema: Some(root_id.to_string()),
..Default::default()
}
});
}
});
continue;
}

View File

@ -1,7 +1,8 @@
use crate::drop::{Error, ErrorDetails};
use serde_json::Value;
use std::collections::{HashMap, HashSet};
pub fn compose(val: &mut Value, errors: &mut Vec<crate::drop::Error>) -> Result<(), String> {
pub fn compose(val: &mut Value, errors: &mut Vec<Error>) {
let mut traits = HashMap::new();
let mut schemas = HashMap::new();
@ -56,15 +57,13 @@ pub fn compose(val: &mut Value, errors: &mut Vec<crate::drop::Error>) -> Result<
}
}
}
Ok(())
}
fn resolve_in_place(
current: &mut Value,
traits: &HashMap<String, Value>,
schemas: &HashMap<String, Value>,
errors: &mut Vec<crate::drop::Error>,
errors: &mut Vec<Error>,
schema_id: &str,
path: &str,
visited: &mut HashSet<String>,
@ -118,10 +117,10 @@ fn resolve_in_place(
for inc in include_arr {
if let Some(inc_name) = inc.as_str() {
if visited.contains(inc_name) {
errors.push(crate::drop::Error {
errors.push(Error {
code: "CIRCULAR_INCLUDE_DETECTED".to_string(),
message: format!("Circular inclusion detected for '{}'", inc_name),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([("include".to_string(), inc_name.to_string())])),
details: ErrorDetails {
schema: Some(schema_id.to_string()),
path: Some(path.to_string()),
..Default::default()
@ -232,10 +231,10 @@ fn resolve_in_place(
}
}
} else {
errors.push(crate::drop::Error {
errors.push(Error {
code: "TRAIT_NOT_FOUND".to_string(),
message: format!("Trait or schema '{}' not found for inclusion", inc_name),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([("include".to_string(), inc_name.to_string())])),
details: ErrorDetails {
schema: Some(schema_id.to_string()),
path: Some(path.to_string()),
..Default::default()

View File

@ -85,14 +85,6 @@ impl DatabaseExecutor for MockExecutor {
Ok("2026-03-10T00:00:00Z".to_string())
}
fn auth_origin(&self) -> Result<Option<Value>, String> {
Ok(None)
}
fn punc_trigger(&self) -> Result<Option<String>, String> {
Ok(None)
}
#[cfg(test)]
fn get_queries(&self) -> Vec<String> {
MOCK_STATE.with(|state| state.borrow().captured_queries.clone())

View File

@ -20,12 +20,6 @@ pub trait DatabaseExecutor: Send + Sync {
/// Returns the current transaction timestamp
fn timestamp(&self) -> Result<String, String>;
/// Returns the current auth.origin session context if configured
fn auth_origin(&self) -> Result<Option<Value>, String>;
/// Returns the current punc.name session context if configured
fn punc_trigger(&self) -> Result<Option<String>, String>;
#[cfg(test)]
fn get_queries(&self) -> Vec<String>;

View File

@ -150,42 +150,4 @@ impl DatabaseExecutor for SpiExecutor {
})
})
}
fn auth_origin(&self) -> Result<Option<Value>, String> {
Spi::connect(|client| {
let mut tup_table = client
.select(
"SELECT NULLIF(current_setting('auth.origin', true), '')::jsonb",
None,
&[],
)
.map_err(|e| format!("SPI Select Error: {}", e))?;
if let Some(row) = tup_table.next() {
if let Ok(Some(jsonb)) = row.get::<pgrx::JsonB>(1) {
return Ok(Some(jsonb.0));
}
}
Ok(None)
})
}
fn punc_trigger(&self) -> Result<Option<String>, String> {
Spi::connect(|client| {
let mut tup_table = client
.select(
"SELECT NULLIF(current_setting('punc.name', true), '')",
None,
&[],
)
.map_err(|e| format!("SPI Select Error: {}", e))?;
if let Some(row) = tup_table.next() {
if let Ok(val_opt) = row.get::<String>(1) {
return Ok(val_opt);
}
}
Ok(None)
})
}
}

View File

@ -28,6 +28,8 @@ use serde_json::Value;
use indexmap::IndexMap;
use std::sync::Arc;
use r#type::Type;
use std::collections::HashMap;
use crate::drop::{Drop, Error, ErrorDetails};
#[derive(serde::Serialize)]
pub struct Database {
@ -57,13 +59,7 @@ impl Database {
let mut errors = Vec::new();
if let Err(e) = compose::compose(&mut val, &mut errors) {
errors.push(crate::drop::Error {
code: "COMPOSE_FAILED".to_string(),
message: format!("Fatal error during trait composition: {}", e),
details: crate::drop::ErrorDetails::default(),
});
}
compose::compose(&mut val, &mut errors);
if let serde_json::Value::Object(mut map) = val {
if let Some(serde_json::Value::Array(arr)) = map.remove("enums") {
@ -78,10 +74,13 @@ impl Database {
db.enums.insert(def.name.clone(), def);
}
Err(e) => {
errors.push(crate::drop::Error {
errors.push(Error {
code: "DATABASE_ENUM_PARSE_FAILED".to_string(),
message: format!("Failed to parse database enum '{}': {}", name, e),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("enum".to_string(), name.clone()),
("reason".to_string(), e.to_string()),
])),
details: ErrorDetails {
context: Some(serde_json::json!(name)),
..Default::default()
},
@ -103,10 +102,13 @@ impl Database {
db.types.insert(def.name.clone(), def);
}
Err(e) => {
errors.push(crate::drop::Error {
errors.push(Error {
code: "DATABASE_TYPE_PARSE_FAILED".to_string(),
message: format!("Failed to parse database type '{}': {}", name, e),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("type".to_string(), name.clone()),
("reason".to_string(), e.to_string()),
])),
details: ErrorDetails {
context: Some(serde_json::json!(name)),
..Default::default()
},
@ -132,10 +134,13 @@ impl Database {
}
}
Err(e) => {
errors.push(crate::drop::Error {
errors.push(Error {
code: "DATABASE_RELATION_PARSE_FAILED".to_string(),
message: format!("Failed to parse database relation '{}': {}", constraint, e),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("relation".to_string(), constraint.clone()),
("reason".to_string(), e.to_string()),
])),
details: ErrorDetails {
context: Some(serde_json::json!(constraint)),
..Default::default()
},
@ -157,10 +162,13 @@ impl Database {
db.puncs.insert(def.name.clone(), def);
}
Err(e) => {
errors.push(crate::drop::Error {
errors.push(Error {
code: "DATABASE_PUNC_PARSE_FAILED".to_string(),
message: format!("Failed to parse database punc '{}': {}", name, e),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("punc".to_string(), name.clone()),
("reason".to_string(), e.to_string()),
])),
details: ErrorDetails {
context: Some(serde_json::json!(name)),
..Default::default()
},
@ -173,9 +181,9 @@ impl Database {
db.compile(&mut errors);
let drop = if errors.is_empty() {
crate::drop::Drop::success()
Drop::success()
} else {
crate::drop::Drop::with_errors(errors)
Drop::with_errors(errors)
};
(db, drop)
}
@ -206,15 +214,6 @@ impl Database {
self.executor.timestamp()
}
/// Returns the current auth.origin session context if configured
pub fn auth_origin(&self) -> Result<Option<Value>, String> {
self.executor.auth_origin()
}
/// Returns the current punc.name session context if configured
pub fn punc_trigger(&self) -> Result<Option<String>, String> {
self.executor.punc_trigger()
}
pub fn compile(&mut self, errors: &mut Vec<crate::drop::Error>) {
// Phase 1: Registration
@ -452,7 +451,7 @@ impl Database {
// Abort relation discovery early if no hierarchical inheritance match was found
if matching_rels.is_empty() {
let mut details = crate::drop::ErrorDetails {
let mut details = ErrorDetails {
path: Some(path.to_string()),
..Default::default()
};
@ -460,12 +459,13 @@ impl Database {
details.schema = Some(sid.to_string());
}
errors.push(crate::drop::Error {
errors.push(Error {
code: "EDGE_MISSING".to_string(),
message: format!(
"No database relation exists between '{}' and '{}' for property '{}'",
parent_type, child_type, prop_name
),
values: Some(HashMap::from([
("parent_type".to_string(), parent_type.to_string()),
("child_type".to_string(), child_type.to_string()),
("property_name".to_string(), prop_name.to_string()),
])),
details,
});
return None;
@ -551,7 +551,7 @@ impl Database {
// we must abort rather than silently guessing. Returning None prevents arbitrary SQL generation
// and forces a clean structural error for the architect.
if !resolved {
let mut details = crate::drop::ErrorDetails {
let mut details = ErrorDetails {
path: Some(path.to_string()),
context: serde_json::to_value(&matching_rels).ok(),
cause: Some("Multiple conflicting constraints found matching prefixes".to_string()),
@ -561,12 +561,13 @@ impl Database {
details.schema = Some(sid.to_string());
}
errors.push(crate::drop::Error {
errors.push(Error {
code: "AMBIGUOUS_TYPE_RELATIONS".to_string(),
message: format!(
"Ambiguous database relation between '{}' and '{}' for property '{}'",
parent_type, child_type, prop_name
),
values: Some(HashMap::from([
("parent_type".to_string(), parent_type.to_string()),
("child_type".to_string(), child_type.to_string()),
("property_name".to_string(), prop_name.to_string()),
])),
details,
});
return None;

View File

@ -57,10 +57,13 @@ impl Drop {
}
}
use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Error {
pub code: String,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub values: Option<HashMap<String, String>>,
pub details: ErrorDetails,
}

View File

@ -31,7 +31,7 @@ lazy_static::lazy_static! {
fn jspg_failure() -> JsonB {
let error = crate::drop::Error {
code: "ENGINE_NOT_INITIALIZED".to_string(),
message: "JSPG extension has not been initialized via jspg_setup".to_string(),
values: None,
details: crate::drop::ErrorDetails {
path: None,
cause: None,

View File

@ -5,7 +5,9 @@ pub mod cache;
use crate::database::Database;
use crate::database::r#type::Type;
use crate::drop::{Drop, Error, ErrorDetails};
use serde_json::Value;
use std::collections::HashMap;
use std::sync::Arc;
pub struct Merger {
@ -21,20 +23,22 @@ impl Merger {
}
}
pub fn merge(&self, schema_id: &str, data: Value) -> crate::drop::Drop {
pub fn merge(&self, schema_id: &str, data: Value) -> Drop {
let mut notifications_queue = Vec::new();
let target_schema = match self.db.schemas.get(schema_id) {
Some(s) => Arc::clone(&s),
None => {
return crate::drop::Drop::with_errors(vec![crate::drop::Error {
code: "MERGE_FAILED".to_string(),
message: format!("Unknown schema_id: {}", schema_id),
details: crate::drop::ErrorDetails {
return Drop::with_errors(vec![Error {
code: "SCHEMA_NOT_FOUND".to_string(),
values: Some(HashMap::from([
("schema".to_string(), schema_id.to_string()),
])),
details: ErrorDetails {
path: None,
cause: None,
context: Some(data),
schema: None,
schema: Some(schema_id.to_string()),
},
}]);
}
@ -72,10 +76,12 @@ impl Merger {
}
}
return crate::drop::Drop::with_errors(vec![crate::drop::Error {
return Drop::with_errors(vec![Error {
code: final_code,
message: final_message,
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("error".to_string(), final_message),
])),
details: ErrorDetails {
path: None,
cause: final_cause,
context: None,
@ -88,10 +94,12 @@ impl Merger {
// Execute the globally collected, pre-ordered notifications last!
for notify_sql in notifications_queue {
if let Err(e) = self.db.execute(&notify_sql, None) {
return crate::drop::Drop::with_errors(vec![crate::drop::Error {
return Drop::with_errors(vec![Error {
code: "MERGE_FAILED".to_string(),
message: format!("Executor Error in pre-ordered notify: {:?}", e),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("error".to_string(), e.to_string()),
])),
details: ErrorDetails {
path: None,
cause: None,
context: None,
@ -138,7 +146,9 @@ impl Merger {
is_child: bool,
) -> Result<Value, String> {
match data {
Value::Array(items) => self.merge_array(schema, items, notifications, parent_org_id, is_child),
Value::Array(items) => {
self.merge_array(schema, items, notifications, parent_org_id, is_child)
}
Value::Object(map) => {
if let Some(options) = schema.obj.compiled_options.get() {
if let Some(disc) = schema.obj.compiled_discriminator.get() {
@ -210,7 +220,13 @@ impl Merger {
let mut resolved_items = Vec::new();
for item in items {
let resolved = self.merge_internal(item_schema.clone(), item, notifications, parent_org_id.clone(), is_child)?;
let resolved = self.merge_internal(
item_schema.clone(),
item,
notifications,
parent_org_id.clone(),
is_child,
)?;
resolved_items.push(resolved);
}
Ok(Value::Array(resolved_items))
@ -340,7 +356,10 @@ impl Merger {
if let Some(relation) = self.db.relations.get(&edge.constraint) {
let parent_is_source = edge.forward;
let org_id_to_pass = entity_fields.get("organization_id").and_then(|v| v.as_str()).map(|s| s.to_string());
let org_id_to_pass = entity_fields
.get("organization_id")
.and_then(|v| v.as_str())
.map(|s| s.to_string());
if parent_is_source {
let mut merged_relative = match self.merge_internal(
rel_schema.clone(),
@ -443,7 +462,10 @@ impl Merger {
}
}
let org_id_to_pass = entity_fields.get("organization_id").and_then(|v| v.as_str()).map(|s| s.to_string());
let org_id_to_pass = entity_fields
.get("organization_id")
.and_then(|v| v.as_str())
.map(|s| s.to_string());
let mut relative_responses = Vec::new();
for relative_item_val in relative_arr {
if let Value::Object(mut relative_item) = relative_item_val {
@ -574,7 +596,7 @@ impl Merger {
.and_then(|v| v.as_str())
.unwrap_or("");
let id_val = if entity_id.is_empty() {
Value::String(uuid::Uuid::new_v4().to_string())
Value::String(uuid::Uuid::now_v7().to_string())
} else {
Value::String(entity_id.to_string())
};
@ -777,13 +799,8 @@ impl Merger {
}
};
let mut execute_order: Vec<String> = entity_type.hierarchy.clone();
if change_kind == "create" {
execute_order.reverse();
}
for table_name in execute_order {
let table_fields = match grouped_fields.get(&table_name).and_then(|v| v.as_array()) {
for table_name in &entity_type.hierarchy {
let table_fields = match grouped_fields.get(table_name).and_then(|v| v.as_array()) {
Some(arr) => arr
.iter()
.filter_map(|v| v.as_str().map(|s| s.to_string()))
@ -946,25 +963,8 @@ impl Merger {
Value::Object(old_vals)
};
let origin = match self.db.auth_origin() {
Ok(Some(orig)) => orig,
_ => serde_json::json!({
"kind": "user",
"user_id": user_id
}),
};
let trigger = match self.db.punc_trigger() {
Ok(Some(trig)) => trig,
_ => "merge_entity".to_string(),
};
let entity_type_name = type_name.as_str().unwrap_or(&type_obj.name);
let mut notification = serde_json::Map::new();
notification.insert("type".to_string(), Value::String(entity_type_name.to_string()));
notification.insert("trigger".to_string(), Value::String(trigger));
notification.insert("origin".to_string(), origin.clone());
notification.insert("kind".to_string(), Value::String(change_kind.to_string()));
notification.insert("complete".to_string(), Value::Object(complete));
notification.insert("new".to_string(), new_val_obj.clone());
@ -979,16 +979,14 @@ impl Merger {
let mut notify_sql = None;
if type_obj.historical && change_kind != "replace" {
let change_sql = format!(
"INSERT INTO agreego.change (\"old\", \"new\", entity_id, id, kind, modified_at, modified_by, origin, entity_type) VALUES ({}, {}, {}, {}, {}, {}, {}, {}, {})",
"INSERT INTO agreego.change (\"old\", \"new\", \"entity_id\", \"id\", \"kind\", \"modified_at\", \"modified_by\") VALUES ({}, {}, {}, {}, {}, {}, {})",
Self::quote_literal(&old_val_obj),
Self::quote_literal(&new_val_obj),
Self::quote_literal(id_str),
Self::quote_literal(&Value::String(uuid::Uuid::new_v4().to_string())),
Self::quote_literal(&Value::String(uuid::Uuid::now_v7().to_string())),
Self::quote_literal(&Value::String(change_kind.to_string())),
Self::quote_literal(&Value::String(timestamp.to_string())),
Self::quote_literal(&Value::String(user_id.to_string())),
Self::quote_literal(&origin),
Self::quote_literal(&Value::String(entity_type_name.to_string()))
Self::quote_literal(&Value::String(user_id.to_string()))
);
self.db.execute(&change_sql, None)?;

View File

@ -1,4 +1,6 @@
use crate::database::Database;
use crate::drop::{Drop, Error, ErrorDetails};
use std::collections::HashMap;
use std::sync::Arc;
pub mod compiler;
@ -22,17 +24,19 @@ impl Queryer {
&self,
schema_id: &str,
filter: Option<&serde_json::Value>,
) -> crate::drop::Drop {
) -> Drop {
let filters_map = filter.and_then(|f| f.as_object());
// 1. Process filters into structured $op keys and linear values
let (filter_keys, args) = match self.parse_filter_entries(filters_map) {
Ok(res) => res,
Err(msg) => {
return crate::drop::Drop::with_errors(vec![crate::drop::Error {
return Drop::with_errors(vec![Error {
code: "FILTER_PARSE_FAILED".to_string(),
message: msg.clone(),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("error".to_string(), msg.clone()),
])),
details: ErrorDetails {
path: None, // filters apply to the root query
cause: Some(msg),
context: filter.cloned(),
@ -134,10 +138,12 @@ impl Queryer {
.insert(cache_key.to_string(), compiled_sql.clone());
Ok(compiled_sql)
}
Err(e) => Err(crate::drop::Drop::with_errors(vec![crate::drop::Error {
Err(e) => Err(Drop::with_errors(vec![Error {
code: "QUERY_COMPILATION_FAILED".to_string(),
message: e.clone(),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("error".to_string(), e.clone()),
])),
details: ErrorDetails {
path: None,
cause: Some(e),
context: None,
@ -152,29 +158,33 @@ impl Queryer {
schema_id: &str,
sql: &str,
args: Vec<serde_json::Value>,
) -> crate::drop::Drop {
) -> Drop {
match self.db.query(sql, Some(args)) {
Ok(serde_json::Value::Array(table)) => {
if table.is_empty() {
crate::drop::Drop::success_with_val(serde_json::Value::Null)
Drop::success_with_val(serde_json::Value::Null)
} else {
crate::drop::Drop::success_with_val(table.first().unwrap().clone())
Drop::success_with_val(table.first().unwrap().clone())
}
}
Ok(other) => crate::drop::Drop::with_errors(vec![crate::drop::Error {
Ok(other) => Drop::with_errors(vec![Error {
code: "QUERY_FAILED".to_string(),
message: format!("Expected array from generic query, got: {:?}", other),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("error".to_string(), format!("Expected array from generic query, got: {:?}", other)),
])),
details: ErrorDetails {
path: None,
cause: Some(format!("Expected array, got {}", other)),
context: Some(serde_json::json!([sql])),
schema: Some(schema_id.to_string()),
},
}]),
Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error {
Err(e) => Drop::with_errors(vec![Error {
code: "QUERY_FAILED".to_string(),
message: format!("SPI error in queryer: {}", e),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("error".to_string(), e.to_string()),
])),
details: ErrorDetails {
path: None,
cause: Some(format!("SPI error in queryer: {}", e)),
context: Some(serde_json::json!([sql])),

View File

@ -18,7 +18,6 @@ fn test_library_api() {
"type": "drop",
"errors": [{
"code": "ENGINE_NOT_INITIALIZED",
"message": "JSPG extension has not been initialized via jspg_setup",
"details": {}
}]
})
@ -44,7 +43,7 @@ fn test_library_api() {
{
"name": "source_schema",
"variations": ["source_schema"],
"hierarchy": ["source_schema", "entity"],
"hierarchy": ["entity", "source_schema"],
"schemas": {
"source_schema": {
"type": "object",
@ -60,7 +59,7 @@ fn test_library_api() {
{
"name": "target_schema",
"variations": ["target_schema"],
"hierarchy": ["target_schema", "entity"],
"hierarchy": ["entity", "target_schema"],
"schemas": {
"target_schema": {
"type": "object",
@ -109,7 +108,7 @@ fn test_library_api() {
"field_types": null,
"fields": [],
"grouped_fields": null,
"hierarchy": ["source_schema", "entity"],
"hierarchy": ["entity", "source_schema"],
"historical": false,
"id": "",
"longevity": null,
@ -174,7 +173,7 @@ fn test_library_api() {
"field_types": null,
"fields": [],
"grouped_fields": null,
"hierarchy": ["target_schema", "entity"],
"hierarchy": ["entity", "target_schema"],
"historical": false,
"id": "",
"longevity": null,
@ -250,13 +249,23 @@ fn test_library_api() {
"errors": [
{
"code": "REQUIRED_FIELD_MISSING",
"message": "Missing name",
"details": { "path": "name" }
"values": {
"field_name": "name"
},
"details": {
"path": "name",
"schema": "source_schema"
}
},
{
"code": "STRICT_PROPERTY_VIOLATION",
"message": "Unexpected property 'wrong'",
"details": { "path": "wrong" }
"values": {
"property_name": "wrong"
},
"details": {
"path": "wrong",
"schema": "source_schema"
}
}
]
})

View File

@ -86,7 +86,7 @@ pub fn run_test_case(path: &str, suite_idx: usize, case_idx: usize) -> Result<()
let error_messages: Vec<String> = drop
.errors
.iter()
.map(|e| format!("Error {} at path {}: {}", e.code, e.details.path.as_deref().unwrap_or("/"), e.message))
.map(|e| format!("Error {} at path {}: {:?}", e.code, e.details.path.as_deref().unwrap_or("/"), e.values))
.collect();
failures.push(format!(
"[{}] Cannot run '{}' test '{}': System Setup Compilation structurally failed:\n{}",
@ -107,7 +107,7 @@ pub fn run_test_case(path: &str, suite_idx: usize, case_idx: usize) -> Result<()
match test.action.as_str() {
"compile" => {
let result = test.run_compile(db);
let result = test.run_compile(db, path, suite_idx, case_idx);
if let Err(e) = result {
println!("TEST COMPILE ERROR FOR '{}': {}", test.description, e);
failures.push(format!(
@ -117,7 +117,7 @@ pub fn run_test_case(path: &str, suite_idx: usize, case_idx: usize) -> Result<()
}
}
"validate" => {
let result = test.run_validate(db_unwrapped.unwrap());
let result = test.run_validate(db_unwrapped.unwrap(), path, suite_idx, case_idx);
if let Err(e) = result {
println!("TEST VALIDATE ERROR FOR '{}': {}", test.description, e);
failures.push(format!(
@ -205,6 +205,25 @@ pub fn canonicalize_with_map(s: &str, uuid_map: &HashMap<String, String>, gen_ma
ts_re.replace_all(&s1, "{{timestamp}}").to_string()
}
pub fn update_validation_fixture(path: &str, suite_idx: usize, case_idx: usize, errors: &[crate::drop::Error]) {
let content = fs::read_to_string(path).unwrap();
let mut file_data: Value = serde_json::from_str(&content).unwrap();
if let Some(expect) = file_data[suite_idx]["tests"][case_idx].get_mut("expect") {
if let Some(obj) = expect.as_object_mut() {
if errors.is_empty() {
obj.remove("errors");
} else {
let serialized_errors = serde_json::to_value(errors).unwrap();
obj.insert("errors".to_string(), serialized_errors);
}
}
}
let formatted_json = serde_json::to_string_pretty(&file_data).unwrap();
fs::write(path, formatted_json).unwrap();
}
pub fn update_sql_fixture(path: &str, suite_idx: usize, case_idx: usize, queries: &[String]) {
use crate::tests::formatter::SqlFormatter;
let content = fs::read_to_string(path).unwrap();

View File

@ -1,7 +1,10 @@
use super::expect::Expect;
use crate::database::Database;
use crate::tests::runner::update_validation_fixture;
use crate::validator::Validator;
use serde::Deserialize;
use serde_json::Value;
use std::env;
use std::sync::Arc;
#[derive(Debug, Deserialize)]
@ -38,6 +41,9 @@ impl Case {
pub fn run_compile(
&self,
db_res: &Result<Arc<Database>, crate::drop::Drop>,
path: &str,
suite_idx: usize,
case_idx: usize,
) -> Result<(), String> {
let expect = match &self.expect {
Some(e) => e,
@ -49,6 +55,10 @@ impl Case {
Err(d) => d.clone(),
};
if env::var("UPDATE_EXPECT").is_ok() {
update_validation_fixture(path, suite_idx, case_idx, &result.errors);
}
expect.assert_drop(&result)?;
if let Ok(db) = db_res {
@ -58,16 +68,16 @@ impl Case {
Ok(())
}
pub fn run_validate(&self, db: Arc<Database>) -> Result<(), String> {
use crate::validator::Validator;
pub fn run_validate(&self, db: Arc<Database>, path: &str, suite_idx: usize, case_idx: usize) -> Result<(), String> {
let validator = Validator::new(db);
let schema_id = &self.schema_id;
let test_data = self.data.clone().unwrap_or(Value::Null);
let result = validator.validate(schema_id, &test_data);
if env::var("UPDATE_EXPECT").is_ok() {
update_validation_fixture(path, suite_idx, case_idx, &result.errors);
}
if let Some(expect) = &self.expect {
expect.assert_drop(&result)?;
}
@ -96,8 +106,10 @@ impl Case {
let queries = db.executor.get_queries();
if std::env::var("UPDATE_EXPECT").is_ok() {
crate::tests::runner::update_sql_fixture(path, suite_idx, case_idx, &queries);
Ok(())
} else {
expect.assert_sql(&queries)
}
expect.assert_sql(&queries)
} else {
Ok(())
}
@ -128,8 +140,10 @@ impl Case {
let queries = db.executor.get_queries();
if std::env::var("UPDATE_EXPECT").is_ok() {
crate::tests::runner::update_sql_fixture(path, suite_idx, case_idx, &queries);
Ok(())
} else {
expect.assert_sql(&queries)
}
expect.assert_sql(&queries)
} else {
Ok(())
}

View File

@ -1,4 +1,5 @@
use super::Expect;
use serde_json::Value;
impl Expect {
pub fn assert_drop(&self, drop: &crate::drop::Drop) -> Result<(), String> {
@ -14,14 +15,14 @@ impl Expect {
if !self.success {
if let Some(expected_errors) = &self.errors {
let actual_values: Vec<serde_json::Value> = drop.errors
let actual_values: Vec<Value> = drop.errors
.iter()
.map(|e| serde_json::to_value(e).unwrap())
.collect();
if expected_errors.len() != actual_values.len() {
return Err(format!(
"Expected {} errors, but got {}.\nExpected subset: {:?}\nActual full errors: {:?}",
"Expected {} errors, but got {}.\nExpected: {:?}\nActual full errors: {:?}",
expected_errors.len(),
actual_values.len(),
expected_errors,
@ -31,17 +32,15 @@ impl Expect {
for (i, expected_val) in expected_errors.iter().enumerate() {
let mut matched = false;
for actual_val in &actual_values {
if subset_match(expected_val, actual_val) {
if expected_val == actual_val {
matched = true;
break;
}
}
if !matched {
return Err(format!(
"Expected error {} was not found in actual errors.\nExpected subset: {}\nActual full errors: {:?}",
"Expected error {} was not found in actual errors.\nExpected: {}\nActual full errors: {:?}",
i,
serde_json::to_string_pretty(expected_val).unwrap(),
drop.errors,
@ -54,35 +53,3 @@ impl Expect {
Ok(())
}
}
// Helper to check if `expected` is a structural subset of `actual`
fn subset_match(expected: &serde_json::Value, actual: &serde_json::Value) -> bool {
match (expected, actual) {
(serde_json::Value::Object(exp_map), serde_json::Value::Object(act_map)) => {
for (k, v) in exp_map {
if let Some(act_v) = act_map.get(k) {
if !subset_match(v, act_v) {
return false;
}
} else {
return false;
}
}
true
}
(serde_json::Value::Array(exp_arr), serde_json::Value::Array(act_arr)) => {
// Basic check: array sizes and elements must match exactly in order
if exp_arr.len() != act_arr.len() {
return false;
}
for (e, a) in exp_arr.iter().zip(act_arr.iter()) {
if !subset_match(e, a) {
return false;
}
}
true
}
// For primitives, exact match
(e, a) => e == a,
}
}

View File

@ -1,4 +1,3 @@
pub mod pattern;
pub mod sql;
pub mod drop;
pub mod schema;

View File

@ -1,132 +0,0 @@
use super::Expect;
use regex::Regex;
use std::collections::HashMap;
impl Expect {
/// Advanced SQL execution assertion algorithm ported from `assert.go`.
/// This compares two arrays of strings, one containing {{uuid:name}} or {{timestamp}} placeholders,
/// and the other containing actual executed database queries. It ensures that placeholder UUIDs
/// are consistently mapped to the same actual UUIDs across all lines, and strictly validates line-by-line sequences.
pub fn assert_pattern(&self, actual: &[String]) -> Result<(), String> {
let patterns = match &self.sql {
Some(s) => s,
None => return Ok(()),
};
if patterns.len() != actual.len() {
return Err(format!(
"Length mismatch: expected {} SQL executions, got {}.\nActual Execution Log:\n{}",
patterns.len(),
actual.len(),
actual.join("\n")
));
}
let ws_re = Regex::new(r"\s+").unwrap();
let types = HashMap::from([
(
"uuid",
r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
),
(
"timestamp",
r"\d{4}-\d{2}-\d{2}(?:[ T])\d{2}:\d{2}:\d{2}(?:\.\d{1,6})?(?:Z|\+\d{2}(?::\d{2})?)?",
),
("integer", r"-?\d+"),
("float", r"-?\d+\.\d+"),
("text", r"(?:''|[^'])*"),
("json", r"(?:''|[^'])*"),
]);
let mut seen: HashMap<String, String> = HashMap::new();
let system_uuid = "00000000-0000-0000-0000-000000000000";
// Placeholder regex: {{type:name}} or {{type}}
let ph_rx = Regex::new(r"\{\{([a-z]+)(?:[:]([^}]+))?\}\}").unwrap();
let clean_str = |s: &str| -> String {
let mut s = ws_re.replace_all(s, " ").into_owned();
for token in ["(", ")", ",", "{", "}", "\"", "=", "'"] {
s = s.replace(&format!(" {}", token), token);
s = s.replace(&format!("{} ", token), token);
}
s.trim().to_string()
};
for (i, pattern_expect) in patterns.iter().enumerate() {
let aline_raw = &actual[i];
let aline = clean_str(aline_raw);
let pattern_str_raw = match pattern_expect {
super::SqlExpectation::Single(s) => s.clone(),
super::SqlExpectation::Multi(m) => m.join(" "),
};
let pattern_str = clean_str(&pattern_str_raw);
let mut pp = regex::escape(&pattern_str);
pp = pp.replace(r"\{\{", "{{").replace(r"\}\}", "}}");
let mut cap_names = HashMap::new(); // cg_X -> var_name
let mut group_idx = 0;
let mut final_rx_str = String::new();
let mut last_match = 0;
let pp_clone = pp.clone();
for caps in ph_rx.captures_iter(&pp_clone) {
let full_match = caps.get(0).unwrap();
final_rx_str.push_str(&pp[last_match..full_match.start()]);
let type_name = caps.get(1).unwrap().as_str();
let var_name = caps.get(2).map(|m| m.as_str());
if let Some(name) = var_name {
if let Some(val) = seen.get(name) {
final_rx_str.push_str(&regex::escape(val));
} else {
let type_pattern = types.get(type_name).unwrap_or(&".*?");
let cg_name = format!("cg_{}", group_idx);
final_rx_str.push_str(&format!("(?P<{}>{})", cg_name, type_pattern));
cap_names.insert(cg_name, name.to_string());
group_idx += 1;
}
} else {
let type_pattern = types.get(type_name).unwrap_or(&".*?");
final_rx_str.push_str(&format!("(?:{})", type_pattern));
}
last_match = full_match.end();
}
final_rx_str.push_str(&pp[last_match..]);
let final_rx = match Regex::new(&format!("^{}$", final_rx_str)) {
Ok(r) => r,
Err(e) => return Err(format!("Bad constructed regex: {} -> {}", final_rx_str, e)),
};
if let Some(captures) = final_rx.captures(&aline) {
for (cg_name, var_name) in cap_names {
if let Some(m) = captures.name(&cg_name) {
let matched_str = m.as_str();
if matched_str != system_uuid {
seen.insert(var_name, matched_str.to_string());
}
}
}
} else {
return Err(format!(
"Line mismatched at execution sequence {}.\nExpected Pattern: {}\nActual SQL: {}\nRegex used: {}\nVariables Mapped: {:?}",
i + 1,
pattern_str,
aline,
final_rx_str,
seen
));
}
}
Ok(())
}
}

View File

@ -1,8 +1,9 @@
use super::Expect;
use regex::Regex;
use sqlparser::ast::{Expr, Query, SelectItem, Statement, TableFactor};
use sqlparser::dialect::PostgreSqlDialect;
use sqlparser::parser::Parser;
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
impl Expect {
pub fn assert_sql(&self, actual: &[String]) -> Result<(), String> {
@ -11,6 +12,7 @@ impl Expect {
return Err(e);
}
}
self.assert_pattern(actual)?;
Ok(())
}
@ -203,4 +205,132 @@ impl Expect {
}
Ok(())
}
/// Advanced SQL execution assertion algorithm ported from `assert.go`.
/// This compares two arrays of strings, one containing {{uuid:name}} or {{timestamp}} placeholders,
/// and the other containing actual executed database queries. It ensures that placeholder UUIDs
/// are consistently mapped to the same actual UUIDs across all lines, and strictly validates line-by-line sequences.
pub fn assert_pattern(&self, actual: &[String]) -> Result<(), String> {
let patterns = match &self.sql {
Some(s) => s,
None => return Ok(()),
};
if patterns.len() != actual.len() {
return Err(format!(
"Length mismatch: expected {} SQL executions, got {}.\nActual Execution Log:\n{}",
patterns.len(),
actual.len(),
actual.join("\n")
));
}
let ws_re = Regex::new(r"\s+").unwrap();
let types = HashMap::from([
(
"uuid",
r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
),
(
"timestamp",
r"\d{4}-\d{2}-\d{2}(?:[ T])\d{2}:\d{2}:\d{2}(?:\.\d{1,6})?(?:Z|\+\d{2}(?::\d{2})?)?",
),
("integer", r"-?\d+"),
("float", r"-?\d+\.\d+"),
("text", r"(?:''|[^'])*"),
("json", r"(?:''|[^'])*"),
]);
let mut seen: HashMap<String, String> = HashMap::new();
let system_uuid = "00000000-0000-0000-0000-000000000000";
// Placeholder regex: {{type:name}} or {{type}}
let ph_rx = Regex::new(r"\{\{([a-z]+)(?:[:]([^}]+))?\}\}").unwrap();
let clean_str = |s: &str| -> String {
let mut s = ws_re.replace_all(s, " ").into_owned();
for token in ["(", ")", ",", "{", "}", "\"", "=", "'"] {
s = s.replace(&format!(" {}", token), token);
s = s.replace(&format!("{} ", token), token);
}
s.trim().to_string()
};
for (i, pattern_expect) in patterns.iter().enumerate() {
let aline_raw = &actual[i];
let formatted_actual = crate::tests::formatter::SqlFormatter::format(aline_raw).join(" ");
let aline = clean_str(&formatted_actual);
let pattern_str_raw = match pattern_expect {
super::SqlExpectation::Single(s) => s.clone(),
super::SqlExpectation::Multi(m) => m.join(" "),
};
let pattern_str = clean_str(&pattern_str_raw);
let mut pp = regex::escape(&pattern_str);
pp = pp.replace(r"\{\{", "{{").replace(r"\}\}", "}}");
let mut cap_names = HashMap::new(); // cg_X -> var_name
let mut group_idx = 0;
let mut final_rx_str = String::new();
let mut last_match = 0;
let pp_clone = pp.clone();
for caps in ph_rx.captures_iter(&pp_clone) {
let full_match = caps.get(0).unwrap();
final_rx_str.push_str(&pp[last_match..full_match.start()]);
let type_name = caps.get(1).unwrap().as_str();
let var_name = caps.get(2).map(|m| m.as_str());
if let Some(name) = var_name {
if let Some(val) = seen.get(name) {
final_rx_str.push_str(&regex::escape(val));
} else {
let type_pattern = types.get(type_name).unwrap_or(&".*?");
let cg_name = format!("cg_{}", group_idx);
final_rx_str.push_str(&format!("(?P<{}>{})", cg_name, type_pattern));
cap_names.insert(cg_name, name.to_string());
group_idx += 1;
}
} else {
let type_pattern = types.get(type_name).unwrap_or(&".*?");
final_rx_str.push_str(&format!("(?:{})", type_pattern));
}
last_match = full_match.end();
}
final_rx_str.push_str(&pp[last_match..]);
let final_rx = match Regex::new(&format!("^{}$", final_rx_str)) {
Ok(r) => r,
Err(e) => return Err(format!("Bad constructed regex: {} -> {}", final_rx_str, e)),
};
if let Some(captures) = final_rx.captures(&aline) {
for (cg_name, var_name) in cap_names {
if let Some(m) = captures.name(&cg_name) {
let matched_str = m.as_str();
if matched_str != system_uuid {
seen.insert(var_name, matched_str.to_string());
}
}
}
} else {
return Err(format!(
"Line mismatched at execution sequence {}.\nExpected Pattern: {}\nActual SQL: {}\nRegex used: {}\nVariables Mapped: {:?}",
i + 1,
pattern_str,
aline,
final_rx_str,
seen
));
}
}
Ok(())
}
}

View File

@ -1,6 +1,9 @@
use std::collections::HashMap;
#[derive(Debug, Clone, serde::Serialize)]
pub struct ValidationError {
pub code: String,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub values: Option<HashMap<String, String>>,
pub path: String,
}

View File

@ -1,4 +1,4 @@
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
pub mod context;
pub mod error;
@ -13,6 +13,7 @@ use crate::database::Database;
use crate::validator::rules::util::is_integer;
use serde_json::Value;
use std::sync::Arc;
use crate::drop::{Drop, Error, ErrorDetails};
pub struct Validator {
pub db: Arc<Database>,
@ -57,45 +58,47 @@ impl Validator {
match ctx.validate_scoped() {
Ok(result) => {
if result.is_valid() {
crate::drop::Drop::success()
Drop::success()
} else {
let errors: Vec<crate::drop::Error> = result
let errors: Vec<Error> = result
.errors
.into_iter()
.map(|e| crate::drop::Error {
.map(|e| Error {
code: e.code,
message: e.message,
details: crate::drop::ErrorDetails {
values: e.values,
details: ErrorDetails {
path: Some(e.path),
cause: None,
context: None,
schema: None,
schema: Some(schema_id.to_string()),
},
})
.collect();
crate::drop::Drop::with_errors(errors)
Drop::with_errors(errors)
}
}
Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error {
Err(e) => Drop::with_errors(vec![Error {
code: e.code,
message: e.message,
details: crate::drop::ErrorDetails {
values: e.values,
details: ErrorDetails {
path: Some(e.path),
cause: None,
context: None,
schema: None,
schema: Some(schema_id.to_string()),
},
}]),
}
} else {
crate::drop::Drop::with_errors(vec![crate::drop::Error {
Drop::with_errors(vec![Error {
code: "SCHEMA_NOT_FOUND".to_string(),
message: format!("Schema {} not found", schema_id),
details: crate::drop::ErrorDetails {
values: Some(HashMap::from([
("schema".to_string(), schema_id.to_string()),
])),
details: ErrorDetails {
path: Some("/".to_string()),
cause: None,
context: None,
schema: None,
schema: Some(schema_id.to_string()),
},
}])
}

View File

@ -1,4 +1,4 @@
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
use serde_json::Value;
@ -17,8 +17,11 @@ impl<'a> ValidationContext<'a> {
&& (arr.len() as f64) < min
{
result.errors.push(ValidationError {
code: "MIN_ITEMS".to_string(),
message: "Too few items".to_string(),
code: "MIN_ITEMS_VIOLATED".to_string(),
values: Some(HashMap::from([
("count".to_string(), arr.len().to_string()),
("limit".to_string(), min.to_string()),
])),
path: self.path.to_string(),
});
}
@ -26,8 +29,11 @@ impl<'a> ValidationContext<'a> {
&& (arr.len() as f64) > max
{
result.errors.push(ValidationError {
code: "MAX_ITEMS".to_string(),
message: "Too many items".to_string(),
code: "MAX_ITEMS_VIOLATED".to_string(),
values: Some(HashMap::from([
("count".to_string(), arr.len().to_string()),
("limit".to_string(), max.to_string()),
])),
path: self.path.to_string(),
});
}
@ -38,7 +44,7 @@ impl<'a> ValidationContext<'a> {
if seen.contains(&item) {
result.errors.push(ValidationError {
code: "UNIQUE_ITEMS_VIOLATED".to_string(),
message: "Array has duplicate items".to_string(),
values: None,
path: self.path.to_string(),
});
break;
@ -71,7 +77,10 @@ impl<'a> ValidationContext<'a> {
if _match_count < min {
result.errors.push(ValidationError {
code: "CONTAINS_VIOLATED".to_string(),
message: format!("Contains matches {} < min {}", _match_count, min),
values: Some(HashMap::from([
("count".to_string(), _match_count.to_string()),
("limit".to_string(), min.to_string()),
])),
path: self.path.to_string(),
});
}
@ -80,7 +89,10 @@ impl<'a> ValidationContext<'a> {
{
result.errors.push(ValidationError {
code: "CONTAINS_VIOLATED".to_string(),
message: format!("Contains matches {} > max {}", _match_count, max),
values: Some(HashMap::from([
("count".to_string(), _match_count.to_string()),
("limit".to_string(), max.to_string()),
])),
path: self.path.to_string(),
});
}

View File

@ -1,3 +1,5 @@
use std::collections::HashMap;
use crate::validator::Validator;
use crate::validator::context::ValidationContext;
use crate::validator::error::ValidationError;
@ -17,7 +19,9 @@ impl<'a> ValidationContext<'a> {
if !Validator::check_type(t, current) {
result.errors.push(ValidationError {
code: "INVALID_TYPE".to_string(),
message: format!("Expected type '{}'", t),
values: Some(HashMap::from([
("expected".to_string(), t.to_string()),
])),
path: self.path.to_string(),
});
}
@ -33,7 +37,9 @@ impl<'a> ValidationContext<'a> {
if !valid {
result.errors.push(ValidationError {
code: "INVALID_TYPE".to_string(),
message: format!("Expected one of types {:?}", types),
values: Some(HashMap::from([
("expected".to_string(), format!("{:?}", types)),
])),
path: self.path.to_string(),
});
}
@ -45,7 +51,9 @@ impl<'a> ValidationContext<'a> {
if !equals(current, const_val) {
result.errors.push(ValidationError {
code: "CONST_VIOLATED".to_string(),
message: "Value does not match const".to_string(),
values: Some(HashMap::from([
("expected".to_string(), format!("{:?}", const_val)),
])),
path: self.path.to_string(),
});
} else if let Some(obj) = current.as_object() {
@ -66,7 +74,9 @@ impl<'a> ValidationContext<'a> {
if !found {
result.errors.push(ValidationError {
code: "ENUM_MISMATCH".to_string(),
message: "Value is not in enum".to_string(),
values: Some(HashMap::from([
("expected".to_string(), format!("{:?}", enum_vals)),
])),
path: self.path.to_string(),
});
} else if let Some(obj) = current.as_object() {

View File

@ -1,3 +1,5 @@
use std::collections::HashMap;
use crate::validator::context::ValidationContext;
use crate::validator::error::ValidationError;
use crate::validator::result::ValidationResult;
@ -27,7 +29,9 @@ impl<'a> ValidationContext<'a> {
if !result.evaluated_keys.contains(key) && !self.overrides.contains(key) {
result.errors.push(ValidationError {
code: "STRICT_PROPERTY_VIOLATION".to_string(),
message: format!("Unexpected property '{}'", key),
values: Some(HashMap::from([
("property_name".to_string(), key.to_string()),
])),
path: self.join_path(key),
});
}
@ -47,7 +51,9 @@ impl<'a> ValidationContext<'a> {
}
result.errors.push(ValidationError {
code: "STRICT_ITEM_VIOLATION".to_string(),
message: format!("Unexpected item at index {}", i),
values: Some(HashMap::from([
("index".to_string(), i.to_string()),
])),
path: item_path,
});
}

View File

@ -1,3 +1,5 @@
use std::collections::HashMap;
use crate::validator::context::ValidationContext;
use crate::validator::error::ValidationError;
use crate::validator::result::ValidationResult;
@ -19,7 +21,10 @@ impl<'a> ValidationContext<'a> {
if should && let Err(e) = f(current) {
result.errors.push(ValidationError {
code: "FORMAT_MISMATCH".to_string(),
message: format!("Format error: {}", e),
values: Some(HashMap::from([
("format".to_string(), self.schema.format.clone().unwrap_or_default()),
("error".to_string(), e.to_string()),
])),
path: self.path.to_string(),
});
}
@ -30,7 +35,9 @@ impl<'a> ValidationContext<'a> {
{
result.errors.push(ValidationError {
code: "FORMAT_MISMATCH".to_string(),
message: "Format regex mismatch".to_string(),
values: Some(HashMap::from([
("format".to_string(), self.schema.format.clone().unwrap_or_default()),
])),
path: self.path.to_string(),
});
}

View File

@ -1,6 +1,7 @@
use crate::validator::context::ValidationContext;
use crate::validator::error::ValidationError;
use crate::validator::result::ValidationResult;
use std::collections::HashMap;
pub mod array;
pub mod cases;
@ -61,7 +62,9 @@ impl<'a> ValidationContext<'a> {
if self.depth > 100 {
Err(ValidationError {
code: "RECURSION_LIMIT_EXCEEDED".to_string(),
message: "Recursion limit exceeded".to_string(),
values: Some(HashMap::from([
("limit".to_string(), 100.to_string()),
])),
path: self.path.to_string(),
})
} else {
@ -73,7 +76,7 @@ impl<'a> ValidationContext<'a> {
if self.schema.always_fail {
result.errors.push(ValidationError {
code: "FALSE_SCHEMA".to_string(),
message: "Schema is false".to_string(),
values: None,
path: self.path.to_string(),
});
// Short-circuit

View File

@ -13,7 +13,7 @@ impl<'a> ValidationContext<'a> {
if sub_res.is_valid() {
result.errors.push(ValidationError {
code: "NOT_VIOLATED".to_string(),
message: "Matched 'not' schema".to_string(),
values: None,
path: self.path.to_string(),
});
}

View File

@ -1,3 +1,5 @@
use std::collections::HashMap;
use crate::validator::context::ValidationContext;
use crate::validator::error::ValidationError;
use crate::validator::result::ValidationResult;
@ -14,7 +16,10 @@ impl<'a> ValidationContext<'a> {
{
result.errors.push(ValidationError {
code: "MINIMUM_VIOLATED".to_string(),
message: format!("Value {} < min {}", num, min),
values: Some(HashMap::from([
("value".to_string(), num.to_string()),
("limit".to_string(), min.to_string()),
])),
path: self.path.to_string(),
});
}
@ -23,7 +28,10 @@ impl<'a> ValidationContext<'a> {
{
result.errors.push(ValidationError {
code: "MAXIMUM_VIOLATED".to_string(),
message: format!("Value {} > max {}", num, max),
values: Some(HashMap::from([
("value".to_string(), num.to_string()),
("limit".to_string(), max.to_string()),
])),
path: self.path.to_string(),
});
}
@ -32,7 +40,10 @@ impl<'a> ValidationContext<'a> {
{
result.errors.push(ValidationError {
code: "EXCLUSIVE_MINIMUM_VIOLATED".to_string(),
message: format!("Value {} <= ex_min {}", num, ex_min),
values: Some(HashMap::from([
("value".to_string(), num.to_string()),
("limit".to_string(), ex_min.to_string()),
])),
path: self.path.to_string(),
});
}
@ -41,7 +52,10 @@ impl<'a> ValidationContext<'a> {
{
result.errors.push(ValidationError {
code: "EXCLUSIVE_MAXIMUM_VIOLATED".to_string(),
message: format!("Value {} >= ex_max {}", num, ex_max),
values: Some(HashMap::from([
("value".to_string(), num.to_string()),
("limit".to_string(), ex_max.to_string()),
])),
path: self.path.to_string(),
});
}
@ -50,7 +64,10 @@ impl<'a> ValidationContext<'a> {
if (val - val.round()).abs() > f64::EPSILON {
result.errors.push(ValidationError {
code: "MULTIPLE_OF_VIOLATED".to_string(),
message: format!("Value {} not multiple of {}", num, multiple_of),
values: Some(HashMap::from([
("value".to_string(), num.to_string()),
("multiple_of".to_string(), multiple_of.to_string()),
])),
path: self.path.to_string(),
});
}

View File

@ -1,4 +1,4 @@
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
use serde_json::Value;
@ -38,10 +38,9 @@ impl<'a> ValidationContext<'a> {
} else {
result.errors.push(ValidationError {
code: "CONST_VIOLATED".to_string(), // Aligning with original const override errors natively
message: format!(
"Type '{}' is not a valid descendant for this entity bound schema",
type_str
),
values: Some(HashMap::from([
("value".to_string(), type_str.to_string()),
])),
path: self.join_path("type"),
});
}
@ -50,10 +49,9 @@ impl<'a> ValidationContext<'a> {
// Because it's a global entity target, the payload must structurally provide a discriminator natively
result.errors.push(ValidationError {
code: "MISSING_TYPE".to_string(),
message: format!(
"Schema mechanically requires type discrimination '{}'",
expected_type
),
values: Some(HashMap::from([
("expected".to_string(), expected_type.to_string()),
])),
path: self.path.clone(), // Empty boundary
});
}
@ -70,8 +68,7 @@ impl<'a> ValidationContext<'a> {
if obj.get("kind").is_none() {
result.errors.push(ValidationError {
code: "MISSING_KIND".to_string(),
message: "Schema mechanically requires horizontal kind discrimination"
.to_string(),
values: None,
path: self.path.clone(),
});
} else {
@ -106,8 +103,11 @@ impl<'a> ValidationContext<'a> {
&& (obj.len() as f64) < min
{
result.errors.push(ValidationError {
code: "MIN_PROPERTIES".to_string(),
message: "Too few properties".to_string(),
code: "MIN_PROPERTIES_VIOLATED".to_string(),
values: Some(HashMap::from([
("count".to_string(), obj.len().to_string()),
("limit".to_string(), min.to_string()),
])),
path: self.path.to_string(),
});
}
@ -116,8 +116,11 @@ impl<'a> ValidationContext<'a> {
&& (obj.len() as f64) > max
{
result.errors.push(ValidationError {
code: "MAX_PROPERTIES".to_string(),
message: "Too many properties".to_string(),
code: "MAX_PROPERTIES_VIOLATED".to_string(),
values: Some(HashMap::from([
("count".to_string(), obj.len().to_string()),
("limit".to_string(), max.to_string()),
])),
path: self.path.to_string(),
});
}
@ -128,13 +131,17 @@ impl<'a> ValidationContext<'a> {
if field == "type" {
result.errors.push(ValidationError {
code: "MISSING_TYPE".to_string(),
message: "Missing type discriminator".to_string(),
values: Some(HashMap::from([
("field_name".to_string(), "type".to_string()),
])),
path: self.join_path(field),
});
} else {
result.errors.push(ValidationError {
code: "REQUIRED_FIELD_MISSING".to_string(),
message: format!("Missing {}", field),
values: Some(HashMap::from([
("field_name".to_string(), field.to_string()),
])),
path: self.join_path(field),
});
}
@ -151,7 +158,10 @@ impl<'a> ValidationContext<'a> {
if !obj.contains_key(req_prop) {
result.errors.push(ValidationError {
code: "DEPENDENCY_MISSING".to_string(),
message: format!("Property '{}' requires property '{}'", prop, req_prop),
values: Some(HashMap::from([
("property_name".to_string(), prop.to_string()),
("required_property".to_string(), req_prop.to_string()),
])),
path: self.path.to_string(),
});
}

View File

@ -1,3 +1,5 @@
use std::collections::HashMap;
use crate::validator::context::ValidationContext;
use crate::validator::error::ValidationError;
use crate::validator::result::ValidationResult;
@ -22,7 +24,7 @@ impl<'a> ValidationContext<'a> {
if conflicts {
result.errors.push(ValidationError {
code: "INVALID_SCHEMA".to_string(),
message: "family must be used exclusively without other constraints".to_string(),
values: None,
path: self.path.to_string(),
});
return Ok(false);
@ -35,7 +37,7 @@ impl<'a> ValidationContext<'a> {
} else {
result.errors.push(ValidationError {
code: "UNCOMPILED_FAMILY".to_string(),
message: "Encountered family block that could not be mapped to deterministic options during db schema compilation.".to_string(),
values: None,
path: self.path.to_string(),
});
return Ok(false);
@ -55,7 +57,7 @@ impl<'a> ValidationContext<'a> {
} else {
result.errors.push(ValidationError {
code: "UNCOMPILED_ONEOF".to_string(),
message: "Encountered oneOf block that could not be mapped to deterministic compiled options natively.".to_string(),
values: None,
path: self.path.to_string(),
});
return Ok(false);
@ -109,10 +111,9 @@ impl<'a> ValidationContext<'a> {
} else {
result.errors.push(ValidationError {
code: "MISSING_COMPILED_SCHEMA".to_string(),
message: format!(
"Polymorphic router target '{}' does not exist in the database schemas map",
target_id
),
values: Some(HashMap::from([
("target_id".to_string(), target_id.to_string()),
])),
path: self.path.to_string(),
});
return Ok(false);
@ -132,10 +133,9 @@ impl<'a> ValidationContext<'a> {
} else {
result.errors.push(ValidationError {
code: "MISSING_COMPILED_SCHEMA".to_string(),
message: format!(
"Polymorphic index target '{}' does not exist in the local oneOf array",
idx
),
values: Some(HashMap::from([
("index".to_string(), idx.to_string()),
])),
path: self.path.to_string(),
});
return Ok(false);
@ -144,10 +144,15 @@ impl<'a> ValidationContext<'a> {
return Ok(false);
}
} else {
let disc_msg = if let Some(d) = self.schema.compiled_discriminator.get() {
format!("discriminator {}='{}'", d, val)
let values = if let Some(d) = self.schema.compiled_discriminator.get() {
Some(HashMap::from([
("discriminator".to_string(), d.to_string()),
("value".to_string(), val.to_string()),
]))
} else {
format!("structural JSON base primitive '{}'", val)
Some(HashMap::from([
("primitive".to_string(), val.to_string()),
]))
};
result.errors.push(ValidationError {
code: if self.schema.family.is_some() {
@ -155,10 +160,7 @@ impl<'a> ValidationContext<'a> {
} else {
"NO_ONEOF_MATCH".to_string()
},
message: format!(
"Payload matched no candidate boundaries based on its {}",
disc_msg
),
values,
path: self.path.to_string(),
});
return Ok(false);
@ -167,10 +169,9 @@ impl<'a> ValidationContext<'a> {
if let Some(d) = self.schema.compiled_discriminator.get() {
result.errors.push(ValidationError {
code: "MISSING_TYPE".to_string(),
message: format!(
"Missing explicit '{}' discriminator. Unable to resolve polymorphic boundaries",
d
),
values: Some(HashMap::from([
("discriminator".to_string(), d.to_string()),
])),
path: self.path.to_string(),
});
}

View File

@ -1,3 +1,5 @@
use std::collections::HashMap;
use crate::validator::context::ValidationContext;
use crate::validator::error::ValidationError;
use crate::validator::result::ValidationResult;
@ -15,7 +17,10 @@ impl<'a> ValidationContext<'a> {
{
result.errors.push(ValidationError {
code: "MIN_LENGTH_VIOLATED".to_string(),
message: format!("Length < min {}", min),
values: Some(HashMap::from([
("count".to_string(), s.chars().count().to_string()),
("limit".to_string(), min.to_string()),
])),
path: self.path.to_string(),
});
}
@ -24,7 +29,10 @@ impl<'a> ValidationContext<'a> {
{
result.errors.push(ValidationError {
code: "MAX_LENGTH_VIOLATED".to_string(),
message: format!("Length > max {}", max),
values: Some(HashMap::from([
("count".to_string(), s.chars().count().to_string()),
("limit".to_string(), max.to_string()),
])),
path: self.path.to_string(),
});
}
@ -32,7 +40,9 @@ impl<'a> ValidationContext<'a> {
if !compiled_re.0.is_match(s) {
result.errors.push(ValidationError {
code: "PATTERN_VIOLATED".to_string(),
message: format!("Pattern mismatch {:?}", self.schema.pattern),
values: Some(HashMap::from([
("pattern".to_string(), self.schema.pattern.clone().unwrap_or_default()),
])),
path: self.path.to_string(),
});
}
@ -42,7 +52,9 @@ impl<'a> ValidationContext<'a> {
{
result.errors.push(ValidationError {
code: "PATTERN_VIOLATED".to_string(),
message: format!("Pattern mismatch {}", pattern),
values: Some(HashMap::from([
("pattern".to_string(), pattern.to_string()),
])),
path: self.path.to_string(),
});
}

View File

@ -1,6 +1,8 @@
use crate::database::object::{is_primitive_type, SchemaTypeOrArray};
use crate::validator::context::ValidationContext;
use crate::validator::error::ValidationError;
use crate::validator::result::ValidationResult;
use std::collections::HashMap;
impl<'a> ValidationContext<'a> {
pub(crate) fn validate_type(
@ -24,19 +26,19 @@ impl<'a> ValidationContext<'a> {
let mut custom_types = Vec::new();
match &self.schema.type_ {
Some(crate::database::object::SchemaTypeOrArray::Single(t)) => {
if !crate::database::object::is_primitive_type(t) {
Some(SchemaTypeOrArray::Single(t)) => {
if !is_primitive_type(t) {
custom_types.push(t.clone());
}
}
Some(crate::database::object::SchemaTypeOrArray::Multiple(arr)) => {
Some(SchemaTypeOrArray::Multiple(arr)) => {
if arr.contains(&payload_primitive.to_string())
|| (payload_primitive == "integer" && arr.contains(&"number".to_string()))
{
// It natively matched a primitive in the array options, skip forcing custom proxy fallback
} else {
for t in arr {
if !crate::database::object::is_primitive_type(t) {
if !is_primitive_type(t) {
custom_types.push(t.clone());
}
}
@ -51,7 +53,7 @@ impl<'a> ValidationContext<'a> {
// 1. DYNAMIC TYPE (Composition)
if t.starts_with('$') {
let parts: Vec<&str> = t.split('.').collect();
let var_name = &parts[0][1..]; // Remove the $ prefix
let var_name = parts[0].trim_start_matches('$');
let suffix = if parts.len() > 1 {
format!(".{}", parts[1..].join("."))
} else {
@ -74,10 +76,10 @@ impl<'a> ValidationContext<'a> {
if !resolved {
result.errors.push(ValidationError {
code: "DYNAMIC_TYPE_RESOLUTION_FAILED".to_string(),
message: format!(
"Dynamic type pointer '{}' could not resolve discriminator property '{}' on parent instance",
t, var_name
),
values: Some(HashMap::from([
("pointer".to_string(), t.clone()),
("discriminator".to_string(), var_name.to_string()),
])),
path: self.path.to_string(),
});
continue;
@ -107,28 +109,25 @@ impl<'a> ValidationContext<'a> {
if t.starts_with('$') {
result.errors.push(ValidationError {
code: "DYNAMIC_TYPE_RESOLUTION_FAILED".to_string(),
message: format!(
"Resolved dynamic type pointer '{}' was not found in schema registry",
target_id
),
values: Some(HashMap::from([
("pointer".to_string(), target_id.to_string()),
])),
path: self.path.to_string(),
});
} else if self.schema.is_proxy() {
result.errors.push(ValidationError {
code: "PROXY_TYPE_RESOLUTION_FAILED".to_string(),
message: format!(
"Composed proxy entity pointer '{}' was not found in schema registry",
target_id
),
values: Some(HashMap::from([
("pointer".to_string(), target_id.to_string()),
])),
path: self.path.to_string(),
});
} else {
result.errors.push(ValidationError {
code: "INHERITANCE_RESOLUTION_FAILED".to_string(),
message: format!(
"Inherited entity pointer '{}' was not found in schema registry",
target_id
),
values: Some(HashMap::from([
("pointer".to_string(), target_id.to_string()),
])),
path: self.path.to_string(),
});
}

View File

@ -1 +1 @@
1.0.154
1.0.163