Skip to content

Modular types#100

Open
javier-garcia-meteologica wants to merge 1 commit intojawj:masterfrom
javier-garcia-meteologica:modular_types
Open

Modular types#100
javier-garcia-meteologica wants to merge 1 commit intojawj:masterfrom
javier-garcia-meteologica:modular_types

Conversation

@javier-garcia-meteologica
Copy link
Copy Markdown

@javier-garcia-meteologica javier-garcia-meteologica commented Aug 11, 2021

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

@javier-garcia-meteologica javier-garcia-meteologica force-pushed the modular_types branch 3 times, most recently from fcc4d5c to d59e486 Compare August 11, 2021 12:05
@jawj
Copy link
Copy Markdown
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.

@javier-garcia-meteologica javier-garcia-meteologica force-pushed the modular_types branch 6 times, most recently from d2c924c to 6bedee5 Compare August 16, 2021 17:12
@AeroNotix
Copy link
Copy Markdown

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.

3 participants