mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
fix: FindOptionsSelect to use correct type when property is an object (#11355)
* fix: FindOptionsSelectProperty or boolean when Property is object * fix: add test cases for find options select * fix: use simple-json for tests
This commit is contained in:
parent
00d5639efb
commit
834e85692f
@ -24,7 +24,7 @@ export type FindOptionsSelectProperty<Property> = Property extends Promise<
|
||||
: Property extends ObjectId
|
||||
? boolean
|
||||
: Property extends object
|
||||
? FindOptionsSelect<Property>
|
||||
? FindOptionsSelect<Property> | boolean
|
||||
: boolean
|
||||
|
||||
/**
|
||||
|
||||
30
test/functional/find-options/select/entity/Category.ts
Normal file
30
test/functional/find-options/select/entity/Category.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { Entity } from "../../../../../src/decorator/entity/Entity"
|
||||
import { PrimaryGeneratedColumn } from "../../../../../src/decorator/columns/PrimaryGeneratedColumn"
|
||||
import { Column } from "../../../../../src/decorator/columns/Column"
|
||||
import { VersionColumn } from "../../../../../src/decorator/columns/VersionColumn"
|
||||
import { Post } from "./Post"
|
||||
import { OneToMany } from "../../../../../src"
|
||||
import { CategoryMeta } from "../types"
|
||||
|
||||
@Entity()
|
||||
export class Category {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
@Column()
|
||||
name: string
|
||||
|
||||
@Column()
|
||||
description: string
|
||||
|
||||
@VersionColumn()
|
||||
version: string
|
||||
|
||||
@Column("simple-json", { nullable: true })
|
||||
meta?: CategoryMeta
|
||||
|
||||
@OneToMany(() => Post, (post) => post.category, {
|
||||
cascade: ["insert", "update", "soft-remove", "recover"],
|
||||
})
|
||||
posts: Post[]
|
||||
}
|
||||
35
test/functional/find-options/select/entity/Post.ts
Normal file
35
test/functional/find-options/select/entity/Post.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
JoinTable,
|
||||
ManyToMany,
|
||||
ManyToOne,
|
||||
PrimaryColumn,
|
||||
} from "../../../../../src"
|
||||
import { Tag } from "./Tag"
|
||||
import { Category } from "./Category"
|
||||
import { PostMeta } from "../types"
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
@PrimaryColumn()
|
||||
id: number
|
||||
|
||||
@Column()
|
||||
title: string
|
||||
|
||||
@Column()
|
||||
description: string
|
||||
|
||||
@ManyToOne((type) => Category)
|
||||
category: Category
|
||||
|
||||
@Column("simple-json", { nullable: true })
|
||||
meta?: PostMeta
|
||||
|
||||
@ManyToMany(() => Tag, (tag) => tag.posts, {
|
||||
cascade: ["insert", "update", "soft-remove", "recover"],
|
||||
})
|
||||
@JoinTable()
|
||||
tags: Tag[]
|
||||
}
|
||||
19
test/functional/find-options/select/entity/Tag.ts
Normal file
19
test/functional/find-options/select/entity/Tag.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Post } from "./Post"
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
ManyToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
} from "../../../../../src"
|
||||
|
||||
@Entity()
|
||||
export class Tag {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
@Column()
|
||||
name: string
|
||||
|
||||
@ManyToMany(() => Post, (post) => post.tags)
|
||||
posts: Post[]
|
||||
}
|
||||
187
test/functional/find-options/select/find-options-select.ts
Normal file
187
test/functional/find-options/select/find-options-select.ts
Normal file
@ -0,0 +1,187 @@
|
||||
import "reflect-metadata"
|
||||
import "../../../utils/test-setup"
|
||||
import { DataSource } from "../../../../src"
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
} from "../../../utils/test-utils"
|
||||
import { Post } from "./entity/Post"
|
||||
import { Category } from "./entity/Category"
|
||||
import { Tag } from "./entity/Tag"
|
||||
|
||||
describe("find options > select", () => {
|
||||
let dataSources: DataSource[]
|
||||
before(
|
||||
async () =>
|
||||
(dataSources = await createTestingConnections({
|
||||
__dirname,
|
||||
})),
|
||||
)
|
||||
beforeEach(() => reloadTestingDatabases(dataSources))
|
||||
after(() => closeTestingConnections(dataSources))
|
||||
|
||||
async function prepareData(dataSource: DataSource) {
|
||||
const tag = new Tag()
|
||||
tag.id = 1
|
||||
tag.name = "SuperTag"
|
||||
|
||||
const post = new Post()
|
||||
post.id = 1
|
||||
post.title = "Hello"
|
||||
post.description = "This is a post!"
|
||||
post.meta = {
|
||||
likes: 10,
|
||||
dislikes: 1,
|
||||
}
|
||||
post.tags = [tag]
|
||||
|
||||
const category = new Category()
|
||||
category.id = 1
|
||||
category.name = "Action"
|
||||
category.description = "Action movies"
|
||||
category.posts = [post]
|
||||
|
||||
await dataSource.manager.save(category)
|
||||
}
|
||||
|
||||
it("should select all properties of relation post", () =>
|
||||
Promise.all(
|
||||
dataSources.map(async (dataSource) => {
|
||||
await prepareData(dataSource)
|
||||
|
||||
const categories = await dataSource.manager.find(Category, {
|
||||
select: {
|
||||
id: true,
|
||||
posts: true,
|
||||
},
|
||||
relations: ["posts"],
|
||||
})
|
||||
|
||||
categories.should.be.eql([
|
||||
{
|
||||
id: 1,
|
||||
posts: [
|
||||
{
|
||||
id: 1,
|
||||
title: "Hello",
|
||||
description: "This is a post!",
|
||||
meta: {
|
||||
likes: 10,
|
||||
dislikes: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
}),
|
||||
))
|
||||
|
||||
it("should select all properties of relation post and its relation tag", () =>
|
||||
Promise.all(
|
||||
dataSources.map(async (dataSource) => {
|
||||
await prepareData(dataSource)
|
||||
|
||||
const categories = await dataSource.manager.find(Category, {
|
||||
select: {
|
||||
id: true,
|
||||
posts: {
|
||||
id: true,
|
||||
title: true,
|
||||
description: true,
|
||||
meta: true,
|
||||
tags: true,
|
||||
},
|
||||
},
|
||||
relations: ["posts", "posts.tags"],
|
||||
})
|
||||
|
||||
categories.should.be.eql([
|
||||
{
|
||||
id: 1,
|
||||
posts: [
|
||||
{
|
||||
id: 1,
|
||||
title: "Hello",
|
||||
description: "This is a post!",
|
||||
meta: {
|
||||
likes: 10,
|
||||
dislikes: 1,
|
||||
},
|
||||
tags: [
|
||||
{
|
||||
id: 1,
|
||||
name: "SuperTag",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
}),
|
||||
))
|
||||
|
||||
it("should select all from category and meta only from post", () =>
|
||||
Promise.all(
|
||||
dataSources.map(async (dataSource) => {
|
||||
await prepareData(dataSource)
|
||||
|
||||
const categories = await dataSource.manager.find(Category, {
|
||||
select: {
|
||||
id: true,
|
||||
posts: {
|
||||
meta: true,
|
||||
},
|
||||
},
|
||||
relations: ["posts"],
|
||||
})
|
||||
|
||||
categories.should.be.eql([
|
||||
{
|
||||
id: 1,
|
||||
posts: [
|
||||
{
|
||||
meta: {
|
||||
likes: 10,
|
||||
dislikes: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
}),
|
||||
))
|
||||
|
||||
it("should select all from category and meta only from post with all meta properties", () =>
|
||||
Promise.all(
|
||||
dataSources.map(async (dataSource) => {
|
||||
await prepareData(dataSource)
|
||||
|
||||
const categories = await dataSource.manager.find(Category, {
|
||||
select: {
|
||||
id: true,
|
||||
posts: {
|
||||
meta: {
|
||||
likes: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
relations: ["posts"],
|
||||
})
|
||||
|
||||
categories.should.be.eql([
|
||||
{
|
||||
id: 1,
|
||||
posts: [
|
||||
{
|
||||
meta: {
|
||||
likes: 10,
|
||||
dislikes: 1,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
}),
|
||||
))
|
||||
})
|
||||
8
test/functional/find-options/select/types.ts
Normal file
8
test/functional/find-options/select/types.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export interface PostMeta {
|
||||
likes: number
|
||||
dislikes: number
|
||||
}
|
||||
|
||||
export interface CategoryMeta {
|
||||
views: number
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user