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

0.3.0 #8616

Merged
merged 119 commits into from Mar 17, 2022
Merged

0.3.0 #8616

merged 119 commits into from Mar 17, 2022

Conversation

pleerock
Copy link
Member

@pleerock pleerock commented Feb 9, 2022

0.3.0 (2022-03-17)

Changes in the version includes changes from the next branch and typeorm@next version.
They were pending their migration from 2018. Finally, we are ready to merge them into master and release new 0.3.0.

FEATURES

  • compilation target now is es2020. This requires Node.JS version 12.9.0+

  • Connection was renamed to DataSource.
    Old Connection is still there, but now it's deprecated. It will be removed in next version.
    New API:

export const dataSource = new DataSource({
    // ... options ...
})

// load entities, establish db connection, sync schema, etc.
await dataSource.connect()

Previously, you could use new Connection(), createConnection(), getConnectionManager().create(), etc.
They all deprecated in favour of new syntax you can see above.

New way gives you more flexibility and simplicity in usage.

  • new custom repositories syntax:
export const UserRepository = myDataSource.getRepository(UserEntity).extend({
    findUsersWithPhotos() {
        return this.find({
            relations: {
                photos: true
            }
        })
    }
})

Old ways of custom repository creation were deprecated.

  • added new option on relation load strategy called relationLoadStrategy.
    Relation load strategy is used on entity load and their relations load when you query entities from the database.
    Used on find* methods and QueryBuilder. Value can be set to join or query.

    • join loads relations using SQL's JOIN
    • query executes separate SQL queries for each relation

Default is join, but default can be set in ConnectionOptions:

createConnection({
    /* ... */
    relationLoadStrategy: "query"
})

Also, it can be set per-query in find* methods:

userRepository.find({
    relations: {
        photos: true
    }
})

And QueryBuilder:

userRepository
    .createQueryBuilder()
    .setRelationLoadStrategy("query")

For queries returning big amount of data, we recommend to use query strategy,
because it can be a more performant approach to query relations.

  • new select type signature in FindOptions (used in find* methods):
userRepository.find({
    select: {
        id: true,
        firstName: true,
        lastName: true,
    }
})

Also, now it's possible to specify select columns of the loaded relations:

userRepository.find({
    select: {
        id: true,
        firstName: true,
        lastName: true,
        photo: {
            id: true,
            filename: true,
            album: {
                id: true,
                name: true,
            }
        }
    }
})
  • new relations type signature in FindOptions (used in find* methods):
userRepository.find({
    relations: {
        contacts: true,
        photos: true,
    }
})

To load nested relations use a following signature:

userRepository.find({
    relations: {
        contacts: true,
        photos: {
            album: true,
        },
    }
})
  • new order type signature in FindOptions (used in find* methods):
userRepository.find({
    order: {
        id: "ASC"
    }
})

Now supports nested order by-s:

userRepository.find({
    order: {
        photos: {
            album: {
                name: "ASC"
            },
        },
    }
})
  • new where type signature in FindOptions (used in find* methods) now allows to build nested statements with conditional relations, for example:
userRepository.find({
    where: {
        photos: {
            album: {
                name: "profile"
            }
        }
    }
})

Gives you users who have photos in their "profile" album.

  • FindOperator-s can be applied for relations in where statement, for example:
userRepository.find({
    where: {
        photos: MoreThan(10),
    }
})

Gives you users with more than 10 photos.

  • boolean can be applied for relations in where statement, for example:
userRepository.find({
    where: {
        photos: true
    }
})

DEPRECATIONS

  • select in FindOptions (used in find* methods) used as an array of property names is deprecated.
    Now you should use a new object-literal notation. Example:

Deprecated way of loading entity relations:

userRepository.find({
    select: ["id", "firstName", "lastName"]
})

New way of loading entity relations:

userRepository.find({
    select: {
        id: true,
        firstName: true,
        lastName: true,
    }
})

This change is due to type-safety improvement new select signature brings.

  • relations in FindOptions (used in find* methods) used as an array of relation names is deprecated.
    Now you should use a new object-literal notation. Example:

Deprecated way of loading entity relations:

userRepository.find({
    relations: ["contacts", "photos", "photos.album"]
})

New way of loading entity relations:

userRepository.find({
    relations: {
        contacts: true,
        photos: {
            album: true
        }
    }
})

