FSET

Structure Editor Series

FModel JSON Schema Editor

No longer write raw schema by hand, no programming tooling required


Algebraic Data Type to JSON Schema

Think in terms of algebraic data type, export sane subset of json schema ( see all types )

      • type Record = {   }
        • field_a : string
        • field_b : int_32
    {
      "properties": {
        "field_a": {
          "type": "string"
        },
        "field_b": {
          "maximum": 2147483647,
          "minimum": -2147483648,
          "type": "integer"
        }
      },
      "required": [
        "field_a"
      ],
      "type": "object"
    }
      • type Tuple = (   )
        • 0 : "ok"
        • 1 : ExportDocs::Record
        • 2 : { any }
    {
      "maxItems": 3,
      "minItems": 3,
      "prefixItems": [
        {
          "const": "ok"
        },
        {
          "$ref": "https://localhost/ExportDocs#/$defs/Record"
        },
        {
          "properties": {},
          "type": "object"
        }
      ],
      "type": "array"
    }
      • type Dict = dict
        • k string
        • v ExportDocs::Record
    {
      "additionalProperties": {
        "$ref": "https://localhost/ExportDocs#/$defs/Record"
      },
      "minProperties": 4,
      "propertyNames": {
        "pattern": "^x-",
        "type": "string"
      },
      "type": "object"
    }
    {
      "items": {
        "$ref": "https://localhost/ExportDocs#/$defs/Record"
      },
      "type": "array"
    }
      • type TaggedUnion = || _mytag
        • | tag_a · {   }
          • field_x : uint_8
        • | tag_b · {   }
          • field_z : string
    {
      "oneOf": [
        {
          "properties": {
            "_mytag": {
              "const": "tag_a"
            },
            "field_x": {
              "maximum": 255,
              "minimum": 0,
              "type": "integer"
            }
          },
          "required": [
            "_mytag",
            "field_x"
          ],
          "type": "object"
        },
        {
          "properties": {
            "_mytag": {
              "const": "tag_b"
            },
            "field_z": {
              "type": "string"
            }
          },
          "required": [
            "_mytag"
          ],
          "type": "object"
        }
      ],
      "unevaluatedProperties": false
    }
      • type UnionOfVal = ||
        • | "a"
        • | 10
        • | true
        • | null
    {
      "enum": [
        "a",
        10,
        true,
        null
      ]
    }

Constructing schema as productive as working in text editor

With essential keyboard commands ( see all commands )

Add

Add random schema to container types
Shift + +

Move

Cut selected schemas
Cmd + x
Copy selected schemas
Cmd + c
Paste
Cmd + v
Cancel copy or cut
Escape

Clone

Clone selected schemas
Shift + Alt + ArrowUp

Shift + Alt + ArrowDown

Reorder

Reorder selected schemas up or down
Alt + ArrowUp

Alt + ArrowDown

Collapse / Expand

Collapse selected schemas
ArrowLeft
Expand selected schemas
ArrowRight

Delete

Delete selected schemas
Delete

Select

Select a schema
ArrowUp
ArrowDown
Select a sibling schema
i
j
Select mutiple schemas
Shift + ArrowUp
Shift + ArrowDown
Select mutiple schema all the way
Shift + Cmd + ArrowUp

Shift + Cmd + ArrowDown
Select the first child
Cmd + ArrowUp
Select the last child
Cmd + ArrowDown
Select the root element of tree
Home
Select the last element of tree
End

Rename key

Enable key editing on a selected schema
Enter
Submit a changed key with current text input value
Enter
Cancel editing
Escape

Change type

Enable type editing on a selected schema
Shift + Enter
Submit a changed type with current text input value
Enter
Cancel editing
Escape
For Windows, use Ctrl in place of Cmd

Reference tracking and integrity

Once a type is referenced, name and namespace updates automatically reflects on referrers

When there exists at least one referrer, the referenced type cannot be deleted, enforced at db-level

reference tracking

Export as a bundle

All modules are bundled as a single JSON Schema file based on Compound Documents Specification

Bundled schema is also a usable schema. Validator can validate the file without decomposing schema definitions into separate files.

exported bundle
AJV validator

Currently AJV needs one step of decomposing files

const Ajv2020 = require("ajv/dist/2020")
let ajv = new Ajv2020()

let programSch = require("./sch.json")

for (modu of Object.keys(programSch.$defs)) {
  ajv.addSchema(programSch.$defs[modu])
  delete programSch.$defs[modu]
}

const data = { data: { values: ["a", "b"] }, mark: "arc" }
let result = ajv.validate(programSch, data)

console.log(result)
console.log(ajv.errors)
            
Hyperjump validator
const hpj = require("@hyperjump/json-schema")
hpj
  .get("file://./sch.json")
  .then(schema => hpj.validate(schema, { data: { values: ["a", "b"] }, mark: "arc" }))
  .then(output => console.log(output))
            

Simply think each $id is a module and each of $defs is a type,

for more information see Export documentation