Skip to content

Commit

Permalink
feat(models): Repository
Browse files Browse the repository at this point in the history
Signed-off-by: Lexus Drumgold <[email protected]>
  • Loading branch information
unicornware committed Apr 30, 2023
1 parent 86ae3ec commit 86ec9e5
Show file tree
Hide file tree
Showing 15 changed files with 778 additions and 30 deletions.
1 change: 1 addition & 0 deletions .dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dessant
dohm
dotenv
dtos
embeddable
fbca
gcloud
ggshield
Expand Down
Empty file removed __fixtures__/.gitkeep
Empty file.
113 changes: 113 additions & 0 deletions __fixtures__/account.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/**
* @file Fixtures - Account
* @module fixtures/Account
*/

import { IsNullable, IsOptional, IsTimestamp } from '#src/decorators'
import type { IEntity } from '#src/interfaces'
import { isNIL, type Nullable } from '@flex-development/tutils'
import {
Entity,
PrimaryKey,
Property,
SerializedPrimaryKey,
Unique,
type EntityData
} from '@mikro-orm/core'
import { ObjectId } from '@mikro-orm/mongodb'
import { IsEmail, IsInstance, IsLowercase, IsMongoId } from 'class-validator'
import plur from 'plur'

/**
* Data used to create a new account via the entity constructor.
*/
type AccountDTO = Omit<EntityData<Account>, 'email'> & { email: string }

/**
* Data model representing an entity in the accounts collection.
*
* @class
* @implements {IEntity}
*/
@Entity({ collection: plur(Account.name).toLowerCase() })
class Account implements IEntity {
/**
* BSON object id.
*
* @public
* @readonly
* @member {ObjectId} _id
*/
@PrimaryKey<Account>({ type: ObjectId })
@IsInstance(ObjectId)
@IsOptional()
public _id!: ObjectId

/**
* Unix timestamp indicating when account was created.
*
* @public
* @readonly
* @member {number} created_at
*/
@Property<Account>({ type: 'integer' })
@IsTimestamp()
public created_at: number = Date.now()

/**
* Account email address.
*
* @public
* @readonly
* @member {Lowercase<string>} email
*/
@Property<Account>({ type: 'string' })
@Unique<Account>({ name: 'email' })
@IsEmail()
@IsLowercase()
public email!: Lowercase<string>

/**
* Unique identifier for account.
*
* @public
* @readonly
* @member {string} id
*/
@SerializedPrimaryKey<Account>({ type: 'string' })
@IsMongoId()
@IsOptional()
public id!: string

/**
* Unix timestamp indicating when account was last modified.
*
* @public
* @readonly
* @member {Nullable<number>} updated_at
*/
@Property<Account>({ nullable: true, type: 'integer' })
@IsTimestamp()
@IsNullable()
public updated_at: Nullable<number> = null

/**
* Creates a new account entity.
*
* @param {AccountDTO} dto - Data transfer object
* @param {string} dto.email - Account email
*/
constructor({ _id, created_at, email, updated_at }: AccountDTO) {
if (!isNIL(_id)) {
this._id = _id
this.id = this._id.toString()
}

!isNIL(created_at) && (this.created_at = created_at)
!isNIL(updated_at) && (this.updated_at = updated_at)

this.email = email.trim().toLowerCase()
}
}

export default Account
56 changes: 56 additions & 0 deletions __fixtures__/account.factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* @file Fixtures - AccountFactory
* @module fixtures/AccountFactory
*/

import type { Constructor } from '@mikro-orm/core'
import type { MongoEntityManager } from '@mikro-orm/mongodb'
import { Factory, Faker } from '@mikro-orm/seeder'
import Account from './account.entity'

/**
* Account entity factory.
*
* @see {@linkcode Account}
*
* @class
* @extends {Factory<Account>}
*/
class AccountFactory extends Factory<Account> {
/**
* Entity the factory generates entity instances for.
*
* @public
* @readonly
* @member {Constructor<Account>} model
*/
public readonly model: Constructor<Account>

/**
* Creates a new {@linkcode Account} entity factory.
*
* @param {MongoEntityManager} em - Entity manager
*/
constructor(em: MongoEntityManager) {
super(em)
this.model = Account
}

/**
* Returns the default set of attribute values that should be applied when
* creating an {@linkcode Account} entity.
*
* @see https://fakerjs.dev
*
* @protected
* @override
*
* @param {Faker} faker - Faker library
* @return {{ email: Account['email'] }} Account entity data
*/
protected override definition(faker: Faker): { email: Account['email'] } {
return { email: faker.internet.email().toLowerCase() }
}
}

export default AccountFactory
139 changes: 139 additions & 0 deletions __fixtures__/subscriber.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/**
* @file Fixtures - Subscriber
* @module fixtures/Subscriber
*/

