-
Notifications
You must be signed in to change notification settings - Fork 64
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
Orm #1942
Conversation
src/app.module.ts
Outdated
imports: [ConfigModule], | ||
useFactory: (configService: ConfigService) => { | ||
return { | ||
...{ autoLoadEntities: true, manualInitialization: true }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would there be any benefit in moving these to the configuration, e.g. should we be able to change these on the fly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I considered it as well, but for now, I think it's too much. Since the app heavily relies on manual initialization, it seems better to hardcode it here. For both cases, since they shouldn't be changed, hardcoding seems like the best approach IMO. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of it being centralised, e.g. if we hardcoded these values in our configuration
file but I am equally impartial. If it makes the most sense to have them here, we can keep it as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of it being centralised
💯
Done ✅
adf7bf4
|
||
@Entity('push_notification_devices') | ||
@Unique('device_uuid', ['device_uuid']) | ||
@Check('device_type', 'device_type IN ("ANDROID", "IOS", "WEB")') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we set this to the values of the enum via TypeORM?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean we should dynamically create the string? TypeOrm Check
only accepts string. I wouldn't dynamically create the string as that kills the readability here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to somehow have them linked. We aren't otherwise certain that our enum and this are the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about changing the field type in the database to ENUM? We can handle that in a separate PR.
P.S. I didn't modify the database fields, as it was beyond the scope of this PR.
type: 'varchar', | ||
length: 255, | ||
}) | ||
device_type!: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we can use the enum in the Check
decorator, this would then be typed that of the enum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, The best solution is to define this field as an enum in the database. But, that's outside the scope of this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be preferable. If it's any benefit, we already have the DeviceType
enum in the project.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you agree with me that it should be refactored in another PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's fine with me.
@Unique('name', ['name']) | ||
export class NotificationType { | ||
@PrimaryGeneratedColumn() | ||
id!: number; | ||
|
||
@Column({ | ||
type: 'varchar', | ||
length: 255, | ||
}) | ||
name!: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As with the device, could we ensure that the name
is of the NotificationType
enum?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can make it an ENUM in the database. I think it should be fixed in another PR. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. We already have a reference enum in the project - NotificationType
.
@Entity('push_notification_devices') | ||
@Unique('device_uuid', ['device_uuid']) | ||
@Check('device_type', 'device_type IN ("ANDROID", "IOS", "WEB")') | ||
export class NotificationDevice { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be done in a follow up, but I would be in favour of (on the domain level) validating these entities and, as such, we could then implement the type here, e.g.
// Datasource
export class NotificationDevice implements z.infer<NotificationDeviceSchema> { ... }
// Domain
function example() {
const deviceFromDatabase = // ...
return NotificationDeviceSchema.parse(device)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea, but let's do it in the notification PR.
@Column({ | ||
type: 'varchar', | ||
length: 42, | ||
}) | ||
safe_address!: string; | ||
|
||
@Column({ | ||
type: 'varchar', | ||
nullable: true, | ||
length: 42, | ||
}) | ||
signer_address!: string | null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should use the refinement functionality to call viem's getAddress
, ensuring that these addresses are checksummed. We can then set the type to 0x${string}
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be addressed in a separate PR focused on notifications.
src/config/entities/configuration.ts
Outdated
@@ -131,11 +131,13 @@ export default () => ({ | |||
apiKey: process.env.INFURA_API_KEY, | |||
}, | |||
}, | |||
typeorm: { autoLoadEntities: true, manualInitialization: true }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I've move these under the db
property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion, a better approach than the current one would be to use db.orm
and Array<db.databases>
, allowing us the flexibility to add multiple databases in the future and easily iterate over them. Do you believe we should move Typeorm under db?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
db.orm
sounds good to me. I wouldn't create and array out of them for now though as we don't have more than one. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
db.orm
also sounds good to me. Regarding the array, no strong opinion, but I'd slightly prefer not having it until it's needed. It can be easily added later if we need to add another db.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iamacook @hectorgomezv What do you think about moving orm
under db
and placing postgres
under db.connection
? My concern is that having orm
and postgres
under the same parent could lead to ambiguity. For now, db.connection
will remain an object, but in the future, we can convert it to an array and rename it to db.connections
(add an s to make it plural).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me @PooyaRaki, thanks! 👍
password: postgresEnvConfig.password, | ||
database: postgresEnvConfig.database, | ||
migrations: ['dist/migrations/*.js'], | ||
// logging: !isCIContext, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we can't have CI logging, I'd remove this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say let's keep it, it's like a TODO. I should have been more clear by adding a TODO.
To keep track of our discussion, we need to consider automatic migrations across multiple instances. |
- Introduces a new query logger to TypeORM. - Ensures TypeORM migrations run after locking the database during startup.
Summary
This pull request introduces TypeORM as the Object-Relational Mapping (ORM) solution for the project. TypeORM simplifies database interactions and enhances code maintainability by mapping database tables to application entities.
Benefits
Reduces boilerplate code and simplifies database operations.
Enhances code readability and maintainability.
Provides built-in support for migrations and schema management.
Improves error handling and validation through TypeORM features.
Changes
Integrated TypeORM into the project.
Updated database connection configuration to support TypeORM.
Created entity models corresponding to database tables.
Updated unit tests to ensure compatibility with TypeORM.
Next Steps
Explore additional features like eager loading and query optimizations in future iterations.