Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to use lazy() in variant() #588

Open
Schleuse opened this issue May 22, 2024 · 1 comment
Open

Unable to use lazy() in variant() #588

Schleuse opened this issue May 22, 2024 · 1 comment
Assignees
Labels
enhancement New feature or request

Comments

@Schleuse
Copy link

I'm currently trying to implement a Schema for the following data structure.

{
    "filters": [
        {
            "type": "and",
            "and": [
                {
                    "type": "or",
                    "or": [
                        {
                            "type": "not",
                            "not": [
                                {
                                    "type": "keyword",
                                    "keyword": "blub"
                                },
                                {
                                    "type": "categories",
                                    "categories": [123, 345, 567]
                                }
                            ]
                        },
                        {
                            "type": "group",
                            "group": 123123123
                        }
                    ]
                }
            ]
        }

    ]
}

I'v already written Schemas for the Value-Filters but struggle to assemble them in a tree-like structure in combination with "or", "and" & "not"-Filters.

import * as v from "valibot";

const CategoryFilterSchema = v.object({
  type: v.literal("category"),
  categories: v.array(v.number())
})
const GroupFilterSchema = v.object({
  type: v.literal("group"),
  group: v.number()
})
const KeywordFilterSchema = v.object({
  type: v.literal("keyword"),
  keyword: v.string()
})

const ValueFilters = v.variant('type', [CategoryFilterSchema, GroupFilterSchema, KeywordFilterSchema]);

type AndFilter = {
  type: "and"
  and: Array<NotFilter | AndFilter | OrFilter | v.InferOutput<typeof ValueFilters>>;
};

type OrFilter = {
  type: "or"
  or: Array<NotFilter | AndFilter | OrFilter | v.InferOutput<typeof ValueFilters>>;
};

type NotFilter = {
  type: "not"
  not: Array<NotFilter | AndFilter | OrFilter | v.InferOutput<typeof ValueFilters>>;
};

const AndFilterSchema: v.GenericSchema<AndFilter> = v.object({
  type: v.literal('and'),
  and: v.array(v.variant('type', [
    ValueFilters,
    v.lazy(() => AndFilterSchema),
    v.lazy(() => OrFilterSchema),
    v.lazy(() => NotFilterSchema),
  ])),
})

const OrFilterSchema: v.GenericSchema<OrFilter> = v.object({
  type: v.literal('or'),
  or: v.array(v.variant('type', [
    ValueFilters,
    v.lazy(() => AndFilterSchema),
    v.lazy(() => OrFilterSchema),
    v.lazy(() => NotFilterSchema),
  ])),
})

const NotFilterSchema: v.GenericSchema<NotFilter> = v.object({
  type: v.literal('not'),
  not: v.array(v.variant('type', [
    ValueFilters,
    v.lazy(() => AndFilterSchema),
    v.lazy(() => OrFilterSchema),
    v.lazy(() => NotFilterSchema),
  ])),
})

const AvailableFilters = v.variant('type', [
  ValueFilters,
  AndFilterSchema,
  OrFilterSchema,
  NotFilterSchema
]);

const Schema = v.object({
  filters: v.array(AvailableFilters)
})

const parsed = v.parse(Schema, {
  "filters": [
    {
      "type": "and",
      "and": [
        {
          "type": "or",
          "or": [
            {
              "type": "not",
              "not": [
                {
                  "type": "keyword",
                  "keyword": "blub"
                },
                {
                  "type": "categories",
                  "categories": [123, 345, 567]
                }
              ]
            },
            {
              "type": "group",
              "group": 123123123
            }
          ]
        }
      ]
    }
  ]
});
console.log(parsed);

Example


Im generally not sure, if I structured things right - how would a schema for such a recursivly nested data structure look like?

It seems be currently not possible to use lazy within variant:
image

Also GenericSchema does not seem to satisfy the requirements for variant() either.

image

Maybe someone has some suggestions how I could improve things.

Thank you very much in advance 🌟

@fabian-hiller
Copy link
Owner

lazy is not currently supported by variant. I will investigate if it is possible and useful to change this. In the meantime, you can switch to union. See this playground.

@fabian-hiller fabian-hiller self-assigned this May 22, 2024
@fabian-hiller fabian-hiller added the enhancement New feature or request label May 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants