Skip to content
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

Create user model #19

Merged
merged 2 commits into from
Dec 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions apps/teloalapi/src/models/User.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Entity, model, property } from "@loopback/repository";
import { User, UserRole } from "../types/User";

@model({
settings: {
description: "A TeloAL user. Created when registering and used when authenticating.",
},
})
export class UserModel extends Entity implements User {
@property({
id: true,
jsonSchema: {
description: "Uniquely identifies a user.",
},
})
username: string;

@property({
jsonSchema: {
description: "Optional email address of the user.",
},
})
email?: string;

@property({
jsonSchema: {
description: "Hashed user password.",
},
})
password: string;

@property({
jsonSchema: {
description: "Hashed user password.",
enum: ["admin", "user"],
},
})
role: UserRole;
}
109 changes: 109 additions & 0 deletions apps/teloalapi/src/repositories/AutoDateRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {
Count,
DataObject,
DefaultCrudRepository,
Entity,
JugglerDataSource,
Options,
Where,
model,
property,
} from "@loopback/repository";

type Timestamps = {
createdAt?: Date;
updatedAt?: Date;
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type GConstructor<T = {}> = new (...args: any[]) => T;

type TimestampedModel<TModel extends Entity> = TModel & Timestamps;

function extendClassWithTimestamps<T extends GConstructor<Entity>>(Base: T, modelName: string) {
@model({
name: modelName,
})
class Extended extends Base {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(...args: any[]) {
super(...args);
}

@property()
createdAt?: Date;

@property()
updatedAt?: Date;
}

return Extended;
}

export function makeRepository<TModel extends Entity, ID>(
TheModel: GConstructor<TModel>,
modelName: string,
idProp: keyof TModel,
) {
type TimestampedTModel = TimestampedModel<TModel>;

class AutoDateRepository extends DefaultCrudRepository<TimestampedTModel, ID> {
constructor(dataSource: JugglerDataSource) {
// @ts-ignore
super(extendClassWithTimestamps<GConstructor<TModel>>(TheModel, modelName), dataSource);
}

async create(
data: DataObject<TimestampedTModel>,
options?: Options,
): Promise<TimestampedTModel> {
data.createdAt = new Date();
data.updatedAt = new Date();
return super.create(data, options);
}

async update(data: TimestampedTModel, options?: Options): Promise<void> {
data.updatedAt = new Date();
return super.update(data, options);
}

async updateAll(
data: DataObject<TimestampedTModel>,
where?: Where<TimestampedTModel>,
options?: Options,
): Promise<Count> {
data.updatedAt = new Date();
return super.updateAll(data, where, options);
}

async replaceById(
id: ID,
data: DataObject<TimestampedTModel>,
options?: Options,
): Promise<void> {
data.updatedAt = new Date();
return super.replaceById(id, data, options);
}

async updateById(
id: ID,
data: DataObject<TimestampedTModel>,
options?: Options,
): Promise<void> {
data.updatedAt = new Date();
return super.updateById(id, data, options);
}

async upsert(data: DataObject<TimestampedTModel>) {
const id = data[idProp] as ID;

if (await this.exists(id)) {
return this.updateById(id, data);
}

return this.create(data);
}
}

return AutoDateRepository;
}
16 changes: 16 additions & 0 deletions apps/teloalapi/src/repositories/Users.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { inject } from "@loopback/core";
import { MongoDataSource } from "../datasources/mongo.datasource";
import { UserModel } from "../models/User.model";
import { makeRepository } from "./AutoDateRepository";

const BaseRepository = makeRepository<UserModel, typeof UserModel.prototype.username>(
UserModel,
"User",
"username",
);

export class UsersRepository extends BaseRepository {
constructor(@inject("datasources.mongo") dataSource: MongoDataSource) {
super(dataSource);
}
}
95 changes: 9 additions & 86 deletions apps/teloalapi/src/repositories/alCharacter.repository.ts
Original file line number Diff line number Diff line change
@@ -1,93 +1,16 @@
import { AlCharacter } from "@teloal/parse-character";
import { inject } from "@loopback/core";
import {
Count,
DefaultCrudRepository,
Entity,
Options,
Where,
model,
property,
} from "@loopback/repository";
import { MongoDataSource } from "../datasources/mongo.datasource";
import { AlCharacter } from "@teloal/parse-character";

type Timestamps = {
createdAt?: Date;
updatedAt?: Date;
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type GConstructor<T = {}> = new (...args: any[]) => T;

function extendClassWithTimestamps<T extends GConstructor<Entity>>(Base: T) {
@model({
name: "AlCharacter",
})
class Extended extends Base {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(...args: any[]) {
super(...args);
}

@property({
type: "date",
})
createdAt?: Date;
import { makeRepository } from "./AutoDateRepository";

@property({
type: "date",
})
updatedAt?: Date;
}

return Extended;
}
const BaseRepository = makeRepository<AlCharacter, typeof AlCharacter.prototype.name>(
AlCharacter,
"AlCharacter",
"name",
);

type TimestampedAlCharacter = AlCharacter & Timestamps;

export class AlCharacterRepository extends DefaultCrudRepository<
TimestampedAlCharacter,
typeof AlCharacter.prototype.name
> {
export class AlCharacterRepository extends BaseRepository {
constructor(@inject("datasources.mongo") dataSource: MongoDataSource) {
super(extendClassWithTimestamps(AlCharacter), dataSource);
}

async create(entity: TimestampedAlCharacter, options?: Options): Promise<TimestampedAlCharacter> {
entity.createdAt = new Date();
entity.updatedAt = new Date();
return super.create(entity, options);
}

async update(data: TimestampedAlCharacter, options?: Options): Promise<void> {
data.updatedAt = new Date();
return super.update(data, options);
}

async updateAll(
data: TimestampedAlCharacter,
where?: Where<TimestampedAlCharacter>,
options?: Options,
): Promise<Count> {
data.updatedAt = new Date();
return super.updateAll(data, where, options);
}

async replaceById(id: string, data: TimestampedAlCharacter, options?: Options): Promise<void> {
data.updatedAt = new Date();
return super.replaceById(id, data, options);
}

async updateById(id: string, data: TimestampedAlCharacter, options?: Options): Promise<void> {
data.updatedAt = new Date();
return super.updateById(id, data, options);
}

async upsert(char: AlCharacter) {
if (await this.exists(char.name)) {
return this.updateById(char.name, char);
}

return this.create(char);
super(dataSource);
}
}
13 changes: 13 additions & 0 deletions apps/teloalapi/src/types/User.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export enum UserRole {
user = "user",
admin = "admin",
}

export type User = {
username: string;
email?: string;
password: string;
role: UserRole;
createdAt?: Date;
updatedAt?: Date;
};
2 changes: 1 addition & 1 deletion apps/teloalapi/tsconfig.app.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"moduleResolution": "node",
"target": "es2018",
"sourceMap": true,
"declaration": true,
"declaration": false,
Telokis marked this conversation as resolved.
Show resolved Hide resolved
"importHelpers": true,
"types": ["node"]
},
Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
version: "3"
services:
teloal-mongo:
image: mongo
image: mongo:7
container_name: teloal-mongo
restart: unless-stopped
environment:
Expand All @@ -17,7 +17,7 @@ services:
- ./scripts/init-mongo.js:/docker-entrypoint-initdb.d/mongo-init.js:ro

teloal-mongo-express:
image: mongo-express
image: mongo-express:1.0.0-18-alpine3.18
container_name: teloal-mongo-express
restart: unless-stopped
environment:
Expand Down