Skip to content

Commit

Permalink
refactor: migrate factories codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Sep 19, 2023
1 parent 7af92d9 commit 2ecaac6
Show file tree
Hide file tree
Showing 18 changed files with 1,774 additions and 1,638 deletions.
36 changes: 26 additions & 10 deletions adonis-typings/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,17 +191,19 @@ export interface FactoryBuilderContract<
/**
* Define custom database connection
*/
connection(connection: string): this
connection(connection: string): FactoryBuilderContract<Model, FactoryModel>

/**
* Define custom query client
*/
client(client: QueryClientContract): this
client(client: QueryClientContract): FactoryBuilderContract<Model, FactoryModel>

/**
* Apply pre-defined state
*/
apply<K extends keyof FactoryModel['states']>(...states: K[]): this
apply<K extends keyof FactoryModel['states']>(
...states: K[]
): FactoryBuilderContract<Model, FactoryModel>

/**
* Create/make relationships for explicitly defined related factories
Expand All @@ -219,14 +221,16 @@ export interface FactoryBuilderContract<
}
: never
) => void
): this
): FactoryBuilderContract<Model, FactoryModel>

/**
* Define pivot attributes when persisting a many to many
* relationship. Results in a noop, when not called
* for a many to many relationship
*/
pivotAttributes(attributes: ModelObject | ModelObject[]): this
pivotAttributes(
attributes: ModelObject | ModelObject[]
): FactoryBuilderContract<Model, FactoryModel>

/**
* Merge custom set of attributes. They are passed to the merge method of
Expand All @@ -235,13 +239,15 @@ export interface FactoryBuilderContract<
* For `createMany` and `makeMany`, you can pass an array of attributes mapped
* according to the array index.
*/
merge(attributes: OneOrMany<ExtractFactoryAttributes<Model>>): this
merge(
attributes: OneOrMany<ExtractFactoryAttributes<Model>>
): FactoryBuilderContract<Model, FactoryModel>

/**
* Merge custom set of attributes with the correct factory builder
* model and all of its relationships as well
*/
mergeRecursive(attributes: any): this
mergeRecursive(attributes: any): FactoryBuilderContract<Model, FactoryModel>

/**
* Define custom runtime context. This method is usually called by
Expand All @@ -251,7 +257,7 @@ export interface FactoryBuilderContract<
* Do not define a custom context, unless you know what you are really
* doing.
*/
useCtx(ctx: FactoryContextContract): this
useCtx(ctx: FactoryContextContract): FactoryBuilderContract<Model, FactoryModel>

/**
* Tap into the persistence layer of factory builder. Allows one
Expand All @@ -262,9 +268,9 @@ export interface FactoryBuilderContract<
callback: (
row: InstanceType<FactoryModel['model']>,
ctx: FactoryContextContract,
builder: this
builder: FactoryBuilderContract<Model, FactoryModel>
) => void
): this
): FactoryBuilderContract<Model, FactoryModel>

/**
* Make model instance without persitance. The make method
Expand Down Expand Up @@ -356,6 +362,11 @@ export interface FactoryModelContract<Model extends LucidModel> {
callback: StateCallback<Model>
): this & { states: { [P in K]: StateCallback<Model> } }

/**
* Returns state callback
*/
getState(state: keyof this['states']): StateCallback<Model>

/**
* Define a relationship on another factory
*/
Expand All @@ -364,6 +375,11 @@ export interface FactoryModelContract<Model extends LucidModel> {
callback: Relation
): this & { relations: { [P in K]: Relation } }

/**
* Returns registered relationship for a factory
*/
getRelation(relation: keyof this['relations']): FactoryRelationContract

/**
* Define before hooks. Only `create` event is invoked
* during the before lifecycle
Expand Down
73 changes: 39 additions & 34 deletions src/Factory/FactoryBuilder.ts → src/factory/factory_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,29 @@
* file that was distributed with this source code.
*/

