ideditor / schema-builder

🏗🏷 Create tagging schemas for iD
ISC License
12 stars 16 forks source link

Schema: Improve `prerequisiteTag` validation #82

Closed tordans closed 1 year ago

tordans commented 1 year ago

This issue is not important, IMO. But it bothers me that I cannot get it to work ;-D.

Maybe someone can spot the issue here…?

My goal is, to improve prerequisiteTag to explicitly state those options

  1. No prerequisiteTag
  2. OR prerequisiteTag: { key: "foo" } (matches all tags with that key; used by data/fields/operator/type.json)
  3. OR prerequisiteTag: { key: "foo", value: "foo" }
  4. OR prerequisiteTag: { key: "foo", notValue: "foo" }
  5. But never prerequisiteTag: { key: "foo", value: "foo", notValue: "foo" }

Ideally, the key description can be different from 2 to 3/4.

The docs I found to learn JSON schema are not great. This is what I managed do build, but it does not allow any value anymore.

        "prerequisiteTag": {
            "description": "Tagging constraint for automatically showing this field in the editor",
            "anyOf": [
                {
                    "type": "object",
                    "properties": {
                        "key": {
                            "description": "The required key",
                            "type": "string",
                            "required": true
                        },
                        "anyOf": [
                            {
                                "value": {
                                    "description": "The required value that the tag must have. (Omit `value` to only match for `key`.)",
                                    "type": "string"
                                }

                            },
                            {
                                "valueNot": {
                                    "description": "The required value that the tag cannot have",
                                    "type": "string"
                                }
                            }
                        ]
                    },
                    "additionalProperties": false
                },
                {
                    "type": "object",
                    "properties": {
                        "keyNot": {
                            "description": "A key that must not be present",
                            "type": "string",
                            "required": true
                        }
                    },
                    "additionalProperties": false
                }
            ]
        },

This is a follow up to https://github.com/ideditor/schema-builder/issues/80.

tyrasd commented 1 year ago

I got it to work by listing all allowed cases individually

        "prerequisiteTag": {
            "description": "Tagging constraint for showing this field in the editor",
            "oneOf": [
                {
                    "$id": "requires-key-is-value",
                    "type": "object",
                    "properties": {
                        "key": {
                            "description": "The key of the required tag",
                            "type": "string",
                            "required": true
                        },
                        "value": {
                            "description": "The value that the tag must have. (alternative to 'valueNot')",
                            "type": "string"
                        }
                    },
                    "additionalProperties": false
                },
                {
                    "$id": "requires-key-is-not-value",
                    "type": "object",
                    "properties": {
                        "key": {
                            "description": "The key of the required tag",
                            "type": "string",
                            "required": true
                        },
                        "valueNot": {
                            "description": "The value that the tag cannot have. (alternative to 'value')",
                            "type": "string"
                        }
                    },
                    "additionalProperties": false
                },
                {
                    "$id": "requires-not-key",
                    "type": "object",
                    "properties": {
                        "keyNot": {
                            "description": "A key that must not be present",
                            "type": "string",
                            "required": true
                        }
                    },
                    "additionalProperties": false
                }
            ]
        },

PS: the $ids are there so that the output of npm test is a bit more understandable: in case of an error (both value and valueNot present), the output is now

instance.prerequisiteTag is not exactly one from field-requires-key-is-value,field-requires-key-is-not-value,field-requires-not-key

instead of

instance.prerequisiteTag is not exactly one from [subschema 0],[subschema 1],[subschema 2]

tordans commented 1 year ago

That sounds great. I would expect the "oneOf" rule to break the "none of them is present" rule, but I guess whenever the whole prerequisiteTag is removed, the oneOf does not apply anymore(?)…

tyrasd commented 1 year ago

I can just say that it works. :sweat_smile: anyOf would have also worked, I guess. In any case, if you would actually want to disallow the none of them are present case, you'd need to add "required": true to the property.

tyrasd commented 1 year ago

I can just say that it works.

I lied. :see_no_evil: I forgot about the requires-key-any-value case. //edit: fixed in 7e9bed5