{"id":18867934,"url":"https://github.com/hodfords-solutions/typeorm-helper","last_synced_at":"2025-04-07T11:03:53.061Z","repository":{"id":257804199,"uuid":"379796552","full_name":"hodfords-solutions/typeorm-helper","owner":"hodfords-solutions","description":"Simplifies TypeORM usage in NestJS apps","archived":false,"fork":false,"pushed_at":"2025-03-31T02:47:24.000Z","size":474,"stargazers_count":48,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-03-31T10:08:45.700Z","etag":null,"topics":["nestjs","nodejs","orm","typeorm"],"latest_commit_sha":null,"homepage":"https://opensource.hodfords.uk/typeorm-helper","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hodfords-solutions.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-24T03:51:17.000Z","updated_at":"2025-03-31T02:47:28.000Z","dependencies_parsed_at":"2024-12-24T13:10:30.073Z","dependency_job_id":"96ed7283-747b-4ce0-97fe-688325a568e9","html_url":"https://github.com/hodfords-solutions/typeorm-helper","commit_stats":{"total_commits":29,"total_committers":4,"mean_commits":7.25,"dds":0.1724137931034483,"last_synced_commit":"e8e08c04834479bd315329e14c338fd28ae30566"},"previous_names":["hodfords-solutions/typeorm-helper"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hodfords-solutions%2Ftypeorm-helper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hodfords-solutions%2Ftypeorm-helper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hodfords-solutions%2Ftypeorm-helper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hodfords-solutions%2Ftypeorm-helper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hodfords-solutions","download_url":"https://codeload.github.com/hodfords-solutions/typeorm-helper/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247640459,"owners_count":20971557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nestjs","nodejs","orm","typeorm"],"created_at":"2024-11-08T05:11:54.647Z","updated_at":"2025-04-07T11:03:53.041Z","avatar_url":"https://github.com/hodfords-solutions.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"http://opensource.hodfords.uk\" target=\"blank\"\u003e\u003cimg src=\"https://opensource.hodfords.uk/img/logo.svg\" width=\"320\" alt=\"Hodfords Logo\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e \u003cb\u003enestjs-validation\u003c/b\u003e enhances validation in your NestJS projects by providing a customized `ValidationPipe` that returns custom error messages. This library simplifies error handling by offering localized and user-friendly responses\u003c/p\u003e\n\n## Installation 🤖\n\nInstall the `typeorm-helper` package with:\n\n```bash\nnpm install @hodfords/typeorm-helper --save\n```\n\n## Usage 🚀\n\n### Defining custom repositories and entities\n\nWhen managing different entities, you can define custom repositories and entities. Below is an example for the Category entity and its corresponding repository.\n\n#### Entity\n\nThe `Category` table in the database is modeled by the `CategoryEntity`, `typeorm` decorators should be used to define this entity.\n\n```typescript\nimport { BaseEntity } from '@hodfords/typeorm-helper';\nimport { Column, Entity, ManyToMany, JoinTable, PrimaryGeneratedColumn } from 'typeorm';\n\n@Entity('Category')\nexport class CategoryEntity extends BaseEntity {\n    @PrimaryGeneratedColumn()\n    id: number;\n\n    @Column()\n    name: string;\n\n    @ManyToMany(() =\u003e PostEntity, (post) =\u003e post.categories)\n    @JoinTable({ name: 'PostCategory' })\n    posts: PostEntity[];\n}\n```\n\n#### Repository\n\nThe `CategoryRepository` is a custom repository that handles all database operations related to the `CategoryEntity`. By using the `@CustomRepository` decorator and extending `BaseRepository`, you ensure that your repository has both common CRUD functionality and can be easily customized with entity-specific methods.\n\n```typescript\nimport { CustomRepository, BaseRepository } from '@hodfords/typeorm-helper';\n\n@CustomRepository(CategoryEntity)\nexport class CategoryRepository extends BaseRepository\u003cCategoryEntity\u003e {}\n```\n\n### Lazy Relations\n\nLazy relations allow you to load related entities only when they are needed. This can significantly improve performance by preventing the fetching of unnecessary data upfront.\n\nThis functionality supports handling single entity, collection of entities, and paginated collection. Below is an example of how to load a list of posts associated with a specific category.\n\n##### Single entity\n\n```typescript\nconst categoryRepo = getDataSource().getCustomRepository(CategoryRepository);\nconst category = await categoryRepo.findOne({});\nawait category.loadRelation(['posts']);\n```\n\n##### Collection of entities\n\n```typescript\nconst categoryRepo = getDataSource().getCustomRepository(CategoryRepository);\nconst categories = await categoryRepo.findOne({ name: ILIKE('%football' });\nawait this.categories.loadRelations(['posts']);\n```\n\n##### Paginate collection\n\n```typescript\nconst categoryRepo = getDataSource().getCustomRepository(CategoryRepository);\nconst pagedCategories = await categoryRepo.pagination({}, { page: 1, perPage: 10 });\nawait pagedCategories.loadRelation('posts');\n```\n\nYou can also make use of the loadRelations function to efficiently load and retrieve related data\n\n```typescript\nawait loadRelations(categories, ['posts']);\n```\n\n### Relation Condition\n\nSometimes, you need to add custom conditions when loading related entities. `typeorm-helper` provides the\n`@RelationCondition` decorator for this purpose.\n\n##### Simple condition\n\nThis ensures that the posts relation is only loaded when the condition `posts.id = :postId` is satisfied.\n\n```typescript\n@Entity('User')\nexport class UserEntity extends BaseEntity {\n    @PrimaryGeneratedColumn()\n    id: number;\n\n    @Column()\n    name: string;\n\n    @RelationCondition((query: SelectQueryBuilder\u003cany\u003e) =\u003e {\n        query.where(' posts.id = :postId', { postId: 1 });\n    })\n    @OneToMany(() =\u003e PostEntity, (post) =\u003e post.user, { cascade: true })\n    posts: PostEntity[];\n\n    @RelationCondition((query: SelectQueryBuilder\u003cany\u003e, entities) =\u003e {\n        query.orderBy('id', 'DESC');\n        if (entities.length === 1) {\n            query.limit(1);\n        } else {\n            query.andWhere(\n                ' \"latestPost\".id in (select max(id) from \"post\" \"maxPost\" where \"maxPost\".\"userId\" = \"latestPost\".\"userId\")'\n            );\n        }\n    })\n    @OneToOne(() =\u003e PostEntity, (post) =\u003e post.user, { cascade: true })\n    latestPost: PostEntity;\n}\n```\n\n#### Complex condition\n\nHere, the condition applies a limit if only one entity is found, and fetches the latest post for each user if there are multiple entities.\n\n```typescript\n@Entity('User')\nexport class UserEntity extends BaseEntity {\n    @PrimaryGeneratedColumn()\n    id: number;\n\n    @Column()\n    name: string;\n\n    @RelationCondition(\n        (query: SelectQueryBuilder\u003cany\u003e) =\u003e {\n            query.where(' posts.id = :postId', { postId: 1 });\n        },\n        (entity, result, column) =\u003e {\n            return entity.id !== 2;\n        }\n    )\n    @OneToMany(() =\u003e PostEntity, (post) =\u003e post.user, { cascade: true })\n    posts: PostEntity[];\n}\n```\n\n### Where Expression\n\nFor complex queries that need to be reused or involve a lot of logic, it's best to put them in a class\n\n```typescript\nexport class BelongToUserWhereExpression extends BaseWhereExpression {\n    constructor(private userId: number) {\n        super();\n    }\n\n    where(query: WhereExpression) {\n        query.where({ userId: this.userId });\n    }\n}\n```\n\n```typescript\nconst posts = await this.postRepo.find({ where: new BelongToUserWhereExpression(1) });\n```\n\n### Query Builder\n\nFor complex and reusable queries, it's helpful to put the logic inside a class. This makes it easier to manage and reuse the query, resulting in cleaner and more maintainable code.\n\n```typescript\nexport class PostOfUserQuery extends BaseQuery\u003cPostEntity\u003e {\n    constructor(private userId: number) {\n        super();\n    }\n\n    query(query: SelectQueryBuilder\u003cPostEntity\u003e) {\n        query.where({ userId: this.userId }).limit(10);\n    }\n\n    order(query: SelectQueryBuilder\u003cPostEntity\u003e) {\n        query.orderBy('id', 'DESC');\n    }\n}\n```\n\n```typescript\nconst posts = await this.postRepo.find(new PostOfUserQuery(1));\n```\n\n## License 📝\n\nThis project is licensed under the MIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhodfords-solutions%2Ftypeorm-helper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhodfords-solutions%2Ftypeorm-helper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhodfords-solutions%2Ftypeorm-helper/lists"}