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
feat(core): simplify entity definition and rework typings of FilterQuery #193
Conversation
Example of entity definition in SQL drivers (integer AI primary key): @Entity()
export class FooBar implements IdEntity<FooBar> {
@PrimaryKey()
id: number;
@Property()
name: string;
} For mongo it is a bit more complicated as now both @Entity()
export class FooBar implements MongoEntity<FooBar> {
@PrimaryKey()
_id: ObjectId;
@SerializedPrimaryKey()
id: string;
@Property()
name: string;
} |
Not yet fully polished, but would love to hear your feedback @lookfirst, @vimmerru, @pepakriz. Available for testing via |
036bc40
to
732144c
Compare
Damn, no wonder you've been so quiet recently. Good work! |
I have just a little experience with the orm code, but it looks very impressive! |
Wow, you made it so quickly. Excellent work! |
What if I want an |
There is still @Entity()
export class FooBar implements IEntity<Test2, 'id'> {
@PrimaryKey()
id: string;
} Btw just found out there are still some issues with const ok: FilterQuery<Author2> = { books: { author: { born: new Date() } } };
const fail: FilterQuery<Author2> = { books: { undef: { born: new Date() } } };
const shouldFail: FilterQuery<Author2> = { undef: { author: { born: new Date() } } }; |
Yea, don't worry about supporting older versions of TS. Happy to stay current with that. Running 3.6.2 and may even switch to the 3.7 beta soon to get all the awesome Re: IEntity, I must admit that it feels awkward to have to switch between two different interfaces and formats just because I'm using a string or number primary key. As always, excellent work. Super appreciate. |
You can use export type IEntity<T = any, PK extends keyof T = keyof T> = { [K in PK]: T[K] };
export type WrappedEntity<T, PK extends keyof T> = IWrappedEntity<T, PK> & IEntity<T, PK>;
export type IdentifiedEntity<T extends { id: number }> = IEntity<T, 'id'>;
export type UuidEntity<T extends { uuid: string }> = IEntity<T, 'uuid'>;
export type MongoEntity<T extends { _id: IPrimaryKey; id: string }> = IEntity<T, 'id' | '_id'>; |
Maybe |
Or NumberEntity |
I picked Not sure about |
Why not type IdentifiedEntity<T extends { id: R}, R=number> = IEntity<T, 'id'>; so user has the ability to specify the type of primary key |
That's pretty much what I just said in last comment :] Will make this happen, was thinking about it anyway... I even think we could just have (other types of PK than string and number are not supported, mongo requires _id property so no need to take ObjectId into account here): type IdentifiedEntity<T extends { id: number | string }> = IEntity<T, 'id'>; |
I am not a fan of prefixing interfaces with |
Me neither, but... naming is hard, you know :D Let's call it |
Change...
into...
Seems sane and now is a good time given the breaking changes... |
Ok done with the Published as |
Found one more small issue with edit: Right, it was just wrong |
I'm not sure about |
Well that was first approach I was thinking about, but I don't like the idea of generating them only via CLI, it would have to be somehow automated (which could work with enabled caching probably). Still current approach looks good to me, so I am not very keen to rewrite that... Will test it for couple more days in the wild, but so far it works good.
Not sure if that is important, as private props are not really supported by the ORM (there is no mechanism that would call your setters instead of just assigning the value internally). Any other issue with current approach?
Still they would be pretty complex as well I think, although definitely less generic/more specific. I did not pay much attention to prisma yet, but from what I saw, they have more strict rules on the query type, e.g. they do not allow query by PK ( Let's see what others are thinking. Edit: One more note - I don't wanna postpone v3 release for too long, but I am definitely open for discussion about this topic for future versions. That said, I think the current approach will be enough for v3. |
Example project updated, all tests pass. No complaints. =) After midnight here, so I'll do my main project tomorrow morning. |
Now it is no longer needed to merge entities with IEntity interface, that was polluting entity's interface with internal methods. New interfaces IdEntity<T>, UuidEntity<T> and MongoEntity<T> are introduced, that should be implemented by entities. They are not adding any new properties or methods, keeping the entity's interface clean. This also introduces new strictly typed FilterQuery<T> implementation based on information provided by those new interfaces. BREAKING CHANGES: IEntity has been renamed to AnyEntity and it no longer has public methods like toJSON(), toObject() or init(). One can use wrap() method provided by ORM that will enhance property type when needed with those methods (`await wrap(book.author).init()`). To keep all methods available on the entity, you can still use interface merging with WrappedEntity that both extends AnyEntity and defines all those methods. FilterQuery now does not allow using smart query operators. You can either cast your condition as any or use object syntax instead (instead of `{ 'age:gte': 18 }` use `{ age: { $gte: 18 } }`). Closes #124, #171
Merging this now and closing both connected issues, but feel free to continue with discussion. For bugs please open new issues. |
* fix(core): disable auto flushing by default [BC] (#79) * feat(core): use knex to generate sql + enable connection pooling [BC] (#76) * fix(mapping): remove deprecated `fk` option from 1:m and m:1 decorators (#87) * feat(mapping): allow overriding getClassName() in NamingStrategy (#88) * chore: remove @Class jsdoc from tests as it does not work in WS anymore * chore: use ObjectId instead of deprecated ObjectID in mongo * feat(metadata): create instance of metadata instead of static one [BC] (#91) * feat(hooks): add onInit hook fired after entity is created (#92) * feat(core): add support for virtual property getters (#93) * feat(sql): support multiple conditions in JOINs (#94) * feat(schema): use knex in schema generator (#81) * feat(schema): add basic entity generator (#98) * chore: update roadmap * fix(mapping): do not override user defined nullable value in m:1 and 1:1 * feat(schema): add basic schema update (#97) * feat(cli): add basic CLI tool (#102) * feat(core): improve logging - add namespaces, colors and highlighting (#109) * refactor: improve handling of unknown types in entity/schema generators * feat(mongo): improve query logging, use `inspect` instead of `stringify` * feat(metadata): improve validation during metadata discovery * fix(schema): prefer user-defined collection names in naming strategy * feat(core): add support for read connections (#116) * feat(core): add `Reference<T>` wrapper to allow improved type safety (#117) * feat(drivers): add support for MariaDB (#120) * docs: update docs for v3 * fix(mapping): remove obsolete parameter in UnderscoreNamingStrategy (#134) * docs: fix typo in reference wrapper section (#137) * docs: comment out comments (#141) * refactor(core): propagate reference PK from entity instead of its clone * feat(core): add findOneOrFail method to entity manager and repository (#142) * refactor(mapping): allow passing Reference to Reference.create() * feat(mapping): add NoopNamingStrategy * refactor(cli): make MIKRO_ORM_CLI env variable highest priority * refactor(validation): validate that entitiesDirs are not file globs * feat(cli): add debug command to help with setting up the CLI * docs: merge entity reference and reference wrapper sections * chore: fix build * docs: fix link to mysql integration tests (#147) * refactor: rename NoopNamingStrategy to EntityCaseNamingStrategy * refactor: allow replication in postgres * refactor: add dependency versions to debug cli command output * refactor: change sqlite dependency to sqlite3 as that is now used (knex) * refactor: change sqlite dependency to sqlite3 in docs * refactor: use globby to check for paths in cli debug command * refactor: allow default export in cli-config * docs: fix schema generator docs (get query methods vs run query methods) * fix(core): always query inverse side of 1:1 association * feat(validation): warn when failing to get metadata of an entity * feat(logging): allow logging full query including params (#155) * refactor: return entity from IEntity.assign() * refactor: improve auto-detection of ts-node * chore: change schema in default postgres connection string (#154) * chore: fix links to repository and homepage after org transfer * feat(mapping): add type-safe way to define relationships * feat(postgres): use timestamps with time zone by default * refactor: use relative paths in metadata cache * feat(core): allow populating all relations via `populate: true` * feat(validation): validate one to one relationship metadata * feat(mapping): auto-wire missing references from owner to inverse side * refactor(core): make em.find() where parameter required * feat(core): add `em.findAndCount()` method * docs: add `findAndCount` method and describe query object in EM section * feat(core): allow empty where condition in `em.count()` * feat(core): allow filtering and sorting by nested query * docs: declare correct type of codeblock (#170) * feat(core): add support for eager loading * docs: declare correct type of codeblock (#173) * feat(cli): rename default config name to mikro-orm.config.js * feat(core): allow whitelisting entity fields in em.find() * fix(core): allow object constructor parameters in entities * feat(core): allow assigning PK to undefined/null * fix(core): do not use request context in transactional/user forks * fix(core): auto-wire 1:1 owner to inverse side * feat(core): add support for deep nested conditions with operators (#185) * fix(cli): rename `--no-fk` schema command parameter to `--fk-checks` * fix(core): ignore inverse side of 1:1 when computing change set * feat(drivers): add native UUID postgres type (#188) * chore(types): improve types in EntityGenerator (#192) * feat(metadata): auto-detect optional properties * docs: fix bash highlighting * fix(generator): fixed default values and types for nullable properties (#191) * feat(core): add @repository decorator * feat(core): simplify entity definition and rework typings of FilterQuery (#193) * docs: add basic upgrading guide (WIP) * fix(query-builder): fix malformed query when populate and join are used * chore: export @SerializedPrimaryKey decorator, omit some internal types * feat(core): propagate nested where and orderBy when populating * refactor: use Set for QB flags * refactor: em `transactional` method return value & improve types (#197) * refactor: em and connection generic types (#198) * chore: remove unused import * refactor: add support for self referencing when auto-joining * fix(core): always init collections when creating entity via em.create() * tests: fix running tests on windows (#199) * refactor(typings): support nested collections in FilterQuery * docs: improve entity definition section, add more examples * docs: add deployment sections * refactor: add Reference.get(prop) method * feat(query-builder): allow mapping to entities directly via getResult() * feat(core): add support for filtering and ordering of Collection items * feat(core): add support for bundling with Webpack (#200) * chore: fix code style and increase timeout for CI tests * docs: add section about bundling with webpack (#202) * refactor: enable strictPropertyInitialization * docs: improve code style of webpack section examples * chore: hide knex's warning about sqlite FK failures * refactor: try inlining deep conditions before renaming * refactor: simplify webpack support test * feat(drivers): allow passing additional driver options * feat(core): use composite PK in many to many relations (#204) * fix(serializing): add check for circular references in toObject() * feat(core): do not require entity attribute in collection decorators (#207) * feat(core): add support for migrations via umzug (#209) * test: 'fix' memory leak in graceful-fs (#211) * refactor: implement allOrNothing in Migrator * docs: add note about possible TS inference problems with FilterQuery * docs: add section about unit of work to readme * refactor: run on init hooks after hydration * fix(core): make sure constructor params are sniffer from the constructor * fix(core): allow persisting 1:1 from inverse side * test: run tests in ci on node 8, 10, 12 and 13 * test: speed up MikroORM.init validation tests * chore: remove lgtm alert in MigrationGenerator * docs: update deployment section (#223) * refactor: do not use some umzug types that are badly defined * feat(schema): allow dropping migrations table via `schema:drop` cli cmd * fix(schema): do not make FK fields nullable if not needed * docs: add section with limitations of migrations * chore: fix build, remove stub of new docs * fix(serializing): do not ignore already visited collection items * feat(cli): add cache:generate command to warm up production cache * feat(core): add support for enums via `@Enum()` decorator (#232) * docs: add not about enums to deployment section * docs: use `!` and `?` in entity props definition * refactor: remove `AUTO_GROUP_BY` flag from query builder * fix(core): fix querying by m:n primary keys * refactor(core): do not propagate flat order by * chore(dependencies): downgrade ts-morph to v4 as v5 requires TS 3.7 * perf(sql): use multi-insert when populating m:n collections * fix(sql): support self-referencing m:n in pivot tables * docs: add link to realworld example app * docs: add link to migrations section into sidebar * chore: fix typo and remove unreachable getReference() signature * feat(schema): add support for create/drop database (#237) * feat(cli): add `database:import` command to run external sql dumps * feat(sqlite): ensure the directory with database exists * chore: update mongodb to 3.3 and use new unified topology (#241) * feat(metadata): add `ReflectMetadataProvider`, rename the `ts-morph` one (#240) * refactor: fix create/drop db commands in mariadb driver * chore: move typescript to dev dependencies * chore: improve upgrading docs * chore: add note about v2 docs * chore: add script to generate the changelog * chore: update changelog
Now it is no longer needed to merge entities with
IEntity
interface, that was polluting entity's interface with internal methods.New interfaces
IdentifiedEntity<T>
,UuidEntity<T>
andMongoEntity<T>
are introduced, that should be implemented by entities. Theyare not adding any new properties or methods, keeping the entity's interface clean.
This also introduces new strictly typed
FilterQuery<T>
implementation based on information provided by those new interfaces (type of primary keyin particular). It is not used in query builder, as there string keys needs to be supported for aliasing to work (
{ 'a.books': 1 }
).BREAKING CHANGES:
IEntity
interface no longer has public methods liketoJSON()
,toObject()
orinit()
. One can usewrap()
method provided by ORM thatwill enhance property type when needed with those methods (
await wrap(book.author).init()
). To keep all methods available on theentity, you can still use interface merging with
WrappedEntity<T, PK>
that both extendsIEntity<T, PK>
and defines all those methods.FilterQuery now does not allow using smart query operators. You can either cast your condition as any or use object syntax instead
(instead of
{ 'age:gte': 18 }
use{ age: { $gte: 18 } }
).Closes #124, #171