import { IsNullable, IsOptional, IsTimestamp } from '#src/decorators'
import type { IEntity } from '#src/interfaces'
import { isNIL, type Nullable } from '@flex-development/tutils'
import {
Entity,
Index,
PrimaryKey,
Property,
SerializedPrimaryKey,
Unique,
type EntityData
} from '@mikro-orm/core'
import { ObjectId } from '@mikro-orm/mongodb'
import {
IsEmail,
IsInstance,
IsLowercase,
IsMongoId,
IsString,
MinLength
} from 'class-validator'
import plur from 'plur'

/**
* Data used to create a new subscriber via the entity constructor.
*/
type SubscriberDTO = Omit<EntityData<Subscriber>, 'email' | 'name'> & {
email: string
name: string
}

/**
* Data model representing an entity in the subscribers collection.
*
* @class
* @implements {IEntity}
*/
@Entity({ collection: plur(Subscriber.name).toLowerCase() })
class Subscriber implements IEntity {
/**
* BSON object id.
*
* @public
* @readonly
* @member {ObjectId} _id
*/
@PrimaryKey<Subscriber>({ type: ObjectId })
@IsInstance(ObjectId)
@IsOptional()
public _id!: ObjectId

/**
* Unix timestamp indicating when subscriber signed up.
*
* @public
* @readonly
* @member {number} created_at
*/
@Property<Subscriber>({ type: 'integer' })
@IsTimestamp()
public created_at: number = Date.now()

/**
* Subscriber email address.
*
* @public
* @readonly
* @member {Lowercase<string>} email
*/
@Property<Subscriber>({ type: 'string' })
@Unique<Subscriber>({ name: 'email' })
@IsEmail()
@IsLowercase()
public email!: Lowercase<string>

/**
* Unique identifier for subscriber.
*
* @public
* @readonly
* @member {string} id
*/
@SerializedPrimaryKey<Subscriber>({ type: 'string' })
@IsMongoId()
@IsOptional()
public id!: string

/**
* Subscriber name.
*
* @public
* @readonly
* @member {string} name
*/
@Property<Subscriber>({ type: 'string' })
@Index<Subscriber>({ name: 'name' })
@IsString()
@MinLength(1)
public name!: string

/**
* Unix timestamp indicating when subscriber was last modified.
*
* @public
* @readonly
* @member {Nullable<number>} updated_at
*/
@Property<Subscriber>({ nullable: true, type: 'integer' })
@IsTimestamp()
@IsNullable()
public updated_at: Nullable<number> = null

/**
* Creates a new subscriber entity.
*
* @param {SubscriberDTO} dto - Data transfer object
* @param {string} dto.email - Subscriber email
* @param {string} dto.name - Subscriber name
*/
constructor({ _id, created_at, name, email, updated_at }: SubscriberDTO) {
if (!isNIL(_id)) {
this._id = _id
this.id = this._id.toString()
}

!isNIL(created_at) && (this.created_at = created_at)
!isNIL(updated_at) && (this.updated_at = updated_at)

this.email = email.trim().toLowerCase()
this.name = name.trim()
}
}

export default Subscriber
61 changes: 61 additions & 0 deletions __fixtures__/subscriber.factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* @file Fixtures - SubscriberFactory
* @module fixtures/SubscriberFactory
*/

import type { Constructor } from '@mikro-orm/core'
import type { MongoEntityManager } from '@mikro-orm/mongodb'
import { Factory, Faker } from '@mikro-orm/seeder'
import Subscriber from './subscriber.entity'

/**
* Subscriber entity factory.
*
* @see {@linkcode Subscriber}
*
* @class
* @extends {Factory<Subscriber>}
*/
class SubscriberFactory extends Factory<Subscriber> {
/**
* Entity the factory generates entity instances for.
*
* @public
* @readonly
* @member {Constructor<Subscriber>} model
*/
public readonly model: Constructor<Subscriber>

/**
* Creates a new {@linkcode Subscriber} entity factory.
*
* @param {MongoEntityManager} em - Entity manager
*/
constructor(em: MongoEntityManager) {
super(em)
this.model = Subscriber
}

/**
* Returns the default set of attribute values that should be applied when
* creating an {@linkcode Subscriber} entity.
*
* @see https://fakerjs.dev
*
* @protected
* @override
*
* @param {Faker} faker - Faker library
* @return {Pick<Subscriber, 'email' | 'name'>} Subscriber entity data
*/
protected override definition(
faker: Faker
): Pick<Subscriber, 'email' | 'name'> {
return {
email: faker.internet.email().toLowerCase(),
name: faker.person.firstName()
}
}
}

export default SubscriberFactory
3 changes: 3 additions & 0 deletions __tests__/setup/chai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
* @see https://chaijs.com
*/

import chaiEach from 'chai-each'
import chaiHttp from 'chai-http'
import { chai } from 'vitest'

/**
* initialize chai plugins.
*
* @see https://github.com/jamesthomasonjr/chai-each
* @see https://github.com/chaijs/chai-http
*/
chai.use(chaiEach)
chai.use(chaiHttp)
Loading

0 comments on commit 86ec9e5

Please sign in to comment.