I have recently started getting type errors on Nest.js (I think after upgrading to v8) and can't figure them out. This is on models. Here is my territory model.
import { Field, ObjectType } from '#nestjs/graphql'
import { Region } from '#biztobiz/api/region/data-access'
import { User } from '#biztobiz/api/user/data-access'
#ObjectType()
export class Territory {
#Field()
id: string
#Field()
createdAt: Date
#Field()
updatedAt: Date
#Field({ nullable: true })
name?: string
#Field({ nullable: true })
manager?: User
#Field(() => [Region], { nullable: true })
regions?: Region[]
}
Here is my user model.
import { Field, Int, ObjectType } from '#nestjs/graphql'
import { Role } from './role.enum'
import { UserStatus } from './user-status.enum'
import { Chapter } from '#biztobiz/api/chapter/data-access'
import { Company } from '#biztobiz/api/company/data-access'
import { Territory } from '#biztobiz/api/territory/data-access'
import { Region } from '#biztobiz/api/region/data-access'
import { Upload } from '#biztobiz/api/upload/data-access'
#ObjectType()
export class User {
#Field({ nullable: true })
id?: string
#Field({ nullable: true })
createdAt?: Date
#Field({ nullable: true })
updatedAt?: Date
#Field({ nullable: true })
firstName?: string
#Field({ nullable: true })
lastName?: string
#Field({ nullable: true })
avatarUrl?: string
#Field({ nullable: true })
showGravatar?: boolean
#Field(() => Role, { nullable: true })
role?: Role
#Field({ nullable: true })
developer?: boolean
#Field({ nullable: true })
bio?: string
#Field({ nullable: true })
email?: string
#Field({ nullable: true })
phone?: string
#Field({ nullable: true })
location?: string
#Field({ nullable: true })
facebook?: string
#Field({ nullable: true })
twitter?: string
#Field({ nullable: true })
instagram?: string
#Field({ nullable: true })
linkedin?: string
#Field({ nullable: true })
youtube?: string
#Field({ nullable: true })
website?: string
#Field({ nullable: true })
lastSeen?: Date
#Field({ nullable: true })
industry?: string
#Field({ nullable: true })
timeInIndustry?: string
#Field({ nullable: true })
address?: string
#Field({ nullable: true })
address2?: string
#Field({ nullable: true })
applicationDate?: Date
#Field({ nullable: true })
cell?: string
#Field({ nullable: true })
chapterTitle?: string
#Field({ nullable: true })
city?: string
#Field({ nullable: true })
comments?: string
#Field({ nullable: true })
company?: string
#Field({ nullable: true })
fax?: string
#Field({ nullable: true })
hear?: string
#Field({ nullable: true })
hearOther?: string
#Field({ nullable: true })
inactiveDate?: Date
#Field({ nullable: true })
inquiryDate?: Date
#Field({ nullable: true })
internalComments?: string
#Field({ nullable: true })
launchComplete?: boolean
#Field({ nullable: true })
membershipDate?: Date
#Field({ nullable: true })
mentorName?: string
#Field({ nullable: true })
merchantCircle?: string
#Field({ nullable: true })
multipleBusinesses?: boolean
#Field({ nullable: true })
multipleLocations?: boolean
#Field({ nullable: true })
numberOfEmployees?: number
#Field({ nullable: true })
organizer?: number
#Field({ nullable: true })
otherBusinesses?: string
#Field({ nullable: true })
otherLocations?: string
#Field({ nullable: true })
postcode?: string
#Field({ nullable: true })
promoter?: number
#Field({ nullable: true })
recognized?: number
#Field({ nullable: true })
renewalDate?: Date
#Field({ nullable: true })
salesAgentName?: string
#Field({ nullable: true })
state?: string
#Field({ nullable: true })
strategizer?: number
#Field({ nullable: true })
substitute?: boolean
#Field({ nullable: true })
tagline?: string
#Field({ nullable: true })
terminatedByName?: string
#Field({ nullable: true })
terminationDate?: Date
#Field({ nullable: true })
terminationComments?: string
#Field({ nullable: true })
terminationReason?: string
#Field({ nullable: true })
thinker?: number
#Field({ nullable: true })
title?: string
#Field({ nullable: true })
transferDate?: Date
#Field({ nullable: true })
type?: string
#Field({ nullable: true })
vet?: boolean
#Field(() => UserStatus, { nullable: true })
status?: UserStatus
#Field({ nullable: true })
notifyByEmail?: boolean
#Field({ nullable: true })
notifyBySMS?: boolean
#Field({ nullable: true })
notifyByWeb?: boolean
#Field({ nullable: true })
notifyByMobile?: boolean
#Field(() => Chapter, { nullable: true })
chapter?: Chapter
#Field(() => [Company], { nullable: true })
companies?: Company[]
#Field(() => Territory, { nullable: true })
territoryManaged?: Territory
#Field(() => Region, { nullable: true })
regionManaged?: Region
#Field((type) => Int, { nullable: true })
infusionsoftId?: number
#Field({ nullable: true })
password?: string
#Field(() => Upload, { nullable: true })
avatar?: Upload
}
And here is the error I'm getting.
TypeError: Cannot read properties of undefined (reading 'User')
at Module.User (/Users/justinhandley/IdeaProjects/biztobizglobal/dist/apps/api/main.js:12459:111)
at Object../libs/api/territory/data-access/src/lib/models/territory.model.ts (/Users/justinhandley/IdeaProjects/biztobizglobal/dist/apps/api/webpack:/biz-to-biz-global/libs/api/territory/data-access/src/lib/models/territory.model.ts:20:13)
at __webpack_require__ (/Users/justinhandley/IdeaProjects/biztobizglobal/dist/apps/api/webpack:/biz-to-biz-global/webpack/bootstrap:19:1)
at Object../libs/api/territory/data-access/src/index.ts (/Users/justinhandley/IdeaProjects/biztobizglobal/dist/apps/api/main.js:9381:85)
at __webpack_require__ (/Users/justinhandley/IdeaProjects/biztobizglobal/dist/apps/api/webpack:/biz-to-biz-global/webpack/bootstrap:19:1)
at Object../libs/api/region/data-access/src/lib/models/region.model.ts (/Users/justinhandley/IdeaProjects/biztobizglobal/dist/apps/api/main.js:7619:93)
at __webpack_require__ (/Users/justinhandley/IdeaProjects/biztobizglobal/dist/apps/api/webpack:/biz-to-biz-global/webpack/bootstrap:19:1)
at Object../libs/api/region/data-access/src/index.ts (/Users/justinhandley/IdeaProjects/biztobizglobal/dist/apps/api/main.js:7232:82)
at __webpack_require__ (/Users/justinhandley/IdeaProjects/biztobizglobal/dist/apps/api/webpack:/biz-to-biz-global/webpack/bootstrap:19:1)
at Object../libs/api/chapter/data-access/src/lib/models/chapter.model.ts (/Users/justinhandley/IdeaProjects/biztobizglobal/dist/apps/api/main.js:2033:90)
I've looked through all the documentation I can find, and have seen several people report this as well as 'fixes' but none are working for me.
This is a circular dependency issue. You need to move one of the model relationships into a resolver to fix this.
Related
I have a problem, when launching a query "Cannot return null for non-nullable field Account.groups".
I have graphql resolver:
#Resolver(of => Account)
export class AccountResolver {
constructor(
#Inject(AccountService) private accountService: AccountService,
) { }
#Query(returns => [Account], {
description: `To get all client's accounts`
})
#UseGuards(AuthGuard)
async accounts(
#Context('clientId') clientId: string,
): Promise<Account[]> {
return await this.accountService.getAllAccounts(clientId);
}
}
And model:
#ObjectType()
#Entity()
export class Account {
#Field()
#PrimaryGeneratedColumn('uuid')
id: string;
#Field()
#Column('text', {
default: ''
})
firstName: string;
#Field()
#Column('text', {
default: ''
})
lastName: string;
#Field()
#Column('text', {
nullable: true,
default: ''
})
avatar: string;
#Field()
#Column('text', {
unique: true,
})
username: string;
#Column('text', { nullable: false })
#Exclude({ toPlainOnly: true })
password: string;
#Field()
#Column({
type: 'varchar',
length: 300,
enum: Roles,
nullable: false
})
role: Roles
#Field()
#Column('text', { nullable: false, unique: true })
email: string;
#Field()
#Column({
default: false
})
emailVerified: boolean;
#Field()
#Column('text', { nullable: true, default: ''})
verificationLink: string;
#OneToMany(() => KitTask, kitTask => kitTask.account)
kitTasks: KitTask[];
#OneToMany(() => Trace, trace => trace.account)
traces: Trace[];
#Field(type => Client)
#ManyToOne(() => Client, client => client.accounts, { onDelete: 'CASCADE' })
client: Client;
#Field(type => Group)
#ManyToMany(() => Group, group => group.accounts)
#JoinTable()
groups: Group[];
}
I'm trying to launch query:
query accounts{
accounts{
id
firstName
lastName
avatar
username
role
email
emailVerified
client {
name
}
groups {
id
}
}
And getting the following error:
What is wrong?
I create a user entity with password:
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: number;
#Column({ type: "text", nullable: false })
userName: string;
#Column({ type: "text", nullable: false })
email: string;
#Column({ type: "text", nullable: false })
firstName: string;
#Column({ type: "text", nullable: false })
lastName: string;
#Column({ type: "text", nullable: false, select: false }) //It is select as false
password: string;
#Column({ type: "text", nullable: true })
socket_id: string;
#Column({ type: "text", nullable: true })
avatar: string;
#Column({ type: "boolean", default: false, nullable: false })
is_verify: boolean;
#CreateDateColumn()
created_at: Date;
#UpdateDateColumn()
updated_at: Date;
}
In this entity, I set select as false for password. When I find it, don't see the password column. How can I find this column?
const user = await this.userRepository.findOneBy({
email: loginInput.email,
is_verify: true
})
console.log(user)
What things I have to change in this code to get password column?
You can select hidden column:
const user = await this.userRepository.findOne({
where: {
email: loginInput.email,
is_verify: true,
},
select:{
password:true,
},
});
console.log(user);
When i'm trying to make a POST request, it records data in client table but doesn't in user_profile table, also it's doesn't record passportId in passport table. And also after request i got this error.
What am i missing?
{
"msg": "insert or update on table "user_profile" violates foreign key constraint "FK_259184fcdfba6d78485f5a048a0""
}
My ClientEntity:
#Entity()
export default class Client extends BaseEntity {
#PrimaryGeneratedColumn()
clientId: number;
#Column({ type: 'enum', enum: ClientStatus, default: ClientStatus.NOT_CLIENT })
clientStatus: ClientStatus;
#Column({ nullable: true })
countryOfResidence: string;
#Column({ nullable: true, length: 30 })
firstName: string;
#Column({ nullable: true, length: 30 })
lastName: string;
#Column({ nullable: true, length: 30 })
middleName: string;
#OneToOne(() => Passport)
#JoinColumn({ referencedColumnName: 'passportId', name: 'passportId' })
passportId: string;
#OneToOne(() => AuthVerification)
#JoinColumn({ referencedColumnName: 'mobilePhone', name: 'mobilePhone' })
mobilePhone: string;
#OneToOne(() => UserProfile, (userProfile) => userProfile.clientId)
userProfile: UserProfile;
}
My UserProfileEntity:
#Entity()
class UserProfile extends BaseEntity {
#PrimaryColumn()
#OneToOne(() => Client)
#JoinColumn({ referencedColumnName: 'clientId', name: 'clientId' })
clientId: number;
#Column({ nullable: true, default: false })
smsNotification: boolean;
#Column({ nullable: true, default: false })
pushNotification: boolean;
#Column({ nullable: true, default: false })
emailSubscription: boolean;
#Column({ length: 50, nullable: true })
securityQuestion: string;
#Column({ length: 50, nullable: true })
securityAnswer: string;
#Column({ length: 50, nullable: true, default: null })
email: string;
#Column({ length: 255, nullable: true })
password: string;
}
Line in migration with Constraint:
await queryRunner.query(
`ALTER TABLE "user_profile" ADD CONSTRAINT "FK_259184fcdfba6d78485f5a048a0" FOREIGN KEY ("clientId") REFERENCES "client"("clientId") ON DELETE NO ACTION ON UPDATE NO ACTION`
);
My register function:
public async registerNonClients(req: Request, res: Response) {
try {
const {
clientId,
mobilePhone,
password,
securityQuestion,
securityAnswer,
email,
firstName,
lastName,
middleName,
passportId,
countryOfResidence,
} = req.body;
await getRepository(Client).save({
clientId,
mobilePhone,
firstName,
lastName,
middleName,
countryOfResidence,
});
await getRepository(UserProfile).save({ clientId, password, securityQuestion, securityAnswer, email });
await getRepository(Passport).save({ passportId });
return res.status(StatusCodes.OK).json({ msg: 'Register successfull' });
} catch (error) {
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ msg: error.message });
}
}
I have two entities, users and roleuser, I have one to many mapping from user to role and many to one on user. while I am querying the result set, I am getting error as cannot read property joincolumns of undefined.Could anyone help me in solving this error, what am I doing wrong
Here are my entities.
// mosaique_user
#Entity()
export class MosaiqueUser {
#PrimaryGeneratedColumn()
id: number;
#Column({nullable: true, length: 100})
name: string;
#Column({unique: true, length: 255})
email: string;
#Column({nullable: true})
password: string;
#Column({nullable: true})
is_temp: number;
#Column({nullable: true})
salt: string;
#Column({nullable: true, default: 2})
status: number;
#Column({nullable: true, default: 2})
apply_status: number;
#Column({ type: 'timestamp', nullable: true})
created_at: Date;
#Column({ type: 'timestamp', nullable: true})
updated_at: Date;
#Column({ nullable: true})
created_by: number;
#Column({ nullable: true})
updated_by: number;
#OneToOne(() => MosaiqueUserProfile, userprofile => userprofile.user)
userprofile: MosaiqueUserProfile;
#OneToMany(() => RoleUser, userRole => userRole.user_id, {
cascade: true,
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
})
#JoinColumn({ referencedColumnName: 'user_id' })
userRoles!: RoleUser[];
}
// role_user
#Entity()
export class RoleUser {
#PrimaryGeneratedColumn()
id: number;
#Column()
user_id: number;
#Column()
role_id: number;
#CreateDateColumn()
created_at: Date;
#UpdateDateColumn()
updated_at: Date;
#ManyToOne(() => MosaiqueUser, user => user.userRoles)
#JoinColumn({ name: 'user_id' })
user!: MosaiqueUser;
#ManyToOne(() => MRole, role => role.userRoles)
#JoinColumn({ name: 'role_id' })
role!: MRole;
}
// with relations query
let userData = await this.mosaiqueUser.find({
relations: ['userRoles'],
where: {'id':1}
});
Error
(node:57872) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'joinColumns' of undefined
at C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:1549:61
at Array.map ()
at SelectQueryBuilder.createJoinExpression (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:1520:57)
at SelectQueryBuilder.getQuery (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:57:21)
at SelectQueryBuilder.QueryBuilder.getQueryAndParameters (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\QueryBuilder.ts:446:28)
at SelectQueryBuilder. (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:2112:40)
at step (C:\Sites\Dynamodb\TypeORMProject\node_modules\tslib\tslib.js:144:27)
at Object.next (C:\Sites\Dynamodb\TypeORMProject\node_modules\tslib\tslib.js:125:57)
at C:\Sites\Dynamodb\TypeORMProject\node_modules\tslib\tslib.js:118:75
at new Promise ()
I created an API which is returning selected fields of user data.
User model:
#Exclude()
#Entity('users')
export class User extends Timestampable {
#ApiProperty()
#PrimaryGeneratedColumn()
id: number;
#ApiProperty()
#Expose({ groups: ['create', 'profile'] })
#Column({ unique: true })
email: string;
#ApiProperty()
#Expose({ groups: ['create'] })
#Column()
password: string;
#ApiProperty()
#Expose({ groups: ['profile'] })
#Column({ nullable: true })
firstName: string;
#ApiProperty()
#Expose({ groups: ['profile'] })
#Column({ nullable: true })
lastName: string;
#ApiProperty()
#Expose({ groups: ['profile'] })
#Column({ nullable: true })
paternalName: string;
#ApiProperty()
#Expose({ groups: ['profile'] })
#Column({ nullable: true })
phone: string;
#ApiProperty()
#Expose({ groups: ['profile'] })
#Column({ nullable: true, type: 'enum', enum: UserGender })
gender: UserGender;
}
Inside the controller, I just return:
return instanceToPlain(user, {
groups: ['profile'],
});
here will be returned only the fields of the user which have a profile group.
Everything working properly. But for swagger documentation I used:
{
schema: {shows
$ref: getSchemaPath(User),
},
}
and in the documentation, it shows all fields of the user.
How can I show only fields from the particular group?
One of the options create 2 different DTOs and use them but that solution in my opinion is not that good.