Added users entity; formatted all files
This commit is contained in:
@@ -7,12 +7,14 @@ import { AppService } from './app.service';
|
|||||||
import { dataSourceOptions } from './appDataSource';
|
import { dataSourceOptions } from './appDataSource';
|
||||||
import { EntryModule } from './entries/entries.module';
|
import { EntryModule } from './entries/entries.module';
|
||||||
import { DataSource, EntityManager } from 'typeorm';
|
import { DataSource, EntityManager } from 'typeorm';
|
||||||
|
import { UsersModule } from './users/users.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot(),
|
ConfigModule.forRoot(),
|
||||||
TypeOrmModule.forRoot(dataSourceOptions),
|
TypeOrmModule.forRoot(dataSourceOptions),
|
||||||
EntryModule
|
EntryModule,
|
||||||
|
UsersModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService],
|
providers: [AppService],
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
import { DataSource, DataSourceOptions } from "typeorm";
|
import { DataSource, DataSourceOptions } from 'typeorm';
|
||||||
import { Entry } from "./entries/entries.entity";
|
import { Entry } from './entries/entries.entity';
|
||||||
import { Initial1770020781006 } from "./migrations/1770020781006-initial";
|
import { Initial1770020781006 } from './migrations/1770020781006-initial';
|
||||||
import { AddCreateUpdateDeleteColsAndRenameSourceToSourceText1770067407619 } from "./migrations/1770067407619-add_create_update_delete_cols_and_rename_source_to_sourceText";
|
import { AddCreateUpdateDeleteColsAndRenameSourceToSourceText1770067407619 } from './migrations/1770067407619-add_create_update_delete_cols_and_rename_source_to_sourceText';
|
||||||
|
import { User } from './users/users.entity';
|
||||||
|
import { AddUserEntity1770147074119 } from './migrations/1770147074119-add_user_entity';
|
||||||
|
|
||||||
export const dataSourceOptions: DataSourceOptions = {
|
export const dataSourceOptions: DataSourceOptions = {
|
||||||
type: "postgres",
|
type: 'postgres',
|
||||||
host: process.env.DB_HOST,
|
host: process.env.DB_HOST,
|
||||||
port: parseInt(process.env.DB_PORT as string, 10) || 5432,
|
port: parseInt(process.env.DB_PORT as string, 10) || 5432,
|
||||||
username: process.env.DB_USERNAME,
|
username: process.env.DB_USERNAME,
|
||||||
password: process.env.DB_PASSWORD,
|
password: process.env.DB_PASSWORD,
|
||||||
database: process.env.DB_NAME,
|
database: process.env.DB_NAME,
|
||||||
entities: [Entry],
|
entities: [Entry, User],
|
||||||
migrations: [Initial1770020781006, AddCreateUpdateDeleteColsAndRenameSourceToSourceText1770067407619],
|
migrations: [
|
||||||
synchronize: false,
|
Initial1770020781006,
|
||||||
}
|
AddCreateUpdateDeleteColsAndRenameSourceToSourceText1770067407619,
|
||||||
|
AddUserEntity1770147074119
|
||||||
|
],
|
||||||
|
synchronize: false,
|
||||||
|
};
|
||||||
|
|
||||||
export const appDataSource = new DataSource(dataSourceOptions)
|
export const appDataSource = new DataSource(dataSourceOptions);
|
||||||
|
|||||||
@@ -1,50 +1,60 @@
|
|||||||
import { Body, Controller, Delete, Get, Inject, Param, Post, Put } from '@nestjs/common';
|
import {
|
||||||
|
Body,
|
||||||
|
Controller,
|
||||||
|
Delete,
|
||||||
|
Get,
|
||||||
|
Inject,
|
||||||
|
Param,
|
||||||
|
Post,
|
||||||
|
Put,
|
||||||
|
} from '@nestjs/common';
|
||||||
import { EntryService } from './entries.service';
|
import { EntryService } from './entries.service';
|
||||||
import { EntryDTO } from './entries.dto';
|
import { EntryDTO } from './entries.dto';
|
||||||
import { Entry } from './entries.entity';
|
import { Entry } from './entries.entity';
|
||||||
|
|
||||||
@Controller('entries')
|
@Controller('entries')
|
||||||
export class EntriesController {
|
export class EntriesController {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(EntryService)
|
@Inject(EntryService)
|
||||||
private readonly entryService: EntryService
|
private readonly entryService: EntryService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
async saveEntry(@Body() entry: EntryDTO): Promise<string | undefined> {
|
||||||
|
return (await this.entryService.save(entry)).uuid;
|
||||||
|
}
|
||||||
|
|
||||||
@Post()
|
@Put(':uuid')
|
||||||
async saveEntry(@Body() entry: EntryDTO): Promise<string | undefined> {
|
async updateEntry(
|
||||||
return (await this.entryService.save(entry)).uuid
|
@Param('uuid') uuid: string,
|
||||||
}
|
@Body() entry: EntryDTO,
|
||||||
|
): Promise<string | undefined> {
|
||||||
|
return (await this.entryService.updateByUuid(uuid, entry)).uuid;
|
||||||
|
}
|
||||||
|
|
||||||
@Put(":uuid")
|
@Get()
|
||||||
async updateEntry(@Param("uuid") uuid: string, @Body() entry: EntryDTO): Promise<string | undefined> {
|
async findAll(): Promise<Entry[]> {
|
||||||
return (await this.entryService.updateByUuid(uuid, entry)).uuid
|
const entries = await this.entryService.findAll();
|
||||||
}
|
return entries.sort((a, b) => {
|
||||||
|
return (
|
||||||
|
new Date(b.created_at as Date).getTime() -
|
||||||
|
new Date(a.created_at as Date).getTime()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Get()
|
@Get(':uuid')
|
||||||
async findAll(): Promise<Entry[]>
|
async findOneByUuid(@Param('uuid') uuid: string): Promise<Entry | null> {
|
||||||
{
|
return await this.entryService.findOneByUuid(uuid);
|
||||||
const entries = await this.entryService.findAll()
|
}
|
||||||
return entries.sort((a, b) => {
|
|
||||||
return (
|
|
||||||
new Date(b.created_at as Date).getTime() - new Date(a.created_at as Date).getTime()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
@Get(":uuid")
|
@Delete(':uuid')
|
||||||
async findOneByUuid(@Param("uuid") uuid: string): Promise<Entry | null> {
|
async softDelete(@Param('uuid') uuid: string): Promise<void> {
|
||||||
return await this.entryService.findOneByUuid(uuid)
|
await this.entryService.softDeleteByUuid(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(":uuid")
|
@Put('/restore/:uuid')
|
||||||
async softDelete(@Param("uuid") uuid: string): Promise<void>
|
async restoreSoftDeleted(@Param('uuid') uuid: string): Promise<Entry | null> {
|
||||||
{
|
return await this.entryService.restoreDeletedByUuid(uuid);
|
||||||
await this.entryService.softDeleteByUuid(uuid)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Put("/restore/:uuid")
|
|
||||||
async restoreSoftDeleted(@Param("uuid") uuid: string): Promise<Entry | null> {
|
|
||||||
return await this.entryService.restoreDeletedByUuid(uuid)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Entry } from "./entries.entity";
|
import { Entry } from './entries.entity';
|
||||||
|
|
||||||
export class EntryDTO implements Partial<Entry> {
|
export class EntryDTO implements Partial<Entry> {
|
||||||
title?: string;
|
title?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
sourceText?: string;
|
sourceText?: string;
|
||||||
sourceUrl?: string;
|
sourceUrl?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,40 @@
|
|||||||
import { Column, CreateDateColumn, DeleteDateColumn, Entity, Generated, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";
|
import {
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
DeleteDateColumn,
|
||||||
|
Entity,
|
||||||
|
Generated,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
@Entity({ name: "entries"})
|
@Entity({ name: 'entries' })
|
||||||
export class Entry {
|
export class Entry {
|
||||||
@Column()
|
@Column()
|
||||||
@Generated("uuid")
|
@Generated('uuid')
|
||||||
uuid?: string;
|
uuid?: string;
|
||||||
|
|
||||||
@PrimaryGeneratedColumn("increment")
|
@PrimaryGeneratedColumn('increment')
|
||||||
id?: number;
|
id?: number;
|
||||||
|
|
||||||
@Column({ type: String, default: "" })
|
@Column({ type: String, default: '' })
|
||||||
title?: string;
|
title?: string;
|
||||||
|
|
||||||
@Column({ type: String, default: "" })
|
@Column({ type: String, default: '' })
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
@Column({ type: String, default: "" })
|
|
||||||
sourceText?: string;
|
|
||||||
|
|
||||||
@Column({ type: String, default: "" })
|
|
||||||
sourceUrl?: string;
|
|
||||||
|
|
||||||
@CreateDateColumn()
|
@Column({ type: String, default: '' })
|
||||||
created_at?: Date;
|
sourceText?: string;
|
||||||
|
|
||||||
@UpdateDateColumn()
|
@Column({ type: String, default: '' })
|
||||||
updated_at?: Date;
|
sourceUrl?: string;
|
||||||
|
|
||||||
@DeleteDateColumn()
|
@CreateDateColumn()
|
||||||
deleted_at?: Date;
|
created_at?: Date;
|
||||||
}
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updated_at?: Date;
|
||||||
|
|
||||||
|
@DeleteDateColumn()
|
||||||
|
deleted_at?: Date;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
import { Module } from "@nestjs/common";
|
import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from "@nestjs/typeorm";
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { Entry } from "./entries.entity";
|
import { Entry } from './entries.entity';
|
||||||
import { EntryService } from "./entries.service";
|
import { EntryService } from './entries.service';
|
||||||
import { EntriesController } from "./entries.controller";
|
import { EntriesController } from './entries.controller';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [TypeOrmModule.forFeature([Entry])],
|
||||||
TypeOrmModule.forFeature([Entry]),
|
exports: [EntryService],
|
||||||
],
|
providers: [EntryService],
|
||||||
exports: [EntryService],
|
controllers: [EntriesController],
|
||||||
providers: [EntryService],
|
|
||||||
controllers: [EntriesController],
|
|
||||||
})
|
})
|
||||||
export class EntryModule {}
|
export class EntryModule {}
|
||||||
|
|||||||
@@ -1,85 +1,85 @@
|
|||||||
import { Injectable, Logger } from "@nestjs/common";
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import { InjectRepository } from "@nestjs/typeorm";
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Entry } from "./entries.entity";
|
import { Entry } from './entries.entity';
|
||||||
import { Repository } from "typeorm";
|
import { Repository } from 'typeorm';
|
||||||
import { EntryDTO } from "./entries.dto";
|
import { EntryDTO } from './entries.dto';
|
||||||
import EntryNotFoundException from "./exceptions/entryNotFound.exception";
|
import EntryNotFoundException from './exceptions/entryNotFound.exception';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class EntryService {
|
export class EntryService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Entry)
|
@InjectRepository(Entry)
|
||||||
private entryRepository: Repository<Entry>
|
private entryRepository: Repository<Entry>,
|
||||||
) {}
|
) {}
|
||||||
private readonly logger = new Logger(EntryService.name)
|
private readonly logger = new Logger(EntryService.name);
|
||||||
|
|
||||||
async save(data: EntryDTO): Promise<Entry> {
|
async save(data: EntryDTO): Promise<Entry> {
|
||||||
this.logger.log("Creating entry")
|
this.logger.log('Creating entry');
|
||||||
const lEntry = new Entry();
|
const lEntry = new Entry();
|
||||||
lEntry.description = data.description
|
lEntry.description = data.description;
|
||||||
lEntry.sourceText = data.sourceText
|
lEntry.sourceText = data.sourceText;
|
||||||
lEntry.sourceUrl = data.sourceUrl
|
lEntry.sourceUrl = data.sourceUrl;
|
||||||
lEntry.title = data.title
|
lEntry.title = data.title;
|
||||||
await this.entryRepository.save(lEntry)
|
await this.entryRepository.save(lEntry);
|
||||||
return lEntry
|
return lEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateByUuid(uuid: string, data: EntryDTO): Promise<Entry> {
|
async updateByUuid(uuid: string, data: EntryDTO): Promise<Entry> {
|
||||||
this.logger.log(`Updating entry with UUID ${uuid}`)
|
this.logger.log(`Updating entry with UUID ${uuid}`);
|
||||||
const oldEntry = await this.entryRepository.findOneBy({ uuid: uuid})
|
const oldEntry = await this.entryRepository.findOneBy({ uuid: uuid });
|
||||||
if (!oldEntry) {
|
if (!oldEntry) {
|
||||||
throw new EntryNotFoundException(uuid)
|
throw new EntryNotFoundException(uuid);
|
||||||
} else {
|
} else {
|
||||||
const lEntry = new Entry();
|
const lEntry = new Entry();
|
||||||
// `id` is the primary key
|
// `id` is the primary key
|
||||||
lEntry.id = oldEntry.id
|
lEntry.id = oldEntry.id;
|
||||||
// These options can be updated
|
// These options can be updated
|
||||||
lEntry.description = data.description
|
lEntry.description = data.description;
|
||||||
lEntry.sourceText = data.sourceText
|
lEntry.sourceText = data.sourceText;
|
||||||
lEntry.sourceUrl = data.sourceUrl
|
lEntry.sourceUrl = data.sourceUrl;
|
||||||
lEntry.title = data.title
|
lEntry.title = data.title;
|
||||||
await this.entryRepository.save(lEntry)
|
await this.entryRepository.save(lEntry);
|
||||||
return lEntry
|
return lEntry;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async findOneByUuid(uuid: string): Promise<Entry | null> {
|
|
||||||
this.logger.log(`Returning entry with UUID ${uuid}`)
|
|
||||||
return this.entryRepository.findOneByOrFail({uuid: uuid})
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async findAll(): Promise<Entry[]> {
|
async findOneByUuid(uuid: string): Promise<Entry | null> {
|
||||||
this.logger.log("Returning all entries")
|
this.logger.log(`Returning entry with UUID ${uuid}`);
|
||||||
return this.entryRepository.find()
|
return this.entryRepository.findOneByOrFail({ uuid: uuid });
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAllAndDeleted(): Promise<Entry[]> {
|
async findAll(): Promise<Entry[]> {
|
||||||
this.logger.log("Returning all entries, active and deleted")
|
this.logger.log('Returning all entries');
|
||||||
return this.entryRepository.find({ withDeleted: true })
|
return this.entryRepository.find();
|
||||||
}
|
}
|
||||||
|
|
||||||
async softDeleteByUuid(uuid: string): Promise<void> {
|
async findAllAndDeleted(): Promise<Entry[]> {
|
||||||
this.logger.log(`Soft deleting entry with UUID ${uuid}`)
|
this.logger.log('Returning all entries, active and deleted');
|
||||||
const deleteResponse = await this.entryRepository.softDelete({
|
return this.entryRepository.find({ withDeleted: true });
|
||||||
uuid: uuid
|
}
|
||||||
})
|
|
||||||
if (!deleteResponse.affected) {
|
|
||||||
throw new EntryNotFoundException(uuid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async restoreDeletedByUuid(uuid: string): Promise<Entry | null> {
|
async softDeleteByUuid(uuid: string): Promise<void> {
|
||||||
this.logger.log(`Restoring entry with UUID ${uuid}`)
|
this.logger.log(`Soft deleting entry with UUID ${uuid}`);
|
||||||
const restoreResponse = await this.entryRepository.restore({
|
const deleteResponse = await this.entryRepository.softDelete({
|
||||||
uuid: uuid
|
uuid: uuid,
|
||||||
})
|
});
|
||||||
|
if (!deleteResponse.affected) {
|
||||||
if (!restoreResponse.affected) {
|
throw new EntryNotFoundException(uuid);
|
||||||
throw new EntryNotFoundException(uuid)
|
|
||||||
} else {
|
|
||||||
return this.entryRepository.findOneByOrFail({
|
|
||||||
uuid: uuid
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async restoreDeletedByUuid(uuid: string): Promise<Entry | null> {
|
||||||
|
this.logger.log(`Restoring entry with UUID ${uuid}`);
|
||||||
|
const restoreResponse = await this.entryRepository.restore({
|
||||||
|
uuid: uuid,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!restoreResponse.affected) {
|
||||||
|
throw new EntryNotFoundException(uuid);
|
||||||
|
} else {
|
||||||
|
return this.entryRepository.findOneByOrFail({
|
||||||
|
uuid: uuid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { NotFoundException } from "@nestjs/common";
|
import { NotFoundException } from '@nestjs/common';
|
||||||
|
|
||||||
class EntryNotFoundException extends NotFoundException {
|
class EntryNotFoundException extends NotFoundException {
|
||||||
constructor(uuid: string) {
|
constructor(uuid: string) {
|
||||||
super(`Entry with UUID ${uuid} not found`)
|
super(`Entry with UUID ${uuid} not found`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default EntryNotFoundException
|
export default EntryNotFoundException;
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
export class Initial1770020781006 implements MigrationInterface {
|
export class Initial1770020781006 implements MigrationInterface {
|
||||||
name = 'Initial1770020781006'
|
name = 'Initial1770020781006';
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.query(`CREATE TABLE "entries" ("uuid" uuid NOT NULL DEFAULT uuid_generate_v4(), "id" SERIAL NOT NULL, "title" character varying NOT NULL DEFAULT '', "description" character varying NOT NULL DEFAULT '', "source" character varying NOT NULL DEFAULT '', "sourceUrl" character varying NOT NULL DEFAULT '', CONSTRAINT "PK_8640855ae82083455cbb806173d" PRIMARY KEY ("id"))`);
|
await queryRunner.query(
|
||||||
}
|
`CREATE TABLE "entries" ("uuid" uuid NOT NULL DEFAULT uuid_generate_v4(), "id" SERIAL NOT NULL, "title" character varying NOT NULL DEFAULT '', "description" character varying NOT NULL DEFAULT '', "source" character varying NOT NULL DEFAULT '', "sourceUrl" character varying NOT NULL DEFAULT '', CONSTRAINT "PK_8640855ae82083455cbb806173d" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
}
|
||||||
await queryRunner.query(`DROP TABLE "entries"`);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE "entries"`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,29 @@
|
|||||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
export class AddCreateUpdateDeleteColsAndRenameSourceToSourceText1770067407619 implements MigrationInterface {
|
export class AddCreateUpdateDeleteColsAndRenameSourceToSourceText1770067407619 implements MigrationInterface {
|
||||||
name = 'AddCreateUpdateDeleteColsAndRenameSourceToSourceText1770067407619'
|
name = 'AddCreateUpdateDeleteColsAndRenameSourceToSourceText1770067407619';
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.query(`ALTER TABLE "entries" DROP COLUMN "source"`);
|
await queryRunner.query(`ALTER TABLE "entries" DROP COLUMN "source"`);
|
||||||
await queryRunner.query(`ALTER TABLE "entries" ADD "sourceText" character varying NOT NULL DEFAULT ''`);
|
await queryRunner.query(
|
||||||
await queryRunner.query(`ALTER TABLE "entries" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`);
|
`ALTER TABLE "entries" ADD "sourceText" character varying NOT NULL DEFAULT ''`,
|
||||||
await queryRunner.query(`ALTER TABLE "entries" ADD "updated_at" TIMESTAMP NOT NULL DEFAULT now()`);
|
);
|
||||||
await queryRunner.query(`ALTER TABLE "entries" ADD "deleted_at" TIMESTAMP`);
|
await queryRunner.query(
|
||||||
}
|
`ALTER TABLE "entries" ADD "created_at" TIMESTAMP NOT NULL DEFAULT now()`,
|
||||||
|
);
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
await queryRunner.query(
|
||||||
await queryRunner.query(`ALTER TABLE "entries" DROP COLUMN "deleted_at"`);
|
`ALTER TABLE "entries" ADD "updated_at" TIMESTAMP NOT NULL DEFAULT now()`,
|
||||||
await queryRunner.query(`ALTER TABLE "entries" DROP COLUMN "updated_at"`);
|
);
|
||||||
await queryRunner.query(`ALTER TABLE "entries" DROP COLUMN "created_at"`);
|
await queryRunner.query(`ALTER TABLE "entries" ADD "deleted_at" TIMESTAMP`);
|
||||||
await queryRunner.query(`ALTER TABLE "entries" DROP COLUMN "sourceText"`);
|
}
|
||||||
await queryRunner.query(`ALTER TABLE "entries" ADD "source" character varying NOT NULL DEFAULT ''`);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "entries" DROP COLUMN "deleted_at"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "entries" DROP COLUMN "updated_at"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "entries" DROP COLUMN "created_at"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "entries" DROP COLUMN "sourceText"`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE "entries" ADD "source" character varying NOT NULL DEFAULT ''`,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/migrations/1770147074119-add_user_entity.ts
Normal file
15
src/migrations/1770147074119-add_user_entity.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class AddUserEntity1770147074119 implements MigrationInterface {
|
||||||
|
name = 'AddUserEntity1770147074119';
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(
|
||||||
|
`CREATE TABLE "users" ("uuid" uuid NOT NULL DEFAULT uuid_generate_v4(), "id" SERIAL NOT NULL, "username" character varying NOT NULL DEFAULT '', "email" character varying NOT NULL DEFAULT '', "firstName" character varying NOT NULL DEFAULT '', "lastName" character varying NOT NULL DEFAULT '', "isAdmin" boolean NOT NULL DEFAULT false, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), "deleted_at" TIMESTAMP, CONSTRAINT "PK_a3ffb1c0c8416b9fc6f907b7433" PRIMARY KEY ("id"))`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`DROP TABLE "users"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/users/users.controller.spec.ts
Normal file
18
src/users/users.controller.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { UsersController } from './users.controller';
|
||||||
|
|
||||||
|
describe('UsersController', () => {
|
||||||
|
let controller: UsersController;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
controllers: [UsersController],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
controller = module.get<UsersController>(UsersController);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(controller).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
22
src/users/users.controller.ts
Normal file
22
src/users/users.controller.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { Controller, Inject } from '@nestjs/common';
|
||||||
|
import { UserService } from './users.service';
|
||||||
|
|
||||||
|
@Controller('users')
|
||||||
|
export class UsersController {
|
||||||
|
constructor(
|
||||||
|
@Inject(UserService)
|
||||||
|
private readonly userService: UserService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
// TODO: POST: save (create new) user
|
||||||
|
|
||||||
|
// TODO: PUT: update user by UUID
|
||||||
|
|
||||||
|
// TODO: GET: find all users
|
||||||
|
|
||||||
|
// TODO: GET: find user by UUID
|
||||||
|
|
||||||
|
// TODO: DELETE: soft delete user
|
||||||
|
|
||||||
|
// TODO: PUT: restore soft deleted user
|
||||||
|
}
|
||||||
9
src/users/users.dto.ts
Normal file
9
src/users/users.dto.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { User } from './users.entity';
|
||||||
|
|
||||||
|
export class UserDTO implements Partial<User> {
|
||||||
|
email?: string;
|
||||||
|
firstName?: string;
|
||||||
|
isAdmin?: boolean;
|
||||||
|
lastName?: string;
|
||||||
|
username?: string;
|
||||||
|
}
|
||||||
43
src/users/users.entity.ts
Normal file
43
src/users/users.entity.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import {
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
DeleteDateColumn,
|
||||||
|
Entity,
|
||||||
|
Generated,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
|
||||||
|
@Entity({ name: 'users' })
|
||||||
|
export class User {
|
||||||
|
@Column()
|
||||||
|
@Generated('uuid')
|
||||||
|
uuid?: string;
|
||||||
|
|
||||||
|
@PrimaryGeneratedColumn('increment')
|
||||||
|
id?: number;
|
||||||
|
|
||||||
|
@Column({ type: String, default: '' })
|
||||||
|
username?: string;
|
||||||
|
|
||||||
|
@Column({ type: String, default: '' })
|
||||||
|
email?: string;
|
||||||
|
|
||||||
|
@Column({ type: String, default: '' })
|
||||||
|
firstName?: string;
|
||||||
|
|
||||||
|
@Column({ type: String, default: '' })
|
||||||
|
lastName?: string;
|
||||||
|
|
||||||
|
@Column({ type: Boolean, default: false })
|
||||||
|
isAdmin?: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
created_at?: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updated_at?: Date;
|
||||||
|
|
||||||
|
@DeleteDateColumn()
|
||||||
|
deleted_at?: Date;
|
||||||
|
}
|
||||||
13
src/users/users.module.ts
Normal file
13
src/users/users.module.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { User } from './users.entity';
|
||||||
|
import { UserService } from './users.service';
|
||||||
|
import { UsersController } from './users.controller';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([User])],
|
||||||
|
exports: [UserService],
|
||||||
|
providers: [UserService],
|
||||||
|
controllers: [UsersController],
|
||||||
|
})
|
||||||
|
export class UsersModule {}
|
||||||
27
src/users/users.service.ts
Normal file
27
src/users/users.service.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { User } from './users.entity';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(User)
|
||||||
|
private userRepository: Repository<User>,
|
||||||
|
) {}
|
||||||
|
private readonly logger = new Logger(UserService.name);
|
||||||
|
|
||||||
|
// TODO: save (create new)
|
||||||
|
|
||||||
|
// TODO: update by UUID
|
||||||
|
|
||||||
|
// TODO: find one by UUID
|
||||||
|
|
||||||
|
// TODO: find all
|
||||||
|
|
||||||
|
// TODO: find all and deleted
|
||||||
|
|
||||||
|
// TODO: soft delete
|
||||||
|
|
||||||
|
// TODO: restore soft deleted by UUID
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user