npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

typeorm-fixture-builder

v3.0.1

Published

Painless and type safe data fixtures for typeorm

Downloads

4,739

Readme

Build Status Maintainability Test Coverage

typeorm-fixture-builder

typeorm-fixture-builder was created when I struggled with the current fixture solutions for typeorm avaible. They simply didn't fit my needs and/or weren't flexible enough. So I decided to create another one.

Documentation

Installation

Install typeorm-fixture-builder and it's peer dependencies. Usually you will install typescript as dev dependency:

yarn add typeorm typeorm-fixture-builder
yarn add -D typescript

This will give you access to the fixtures cli utitlity as also to the programmatic api.

Usage

We need at least one fixture bundle. Fixtures are written - as typeorm itself - in typescript. Therefore, we are able to create typesafe fixture definitions. By default, the CLI will look for a fixtures folder, scanning for all files with a .bundle.ts suffix:

import { fixture } from 'typeorm-fixture-builder';
import { User } from '../entities/user.entity';

export const user1 = fixture(User, {
  firstName: 'John',
  lastName: 'Doe',
});

export const user2 = fixture(User, {
  firstName: 'Max',
  lastName: 'Mustermann',
});

Now you can run these fixtures using the CLI:

# yarn
yarn fixtures install

# npm/npx
npx fixtures install

For more CLI options checkout

# yarn
yarn fixtures --help
yarn fixtures install --help

# npm/npx
npx fixtures --help
npx fixtures install --help

Fixture Bundle Files

The CLI will collect your fixtures from bundles in a smart but yet simple way. Every fixture you want to get peristed has to be exported by the bundle file. Also, it's not allowed to export anything else but fixtures from a bundle file.

However, there are exceptions to this which will allow you to organize fixtures the way you wish to.

The following rules apply to exports from bundle files:

  1. The export is a fixture itself:

    import { fixture } from 'typeorm-fixture-builder';
    import { User } from '../entities/User.entity';
    
    export const user = fixture(User, { firstName: 'Foo' });
  2. The export is an array of fixtures:

    import { fixture } from 'typeorm-fixture-builder';
    import { User } from '../entities/User.entity';
    
    export const users = [
      fixture(User, { firstName: 'Foo' }),
      fixture(User, { firstName: 'Bar' }),
      fixture(User, { firstName: 'Baz' }),
    ];
  3. The export is an Object where the property values are fixtures:

    import { fixture } from 'typeorm-fixture-builder';
    import { User } from '../entities/User.entity';
    
    export const users = {
      foo: fixture(User, { firstName: 'Foo' }),
      bar: fixture(User, { firstName: 'Bar' }),
      baz: fixture(User, { firstName: 'Baz' }),
    };

These rules can be combined to allow deeper nested structures:

import { fixture } from 'typeorm-fixture-builder';
import { User } from '../entities/User.entity';
import { Picture } from '../entities/picture.entity';

export const users = [
  {
    user: fixture(User, { firstName: 'Foo' }),
    picture: fixture(Picture, { path: 'foo.jpg' }),
  },
  {
    user: fixture(User, { firstName: 'Bar' }),
    picture: fixture(Picture, { path: 'Bar.jpg' }),
  },
];

Relations

Relations as easy to manage as they can get. Just assign a fixture as a relation and you are done. The CLI will handle your relations.

You do not have to care about cascade setups since the CLI will walk over your relations, no matter on which side of the relation.

Also, the CLI ensures that every fixture is persisted exactly once. While you could place related fixtures inside a fixture without exporting it from the bundle, it's still a good practice to export all fixtures you define:

import { fixture } from 'typeorm-fixture-builder';
import { Group } from '../entities/group.entity';

export const groups = {
  administrators: fixture(Group, { name: 'Administrators' }),
  customers: fixture(Group, { name: 'Customers' }),
};

export const users = [
  fixture(User, {
    firstName: 'Admin',
    groups: [groups.administrators],
  }),

  fixture(User, {
    firstName: 'Customer',
    groups: [groups.customers],
  }),
];

Foreign Bundle Files and Helpers

It's absolutely safe to use fixtures from foreign bundle files:

// fixtures/groups.bundle.ts
import { fixture } from 'typeorm-fixture-builder';
import { Group } from '../entities/group.entity';