This change is due to type-safety improvement new relations signature brings.

  • join in FindOptions (used in find* methods) is deprecated. Use QueryBuilder to build queries containing manual joins.

  • Connection, ConnectionOptions are deprecated, new names to use are: DataSource and DataSourceOptions.
    To create the same connection you had before use a new syntax: new DataSource({ /*...*/ }).

  • createConnection(), createConnections() are deprecated, since Connection is called DataSource now, to create a connection and connect to the database
    simply do:

const myDataSource = new DataSource({ /*...*/ })
await myDataSource.connect()
  • getConnection() is deprecated. To have a globally accessible connection, simply export your data source and use it in places you need it:
export const myDataSource = new DataSource({ /*...*/ })
// now you can use myDataSource anywhere in your application
  • getManager(), getMongoManager(), getSqljsManager(), getRepository(), getTreeRepository(), getMongoRepository(), createQueryBuilder()
    are all deprecated now. Use globally accessible data source instead:
export const myDataSource = new DataSource({ /*...*/ })
export const Manager = myDataSource.manager
export const UserRepository = myDataSource.getRepository(UserEntity)
export const PhotoRepository = myDataSource.getRepository(PhotoEntity)
// ...
  • getConnectionManager() and ConnectionManager itself are deprecated - now Connection is called DataSource,
    and each data source can be defined in exported variable. If you want to have a collection
    of data sources, just define them in a variable, simply as:
const dataSource1 = new DataSource({ /*...*/ })
const dataSource2 = new DataSource({ /*...*/ })
const dataSource3 = new DataSource({ /*...*/ })

export const MyDataSources = {
    dataSource1,
    dataSource2,
    dataSource3,
}
  • getConnectionOptions() is deprecated - in next version we are going to implement different mechanism of connection options loading

  • AbstractRepository is deprecated. Use new way of custom repositories creation.

  • @TransactionRepository, @TransactionManager, @Transaction decorators were deprecated.

  • all deprecated signatures will be removed in 0.4.0

