Skip to content

Commit

Permalink
feat: union schema using if-else pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
raxhvl committed Mar 17, 2024
1 parent ae00c5b commit c4cc4f9
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 27 deletions.
1 change: 1 addition & 0 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"typecheck": "tsc"
},
"dependencies": {
"@apideck/better-ajv-errors": "^0.3.6",
"@docusaurus/core": "^3.0.1",
"@docusaurus/preset-classic": "^3.0.1",
"@ethdebug/format": "^0.1.0-0",
Expand Down
27 changes: 19 additions & 8 deletions packages/web/src/components/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { editor } from "monaco-editor";
import { useEffect, useRef, useState } from "react";
import { useColorMode } from "@docusaurus/theme-common";
import JSONSourceMap from "@mischnic/json-sourcemap";
import { betterAjvErrors, ValidationError } from "@apideck/better-ajv-errors";

// To use Ajv with the support of all JSON Schema draft-2019-09/2020-12
// features you need to use a different export:
Expand Down Expand Up @@ -81,33 +82,43 @@ export default function Playground(props: PlaygroundProps): JSX.Element {
const sourceMap = getParsedEditorInput();
validate(sourceMap.data);

showValidationErrors(validate.errors, sourceMap);
const errors = betterAjvErrors({
// @ts-ignore
schema: schemas[props.schema.id],
data: sourceMap.data,
errors: validate.errors,
});

//console.log(betterErrors, validate.errors, sourceMap);

showValidationErrors(errors, sourceMap);
}

/**
* Shows validation error in the Monaco editor
* @param {ErrorObject[] | null | undefined} errors - Validation errors if any
* @param {ValidationError[]} errors - Validation errors
* @param {string} sourceMap - The source map of the editor input
*/
function showValidationErrors(
errors: ErrorObject[] | null | undefined,
errors: ValidationError[],
sourceMap: SourceMap
) {
const model = editorRef.current?.getModel();
if (!model || !monaco) return showError("Unable to validate schema");
let markers = [];
if (errors) {
for (const [_, error] of Object.entries(errors)) {
let node = sourceMap.pointers[error.instancePath];
const path = error.path.replace("{base}", "").replace(/\./g, "/");
let node = sourceMap.pointers[path];
const message = error.message;

if (!node || !message) continue;

markers.push({
startLineNumber: node.value.line + 1,
startColumn: node.value.column + 1,
endColumn: node.valueEnd.line + 1,
endLineNumber: node.valueEnd.column + 1,
endLineNumber: node.valueEnd.line + 1,
endColumn: node.valueEnd.column + 1,
message,
severity: monaco.MarkerSeverity.Error,
});
Expand All @@ -116,8 +127,8 @@ export default function Playground(props: PlaygroundProps): JSX.Element {
markers.push({
startLineNumber: node.key.line + 1,
startColumn: node.key.column + 1,
endColumn: node.keyEnd.line + 1,
endLineNumber: node.keyEnd.column + 1,
endLineNumber: node.keyEnd.line + 1,
endColumn: node.keyEnd.column + 1,
message,
severity: monaco.MarkerSeverity.Error,
});
Expand Down
31 changes: 18 additions & 13 deletions schemas/type.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ $schema: "https://json-schema.org/draft/2020-12/schema"
$id: "schema:ethdebug/format/type"

title: ethdebug/format/type
description:
Canonical representation for all types.
description: Canonical representation for all types.
type: object

if:
type: object
title: Known kind
description:
If `kind` adheres to the set of known kinds defined by this format
description: If `kind` adheres to the set of known kinds defined by this format
properties:
kind:
anyOf:
Expand All @@ -20,11 +18,20 @@ if:
then:
type: object
title: KnownType
description:
Then the object must adhere to exactly one known kind of type
oneOf:
- $ref: "schema:ethdebug/format/type/elementary"
- $ref: "schema:ethdebug/format/type/complex"
description: Then the object must adhere to exactly one known kind of type
allOf:
- if:
properties:
kind:
$ref: "schema:ethdebug/format/type/elementary#/$defs/Kind"
then:
$ref: "schema:ethdebug/format/type/elementary"
- if:
properties:
kind:
$ref: "schema:ethdebug/format/type/complex#/$defs/Kind"
then:
$ref: "schema:ethdebug/format/type/complex"

else:
type: object
Expand All @@ -39,14 +46,12 @@ else:
- title: Specialized complex type `contains` field
type: object
if:
description:
If this object is a complex type
description: If this object is a complex type
properties:
class:
const: complex
then:
description:
Then the `contains` field must adhere to
description: Then the `contains` field must adhere to
**ethdebug/format/type/wrapper** schemas, not the
**ethdebug/format/type/base** equivalent.

Expand Down
15 changes: 9 additions & 6 deletions schemas/type/wrapper.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ description:
type: object
properties:
type:
oneOf:
- $ref: "schema:ethdebug/format/type"
- $ref: "schema:ethdebug/format/type/reference"

# Discriminate between reference and type based on presence of `id`
if:
required:
- id
then:
$ref: "schema:ethdebug/format/type/reference"
else:
$ref: "schema:ethdebug/format/type"
required:
- type

Expand All @@ -34,8 +38,7 @@ $defs:

Object:
title: '{ "key": { "type": ... }, ... }'
description:
A key-value mapping of wrapped types, where the wrapper may add fields
description: A key-value mapping of wrapped types, where the wrapper may add fields
type: object
additionalProperties:
$ref: "schema:ethdebug/format/type/wrapper"

0 comments on commit c4cc4f9

Please sign in to comment.