export const administrators: fixture(Group, { name: 'Administrators' });
export const customers: fixture(Group, { name: 'Customers' });
// fixtures/users.bundle.ts
import { fixture } from 'typeorm-fixture-builder';
import { User } from '../entities/user.entity';
import { administrators, customers } from './groups.bundle';

export const administrator = fixture(User, {
  firstName: 'Admin',
  groups: [administrators],
});

export const customer = fixture(User, {
  firstName: 'Customer',
  groups: [customers],
});

You could even define your fixtures, or functions that will create fixtures in non bundle files. It's only important that all your intended fixtures are exported from a bundle file in the end:

import { fixture } from 'typeorm-fixture-builder';
import faker from 'faker';
import { groups } from './groups.bundle';

export function createRandomUser(): User {
  return fixture(User, {
    firstName: faker.name.firstName(),
    lastName: faker.name.lastName(),
    groups: [faker.random.arrayElement(groups)],
  });
}

export function createRandomUsers(count: number): User[] {
  return [...new Array(count)].map(createRandomUser);
}
import { builder } from 'typeorm-fixture-builder';
import { User } from '../entities/user.entity';
import { createRandomUsers } from './helpers.ts';

export const users = createRandomUsers(10);

Soft Fixture Creation / Resolvers

Sometimes, we do not want to create new database entries but use existing ones to update them or to prevent new data creation when fixtures run more than once.

This can be achieved by passing a third parameter to the fixture function.

It has to be a callback which will receive the repository for the entity and the fixture values and should return a setup query builder. We call this a resolver function.

The CLI will use this query builder to find a single entity by it's criteria. If it finds an entity, it will be merged with the fixture data, otherwise a new entity will be persisted:

import { fixture } from 'typeorm-fixture-builder';
import { User } from '../entities/user.entity';

export const user = fixture(
  User,
  { firstName: 'Foo', lastName: 'Bar' },
  (repository, { firstName }) =>
    repository
      .createQueryBuilder('user')
      .where('user.firstName = :firstName', { firstName }),
);

However, if you want to do this often on a certain type of entity, or even with a fixed set of conditions, it's useful to create a decorated fixture function which will setup the resolver function for you:

import { fixture } from 'typeorm-fixture-builder';
import { DeepPartial } from 'typeorm';
import { User } from '../entities/user.entity';

function createOrUpdateUser(data: DeepPartial<User>) {
  return fixture(User, data, (repository, { firstName }) =>
    repository
      .createQueryBuilder('user')
      .where('user.firstName = :firstName', { firstName }),
  );
}

export const user = createOrUpdateUser({
  firstName: 'Foo',
  lastName: 'Bar',
});

Such functions could also be placed in some kind of non bundle helper files, of course.

Programmatic Usage

If you just want to install some fixtures programmatically, you can import and use the install function. It takes a TypeORM DataSource and an array of fixtures:

import { fixture, install } from 'typeorm-fixture-builder';
import { DataSource } from 'typeorm';
import { User } from '../entities/user.entity';

export const user1 = fixture(User, {
  firstName: 'John',
  lastName: 'Doe',
});

export const user2 = fixture(User, {
  firstName: 'Max',
  lastName: 'Mustermann',
});

async function installFixtures() {
  const source = new DataSource();

  await source.initialize();
  await install(source, [user1, user2]);
}

installFixtures();

You can also import and collect fixtures from bundle files. Import and use the collect function. Pass the imported bundle module and it will return an array of collected fixtures:

import { collect, install } from 'typeorm-fixture-builder';
import { DataSource } from 'typeorm';
import UserBundle from '../fixtures/user.bundle';

async function installFixtures() {
  const source = new DataSource();

  await source.initialize();
  await install(source, collect(UserBundle));
}

installFixtures();

Clearing the Persistence Cache

Internally, the library will cache every fixture it has already persisted. This can become quite cumbersome, for example when you're using fixtures in end to end testing scenarios which wants to redeploy fixtures frequently in one process.

To overcome this, you can use the clear function before calling install again, which will clear the internal caching, allowing fixtures to be persisted again:

import { collect, install, clear } from 'typeorm-fixture-builder';
import { DataSource } from 'typeorm';
import UserBundle from '../fixtures/user.bundle';

beforeEach(async () => {
  const source = new DataSource();

  await source.initialize();
  await install(source, collect(UserBundle));
});

afterEach(() => {
  clear();
});

// your tests using fixtures...