import { QueryClientContract } from '@ioc:Adonis/Lucid/Database'
import { LucidRow, LucidModel, ModelAdapterOptions, ModelObject } from '@ioc:Adonis/Lucid/Orm'
import { QueryClientContract } from '../../adonis-typings/database.js'
import {
LucidRow,
LucidModel,
ModelAdapterOptions,
ModelObject,
} from '../../adonis-typings/model.js'
import {
FactoryModelContract,
FactoryContextContract,
FactoryBuilderContract,
FactoryRelationContract,
} from '@ioc:Adonis/Lucid/Factory'
} from '../../adonis-typings/factory.js'

import { FactoryModel } from './FactoryModel'
import { FactoryContext } from './FactoryContext'
import { FactoryModel } from './factory_model.js'
import { FactoryContext } from './factory_context.js'

/**
* Factory builder exposes the API to create/persist factory model instances.
*/
export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContract<LucidModel>> {
export class FactoryBuilder
implements FactoryBuilderContract<LucidModel, FactoryModelContract<LucidModel>>
{
/**
* Relationships to setup. Do note: It is possible to load one relationship
* twice. A practical use case is to apply different states. For example:
Expand Down Expand Up @@ -102,7 +109,7 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
* Access the parent relationship for which the model instance
* is created
*/
public get parent() {
get parent() {
return this.viaRelation ? this.viaRelation.parent : undefined
}

Expand Down Expand Up @@ -262,12 +269,12 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
/**
* Fire the after "make" hook. There is no before make hook
*/
await this.factory.hooks.exec('after', 'make', this, modelInstance, ctx)
await this.factory.hooks.runner('after:make').run(this, modelInstance, ctx)

/**
* Fire the before "create" hook
*/
await this.factory.hooks.exec('before', 'create', this, modelInstance, ctx)
await this.factory.hooks.runner('before:create').run(this, modelInstance, ctx)

/**
* Sharing transaction with the model
Expand Down Expand Up @@ -296,13 +303,13 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
* Fire after hook before the transaction is committed, so that
* hook can run db operations using the same transaction
*/
await this.factory.hooks.exec('after', 'create', this, modelInstance, ctx)
await this.factory.hooks.runner('after:create').run(this, modelInstance, ctx)
}

/**
* Define custom database connection
*/
public connection(connection: string): this {
connection(connection: string): this {
this.options = this.options || {}
this.options.connection = connection
return this
Expand All @@ -311,7 +318,7 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
/**
* Define custom query client
*/
public client(client: QueryClientContract): this {
client(client: QueryClientContract): this {
this.options = this.options || {}
this.options.client = client
return this
Expand All @@ -321,31 +328,31 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
* Define custom context. Usually called by the relationships
* to share the parent context with relationship factory
*/
public useCtx(ctx: FactoryContextContract): this {
useCtx(ctx: FactoryContextContract): this {
this.ctx = ctx
return this
}

/**
* Load relationship
*/
public with(name: string, count?: number, callback?: (factory: never) => void): this {
with(name: string, count?: number, callback?: (factory: never) => void): this {
const relation = this.factory.getRelation(name)

if (relation.relation.type === 'belongsTo') {
this.withBelongsToRelations.push({ name, count, callback })
this.withBelongsToRelations.push({ name, count, callback: callback as any })
return this
}

this.withRelations.push({ name, count, callback })
this.withRelations.push({ name, count, callback: callback as any })
return this
}

/**
* Apply one or more states. Multiple calls to apply a single
* state will be ignored
*/
public apply(...states: string[]): this {
apply(...states: string[]): this {
states.forEach((state) => this.appliedStates.add(state))
return this
}
Expand All @@ -354,7 +361,7 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
* Fill custom set of attributes. They are passed down to the newUp
* method of the factory
*/
public merge(attributes: any) {
merge(attributes: any) {
this.attributes = attributes
return this
}
Expand All @@ -363,7 +370,7 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
* Merge custom set of attributes with the correct factory builder
* model and all of its relationships as well
*/
public mergeRecursive(attributes: any): this {
mergeRecursive(attributes: any): this {
this.recursiveAttributes = attributes
return this
}
Expand All @@ -373,7 +380,7 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
* relationship. Results in a noop, when not called
* for a many to many relationship
*/
public pivotAttributes(attributes: ModelObject | ModelObject[]): this {
pivotAttributes(attributes: ModelObject | ModelObject[]): this {
this.attributesForPivotTable = attributes
return this
}
Expand All @@ -383,27 +390,25 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
* to modify the model instance just before it is persisted
* to the database
*/
public tap(
callback: (row: LucidRow, state: FactoryContextContract, builder: this) => void
): this {
tap(callback: (row: LucidRow, state: FactoryContextContract, builder: this) => void): this {
this.tapCallbacks.push(callback)
return this
}

/**
* Make model instance. Relationships are not processed with the make function.
*/
public async make() {
async make() {
const ctx = this.ctx || (await this.getCtx(false, false))
const modelInstance = await this.compile(ctx)
await this.factory.hooks.exec('after', 'make', this, modelInstance, ctx)
await this.factory.hooks.runner('after:make').run(this, modelInstance, ctx)
return modelInstance
}

/**
* Create many of the factory model instances
*/
public async makeMany(count: number) {
async makeMany(count: number) {
let modelInstances: LucidRow[] = []

const counter = new Array(count).fill(0).map((_, i) => i)
Expand All @@ -419,15 +424,15 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
* Returns a model instance without persisting it to the database.
* Relationships are still loaded and states are also applied.
*/
public async makeStubbed() {
async makeStubbed() {
const ctx = this.ctx || (await this.getCtx(true, false))
const modelInstance = await this.compile(ctx)

await this.factory.hooks.exec('after', 'make', this, modelInstance, ctx)
await this.factory.hooks.exec('before', 'makeStubbed', this, modelInstance, ctx)
await this.factory.hooks.runner('after:make').run(this, modelInstance, ctx)
await this.factory.hooks.runner('before:makeStubbed').run(this, modelInstance, ctx)

const id = modelInstance.$primaryKeyValue || this.factory.manager.getNextId(modelInstance)
modelInstance[this.factory.model.primaryKey] = id
;(modelInstance as any)[this.factory.model.primaryKey] = id

/**
* Make relationships. The relationships will be not persisted
Expand All @@ -437,15 +442,15 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
/**
* Fire the after hook
*/
await this.factory.hooks.exec('after', 'makeStubbed', this, modelInstance, ctx)
await this.factory.hooks.runner('after:makeStubbed').run(this, modelInstance, ctx)

return modelInstance
}

/**
* Create many of model factory instances
*/
public async makeStubbedMany(count: number) {
async makeStubbedMany(count: number) {
let modelInstances: LucidRow[] = []

const counter = new Array(count).fill(0).map((_, i) => i)
Expand All @@ -461,7 +466,7 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
* Similar to make, but also persists the model instance to the
* database.
*/
public async create() {
async create() {
/**
* Use pre-defined ctx or create a new one
*/
Expand Down Expand Up @@ -491,7 +496,7 @@ export class FactoryBuilder implements FactoryBuilderContract<FactoryModelContra
/**
* Create and persist many of factory model instances
*/
public async createMany(count: number) {
async createMany(count: number) {
let modelInstances: LucidRow[] = []

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
*/

import { faker } from '@faker-js/faker'
import { FactoryContextContract } from '@ioc:Adonis/Lucid/Factory'
import { TransactionClientContract } from '@ioc:Adonis/Lucid/Database'
import { FactoryContextContract } from '../../adonis-typings/factory.js'
import { TransactionClientContract } from '../../adonis-typings/database.js'

export class FactoryContext implements FactoryContextContract {
public faker = faker
faker = faker

constructor(
public isStubbed: boolean,
Expand Down
Loading

0 comments on commit 2ecaac6

Please sign in to comment.