BREAKING CHANGES

  • minimal Node.JS version requirement now is 12.9.0

  • now migrations are running before schema synchronization if you have both pending migrations and schema synchronization pending
    (it works if you have both migrationsRun and synchronize enabled in connection options).

  • findOne and QueryBuilder.getOne() now return null instead of undefined in the case if it didn't find anything in the database.
    Logically it makes more sense to return null.

  • where in FindOptions (e.g. find({ where: { ... })) is more sensitive to input criteria now.

  • if you had entity properties of a non-primitive type (except Buffer) defined as columns,
    then you won't be able to use it in find*'s where. Example:

Before for the @Column(/*...*/) membership: MembershipKind you could have a query like:

userRepository.find({
    membership: new MembershipKind("premium")
})

now, you need to wrap this value into Equal operator:

userRepository.find({
    membership: Equal(new MembershipKind("premium"))
})

This change is due to type-safety improvement new where signature brings.

  • order in FindOptions (used in find* methods) doesn't support ordering by relations anymore.
    Define relation columns, and order by them instead.

  • where in FindOptions (used in find* methods) previously supported ObjectLiteral and string types.
    Now both signatures were removed. ObjectLiteral was removed because it seriously breaks the type safety,
    and string doesn't make sense in the context of FindOptions. Use QueryBuilder instead.

  • MongoRepository and MongoEntityManager now use new types called MongoFindManyOptions and MongoFindOneOptions
    for their find* methods.

  • primary relation (e.g. @ManyToOne(() => User, { primary: true }) user: User) support is removed.
    You still have an ability to use foreign keys as your primary keys,
    however now you must explicitly define a column marked as primary.

Example, before:

@ManyToOne(() => User, { primary: true })
user: User

Now:

@PrimaryColumn()
userId: number

@ManyToOne(() => User)
user: User

Primary column name must match the relation name + join column name on related entity.
If related entity has multiple primary keys, and you want to point to multiple primary keys,
you can define multiple primary columns the same way:

@PrimaryColumn()
userFirstName: string

@PrimaryColumn()
userLastName: string

@ManyToOne(() => User)
user: User

This change was required to simplify ORM internals and introduce new features.

EXPERIMENTAL FEATURES NOT PORTED FROM NEXT BRANCH

  • observers - we will consider returning them back with new API in future versions
  • alternative find operators - using $any, $in, $like and other operators in where condition.

THINGS I ASK TO HELP ME WITH

  • test it (you can install it using npm i typeorm@rc)
  • review this PR, add any other relevant information to the CHANGELOG
  • update documentation to reflect new changes on our website
  • add tests to new functionality
  • update other repositories with new changes introduced in 0.3.0

@Ginden
Copy link
Collaborator

Ginden commented Feb 9, 2022

new custom repositories syntax:
Old ways of custom repository creation were deprecated.

Can you provide rationale on this?

src/repository/Repository.ts Outdated Show resolved Hide resolved
src/util/OrmUtils.ts Outdated Show resolved Hide resolved
@Ginden

This comment was marked as resolved.

@glen-84
Copy link

glen-84 commented Feb 9, 2022

@pleerock When might you consider switching to a 1.x release?

*
* (works like a discriminator property).
*/
readonly typename?: string;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be sensible to make it string | symbol.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pleerock It's useful to have discriminator property not returned through JSON.stringify and not conflicting with any possible column name.

src/connection/Connection.ts Outdated Show resolved Hide resolved
@pleerock
Copy link
Member Author

pleerock commented Feb 10, 2022

@pleerock When might you consider switching to a 1.x release?

@glen-84 not yet. Don't have in plans.

Can you provide rationale on this?

@Ginden new way is much simpler and flexible to use

@pleerock
Copy link
Member Author

@Ginden yes we can, but it will also work on node 12, because I think we don't use anything node-14 specific. But yes, officially we can say we support 14+.

@Q16solver
Copy link
Contributor

Q16solver commented Mar 15, 2022

Hey! I was just testing typeorm rc and migrating my project over and encountered some difficulties with extending a tree repository for posts compared to how I did it previously

previous:
image

now:
image

I required the protected functions of creating relationship maps and building children entity tree so I could implement my own way of only fetching up to say 20 of the top level children posts and paginating those children posts, but now I cannot access this, is there any other way I can migrate across?

image

Edit: Aside from that everything works fine! The query logs in console are also much neater now, can't wait till this is actually released 🙂

@pleerock
Copy link
Member Author

pleerock commented Mar 15, 2022

@Q16solver thanks for testing! Oh yeah protected methods are not accessible now. We have two options: make them public (but it will be temporary approach), or refactor the code in the TreeRepository and extract functionality into separate class, for example into TreeRepositoryUtils with public methods which you'll be able to use. Feel free to PR against this branch.

@Q16solver
Copy link
Contributor

Q16solver commented Mar 16, 2022

@pleerock Sweet! I'll just do a simple refactor into TreeRepositoryUtils in the utils folder, I don't believe we will need to add new test cases for this as there shouldn't be any drastic changes, however, in saying that I do also realise that the extends method only covers the general repository case as well, and I'm thinking if I can add an override extends type in TreeRepository

Edit: Done that and made a PR #8753! Hopefully it's exactly what you wanted

* Migrated protected tree methods to util class

* Added tree repository extend override

* Ran prettier format
@Q16solver
Copy link
Contributor

Q16solver commented Mar 17, 2022

Trivial merge conflict fix PR #8754 for formatting spaces, it passes linting so it should be fine
Do we know when 0.3.0 is going to be released? Seems like the idea was to do at 1st March, then 10th now, but it's 17th, otherwise might take you a lot of effort to continue maintaining merge conflicts 😢

Co-authored-by: Bitcollage <serkan.sipahi@yahoo.de>
@pleerock
Copy link
Member Author

@Q16solver I don't really expect to merge something non-trivial into master anymore, until 0.3.0 is merged into it. The only thing that is left is to update the documentation "docs" directory and improve CHANGELOG. Would be great to receive any help in this front.

# Conflicts:
#	sample/sample5-subscribers/subscriber/EverythingSubscriber.ts
@pleerock pleerock merged commit 3b8a031 into master Mar 17, 2022
@pleerock pleerock deleted the 0.3.0 branch March 17, 2022 16:01
phatnguyen1006 referenced this pull request in phatnguyen1006/PN_FullStack_v1 Mar 19, 2022
thingseong pushed a commit to E107-GPT/LostTaste that referenced this pull request Apr 25, 2024
참고 : typeorm/typeorm#8616
> "primary relation (e.g. @manytoone(() => User, { primary: true }) user: User) support is removed. ..."
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