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

Modular types #100

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

javier-garcia-meteologica
Copy link

Issue #49

  • Configures global table definitions through the interface StructureMap using module augmentation instead of using zapatos/schema. This approach is more modular, allows an arbitrary number of modules making extensions to Zapatos (as long as there are no name collisions). This is similar to how HTMLElementTagNameMap works. If there are name collisions across modules (e.g. multiple databases), the option globalStructureName can be used to solve the conflict or to disable augmentation of StructureMap.
export interface mytable {
    Table: 'mytable';
    Insertable: { id: string; name: string };
    ...
}

declare module 'zapatos/db' {
  interface StructureMap {
    mytable: mytable;
  }
}
  • By default, sql and shortcuts use SQL and SQLStructure for inference which derive all of their information from StructureMap.

  • Adds support for inferring the schema name of the table from the database.

sql`select * from ${'foo'}.${'mytable'};`
  • Allow developers to override the type argument specifying the SQLStructure to use in a shortcut and also maintain type inference in the rest of type arguments. It's necessary to workaround microsoft/TypeScript#26242, so I created 2 shortcuts to make it possbile: table and tables.
import db from 'zapatos/db';
import s from './types/db';

// Implicitly uses "SQLStructure", which derives information from "StructureMap"
db.insert('mytable', { id: '123', name: 'foo' }).run(pool)
db.table('mytable').insert({ id: '123', name: 'foo' }).run(pool)

// "mytable" is used as a type argument for "table" while "insert" maintains type inference for the rest of type arguments
db.table<s.mytable>('mytable').insert({ id: '123', name: 'foo' }).run(pool)

In order to make zapatos compatible with multiple databases, I had to use a modular architecture to avoid conflicts. Now zapatos doesn't require centralized ambient modules or namespaces, it can work only by passing type arguments to functions. Optionally, StructureMap can be augmented to provide centralized typings, but the user can choose to disable it or can configure how to resolve name conflicts.

There are a few tasks left, like changing how schema/custom works to be more modular. I don't know much about how those custom types are used and, if some maintainer can help me, I'm going to need some help with schema/custom and polishing this PR.

EDIT: Change schema/custom to modules

@jawj
Copy link
Owner

jawj commented Aug 11, 2021

@javier-garcia-meteologica Thanks for the tickets and PRs you're submitting. I don't have time right away to look at these in detail they need, but I'll try to catch up with them in the week or two.

@AeroNotix
Copy link

Can you grant maintainership to someone you trust, or has more time? The library is an oasis in the desert of janky ORMs in the JS/TS land. Would be good to keep on truckin'.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants