Adonis js loading only first preload - javascript

Im trying to list the itens of Chamados and the respective users, but only the first chamado return the user.
Model Usuario:
export default class Usuario extends BaseModel {
#hasMany(() => Chamado)
public chamados: HasMany<typeof Chamado>
#column({ isPrimary: true })
public id: number
#column()
public nome: string
#column()
public nivel: number
#column()
public email: string
#column()
public senha: string
#column.dateTime({ autoCreate: true })
public createdAt: DateTime
#column.dateTime({ autoCreate: true, autoUpdate: true })
public updatedAt: DateTime
}
Model Chamado:
export default class Chamado extends BaseModel {
#belongsTo(() => Usuario, {
foreignKey: 'id'
})
public user: BelongsTo<typeof Usuario>
#column({ isPrimary: true })
public id: number
#column()
public titulo: string
#column()
public descricao: string
#column()
public url_erro: string
ChamadosController
// Get chamados
public async index() {
const chamados = await Chamado.query().preload('user')
return {
data: chamados,
}
}
is returning 'user' only in first result:
result from get

Related

findOne() in TypeORM not working properly and giving error

I want to get the prospectousId from Dto, but I am getting the below error:,
tenant.controller.ts
#Post('/promote-prospectus')
#HttpCode(HttpStatus.OK)
#ApiOperation({ summary: 'Promoting a prospectus to a tenant.' })
#ApiResponse({ status: HttpStatus.OK, description: 'successful operation', })
async promoteAProspectus(#Res() response: Response, #Body() Dto: promoteProspectousDto) {
let result = await this.tenantsService.promoteAProspectus(Dto);
return response.status(HttpStatus.CREATED).json({ message: 'Prospectous promoted as a tenant by the system.', data: result });
}
tenant.service.ts
public async promoteAProspectus(Dto: promoteProspectousDto): Promise<Tenants> {
/**
* Scopes to be implement while promoting a prospectous to a tenant.
*
* #scope 1 promote the prospectous to a tenant and construct DB.
* #scope 2 Configure all default roles for the newly created tenant.
* #scope 3 Configure administrator user. & assign the administrator role.
*
*/
let prospectus = await this.tenantsRepository.findOne({ Dto.prospectousId });
console.log('hyyyyyyyyyyyyyyyyyyyyyyyyyyy', prospectus);
if (prospectus) {
const { id } = prospectus;
// let tenant: Tenants = await this.promoteAsTenant(prospectus);
// await this.rolesService.onBoardTenantDefaultRoles(tenant.tenantDb);
// let administrator: Users = await this.onBoardAdministratorUser(RequestedBy);
// await this.allocateAdministratorRole(administrator, tenant);
return tenant;
}
throw new ConflictException(`Unable to promote.`);
}
tenant.entity.ts
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
export enum ETenantStatus {
TRIAL = 'TRIAL',
ACTIVE = 'ACTIVE',
BLOCKED = 'BLOCKED',
ARCHIVED = 'ARCHIVED',
}
#Entity({ name: `${Tenants.name}` })
export class Tenants {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column({ nullable: false })
organization: string;
#Column({ unique: false })
db: string;
#Column({ unique: true })
key: string;
#Column({ unique: true })
domain: string;
#Column({ nullable: false })
location: string;
#Column({ nullable: false })
referedBy: string;
#Column()
#CreateDateColumn({ type: 'timestamp without time zone' })
public createdAt: Date;
#Column()
#UpdateDateColumn({ type: 'timestamp without time zone' })
public updatedAt: Date;
}
dto:
import { ApiProperty, ApiPropertyOptional } from "#nestjs/swagger";
import { IsBoolean, IsNotEmpty } from "class-validator";
export class tenantsDto {
#ApiProperty({ required: true, default: '' })
#IsNotEmpty()
organization: string;
#ApiProperty({ required: true, default: '' })
#IsNotEmpty()
domain: string;
#ApiPropertyOptional({ default: '' })
notes: string;
#ApiPropertyOptional({ default: '' })
db: string;
#ApiPropertyOptional({ default: '' })
#IsNotEmpty()
key: string;
#ApiPropertyOptional({ default: '' })
location: string;
#ApiPropertyOptional({ default: '' })
referedBy: string;
#ApiPropertyOptional({ default: false })
skipDbMigration: boolean;
#ApiProperty({ default: true })
#IsBoolean()
acceptedTermsAndConditions: boolean;
}
export class promoteProspectousDto {
#ApiProperty({ required: true, default: '' })
#IsNotEmpty()
prospectousId: string;
#ApiProperty({ required: true, default: '' })
#IsNotEmpty()
key: string;
}
What to do to achieve this? Thanks in advance!
Try using the below code. findOne() is to be replaced by findOneBy() as they say in their changelog.
let prospectus = await this.tenantsRepository.findOneBy({ id: Dto.prospectousId });
See the Changelog of TypeORM for more:
findOne() signature without parameters was dropped. If you need a single row from the db you can use a following syntax:
const [user] = await userRepository.find()
findOne(id) signature was dropped. Use following syntax instead:
const user = await userRepository.findOneBy({
id: id // where id is your column name
})

