Skip to content

Field level metadata for storage #91

Description

@patroza

One of the best things about Schema is how it is the central definition of all models throughout the system.
By centralising all information for a model schema, property metadata, jsonschema metadata, and more, while deriving variations and views from them, there is a single source of truth and the distance between related information is very short, making it easy to get an overview quickly.

A great example is that you can access aTag.tag, aLiteral.literals, or aUnion.members, or aStruct.fields, instead of maintaining separate lists, possibly located at different ends of the application, making it harder to keep things in sync.

For Repositories we separately define the primary key and defaultValues/jitM from the Schema,
I would like to explore if and how we could centralise this too, as they are in fact kind of properties of the Model,
even though interpreted/executed by the Repositories/storage layer.

When type information is not required, one can simply use Schema annotations.
But in case of type information required, we should either wrap PropertySignature or Schemas, similar to how effect model in sql does.

Suggested helpers (WIP names):

  • PrimaryKey, so that we don't need to manually setup decoded: X, encoded: id, nor track idKey option in Repositories. It also helps the reader.
    example: isin: PrimaryKey(ISIN)
    a more detailed suggestion for this is available in Support idKey conversion in the storage driver, instead of requiring X.fromKey("id") #92
    a preliminary implementation is available in GS Security - but it does not enhance the metadata to say this is a Primary Key yet, so the Repository does not pick it up, and has to be configured manually.
    • we could consider dropping find and get and removeById, but then also byIdAndSaveWithPure , from the repo interface, and we no longer would need type level information. Because they could be expressed instead with Q.where("id", x), Q.one. Then again, most db adapters, ORMs etc, provide the convenience "find", "one" etc helpers..
  • withMigrationDefault, so that we don't need to specify defaultValues or perhaps even jitM at repositories.
    example: createdAt: S.Date.withDefault.pipe(S.withMigrationDefault(() => new Date(...some static date...)).
    this is preferred over S.optional etc, because those leak into the Encoded shape, and affect decoding from all sources, instead of just storage.
  • Streamline the updating of updatedAt #99

Some inspiration in Effect sql Model:

Not saying we should go that level, to expose more SQLesque stuff into our model though.
We should remain abstract enough and not "infect".

Schema annotations: https://effect.website/docs/guides/schema/annotations
which power all kinds of things like https://effect.website/docs/guides/schema/schema-to-x/json-schema

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions