@exanderal/stackcraft 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +57 -8
  2. package/dist/create/index.d.ts +1 -1
  3. package/dist/create/index.d.ts.map +1 -1
  4. package/dist/create/index.js +34 -14
  5. package/dist/create/index.js.map +1 -1
  6. package/dist/create/scaffolders/__tests__/web-vite.test.js +1 -0
  7. package/dist/create/scaffolders/__tests__/web-vite.test.js.map +1 -1
  8. package/dist/create/scaffolders/api-nestjs-graphql.d.ts.map +1 -1
  9. package/dist/create/scaffolders/api-nestjs-graphql.js +14 -17
  10. package/dist/create/scaffolders/api-nestjs-graphql.js.map +1 -1
  11. package/dist/create/scaffolders/api-nestjs-rest.d.ts.map +1 -1
  12. package/dist/create/scaffolders/api-nestjs-rest.js +14 -17
  13. package/dist/create/scaffolders/api-nestjs-rest.js.map +1 -1
  14. package/dist/create/scaffolders/orm.d.ts +6 -0
  15. package/dist/create/scaffolders/orm.d.ts.map +1 -0
  16. package/dist/create/scaffolders/orm.js +271 -0
  17. package/dist/create/scaffolders/orm.js.map +1 -0
  18. package/dist/create/scaffolders/setup-docker.js +33 -6
  19. package/dist/create/scaffolders/setup-docker.js.map +1 -1
  20. package/dist/create/scaffolders/utils/copy.d.ts.map +1 -1
  21. package/dist/create/scaffolders/utils/copy.js +1 -0
  22. package/dist/create/scaffolders/utils/copy.js.map +1 -1
  23. package/dist/create/types.d.ts +2 -0
  24. package/dist/create/types.d.ts.map +1 -1
  25. package/dist/index.js +2 -1
  26. package/dist/index.js.map +1 -1
  27. package/package.json +1 -1
  28. package/templates/api-nestjs-graphql/package.json +1 -3
  29. package/templates/api-nestjs-rest/package.json +1 -3
  30. package/templates/base/tools/generators/module/graphql-files/__fileName__.model.ts__tmpl__ +10 -8
  31. package/templates/base/tools/generators/module/index.js +0 -4
  32. package/templates/base/tools/generators/module/schema.json +0 -6
  33. package/templates/orm-kysely/scripts/migration-create.ts +30 -0
  34. package/templates/orm-kysely/src/common/repositories/entity.repository.ts +33 -0
  35. package/templates/orm-kysely/src/common/repositories/readonly-entity.repository.ts +46 -0
  36. package/templates/orm-kysely/src/database/database.types.ts +17 -0
  37. package/templates/orm-kysely/src/database/migrations/.gitkeep +0 -0
  38. package/templates/orm-kysely/src/database/seeds/seed.ts +12 -0
  39. package/templates/orm-kysely/src/database/utils/columns.ts +32 -0
  40. package/templates/orm-kysely/src/database/utils/index.ts +3 -0
  41. package/templates/orm-kysely/src/database/utils/indexes.ts +20 -0
  42. package/templates/orm-kysely/src/database/utils/tables.ts +7 -0
  43. package/templates/orm-kysely/src/modules/database/database.module.ts +9 -0
  44. package/templates/orm-kysely/tools/generators/module/files/__fileName__.model.ts__tmpl__ +16 -0
  45. package/templates/orm-kysely/tools/generators/module/files/__fileName__.module.ts__tmpl__ +9 -0
  46. package/templates/orm-kysely/tools/generators/module/files/__fileName__.repository.ts__tmpl__ +26 -0
  47. package/templates/orm-kysely/tools/generators/module/files/__fileName__.service.ts__tmpl__ +28 -0
  48. package/templates/orm-kysely/tools/generators/module/files/__tests__/__fileName__.integration.spec.ts__tmpl__ +23 -0
  49. package/templates/orm-kysely/tools/generators/module/graphql-files/__fileName__.model.ts__tmpl__ +24 -0
  50. package/templates/orm-prisma/prisma/schema.prisma +8 -0
  51. package/templates/orm-prisma/prisma/seeds/seed.ts +16 -0
  52. package/templates/orm-prisma/src/modules/database/database.module.ts +8 -0
  53. package/templates/orm-prisma/src/modules/prisma/prisma.module.ts +9 -0
  54. package/templates/orm-prisma/src/modules/prisma/prisma.service.ts +9 -0
  55. package/templates/orm-prisma/tools/generators/module/files/__fileName__.model.ts__tmpl__ +15 -0
  56. package/templates/orm-prisma/tools/generators/module/files/__fileName__.module.ts__tmpl__ +9 -0
  57. package/templates/orm-prisma/tools/generators/module/files/__fileName__.repository.ts__tmpl__ +28 -0
  58. package/templates/orm-prisma/tools/generators/module/files/__fileName__.service.ts__tmpl__ +28 -0
  59. package/templates/orm-prisma/tools/generators/module/files/__tests__/__fileName__.integration.spec.ts__tmpl__ +23 -0
  60. package/templates/orm-prisma/tools/generators/module/graphql-files/__fileName__.model.ts__tmpl__ +23 -0
  61. package/templates/api-nestjs-graphql/src/common/entities/base.entity.ts +0 -21
  62. package/templates/api-nestjs-graphql/src/common/repositories/entity.repository.ts +0 -21
  63. package/templates/api-nestjs-graphql/src/common/repositories/readonly-entity.repository.ts +0 -22
  64. package/templates/api-nestjs-graphql/src/common/services/entity.service.ts +0 -24
  65. package/templates/api-nestjs-graphql/src/common/services/readonly-entity.service.ts +0 -23
  66. package/templates/api-nestjs-graphql/src/modules/database/database.module.ts +0 -18
  67. package/templates/api-nestjs-rest/src/common/entities/base.entity.ts +0 -16
  68. package/templates/api-nestjs-rest/src/common/repositories/entity.repository.ts +0 -21
  69. package/templates/api-nestjs-rest/src/common/repositories/readonly-entity.repository.ts +0 -22
  70. package/templates/api-nestjs-rest/src/common/services/entity.service.ts +0 -24
  71. package/templates/api-nestjs-rest/src/common/services/readonly-entity.service.ts +0 -23
  72. package/templates/api-nestjs-rest/src/modules/database/database.module.ts +0 -18
@@ -0,0 +1,32 @@
1
+ import { sql, CreateTableBuilder } from 'kysely';
2
+
3
+ export function withUuid<T extends string, C extends string>(
4
+ builder: CreateTableBuilder<T, C>,
5
+ dialect: 'postgres' | 'mysql' = 'postgres',
6
+ ) {
7
+ const defaultFn =
8
+ dialect === 'mysql' ? sql`(UUID())` : sql`gen_random_uuid()`;
9
+ return builder.addColumn('id', 'uuid', (col) =>
10
+ col.primaryKey().defaultTo(defaultFn),
11
+ );
12
+ }
13
+
14
+ export function withTimestamps<T extends string, C extends string>(
15
+ builder: CreateTableBuilder<T, C>,
16
+ ) {
17
+ return builder
18
+ .addColumn('created_at', 'timestamptz', (col) =>
19
+ col.notNull().defaultTo(sql`now()`),
20
+ )
21
+ .addColumn('updated_at', 'timestamptz', (col) =>
22
+ col.notNull().defaultTo(sql`now()`),
23
+ );
24
+ }
25
+
26
+ // Shorthand: uuid primary key + timestamps
27
+ export function withDefaults<T extends string, C extends string>(
28
+ builder: CreateTableBuilder<T, C>,
29
+ dialect: 'postgres' | 'mysql' = 'postgres',
30
+ ) {
31
+ return withTimestamps(withUuid(builder, dialect));
32
+ }
@@ -0,0 +1,3 @@
1
+ export * from './columns';
2
+ export * from './indexes';
3
+ export * from './tables';
@@ -0,0 +1,20 @@
1
+ import { Kysely } from 'kysely';
2
+
3
+ export async function createIndex(
4
+ db: Kysely<any>,
5
+ table: string,
6
+ columns: string | string[],
7
+ opts?: { unique?: boolean; name?: string },
8
+ ) {
9
+ const cols = Array.isArray(columns) ? columns : [columns];
10
+ const name = opts?.name ?? `idx_${table}_${cols.join('_')}`;
11
+ let b = db.schema.createIndex(name).on(table).columns(cols);
12
+ if (opts?.unique) b = (b as any).unique();
13
+ await b.execute();
14
+ }
15
+
16
+ export const createUniqueIndex = (
17
+ db: Kysely<any>,
18
+ table: string,
19
+ columns: string | string[],
20
+ ) => createIndex(db, table, columns, { unique: true });
@@ -0,0 +1,7 @@
1
+ import { Kysely } from 'kysely';
2
+
3
+ export const createTable = (db: Kysely<any>, name: string) =>
4
+ db.schema.createTable(name);
5
+
6
+ export const dropTable = (db: Kysely<any>, name: string) =>
7
+ db.schema.dropTable(name).ifExists().execute();
@@ -0,0 +1,9 @@
1
+ import { Global, Module } from '@nestjs/common';
2
+ import { KyselyService } from './kysely.service';
3
+
4
+ @Global()
5
+ @Module({
6
+ providers: [KyselyService],
7
+ exports: [KyselyService],
8
+ })
9
+ export class DatabaseModule {}
@@ -0,0 +1,16 @@
1
+ // Define this table in src/database/database.types.ts:
2
+ //
3
+ // export interface <%= className %>sTable {
4
+ // id: Generated<string>
5
+ // created_at: Generated<Date>
6
+ // updated_at: Generated<Date>
7
+ // }
8
+ //
9
+ // Then add to Database interface:
10
+ // <%= fileName %>s: <%= className %>sTable
11
+
12
+ export interface <%= className %> {
13
+ id: string;
14
+ createdAt: Date;
15
+ updatedAt: Date;
16
+ }
@@ -0,0 +1,9 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { <%= className %>Repository } from './<%= fileName %>.repository';
3
+ import { <%= className %>Service } from './<%= fileName %>.service';
4
+
5
+ @Module({
6
+ providers: [<%= className %>Service, <%= className %>Repository],
7
+ exports: [<%= className %>Service, <%= className %>Repository],
8
+ })
9
+ export class <%= className %>Module {}
@@ -0,0 +1,26 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { EntityRepository } from '../../common/repositories/entity.repository';
3
+ import { KyselyService } from '../../modules/database/kysely.service';
4
+ import type { <%= className %> } from './<%= fileName %>.model';
5
+
6
+ // Add properties to enable filtering, e.g.:
7
+ // export type <%= className %>Filters = { id?: string }
8
+ export type <%= className %>Filters = Record<string, never>
9
+
10
+ @Injectable()
11
+ export class <%= className %>Repository extends EntityRepository<<%= className %>, <%= className %>Filters> {
12
+ protected table = '<%= fileName %>s';
13
+
14
+ constructor(kyselyService: KyselyService) {
15
+ super(kyselyService.db);
16
+ }
17
+
18
+ // protected filters = {
19
+ // id: where('<%= fileName %>s.id'),
20
+ // };
21
+
22
+ // protected override queryable() {
23
+ // return super.queryable()
24
+ // .innerJoin('other_table', 'other_table.id', '<%= fileName %>s.other_id')
25
+ // }
26
+ }
@@ -0,0 +1,28 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import type { <%= className %> } from './<%= fileName %>.model';
3
+ import { <%= className %>Repository } from './<%= fileName %>.repository';
4
+
5
+ @Injectable()
6
+ export class <%= className %>Service {
7
+ constructor(private readonly repository: <%= className %>Repository) {}
8
+
9
+ findAll() {
10
+ return this.repository.findAll();
11
+ }
12
+
13
+ findById(id: string) {
14
+ return this.repository.findById(id);
15
+ }
16
+
17
+ create(data: Omit<<%= className %>, 'id' | 'createdAt' | 'updatedAt'>) {
18
+ return this.repository.create(data);
19
+ }
20
+
21
+ update(id: string, data: Partial<Omit<<%= className %>, 'id' | 'createdAt' | 'updatedAt'>>) {
22
+ return this.repository.update(id, data);
23
+ }
24
+
25
+ remove(id: string) {
26
+ return this.repository.remove(id);
27
+ }
28
+ }
@@ -0,0 +1,23 @@
1
+ import { Test } from '@nestjs/testing';
2
+ import { KyselyService } from '../../modules/database/kysely.service';
3
+ import { <%= className %>Module } from '../<%= fileName %>.module';
4
+ import { <%= className %>Service } from '../<%= fileName %>.service';
5
+
6
+ describe('<%= className %>Service', () => {
7
+ let service: <%= className %>Service;
8
+
9
+ beforeAll(async () => {
10
+ const module = await Test.createTestingModule({
11
+ imports: [<%= className %>Module],
12
+ })
13
+ .overrideProvider(KyselyService)
14
+ .useValue({ db: {} })
15
+ .compile();
16
+
17
+ service = module.get(<%= className %>Service);
18
+ });
19
+
20
+ it('is defined', () => {
21
+ expect(service).toBeDefined();
22
+ });
23
+ });
@@ -0,0 +1,24 @@
1
+ import { Field, ID, ObjectType } from '@nestjs/graphql';
2
+
3
+ // Define this table in src/database/database.types.ts:
4
+ //
5
+ // export interface <%= className %>sTable {
6
+ // id: Generated<string>
7
+ // created_at: Generated<Date>
8
+ // updated_at: Generated<Date>
9
+ // }
10
+ //
11
+ // Then add to Database interface:
12
+ // <%= fileName %>s: <%= className %>sTable
13
+
14
+ @ObjectType()
15
+ export class <%= className %> {
16
+ @Field(() => ID)
17
+ id: string;
18
+
19
+ @Field(() => String)
20
+ createdAt: Date;
21
+
22
+ @Field(() => String)
23
+ updatedAt: Date;
24
+ }
@@ -0,0 +1,8 @@
1
+ generator client {
2
+ provider = "prisma-client-js"
3
+ }
4
+
5
+ datasource db {
6
+ provider = "{{dbProvider}}"
7
+ url = env("DATABASE_URL")
8
+ }
@@ -0,0 +1,16 @@
1
+ import { PrismaClient } from '@prisma/client';
2
+
3
+ const prisma = new PrismaClient();
4
+
5
+ async function main() {
6
+ // Example:
7
+ // await prisma.user.create({ data: { email: 'admin@example.com', name: 'Admin' } });
8
+ console.log('Seed complete.');
9
+ }
10
+
11
+ main()
12
+ .catch((e) => {
13
+ console.error(e);
14
+ process.exit(1);
15
+ })
16
+ .finally(() => prisma.$disconnect());
@@ -0,0 +1,8 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { PrismaModule } from '../prisma/prisma.module';
3
+
4
+ @Module({
5
+ imports: [PrismaModule],
6
+ exports: [PrismaModule],
7
+ })
8
+ export class DatabaseModule {}
@@ -0,0 +1,9 @@
1
+ import { Global, Module } from '@nestjs/common';
2
+ import { PrismaService } from './prisma.service';
3
+
4
+ @Global()
5
+ @Module({
6
+ providers: [PrismaService],
7
+ exports: [PrismaService],
8
+ })
9
+ export class PrismaModule {}
@@ -0,0 +1,9 @@
1
+ import { Injectable, OnModuleInit } from '@nestjs/common';
2
+ import { PrismaClient } from '@prisma/client';
3
+
4
+ @Injectable()
5
+ export class PrismaService extends PrismaClient implements OnModuleInit {
6
+ async onModuleInit() {
7
+ await this.$connect();
8
+ }
9
+ }
@@ -0,0 +1,15 @@
1
+ // Add this model to prisma/schema.prisma:
2
+ //
3
+ // model <%= className %> {
4
+ // id String @id @default(cuid())
5
+ // createdAt DateTime @default(now())
6
+ // updatedAt DateTime @updatedAt
7
+ // }
8
+ //
9
+ // Then run: pnpm migration:run
10
+
11
+ export type <%= className %> = {
12
+ id: string;
13
+ createdAt: Date;
14
+ updatedAt: Date;
15
+ };
@@ -0,0 +1,9 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { <%= className %>Repository } from './<%= fileName %>.repository';
3
+ import { <%= className %>Service } from './<%= fileName %>.service';
4
+
5
+ @Module({
6
+ providers: [<%= className %>Service, <%= className %>Repository],
7
+ exports: [<%= className %>Service, <%= className %>Repository],
8
+ })
9
+ export class <%= className %>Module {}
@@ -0,0 +1,28 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { PrismaService } from '../../modules/prisma/prisma.service';
3
+ import type { <%= className %> } from './<%= fileName %>.model';
4
+
5
+ @Injectable()
6
+ export class <%= className %>Repository {
7
+ constructor(private readonly prisma: PrismaService) {}
8
+
9
+ findAll() {
10
+ return this.prisma.<%= fileName %>.findMany();
11
+ }
12
+
13
+ findById(id: string) {
14
+ return this.prisma.<%= fileName %>.findUnique({ where: { id } });
15
+ }
16
+
17
+ create(data: Omit<<%= className %>, 'id' | 'createdAt' | 'updatedAt'>) {
18
+ return this.prisma.<%= fileName %>.create({ data });
19
+ }
20
+
21
+ update(id: string, data: Partial<Omit<<%= className %>, 'id' | 'createdAt' | 'updatedAt'>>) {
22
+ return this.prisma.<%= fileName %>.update({ where: { id }, data });
23
+ }
24
+
25
+ remove(id: string) {
26
+ return this.prisma.<%= fileName %>.delete({ where: { id } });
27
+ }
28
+ }
@@ -0,0 +1,28 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import type { <%= className %> } from './<%= fileName %>.model';
3
+ import { <%= className %>Repository } from './<%= fileName %>.repository';
4
+
5
+ @Injectable()
6
+ export class <%= className %>Service {
7
+ constructor(private readonly repository: <%= className %>Repository) {}
8
+
9
+ findAll(): Promise<<%= className %>[]> {
10
+ return this.repository.findAll();
11
+ }
12
+
13
+ findById(id: string): Promise<<%= className %> | null> {
14
+ return this.repository.findById(id);
15
+ }
16
+
17
+ create(data: Omit<<%= className %>, 'id' | 'createdAt' | 'updatedAt'>): Promise<<%= className %>> {
18
+ return this.repository.create(data);
19
+ }
20
+
21
+ update(id: string, data: Partial<Omit<<%= className %>, 'id' | 'createdAt' | 'updatedAt'>>): Promise<<%= className %>> {
22
+ return this.repository.update(id, data);
23
+ }
24
+
25
+ remove(id: string): Promise<<%= className %>> {
26
+ return this.repository.remove(id);
27
+ }
28
+ }
@@ -0,0 +1,23 @@
1
+ import { Test } from '@nestjs/testing';
2
+ import { PrismaService } from '../../modules/prisma/prisma.service';
3
+ import { <%= className %>Module } from '../<%= fileName %>.module';
4
+ import { <%= className %>Service } from '../<%= fileName %>.service';
5
+
6
+ describe('<%= className %>Service', () => {
7
+ let service: <%= className %>Service;
8
+
9
+ beforeAll(async () => {
10
+ const module = await Test.createTestingModule({
11
+ imports: [<%= className %>Module],
12
+ })
13
+ .overrideProvider(PrismaService)
14
+ .useValue({})
15
+ .compile();
16
+
17
+ service = module.get(<%= className %>Service);
18
+ });
19
+
20
+ it('is defined', () => {
21
+ expect(service).toBeDefined();
22
+ });
23
+ });
@@ -0,0 +1,23 @@
1
+ import { Field, ID, ObjectType } from '@nestjs/graphql';
2
+
3
+ // Add this model to prisma/schema.prisma:
4
+ //
5
+ // model <%= className %> {
6
+ // id String @id @default(cuid())
7
+ // createdAt DateTime @default(now())
8
+ // updatedAt DateTime @updatedAt
9
+ // }
10
+ //
11
+ // Then run: pnpm migration:run
12
+
13
+ @ObjectType()
14
+ export class <%= className %> {
15
+ @Field(() => ID)
16
+ id: string;
17
+
18
+ @Field(() => String)
19
+ createdAt: Date;
20
+
21
+ @Field(() => String)
22
+ updatedAt: Date;
23
+ }
@@ -1,21 +0,0 @@
1
- import { Field, ID, ObjectType } from '@nestjs/graphql';
2
- import {
3
- CreateDateColumn,
4
- PrimaryGeneratedColumn,
5
- UpdateDateColumn,
6
- } from 'typeorm';
7
-
8
- @ObjectType({ isAbstract: true })
9
- export abstract class BaseEntity {
10
- @Field(() => ID)
11
- @PrimaryGeneratedColumn('uuid')
12
- id: string;
13
-
14
- @Field()
15
- @CreateDateColumn()
16
- createdAt: Date;
17
-
18
- @Field()
19
- @UpdateDateColumn()
20
- updatedAt: Date;
21
- }
@@ -1,21 +0,0 @@
1
- import { DeepPartial } from 'typeorm';
2
- import { BaseEntity } from '../entities/base.entity';
3
- import { ReadonlyEntityRepository } from './readonly-entity.repository';
4
-
5
- export abstract class EntityRepository<
6
- T extends BaseEntity,
7
- > extends ReadonlyEntityRepository<T> {
8
- async create(data: DeepPartial<T>): Promise<T> {
9
- const entity = this.repo.create(data);
10
- return this.repo.save(entity);
11
- }
12
-
13
- async update(id: string, data: DeepPartial<T>): Promise<T> {
14
- await this.repo.update(id, data as any);
15
- return this.findById(id) as Promise<T>;
16
- }
17
-
18
- async remove(id: string): Promise<void> {
19
- await this.repo.delete(id);
20
- }
21
- }
@@ -1,22 +0,0 @@
1
- import { FindManyOptions, FindOptionsWhere, In, Repository } from 'typeorm';
2
- import { BaseEntity } from '../entities/base.entity';
3
-
4
- export abstract class ReadonlyEntityRepository<T extends BaseEntity> {
5
- constructor(protected readonly repo: Repository<T>) {}
6
-
7
- findAll(options?: FindManyOptions<T>): Promise<T[]> {
8
- return this.repo.find(options);
9
- }
10
-
11
- findByIds(ids: string[]): Promise<T[]> {
12
- return this.repo.findBy({ id: In(ids) } as FindOptionsWhere<T>);
13
- }
14
-
15
- findById(id: string): Promise<T | null> {
16
- return this.repo.findOneBy({ id } as FindOptionsWhere<T>);
17
- }
18
-
19
- findOne(where: FindOptionsWhere<T>): Promise<T | null> {
20
- return this.repo.findOneBy(where);
21
- }
22
- }
@@ -1,24 +0,0 @@
1
- import { DeepPartial } from 'typeorm';
2
- import { BaseEntity } from '../entities/base.entity';
3
- import { EntityRepository } from '../repositories/entity.repository';
4
- import { ReadonlyEntityService } from './readonly-entity.service';
5
-
6
- export abstract class EntityService<
7
- T extends BaseEntity,
8
- > extends ReadonlyEntityService<T> {
9
- constructor(protected readonly repository: EntityRepository<T>) {
10
- super(repository);
11
- }
12
-
13
- create(data: DeepPartial<T>): Promise<T> {
14
- return this.repository.create(data);
15
- }
16
-
17
- update(id: string, data: DeepPartial<T>): Promise<T> {
18
- return this.repository.update(id, data);
19
- }
20
-
21
- remove(id: string): Promise<void> {
22
- return this.repository.remove(id);
23
- }
24
- }
@@ -1,23 +0,0 @@
1
- import { FindManyOptions, FindOptionsWhere } from 'typeorm';
2
- import { BaseEntity } from '../entities/base.entity';
3
- import { ReadonlyEntityRepository } from '../repositories/readonly-entity.repository';
4
-
5
- export abstract class ReadonlyEntityService<T extends BaseEntity> {
6
- constructor(protected readonly repository: ReadonlyEntityRepository<T>) {}
7
-
8
- findAll(options?: FindManyOptions<T>): Promise<T[]> {
9
- return this.repository.findAll(options);
10
- }
11
-
12
- findByIds(ids: string[]): Promise<T[]> {
13
- return this.repository.findByIds(ids);
14
- }
15
-
16
- findById(id: string): Promise<T | null> {
17
- return this.repository.findById(id);
18
- }
19
-
20
- findOne(where: FindOptionsWhere<T>): Promise<T | null> {
21
- return this.repository.findOne(where);
22
- }
23
- }
@@ -1,18 +0,0 @@
1
- import { Module } from '@nestjs/common';
2
- import { TypeOrmModule } from '@nestjs/typeorm';
3
-
4
- @Module({
5
- imports: [
6
- TypeOrmModule.forRoot({
7
- type: '{{dbType}}' as 'postgres' | 'mysql',
8
- host: process.env.DB_HOST ?? 'localhost',
9
- port: parseInt(process.env.DB_PORT ?? '{{dbPort}}', 10),
10
- username: process.env.DB_USER ?? 'postgres',
11
- password: process.env.DB_PASSWORD ?? '',
12
- database: process.env.DB_NAME ?? '{{projectName}}',
13
- entities: [],
14
- synchronize: process.env.NODE_ENV !== 'production',
15
- }),
16
- ],
17
- })
18
- export class DatabaseModule {}
@@ -1,16 +0,0 @@
1
- import {
2
- CreateDateColumn,
3
- PrimaryGeneratedColumn,
4
- UpdateDateColumn,
5
- } from 'typeorm';
6
-
7
- export abstract class BaseEntity {
8
- @PrimaryGeneratedColumn('uuid')
9
- id: string;
10
-
11
- @CreateDateColumn()
12
- createdAt: Date;
13
-
14
- @UpdateDateColumn()
15
- updatedAt: Date;
16
- }
@@ -1,21 +0,0 @@
1
- import { DeepPartial } from 'typeorm';
2
- import { BaseEntity } from '../entities/base.entity';
3
- import { ReadonlyEntityRepository } from './readonly-entity.repository';
4
-
5
- export abstract class EntityRepository<
6
- T extends BaseEntity,
7
- > extends ReadonlyEntityRepository<T> {
8
- async create(data: DeepPartial<T>): Promise<T> {
9
- const entity = this.repo.create(data);
10
- return this.repo.save(entity);
11
- }
12
-
13
- async update(id: string, data: DeepPartial<T>): Promise<T> {
14
- await this.repo.update(id, data as any);
15
- return this.findById(id) as Promise<T>;
16
- }
17
-
18
- async remove(id: string): Promise<void> {
19
- await this.repo.delete(id);
20
- }
21
- }
@@ -1,22 +0,0 @@
1
- import { FindManyOptions, FindOptionsWhere, In, Repository } from 'typeorm';
2
- import { BaseEntity } from '../entities/base.entity';
3
-
4
- export abstract class ReadonlyEntityRepository<T extends BaseEntity> {
5
- constructor(protected readonly repo: Repository<T>) {}
6
-
7
- findAll(options?: FindManyOptions<T>): Promise<T[]> {
8
- return this.repo.find(options);
9
- }
10
-
11
- findByIds(ids: string[]): Promise<T[]> {
12
- return this.repo.findBy({ id: In(ids) } as FindOptionsWhere<T>);
13
- }
14
-
15
- findById(id: string): Promise<T | null> {
16
- return this.repo.findOneBy({ id } as FindOptionsWhere<T>);
17
- }
18
-
19
- findOne(where: FindOptionsWhere<T>): Promise<T | null> {
20
- return this.repo.findOneBy(where);
21
- }
22
- }
@@ -1,24 +0,0 @@
1
- import { DeepPartial } from 'typeorm';
2
- import { BaseEntity } from '../entities/base.entity';
3
- import { EntityRepository } from '../repositories/entity.repository';
4
- import { ReadonlyEntityService } from './readonly-entity.service';
5
-
6
- export abstract class EntityService<
7
- T extends BaseEntity,
8
- > extends ReadonlyEntityService<T> {
9
- constructor(protected readonly repository: EntityRepository<T>) {
10
- super(repository);
11
- }
12
-
13
- create(data: DeepPartial<T>): Promise<T> {
14
- return this.repository.create(data);
15
- }
16
-
17
- update(id: string, data: DeepPartial<T>): Promise<T> {
18
- return this.repository.update(id, data);
19
- }
20
-
21
- remove(id: string): Promise<void> {
22
- return this.repository.remove(id);
23
- }
24
- }
@@ -1,23 +0,0 @@
1
- import { FindManyOptions, FindOptionsWhere } from 'typeorm';
2
- import { BaseEntity } from '../entities/base.entity';
3
- import { ReadonlyEntityRepository } from '../repositories/readonly-entity.repository';
4
-
5
- export abstract class ReadonlyEntityService<T extends BaseEntity> {
6
- constructor(protected readonly repository: ReadonlyEntityRepository<T>) {}
7
-
8
- findAll(options?: FindManyOptions<T>): Promise<T[]> {
9
- return this.repository.findAll(options);
10
- }
11
-
12
- findByIds(ids: string[]): Promise<T[]> {
13
- return this.repository.findByIds(ids);
14
- }
15
-
16
- findById(id: string): Promise<T | null> {
17
- return this.repository.findById(id);
18
- }
19
-
20
- findOne(where: FindOptionsWhere<T>): Promise<T | null> {
21
- return this.repository.findOne(where);
22
- }
23
- }