Nestjs typeorm relation order and limit elements

I am new to relations and typeorm. And now have some troubles with them. And now a little confused.
Is it possible in typeorm sort relation by id or createdDate without mapping it and to have limit elements?
My code example below:
person.entity
#Entity()
export class Person {
#PrimaryGeneratedColumn()
public id!: number;
#Column({ type: 'varchar', length: 120 })
public firstName: string;
#Column({ type: 'varchar', length: 120 })
public lastName: string;
#Column({ type: 'varchar', length: 13 })
public phone: string;
#Column({ type: 'varchar', length: 500 })
public place: string;
#Column({ type: 'boolean', default: false })
public isDeleted: boolean;
#OneToMany(() => Event, (event) => event.person, {
onDelete: 'SET NULL',
})
public events: Event[];
#CreateDateColumn({ type: 'timestamp' })
public createdAt!: Date;
#UpdateDateColumn({ type: 'timestamp' })
public updatedAt!: Date;
}
event.entity
#Entity()
export class Event {
#PrimaryGeneratedColumn()
public id!: number;
#ManyToOne(() => Person, (person) => person.id, {
onDelete: 'CASCADE',
})
public person!: Person;
#ManyToOne(() => User, (user) => user.id, {
onDelete: 'CASCADE',
})
public user!: User;
#CreateDateColumn({ type: 'timestamp' })
public createdAt!: Date;
#UpdateDateColumn({ type: 'timestamp' })
public updatedAt!: Date;
}
My code for sorting
// get persons and sort events
public async getALlPersons(): Promise<Person[]> {
return this.repository
.find({
relations: ['events'],
order: {
createdAt: 'DESC',
},
})
.then((persons) =>
persons.map((person) => {
person.events.sort((a, b) => b.id - a.id);
return person;
}),
);
}
And how to limit the number of events per person, for example I want to show only 10 events?
Thanks
There is a typeorm issue related to this: https://github.com/typeorm/typeorm/issues/89.
But in summary, it is not possible.

how to exclude required entities from a response in TypeORM with NestJS

I have an entity
#Column()
name: string;
#IsEmail()
email: string;
#Column({ select: false })
autogeneratedCode: string;
I'm getting name and string only in my GET request response which is expected.
But when I'm hit my POST Api with body, it is returning name, email, autogeneratedCode as well.
I need to hide autogeneratedCode in all CRUD responses.
Is there anyway to do that? or Am I missing something here?
You can use #Exclude() from 'class-transformer'
Example
import { Exclude } from 'class-transformer';
#Entity()
export class User {
#Column()
name: string;
#IsEmail()
email: string;
#Column({ select: false })
#Exclude()
autogeneratedCode: string;
constructor(entity: Partial<User>) {
Object.assign(this, entity);
}
}
Then you can use the constructor to create a new object excluding the #Exclude() properties.
export class UserService {
constructor(
#InjectRepository(User)
private userRepository: Repository<User>
) {}
public async createUser(user: User): Promise<User> {
return new User(
await this.userRepository.save(user)
);
}
}
NestJS Doc on Serialization
https://docs.nestjs.com/techniques/serialization#exclude-properties

ER_PARSE_ERROR in Nest js

