#Hey all, does anyone know if there is a Table helper equivalent for convex ENTs?

24 messages ยท Page 1 of 1 (latest)

topaz bronze
#

Trying to see if it's possible to collocate validators with schema definitions using the ENTs abstraction.

For example, I am currently using the defineEnts method to define a table in my schema:

      name: v.string(),
      event_img_storage_id: v.optional(v.id("_storage")),
      event_img_url: v.optional(v.string()),
    })
      .field("start_at", v.string(), { index: true })
      .field("timezone", v.string())
      .field("end_at", v.optional(v.string()))
      .field("geo_address_json", v.optional(geo_address_json_validator))
      .field("geo_latitude", v.optional(v.string()))
      .field("geo_longitude", v.optional(v.string()))
      .field("luma_event_id", v.optional(v.string()))
      .edges("teams"),...

And I am exporting a separate obj in order to infer argument validation for the corresponding create mutation: // supplied for frontend mutation export const eventFields = { name: v.string(), start_at: v.string(), timezone: v.string(), end_at: v.optional(v.string()), geo_address_json: v.optional(geo_address_json_validator), geo_latitude: v.optional(v.string()), geo_longitude: v.optional(v.string()), team_ids: v.array(v.id("teams")), event_img_storage_id: v.optional(v.id("_storage")), };

Just wondering if there is a way to declare the validator once and feed it into the schema with the ENT-way of doing things. As outlined in the best practices of not redefining the shape in vanilla convex:

// ...
export const recipeFields = {
  name: v.string(),
  course: courseValidator,
  ingredients: v.array(v.string()),
  steps: v.array(v.string()),
};

export default defineSchema({
  recipes: defineTable(recipeFields)
    .index("by_course", ["course"]),
});```
unique hareBOT
#

Thanks for posting in #1088161997662724167.
Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets.

    - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.)
    - Use [search.convex.dev](https://search.convex.dev) to search Docs, Stack, and Discord all at once.
    - Additionally, you can post your questions in the Convex Community's #1228095053885476985 channel to receive a response from AI.
    - Avoid tagging staff unless specifically instructed.

    Thank you!
lapis kiln
#

I don't think there is a way to do this, otherwise i should rewrite a lot of my schema. I just define most of it the old way. The only issue would be when using unique: true

#

I do vaugely recall this being talked about somewhere here in discord...

finite rune
#

I ended up minimizing my use of .field definitions due to losing this convenience, especially if you're using return type validators. You can still use regular index definitions, and I only use field for the fancy stuff like unique and default, or for fields that I don't usually want in public validators anyway (eg. updatedAtTime).

I'd still definitely recommend colocating your ent definitions with related validators/functions - if you make good use of the convex helper utils, you can vastly cut down on repetitive code, and easily keep your validators in sync if you change your schema. My convex/schema.ts file has very few actualy ent defininitions in it - they're all imported from their domain areas across the app.

topaz bronze
#

this all makes sense - I like your approach. Thanks for clarifying and for the example! Appreciate it.

hushed basalt
#

In my case i extended convex-ents by adding an updateField function in the entitydefinition class that does not throw an exception when a field already exists , using this in place of field, i can pass all fields into the Table helper call , and still define attributes like unique,defualt and index the way i do currently and it works without issues . Am going to do a PR to convex-ents maybe they accept it . for now am using convex-ents off of my github branch

lapis kiln
lapis kiln
hushed basalt
#

in Action

lapis kiln
# hushed basalt in Action

Hmm, i think the only friction would be having to maintain the string() part in two places, maybe something like .fieldProps('teamname', { unique: true }) makes it a bit more clear? or addFieldProps/features.. assuming it is better language, i don't exactly see a label in the docs for that data within { }

hushed basalt
lapis kiln
hushed basalt
#

if you look at the type definition for field (and updateField which is currently thesame), option (the object {}) has a type with 3 optional properties : default,unique and index

lapis kiln
#

lol, yeah duh.. options.. maybe just .options('fieldName', { options })

hushed basalt
#

or .fieldOptions ?

lapis kiln
# hushed basalt or .fieldOptions ?

Yeah, that's probably best. Ill be happy to use it however ๐Ÿ™ƒ - i'm already doing a lot of like what dean is doing, but still got many more tables to update.

#

It would definitely make rewriting ai-town to ents much faster...๐Ÿ˜…

hushed basalt
#

PR is in and updated

hushed basalt
#

OK, am running into an issue at runtime , where the fieldPath for fieldOptions are missing causing queries to fail. Am looking at that

topaz bronze
#

Thanks @finite rune , in regards to collocating validtors within different files, and importing them into the schema, I seem to be having some Uncaught TypeErrors when I try to export validators say from an events.ts file, into the schema.ts. I have my defineEnt args all within the schema.ts , just trying to collocate the validators.

Interestingly, when I declare the validators within the schema.ts file, I am able to use them within the ent definitions without issues.

Is this something you came accross?

finite rune
# topaz bronze Thanks <@184670179698016256> , in regards to collocating validtors within differ...

It's easy to cause circular import loops when using ents. I don't know why it happens exactly, but typescript has to run through a rube goldberg machine to calculate them - and they become intertwined with the regular convex types on the way.

I found that declaring them in the same file as any convex functions (query/mutation/action) would cause the issue. So I only ever declare validators/ents in their own file, while being very careful with what to import. In my example I only import convex ents/utils related to creating the entity shape, constants which import nothing else themselves, and other validators from files which follow the same pattern.

Consider these modules the source of truth of your data model. Keep a tree-like structure, with your ents and validators as the leaves, which all feed down to schema.ts at the root. Anything that needs to use the validators is free to import whatever they want - just don't import the other way.