vinejs / vine

VineJS is a form data validation library for Node.js
https://vinejs.dev
MIT License
1.08k stars 22 forks source link

Question - Recursive objects #76

Open keironlowe-edriving opened 4 days ago

keironlowe-edriving commented 4 days ago

Hi, I'm trying to build some validation that can handle recursive objects and I'm hitting against a TS error. Trying to figure out the best way to handle this.

For the following JSON, the conditions array can either be a condition object, or group object, the group object can have a conditions array which again, can have either group or condition object, and this can go on recursively.

{
    "type": "group",
    "inclusive": "true",
    "matchDescription": "example text",
    "conditions": [
        {
            "type": "condition",
            "conditionId": "status",
            "config": {
                "value": "active"
            }
        },
        {
            "type": "group",
            "inclusive": "true",
            "conditions": [
                {
                    "type": "condition",
                    "conditionId": "score",
                    "config": {
                        "value": "50",
                        "operator": "lessThan"
                    }
                },
                {
                    "type": "condition",
                    "conditionId": "score",
                    "config": {
                        "value": "0",
                        "operator": "notEqualTo"
                    }
                }
            ]
        }
    ]
}

I'm mostly there with it with the following code...


const specConditionValidator = vine.object({
  type: vine.literal('condition'),
  conditionId: vine.string(),
  config: vine.object({}).allowUnknownProperties(),
})

const specGroupValidator = vine.object({
  type: vine.literal('group'),
  inclusive: vine.boolean(),
  conditions: vine.array(
    vine.union([
      vine.union.if((value) => value.type === 'group', specGroupValidator),
      vine.union.if((value) => value.type === 'condition', specConditionValidator),
    ])
  ),
})

export const specValidator = vine.compile(
  vine.object({
    ...specGroupValidator.getProperties(),
    matchDescription: vine.string(),
  })
)

But the problem is the vine.union.if((value) => value.type === 'group', specGroupValidator), line, which throws a TS error saying "Cannot access 'specGroupValidator' before initialization", which makes sense. I'm just not sure of the best way to work around this using Vine.

Thanks!

keironlowe-edriving commented 2 days ago

I resolved that error by making specGroupValidator a function which returns the vine object. But it now throws a maximum call stack size exceeded error.

From the looks if it, Vine doesn't support recursive objects?