Hello i have problem with relations in NestJS.
I was trying to get user with relation named club like that:
async findOne(id: number): Promise<User> {
return this.userRepository.findOne({
where: { id: id },
relations: ['club'],
});
}
And that throws this error:
ER_PARSE_ERROR: You have an error in your SQL syntax;
check the manual that corresponds to your MariaDB server version for the right syntax to use near 'WHERE `User`.`id` = 1) `distinct Alias` ORDER BY `User_id` ASC LIMIT 1' at line 1
I think my entites look correct, can it be problem with MariaDB?
There is my User entity:
export class User {
#PrimaryGeneratedColumn()
id: number;
#Column()
#Unique('email_unique', ['email'])
email: string;
#Column()
#Unique('username_unique', ['username'])
username: string;
#Column()
password: string;
#Column({ type: 'boolean' })
active = false;
#Column()
activationToken: string;
#OneToOne(() => Club, (club) => club.user)
club: Club;
}
And Club entity:
#Entity()
export class Club {
#PrimaryGeneratedColumn()
id: number;
#ManyToOne(() => League)
league: League;
#OneToOne(() => User, (user) => user.club)
user: User;
#Column()
name: string;
#Column()
location: string;
#OneToMany(() => Player, (player) => player.club)
players: Player[];
}
You are missing a JoinColumn annotation - it could be the reason for the erroneous generated sql. Try defining the JoinColumn on the owning side, e.g.
export class User {
// ...
#OneToOne(() => Club, (club) => club.user)
#JoinColumn()
club: Club;
}

Sequelize don't write data as expected

In a Next.js context, I'm trying to insert a data in a table using this code snippet :
const user = new User();
user.firstname = "John";
user.lastname = "Appleseed";
user.email = "john.appleseed#apple.com";
await user.create()
But when I inspect the log here's what I see
Basically, the data I put in the request are not written on the DB, but in a certain way Sequelize receive it (as shown in _previousData). But I don't know why there are moved from dataValues to theses _previousData
Here are the model I'm using
The core model :
export default class User {
id!: bigint
hash!: string
firstname?: string
lastname?: string
email?: string
isValidated?: boolean = false
async create(): Promise<void> {
try {
await UserEntity.create({
accountValidated: false,
firstname: this.firstname,
lastname: this.lastname,
email: this.email
});
} catch (error) {
console.error('User.create', error.message)
throw error
}
}
}
Here's the entity related to Sequelize and my PG
interface UserAttributes {
id?: bigint
hash?: string
firstname?: string
lastname?: string
email?: string
accountValidated: boolean
}
interface UserCreationAttributes extends Optional<UserAttributes, "id"> {}
export default class UserEntity extends Model<UserAttributes, UserCreationAttributes> implements UserAttributes {
public id!: bigint
public hash!: string
public firstname?: string
public lastname?: string
public email?: string
public accountValidated!: boolean
public readonly createdAt!: Date
public readonly updatedAt!: Date
public readonly accounts?: AccountEntity[]; // Note this is optional since it's only populated when explicitly requested in code
public static associations: {
accounts: Association<UserEntity, AccountEntity>;
};
}
UserEntity.init({
id: {
type: DataTypes.BIGINT,
primaryKey: true,
allowNull: false,
autoIncrement: true,
unique: true
},
hash: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
firstname: {
type: DataTypes.STRING,
allowNull: true
},
lastname: {
type: DataTypes.STRING,
allowNull: true
},
email: {
type: DataTypes.STRING,
allowNull: true,
unique: true,
validate: {
isEmail: {
msg: "This email is malformed"
}
}
},
accountValidated: {
type: DataTypes.BOOLEAN,
defaultValue: false
},
}, {
sequelize, // We need to pass the connection instance
modelName: 'User',
underscored: true,
tableName: 'blk_user',
timestamps: true
})
UserEntity.beforeValidate(user => {
user.hash = `usr_${v4()}`
})
UserEntity.beforeCreate(instance => console.log('beforeCreate', instance))
What I've tried
[x] Comment hooks
[x] Comment associations
EDIT 11/16 6:39 CET
Seems that it is linked to my way of declaring my models TS interfaces and models. I'll dig into it

Categories