RobinCK / typeorm-fixtures

:pill: Fixtures loader for typeorm 🇺🇦
https://robinck.github.io/typeorm-fixtures/
MIT License
556 stars 46 forks source link

[Bug] PreProcess hangs with programmatic setup #161

Closed alondahari closed 3 years ago

alondahari commented 3 years ago

Context: I have a relation like so:

Sport.ts

import { Field, ObjectType } from 'type-graphql';
import { Column, Entity, OneToMany, Unique } from 'typeorm';

import { TimeFrame } from '..';
import Base from '../Base';

@ObjectType()
@Entity({ name: 'sports' })
export default class Sport extends Base {
  @Column({ type: 'text' })
  label: string;

  @Field(() => [TimeFrame])
  @OneToMany(() => TimeFrame, (timeFrame) => timeFrame.sport, { lazy: true })
  timeFrames: TimeFrame[];
}

TimeFrame.ts

import { Field, ObjectType } from 'type-graphql';
import { Column, Entity, JoinTable, ManyToMany, ManyToOne, OneToMany } from 'typeorm';

import { Sport } from '..';
import Base from '../Base';

@ObjectType()
@Entity({ name: 'time_frames' })
export default class TimeFrame extends Base {
  @Column({ type: 'text' })
  label: string;

  @Field(() => Sport)
  @ManyToOne(() => Sport, (sport) => sport.timeFrames, { lazy: true })
  sport: Sport;
  @Column({ nullable: false })
  sportId: string;
}

In my timeFrame fixture, I need to access sportId and not just sport. To solve, I want to implement a preprocessor to set the ID based on the sport relation. With programmatic setup, if I add a preprocessor it just hangs while building the entity.

loadFixtures.ts

import * as path from 'path';

import { Connection, getRepository } from 'typeorm';
import {
  Builder,
  IEntity,
  Loader,
  Parser,
  Resolver,
} from 'typeorm-fixtures-cli/dist';

import testConnection from '../../testUtils/testConnection';

import { asyncForEach } from './../../utils/helpers';

interface ICreatedFixtures {
  [entity: string]: IEntity;
}
interface IFixtures {
  conn: Connection;
  createdFixtures: ICreatedFixtures;
}

const loadFixtures = async(fixtureFiles: string[]): Promise<IFixtures> => {
  const conn = await testConnection();
  const loader = new Loader();
  fixtureFiles.forEach((file) => {
    loader.load(path.resolve(`src/__spec__/fixtures/${file}.yml`));
  });

  const resolver = new Resolver();
  const fixtures = resolver.resolve(loader.fixtureConfigs);
  const builder = new Builder(conn, new Parser());

  const createdFixtures: ICreatedFixtures = {};
  await asyncForEach(fixtures, async(fixture) => {
    console.log('before build', fixture);

    const entity = await builder.build(fixture);
    console.log('after build');
    const { tableName } = conn.manager.getRepository(fixture.entity).metadata;

    await conn.manager.query(`DELETE FROM ${tableName}`);

    createdFixtures[fixture.name] = await getRepository(entity.constructor.name).save(entity);
  });

  return { conn, createdFixtures };
};

export default loadFixtures;

timeFrames.yml

entity: TimeFrame
processor: ../processors/TimeFrameProcessor
items:
  timeFrame:
    label: Game
    sport: '@sport'
    idx: 0

TimeFrameProcessor.ts

import { IProcessor } from 'typeorm-fixtures-cli/dist';

import { TimeFrame } from '../../db/entity';

export default class TimeFrameProcessor implements IProcessor<TimeFrame> {
  preProcess(name: string, object: TimeFrame): any {
    return object;
  }
}

It's logging before build but not after build. If I remove the preProcess method it resolves it. Thanks!

Your Environment

Software Version(s)
typeorm-fixtures 1.9.0
Node v14.15.1
npm/Yarn 1.22.10
Operating System macOS
alondahari commented 3 years ago

Sorry this was a typescript issue, I wasn't using name in the processor and typescript blew up. Closing.