Giter Club home page Giter Club logo

typeorm-seeding's Introduction

logo

TypeORM Seeding

NPM package Build Status Dependency Sematic-Release

A delightful way to seed test data into your database.
Inspired by the awesome framework laravel in PHP and of the repositories from pleerock
Made with ❀️ by Gery Hirschfeld and contributors


❯ Table of contents

❯ Introduction

Isn't it exhausting to create some sample data for your database, well this time is over!

How does it work? Just create a entity factory for your entities (models) and a seed script.

Entity

First create your TypeORM entities.

// user.entity.ts
@Entity()
export class User {
  @PrimaryGeneratedColumn('uuid') id: string
  @Column({ nullable: true }) name: string
  @Column({ type: 'varchar', length: 100, nullable: false }) password: string
  @OneToMany((type) => Pet, (pet) => pet.user) pets: Pet[]

  @BeforeInsert()
  async setPassword(password: string) {
    const salt = await bcrypt.genSalt()
    this.password = await bcrypt.hash(password || this.password, salt)
  }
}

// pet.entity.ts
@Entity()
export class Pet {
  @PrimaryGeneratedColumn('uuid') id: string
  @Column() name: string
  @Column() age: number
  @ManyToOne((type) => User, (user) => user.pets)
  @JoinColumn({ name: 'user_id' })
  user: User
}

Factory

Then for each entity define a factory. The purpose of a factory is to create new entites with generate data.

Note: Factories can also be used to generate data for testing.

// user.factory.ts
define(User, (faker: typeof Faker) => {
  const gender = faker.datatype.number(1)
  const firstName = faker.name.firstName(gender)
  const lastName = faker.name.lastName(gender)

  const user = new User()
  user.name = `${firstName} ${lastName}`
  user.password = faker.random.word()
  return user
})

// pet.factory.ts
define(Pet, (faker: typeof Faker) => {
  const gender = faker.datatype.number(1)
  const name = faker.name.firstName(gender)

  const pet = new Pet()
  pet.name = name
  pet.age = faker.datatype.number()
  pet.user = factory(User)() as any
  return pet
})

Seeder

And last but not least, create a seeder. The seeder can be called by the configured cli command seed:run. In this case it generates 10 pets with a owner (User).

Note: seed:run must be configured first. Go to CLI Configuration.

// create-pets.seed.ts
export default class CreatePets implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<any> {
    await factory(Pet)().createMany(10)
  }
}

Until this issue is closed, seeder files must not contain any other export statement besides the one that exports the seeder class.

❯ Installation

Before using this TypeORM extension please read the TypeORM Getting Started documentation. This explains how to setup a TypeORM project.

After that install the extension with npm or yarn.

npm i typeorm-seeding
# or
yarn add typeorm-seeding

Optional, install the type definitions of the Faker library.

npm install -D @types/faker

Configuration

To configure the path to your seeds and factories change the TypeORM config file (ormconfig.js or ormconfig.json).

The default paths are src/database/{seeds,factories}/**/*{.ts,.js}

ormconfig.js

module.exports = {
  ...
  seeds: ['src/seeds/**/*{.ts,.js}'],
  factories: ['src/factories/**/*{.ts,.js}'],
}

.env

TYPEORM_SEEDING_FACTORIES=src/factories/**/*{.ts,.js}
TYPEORM_SEEDING_SEEDS=src/seeds/**/*{.ts,.js}

CLI Configuration

Add the following scripts to your package.json file to configure the seed cli commands.

"scripts": {
  "seed:config": "ts-node ./node_modules/typeorm-seeding/dist/cli.js config",
  "seed:run": "ts-node ./node_modules/typeorm-seeding/dist/cli.js seed",
  ...
}

To execute the seed run npm run seed:run in the terminal.

Note: More CLI options are here

Add the following TypeORM cli commands to the package.json to drop and sync the database.

"scripts": {
  ...
  "schema:drop": "ts-node ./node_modules/typeorm/cli.js schema:drop",
  "schema:sync": "ts-node ./node_modules/typeorm/cli.js schema:sync",
  ...
}

CLI Options

Option Default Description
--seed or -s null Option to specify a seeder class to run individually.
--connection or -c null Name of the typeorm connection. Required if there are multiple connections.
--configName or -n ormconfig.js Name to the typeorm config file.
--root or -r process.cwd() Path to the typeorm config file.

❯ Basic Seeder

A seeder class only contains one method by default run. Within this method, you may insert data into your database. For manually insertion use the Query Builder or use the Entity Factory

Note. The seeder files will be executed alphabetically.

import { Factory, Seeder } from 'typeorm-seeding'
import { Connection } from 'typeorm'
import { User } from '../entities'

export default class CreateUsers implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<any> {
    await connection
      .createQueryBuilder()
      .insert()
      .into(User)
      .values([
        { firstName: 'Timber', lastName: 'Saw' },
        { firstName: 'Phantom', lastName: 'Lancer' },
      ])
      .execute()
  }
}

❯ Using Entity Factory

Of course, manually specifying the attributes for each entity seed is cumbersome. Instead, you can use entity factories to conveniently generate large amounts of database records.

For all entities we want to create, we need to define a factory. To do so we give you the awesome faker library as a parameter into your factory. Then create your "fake" entity and return it. Those factory files should be in the src/database/factories folder and suffixed with .factory like src/database/factories/user.factory.ts.

Types Description
Entity TypeORM Entity like the user or the pet in the samples.
Context Argument to pass some static data into the factory function.
EntityFactory This object is used to make new filled entities or create it into the database.

define

The define function creates a new entity factory.

define: <Entity, Context>(entity: Entity, factoryFn: FactoryFunction<Entity, Context>) => void;
import Faker from 'faker'
import { define } from 'typeorm-seeding'
import { User } from '../entities'

define(User, (faker: typeof Faker, context: { roles: string[] }) => { ... })

factory

Factory retrieves the defined factory function and returns the EntityFactory to start creating new enities.

factory: (entity: Entity) => (context?: Context) => EntityFactory<Entity, Context>
factory(Pet)()
factory(Pet)({ name: 'Balou' })

EntityFactory

map

Use the .map() function to alter the generated value before they get persisted.

map(mapFunction: (entity: Entity) => Promise<Entity>): EntityFactory<Entity, Context>
await factory(User)()
  .map(async (user: User) => {
    const pets: Pet[] = await factory(Pet)().createMany(2)
    const petIds = pets.map((pet: Pet) => pet.Id)
    await user.pets().attach(petIds)
  })
  .createMany(5)

make & makeMany

Make and makeMany executes the factory functions and return a new instance of the given entity. The instance is filled with the generated values from the factory function, but not saved in the database.

overrideParams - Override some of the attributes of the entity.

make(overrideParams: EntityProperty<Entity> = {}): Promise<Entity>
await factory(User)().make()
await factory(User)().makeMany(10)

// override the email
await factory(User)().make({ email: '[email protected]' })
await factory(User)().makeMany(10, { email: '[email protected]' })

create & createMany

the create and createMany method is similar to the make and makeMany method, but at the end the created entity instance gets persisted in the database.

overrideParams - Override some of the attributes of the entity. saveOptions - Save options from typeorm

create(overrideParams: EntityProperty<Entity> = {}, saveOptions?: SaveOptions): Promise<Entity>
createMany(amount: number, overrideParams: EntityProperty<Entity> = {}, saveOptions?: SaveOptions): Promise<Entity>
await factory(User)().create()
await factory(User)().createMany(10)

// override the email
await factory(User)().create({ email: '[email protected]' })
await factory(User)().createMany(10, { email: '[email protected]' })

// using save options
await factory(User)().create({ email: '[email protected]' }, { listeners: false })
await factory(User)().createMany(10, { email: '[email protected]' }, { listeners: false })

❯ Seeding Data in Testing

The entity factories can also be used in testing. To do so call the useSeeding function, which loads all the defined entity factories.

Choose your test database wisley. We suggest to run your test in a sqlite in memory database.

{
  "type": "sqlite",
  "name": "memory",
  "database": ":memory:"
}

However, if the test database is not in memory, than use the --runInBand flag to disable parallelizes runs.

describe("UserService", () => {
  let connection: Connection

  beforeAll(async (done) => {
    connection = await useRefreshDatabase({ connection: 'memory' })
    await useSeeding()

    const user = await factory(User)().make()
    const createdUser = await factory(User)().create()

    await runSeeder(CreateUserSeed)
    done()
  })

  afterAll(async (done) => {
    await tearDownDatabase()
    done()
  })

  test('Should ...', () => { ... })
})

useSeeding

Loads the defined entity factories.

useSeeding(options: ConfigureOption = {}): Promise<void>

runSeeder

Runs the given seeder class.

runSeeder(seed: SeederConstructor): Promise<void>

useRefreshDatabase

Connects to the database, drops it and recreates the schema.

useRefreshDatabase(options: ConfigureOption = {}): Promise<Connection>

tearDownDatabase

Closes the open database connection.

tearDownDatabase(): Promise<void>

ConfigureOption

interface ConfigureOption {
  root?: string // path to the orm config file. Default = process.cwd()
  configName?: string // name of the config file. eg. ormconfig.js
  connection?: string // name of the database connection.
}

❯ Example Projects

Please fill free to add your open-source project here. This helps others to better understand the seeding technology.

Project Description
copa-ch/copa-backend πŸš€ Nest application written in TypeScript for the COPA project. This app manages your tournaments and generates the schedules.

❯ Changelog

Changelog

❯ License

MIT

typeorm-seeding's People

Contributors

buuug7 avatar clovis1122 avatar davicedraz avatar dennisameling avatar dependabot[bot] avatar eugenio165 avatar jesster2k10 avatar jleck avatar jorgebodega avatar jthodge avatar mkorobkov avatar oroce avatar owonwo avatar raphaelwoude avatar semantic-release-bot avatar sfelix-martins avatar stephane-rbn avatar vologab avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

typeorm-seeding's Issues

Cannot load seeds when `__dirname` is in path

As seen on the TypeOrm documentation, one can use __dirname for the path to entities and stuff.

loadFiles util function, probably due to the use of process.cwd(), doesn't load any seeds if the path is declared as such:

{
  // ormconfig.js
  seeds: [`${__dirname}/seeds/*.js`],
  ...
}

Any input on that ?

where's the attach() API?

Hi w3tecch,

I can't see attach() API as written in the documentation.

await user.pets().attach(petIds)

May I ask for help? Because I can't create an entity later and attach it to the relationship.

Thanks,
Chen

How do I run it?

Hey Guys, I loved your aprroach to seeding a database, and I would really like to use it. So here comes a question that may sound a bit stupid, but I just can't figure out how to do it. How do I run my seeds? I have already defined a factory and a class that implements Seed, but how do I make it work? Thanks in advance.

Improve error output

Errors that occur during seeding are catched. Then a new error is thrown which does not include the original error message/name.

EntityFactory:

try {
  const entity = yield this.make();
  return yield em.save(entity);
}
catch (error) {
  throw new Error('Could not save entity');
}

Load seeds from other config file

I'm using Nest.js and dotenv package.
Is it possible to use typeorm-seeding with Nest.js?
My config file is placed here /src/config/database.ts
Thanks.

Use with .env

Hey

Currently it's static, using the ormconfig.js. But I use .env as config. Are there any chance to get this run with .env?

Thank you

Factory returns EntityFactory, which is not assignable

I can't understand how relations work for entity factories. Below is the snippet of code from the README (minus some things for readability)

import Faker from 'faker';
import { define } from 'typeorm-seeding';
import { Pet } from '../entities'

define(Pet, (faker: typeof Faker, settings: undefined) => {
  // ...other stuff
  pet.user = factory(User)() // invalid type
  return pet
})

factory(User)() returns an EntityFactory<User, undefined> object, which is not a User type, and thus not assignable to pet.user.

Am I just doing it wrong?

Add a changelog

I would love if we could include a changelog in the repo or release notes within GithHub (my preference is a CHANGELOG.md file). Not only will this help me keep track of library changes as new releases are made, but this will help out with automated tools like Dependabot when embedding changes in PRs it opens.

Entity with @Column('simple-array') fails to seed

Some column-types in typeorm are resolving to objects. For example entitites with column-type "simple-array" failing to seed because the following expression is "true":

if (typeof entity[attribute] === 'object' && !(entity[attribute] instanceof Date)) {

and the subentity can't be resolved. These issue is even harder to grasp, because the thrown error says simply "Error: Could not save entity".

Module aliases are not resolved

Getting error: Error: Cannot find module '{alias}/{path}', even with alias paths defined in tsconfig.json. typeorm cli works fine with same settings and running the command with ts-node.

I am quite new to typescript, else would have tried to fix it, opening a PR.

TypeError: clazz is not a constructor

I just encountered the error in the title. My code looks like this:

  • entities/User.ts:
import { Entity, PrimaryColumn, Column, BaseEntity, BeforeInsert, BeforeUpdate } from "typeorm";
import bcrypt from "bcrypt";

const saltRounds = 10;
@Entity({ name: "users" })
export class User extends BaseEntity {
  @PrimaryColumn()
  username: string;

  @Column()
  password: string;

  @Column()
  fullname: string;

  @Column({ name: "profile_picture" })
  profilePicture: string;

  @Column()
  birthdate: Date;

  @Column()
  gender: string;

  @Column()
  email: string;

  @Column()
  phone: string;

  @Column()
  address: string;

  @Column({ name: "is_admin" })
  isAdmin: boolean;

  strip() {
    this.username = this.username.trim();
    this.password = this.password.trim();
  }

  @BeforeUpdate()
  @BeforeInsert()
  async encryptPassword() {
    this.password = await bcrypt.hash(this.password, saltRounds);
  }
}

export const DUMMY_USERS = [
  {
    username: "john",
    password: "123",
    fullname: "john",
    profilePicture:
      "https://lh3.googleusercontent.com/a-/AOh14Gi0DgItGDTATTFV6lPiVrqtja6RZ_qrY91zg42o-g",
    birthdate: new Date("1999-11-25"),
    gender: "male",
    email: "[email protected]",
    phone: "0123456789",
    address: "somewhere on this earth"
  }
];
  • seeders/users.seed.ts:
import { Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";
import { User, DUMMY_USERS } from "../entities/User";

export default class UserSeeder implements Seeder {
  public async run(_, connection: Connection): Promise<void> {
    await connection.createQueryBuilder().insert().into(User).values(DUMMY_USERS).execute();
  }
}
  • ormconfig.json:
{
  "type": "postgres",
  "host": "localhost",
  "port": 5432,
  "username": "***",
  "password": "***",
  "database": "***",
  "logging": true,
  "entities": ["build/entities/*.js"],
  "migrations": ["build/migrations/*.js"],
  "seeds": ["server/seeders/*.ts"],
  "cli": {
    "migrationsDir": "server/migrations"
  }
}

The full logs:

yarn run v1.22.4
$ ts-node ./node_modules/typeorm-seeding/dist/cli.js seed
🌱  TypeORM Seeding v1.6.1
βœ” ORM Config loaded
βœ” Factories are imported
βœ” Seeders are imported
βœ” Database connected
βœ– Could not run the seed undefined!
TypeError: clazz is not a constructor
    at /home/lamnhh/Projects/PTUDW-17TN-Nhom13/node_modules/typeorm-seeding/src/typeorm-seeding.ts:44:26
    at step (/home/lamnhh/Projects/PTUDW-17TN-Nhom13/node_modules/tslib/tslib.js:141:27)
    at Object.next (/home/lamnhh/Projects/PTUDW-17TN-Nhom13/node_modules/tslib/tslib.js:122:57)
    at /home/lamnhh/Projects/PTUDW-17TN-Nhom13/node_modules/tslib/tslib.js:115:75
    at new Promise (<anonymous>)
    at Object.__awaiter (/home/lamnhh/Projects/PTUDW-17TN-Nhom13/node_modules/tslib/tslib.js:111:16)
    at Object.exports.runSeeder (/home/lamnhh/Projects/PTUDW-17TN-Nhom13/node_modules/typeorm-seeding/src/typeorm-seeding.ts:43:57)
    at Object.<anonymous> (/home/lamnhh/Projects/PTUDW-17TN-Nhom13/node_modules/typeorm-seeding/src/commands/seed.command.ts:94:15)
    at step (/home/lamnhh/Projects/PTUDW-17TN-Nhom13/node_modules/tslib/tslib.js:141:27)
    at Object.next (/home/lamnhh/Projects/PTUDW-17TN-Nhom13/node_modules/tslib/tslib.js:122:57)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I looked into the code in importer.ts and see these lines:

export const importSeed = async (filePath: string): Promise<SeederConstructor> => {
  const seedFileObject: { [key: string]: SeederConstructor } = await import(filePath)
  const keys = Object.keys(seedFileObject)
  return seedFileObject[keys[0]]
}

That keys[0] part looks weird to me. I logged keys out on my machine and it gives ["_esModules", "UserSeeder"] so the function returns true, causing runSeeder to run new true() and crashes.

May I ask if the keys[0] part was intentional or not?

[Bug] Root Param should be respected in OrmConfig file

Dear @hirsch88 ,

today i tried to add your library to my existing project in order to provide respective seeding functionality.

For the context, please note that i use a mono-repository with nrwl/nx. I have a few applications (all stored in apps/ folder of my project root), whereas one is a NestJS API. The latter uses TypeORM with an ormconfig.js file and your library.

However, when i want to run the commands, i have to set the additional --root parameter, because my ormconfig.js file is not stored in the root folder of the mono-repository, but in the specific application folder (e.g., apps/api/src/ormconfig.js).

My apps/api/src/ormconfig.js file looks like this:

module.exports = {
  // ... lots of params to connect to the database
  synchronize: false,
  seeds: ['my/custom/path/to/seeds/*.ts'],
};

However, because i need to call the seeder command with --root param, i expected the seeds parameter to prepend respective root path. For example, the path should be apps/api/src/my/custom/path/to/seeds/*.ts.

Not sure, if i did something wrong, but my seeds were not properly found. If i entered the full path (relative to the root folder of the project itself) it worked out!

All the best

Error on seed:run

Hello all,

First of all thank you very much for the library is definitely a must! I've been trying to implement it in a project and I don't seem to be able to make it work.
Im implementing NestJS 7 with Typeorm and Postgres
Could you please help me out?

I keep on having this errors:

EntityMetadataNotFound: No metadata for <ENTITY_here> was found.

Error: Could not save entity
    at EntityFactory.<anonymous> (.........../node_modules/typeorm-seeding/src/entity-factory.ts:52:15)

Output of the seed:config without the database configurations

{
  type: 'postgres',
  url: undefined,
  sid: undefined,
  schema: undefined,
  extra: undefined,
  synchronize: false,
  dropSchema: false,
  migrationsRun: false,
  entities: [ 'src/**/*.entity{.ts', '.js}' ],
  migrations: [],
  migrationsTableName: undefined,
  subscribers: [],
  logging: [],
  logger: undefined,
  entityPrefix: undefined,
  maxQueryExecutionTime: undefined,
  debug: undefined,
  cli: {
    entitiesDir: undefined,
    migrationsDir: undefined,
    subscribersDir: undefined
  },
  cache: undefined,
  uuidExtension: undefined,
  factories: [ 'src/**/*.factory{.ts,.js}' ],
  seeds: [ 'src/**/*.seed{.ts,.js}' ]
}

Im trying with a simple entity, factory and seeder

export default class CreateCats implements Seeder {
  public async run(factory: Factory): Promise<void> {
    await factory(Cats)().createMany(5);
  }
}


define(Cats, (faker: typeof Faker) => {
  const cat = new Cats();
  cat.name = "CaT";
  cat.age = 22;

  return cat;
});


@Entity({
  name: "cats",
  orderBy: {
    createdAt: "ASC",
  },
})
export class Cats {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  age: number;
}


What am I missing?

Thank you in advance and I really hope I can use this library because it would save me loads of time

Running a seeder tries to drop foreign keys in multiple tables and fails

I'm using TypeORM with MySQL. For some reason running npm run seed:run with the package.json command suggested in the README results in foreign keys getting dropped from multiple tables, which fails at some point and my data doesn't get seeded at all but my schema is completely borked.

Here is my custom seeder:

import { Factory, Seeder } from 'typeorm-seeding'
import { Connection } from 'typeorm/index'
import { PackageEntity, PackageStyle, PackageType } from '../../vendors/entities/package.entity'

const packages = [
   // some test data here...
]

export default class CreatePackages implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<any> {
    await connection
      .createQueryBuilder()
      .insert()
      .into(PackageEntity)
      .values(packages.map(pkg => new PackageEntity({
        claim: pkg.claim,
        description: pkg.claim,
        entryType: PackageType[pkg.claim],
        icon: pkg.icon,
        isPublic: pkg.isPublic,
        label: pkg.label,
        price: pkg.price,
        style: PackageStyle[pkg.style],
      })))
      .execute()
  }}

This is what I get when running the seeder.

β Έ Connecting to the databasequery: SELECT VERSION() AS `version`
query: SELECT * FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = 'hp24' AND `TABLE_NAME` = 'typeorm_metadata'
query: ALTER TABLE `contact_infos` DROP FOREIGN KEY `FK_ccbecb4c53bd6bb363e946dba2e`
β Ό Connecting to the databasequery: ALTER TABLE `vendor_feature_values` DROP FOREIGN KEY `FK_6fc1266afdcaf7c9d520469cc06`
query: ALTER TABLE `vendor_feature_values` DROP FOREIGN KEY `FK_a87f2c41fb59d6f9efc81a2c0eb`
query: ALTER TABLE `reviews` DROP FOREIGN KEY `FK_dc64fb57616462f713cce274519`
query: ALTER TABLE `review_criteria_ratings` DROP FOREIGN KEY `FK_2642fe113c24977dc4e5c3c8486`
query: ALTER TABLE `locations` DROP FOREIGN KEY `FK_cd8e52f4efbd3e906b80e2bea81`
query: ALTER TABLE `vendors` DROP FOREIGN KEY `FK_7486b81eca8501f67dd662cc1b1`
query: ALTER TABLE `gallery_images` DROP FOREIGN KEY `FK_745f62470c59949a750e006fc87`
query: ALTER TABLE `gallery_images` DROP FOREIGN KEY `FK_b30246956cf74a1baa674014b2c`
β ΄ Connecting to the databasequery: DROP INDEX `IDX_dc64fb57616462f713cce27451` ON `reviews`
query: DROP INDEX `REL_12a0f887b44bb8a6107c02dbb0` ON `reviews`
query failed: DROP INDEX `REL_12a0f887b44bb8a6107c02dbb0` ON `reviews`
error: Error: ER_DROP_INDEX_FK: Cannot drop index 'REL_12a0f887b44bb8a6107c02dbb0': needed in a foreign key constraint

Why is typeorm-seeding attempting to modify my schema at all? I thought it's supposed to just import data.

Allow to override faker's attributes in the seed and make methods

With Laravel factories, you can do this:

$user = factory(App\User::class)->create([
    'type' => 'Admin',
]);

Which is great, because it allows to quickly create many entities with the specified attributes. Right now this is not possible in typeorm-seeding and you're forced into writing something like this:

const bruce = await factory(User)().make();
const em = connection.createEntityManager();

bruce.name = 'Bruce Lee';
await em.save<Entity>(bruce);

Or for many users:

const tenAdmins = await factory(User)().makeMany(10);
const em = connection.createEntityManager();
tenAdmins.forEach(user => user.type = 'Admin');
await Promise.all(tenAdmins.map(user => em.save<Entity>(user)));

Which feels awkward to do.

Using the map() method feels less awkward. For a single key you can get away inlining the function but for multiple keys overriding you'll need to make it too verbose or lose some type safety.

const tenAdmins = await factory(User)()
  .map((user) => {
     user.type = 'Admin';
     user.name = 'John Doe';
     return user;
  })
  .seedMany(10);

I'm proposing that we make the methods make and seed (and as the second argument for makeMany and seedMany) that accepts an object that overrides the faker attributes.

how to configure where ormconfig.js located

i have ormconfig.js located at src/ormconfig.js

import { ConnectionOptions } from "typeorm";
require("dotenv").config();

const ormConfig: ConnectionOptions = {
  type: "mysql",
  host: process.env.DB_HOST || "127.0.0.1",
  port: Number(process.env.DB_PORT) || 3306,
  username: process.env.DB_USER || "root",
  password: process.env.DB_PASSWORD || "secret",
  database: process.env.DB_NAME || "database",
  synchronize: false,
  logging: false,
  entities: ["build/entity/**/*.js"],
  migrations: ["build/migration/**/*.js"],
  subscribers: ["build/subscriber/**/*.js"],
  cli: {
    entitiesDir: "src/entity",
    migrationsDir: "src/migration",
    subscribersDir: "src/subscriber"
  }
};

export = ormConfig;

in my code i use this config like below:

import app from "./app";
import { PORT } from "./constants/app.constant";
import "reflect-metadata";
import { createConnection } from "typeorm";
import ormConfig from "./config/ormconfig";

createConnection(ormConfig)
  .then(async connection => {
    app.listen(PORT, () => console.log(`Listening on port ${PORT}`));
  })
  .catch(error => console.log(error));

How to use define inside a loop?

I am doing this

for (let i = 0; i < results.length; i++) {
  const row = results[i];
  define(MeterEntity, () => {
    const meterEntity = new MeterEntity();
    meterEntity.serial = row["Serial"];
    return meterEntity;
  });
  define(MeterReadingEntity, () => {
    const readingEntityObject = new MeterReadingEntity();
    readingEntityObject.varh = row["VARH"];
    readingEntityObject.wh = row["WH"];
    const dateTimeString: string = row["ReadingDateTimeUTC"];
    const dateTimeUTC = createDate(dateTimeString);
    const date = new Date(dateTimeUTC);
    readingEntityObject.createdAt = date.toISOString();
    readingEntityObject.meter = factory(MeterEntity)() as any;
    return readingEntityObject;
  });
}

where results is an array of objects with all the keys I am accessing in the factory definition.

I later run this factory like this

  public async run(factory: Factory, connection: Connection): Promise<any> {
    if (connection && connection.isConnected) {
      await factory(MeterEntity)().make();
    }
  }
}

I have kept the config of where the seeds and factories live to default and have those folders created in my project as per the defaults docs.

This runs fine. It connects to the db and it finds the seeds and runs them but just always persists the last array entry and never everything in the array.

I would expect define to run through all 100 elements in the array and persist all of them to the db.

Is there something I am missing regarding how this function works?
How can I fix this?

`context` is not inserted by default?

Hi, I'm trying to make some factories that make use of context.

Take a slightly modified version of the sample:

import * as Faker from 'faker'
import { define } from '../../src/typeorm-seeding'
import { User } from '../entities/User.entity'

// user.factory.ts

define(User, (faker: typeof Faker) => {
  const gender = faker.random.number(1)
  const firstName = faker.name.firstName(gender)
  const lastName = faker.name.lastName(gender)
  const email = faker.internet.email(firstName, lastName)

  const user = new User()
  user.firstName = firstName
  user.lastName = lastName
  user.middleName = null
  user.email = email
  user.password = faker.random.word()

  user.roles = ['basic']; /* <---- Explicitly declare default for roles */

  return user
});

// pet.factory.ts

define(Pet, (faker: typeof Faker) => {
  const gender = faker.random.number(1)
  const name = faker.name.firstName(gender)

  const pet = new Pet()
  pet.name = name
  pet.age = faker.random.number()

  pet.user = factory(User)({ roles: ['admin'] }) as any /* <---- Expect this to override ["basic"] */

  return pet
});

Expected behavior

  • Specified a "default" user.roles = ["basic"] in user.factory.ts
  • If create user with passed context (e.g. factory(User)({ roles: ['admin'] })) then the created user will have roles = ['admin']
  • Otherwise, default to the value specified in the module: roles = ['basic']

Actual behavior

  • In the above example,

Question/Suggestions

It looks like the correct way to do this would be:

define(User, (faker: typeof Faker, context: Record<string, any>) => {
  // ...
  user.roles = context.roles || ['basic']; /* <---- Explicitly declare default for roles */

  return user
});

Is that correct? (I've got mine working for this.) If so, it does kind of junk up the factory factory.

Would it perhaps be possible to add on the context after the fact as appears to be the case with a call like factory(User)().make({ roles: ['admin'] })

Alternatively, is there any downside associated with something like this?

// user.factory.ts

// LEAVE AS-IS

// pet.factory.ts

define(Pet, (faker: typeof Faker) => {
  // ....
  pet.user = factory(User)().make({ roles: ['admin'] }) as any /* <---- Expect this to override ["basic"] */

  return pet
});

This also seems to work. Looking here, returning a promise does seem to be kosher.

If so, would it make sense to change the signature of FactoryFunction to:

export type FactoryFunction<Entity, Context> = (faker: typeof Faker, context?: Context) => Entity | Promise<Entity>

so that you could make this fact a bit more explicit? For example:

define(Pet, async (faker: typeof Faker) => {
  // ....
  pet.user = await factory(User)().make({ roles: ['admin'] }) as any /* <---- Expect this to override ["basic"] */

  return pet
});

I guess the downside of this suggestion is that you want to help people to avoid calling create before the parent has been validated/created? Perhaps there are also potential circular dependency issues?

Seeder Ordering?

How do I control the order in which the seeds are ran, for example when it comes to seeding entities with relations, I assume one seed would have to be ran before the other?

EntityFactory using .map give me an error

I ran the example (User and Pet) that you have here and I am getting this error:

(property) User.pets: Pet[] This expression is not callable. Type 'Pet[]' has no call signatures.

I used this as seeder:

await factory(User)() .map(async (user: User) => { const pets: Pet[] = await factory(Pet)().createMany(2) const petIds = pets.map((pet: Pet) => pet.Id) await user.pets().attach(petIds) }) .createMany(5)

Any idea?

Does not work with `export default`

I have a config file called dev_seed.ts and inside it:

export default {
  ...
  seeds: ['db/seed/**/*.seed.ts'],
  factories: ['db/factory/**/*.factory.ts'],
};

This does not work when running command:
"seed": "ts-node-dev ./node_modules/typeorm-seeding/dist/cli.js seed --config /db/seed/config/dev_seed.ts"

Where as this code with same command does work:

module.exports = {
  ...
  seeds: ['db/seed/**/*.seed.ts'],
  factories: ['db/factory/**/*.factory.ts'],
};

Cannot read property 'name' of undefined

Hello,

I have a problem with initializing test data

I run this CLI:
"seed:config": "ts-node ./node_modules/typeorm-seeding/dist/cli.js config"

and this
"seed:run": "ts-node ./node_modules/typeorm-seeding/dist/cli.js seed -n"

And I have this error message:
image

Why ?

My package.json file:
{ "name": "xxxxxxxx", "version": "0.0.1", "description": "Graphql with TypeORM", "private": true, "license": "", "scripts": { "start": "ts-node src/graphql/server.ts", "migrate:create": "ts-node ./node_modules/typeorm/cli.js migrations:create", "migrate:generate": "ts-node ./node_modules/typeorm/cli.js migrations:generate", "migrate:run": "ts-node ./node_modules/typeorm/cli.js migration:run", "schema:drop": "ts-node ./node_modules/typeorm/cli.js schema:drop", "schema:sync": "ts-node ./node_modules/typeorm/cli.js schema:sync", "schema:log": "ts-node ./node_modules/typeorm/cli.js schema:log", "seed:config": "ts-node ./node_modules/typeorm-seeding/dist/cli.js config", "seed:run": "ts-node ./node_modules/typeorm-seeding/dist/cli.js seed -n", "db:setup": "npm run schema:drop && npm run schema:sync && npm run seed:config && npm run seed:run" }, "devDependencies": { "@types/bcryptjs": "^2.4.2", "@types/express": "^4.17.6", "@types/express-session": "^1.17.0", "@types/faker": "^4.1.12", "@types/lodash": "^4.14.153", "@types/node": "^14.0.5", "prettier": "^2.0.5", "ts-node": "^8.10.1", "typescript": "^3.9.3" }, "dependencies": { "@types/express": "^4.17.6", "apollo-server-express": "^2.14.0", "bcryptjs": "^2.4.3", "class-validator": "^0.12.2", "express": "^4.17.1", "express-session": "^1.17.1", "graphql": "^15.0.0", "lodash": "^4.17.15", "mysql": "^2.18.1", "reflect-metadata": "^0.1.13", "typeorm": "^0.2.25", "typeorm-seeding": "^1.6.1" } }

My ormconfig.json file:
[ { "name": "default", "type": "mysql", "host": "localhost", "port": 3306, "username": "admin", "password": "admin", "database": "mydb", "synchronize": true, "logging": true, "logger": "file", "entityPrefix": "", "entities": ["src/db/entity/**/*.ts"], "migrations": ["src/db/migration/**/*.ts"], "subscribers": ["src/db/subscriber/**/*.ts"], "factories": ["src/db/factories/**/*.ts"], "seeds": ["src/db/seeds/**/*.ts"], "cli": { "entitiesDir": "src/db/entity", "migrationsDir": "src/db/migration", "subscribersDir": "src/db/subscriber", "factoriesDir": "src/db/factories", "seedsDir": "src/db/seeds" } } ]

My tsconfig.json file:
{ "compilerOptions": { "lib": ["dom", "es6", "es2017", "esnext.asynciterable"], "target": "es5", "module": "commonjs", "sourceMap": true, "moduleResolution": "node", "outDir": "./build", "removeComments": true, "noImplicitAny": true, "strictNullChecks": true, "strictFunctionTypes": true, "noImplicitThis": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "allowSyntheticDefaultImports": false, "emitDecoratorMetadata": true, "experimentalDecorators": true }, "exclude": ["node_modules"], "include": ["./src/**/*.tsx", "./src/**/*.ts"] }

Seed not working with BeforeInsert decorator

I created a user seed that will insert a new user with a hashed password. On my user.entity.ts, I have a @BeforeInsert decorator to hash the password before inserting it into the DB. This works when calling the API endpoint but wasn't triggered when using typeorm-seeding. It will only insert the password as plain text.

user.seed.ts

import { Connection } from 'typeorm';
import { User } from '../model/user.entity';

export default class CreateUser implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<any> {
    await connection
      .createQueryBuilder()
      .insert()
      .into(User)
      .values([
        {
          name: 'Admin',
          email: '[email protected]',
          company: 'Admin Ltd.',
          password: 'test123'
        }
      ])
      .execute()
  }
}

user.entity.ts

  Entity, 
  Column, 
  Generated, 
  OneToOne, 
  BeforeInsert, 
} from 'typeorm';
import { BaseEntity } from './base.entity';
import { UserRole } from './user-role.entity';
import { ApiProperty } from '@nestjs/swagger';
import { CrudValidationGroups } from '@nestjsx/crud';
import * as bcrypt from 'bcryptjs';
import { 
  IsOptional, 
  IsNotEmpty, 
  IsString, 
  MaxLength, 
  IsEmail 
} from 'class-validator';

const { CREATE, UPDATE } = CrudValidationGroups;

@Entity('users')
export class User extends BaseEntity {
  @IsOptional({ groups: [UPDATE] })
  @IsNotEmpty({ groups: [CREATE] })
  @IsString({ always: true })
  @MaxLength(100, { always: true })
  @Column({ type: 'varchar', length: 100, nullable: false })
  name: string;

  @IsOptional({ groups: [UPDATE] })
  @IsNotEmpty({ groups: [CREATE] })
  @IsEmail()
  @IsString({ always: true })
  @MaxLength(100, { always: true })
  @Column({ type: 'varchar', length: 100, nullable: false, unique: true })
  email: string;

  @IsString({ always: true })
  @MaxLength(100, { always: true })
  @Column({ type: 'varchar', length: 100, nullable: true })
  company: string;

  @Column({ type: 'varchar', length: 100, nullable: false })
  password: string;

  @BeforeInsert()
  async setPassword(password: string) {
    const salt = await bcrypt.genSalt();
    this.password = await bcrypt.hash(password || this.password, salt);
  }

  async checkPassword(plainPassword: string) {
    return await bcrypt.compare(plainPassword, this.password);
  }
}

TypeError: this.subQuery is not a function

I don't really know what I am doing wrong, can you help me?

This is the complete output:

 yarn ts-node -r tsconfig-paths/register ../../node_modules/typeorm-seeding/dist/cli.js seed
yarn run v1.22.0
$ /Volumes/SD/Users/bruno/Projects/corona-down/node_modules/.bin/ts-node -r tsconfig-paths/register ../../node_modules/typeorm-seeding/dist/cli.js seed
🌱 TypeORM Seeding v1.4.4
βœ” ORM Config loaded
βœ” Factories are imported
βœ” Seeders are imported
βœ” Database connected
βœ– Could not run the seed CreateApplicationToken!
TypeError: this.subQuery is not a function
    at InsertQueryBuilder.QueryBuilder.createFromAlias (/Volumes/SD/Users/bruno/Projects/corona-down/src/query-builder/QueryBuilder.ts:551:131)
    at InsertQueryBuilder.into (/Volumes/SD/Users/bruno/Projects/corona-down/src/query-builder/InsertQueryBuilder.ts:158:32)
    at CreateApplicationToken.run (/Volumes/SD/Users/bruno/Projects/corona-down/packages/backend/src/database/seeds/CreateApplicationToken.ts:11:8)
    at /Volumes/SD/Users/bruno/Projects/corona-down/node_modules/typeorm-seeding/src/typeorm-seeding.ts:48:17
    at step (/Volumes/SD/Users/bruno/Projects/corona-down/node_modules/tslib/tslib.js:139:27)
    at Object.next (/Volumes/SD/Users/bruno/Projects/corona-down/node_modules/tslib/tslib.js:120:57)
    at /Volumes/SD/Users/bruno/Projects/corona-down/node_modules/tslib/tslib.js:113:75
    at new Promise (<anonymous>)
    at Object.__awaiter (/Volumes/SD/Users/bruno/Projects/corona-down/node_modules/tslib/tslib.js:109:16)
    at Object.exports.runSeeder (/Volumes/SD/Users/bruno/Projects/corona-down/node_modules/typeorm-seeding/src/typeorm-seeding.ts:46:57)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

This is my seeder:

import { Factory, Seeder } from 'typeorm-seeding';
import { Connection } from 'typeorm';
import { ApplicationToken } from '@backend/entities/ApplicationToken';
import uniqueString = require('unique-string');

export default class CreateApplicationToken implements Seeder {
  public async run(_factory: Factory, connection: Connection): Promise<void> {
    await connection
      .createQueryBuilder()
      .insert()
      .into(ApplicationToken)
      .values([
        { token: uniqueString() },
      ])
      .execute();
  }
}

README has wrong .env configs

Just started using the package on a personal project, and couldn't make the seeds run. I was getting some "Cannot read property 'name' of undefined", so I jumped into the source code, to try and find the error. It comes from what the README states about settings the ".env" configs:

or add the following variables to your .env file.
TYPEORM_SEEDING_FACTORIES=src/seeds/**/*{.ts,.js} TYPEORM_SEEDING_SEEDS=src/factories/**/*{.ts,.js}

As you might noticed, the paths are inverted to the actual feature it should belong to, so src/seeds is used for Factories, and src/factories is used for Seeds.

Error: Cannot find module (typeorm entity)

When I do seed:run in my NestJS app I get the following error:

οΏ½  TypeORM Seeding v1.6.1
- Loading ormconfig
βœ” ORM Config loaded
- Import Factories
βœ– Could not import factories!
Error: Cannot find module 'src/users/user.entity'
Require stack:
- C:\Users\User\Development\example\example-api\src\database\factories\user.factory.ts
- C:\Users\User\Development\example\example-api\node_modules\typeorm-seeding\dist\utils\file.util.js
- C:\Users\User\Development\example\example-api\node_modules\typeorm-seeding\dist\commands\seed.command.js
- C:\Users\User\Development\example\example-api\node_modules\typeorm-seeding\dist\cli.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:797:15)
    at Function.Module._load (internal/modules/cjs/loader.js:690:27)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (C:\Users\User\Development\example\example-api\src\database\factories\user.factory.ts:3:1)
    at Module._compile (internal/modules/cjs/loader.js:959:30)
    at Module.m._compile (C:\Users\User\Development\example\example-api\node_modules\ts-node\src\index.ts:858:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Object.require.extensions.<computed> [as .ts] (C:\Users\User\Development\example\example-api\node_modules\ts-node\src\index.ts:861:12)
    at Module.load (internal/modules/cjs/loader.js:815:32) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    'C:\\Users\\User\\Development\\example\\example-api\\src\\database\\factories\\user.factory.ts',
    'C:\\Users\\User\\Development\\example\\example-api\\node_modules\\typeorm-seeding\\dist\\utils\\file.util.js',
    'C:\\Users\\User\\Development\\example\\example-api\\node_modules\\typeorm-seeding\\dist\\commands\\seed.command.js',
    'C:\\Users\\User\\Development\\example\\example-api\\node_modules\\typeorm-seeding\\dist\\cli.js'
  ]
}

This is my seed:config:

οΏ½  TypeORM Seeding v1.6.1
{
  type: 'postgres',
  host: 'localhost',
  port: 5432,
  username: 'example',
  password: 'example',
  database: 'example',
  entities: [ 'dist/**/*.entity{.ts,.js}' ],
  migrations: [ 'migration/*.js' ],
  cli: { migrationsDir: 'migration' },
  synchronize: true,
  factories: [ 'src/database/factories/**/*{.ts,.js}' ],
  seeds: [ 'src/database/seeds/**/*{.ts,.js}' ]
}

TypeORM is working fine with my app, but not this seeding package.

Generation structure of seeding files

Hello!
Typeorm has command for generation migration files: typeorm migration:generate. Is planned the same feature in typeorm-seeding? This feature will by useful in cases when we want to fill database some data such as catalogues, lists etc.

No repeat seeds in multi-run

More than a issue is a question,

There is a way to no repeat seeding? like migration that save the the last one executed and no repeated it.

Any plan to feature like this?

thank you!

FactoryInterface is not found

I'm attempting to use this example:

export default class CreatePets implements Seeder {
  public async run(factory: FactoryInterface, connection: Connection): Promise<any> {
    const connection = await factory.getConnection()
    const em = connection.createEntityManager()

    await times(10, async n => {
      // This creates a pet in the database
      const pet = await factory(Pet)().create()
      // This only returns a entity with fake data
      const user = await factory(User)({ roles: ['admin'] }).make()
      user.pets = [pet]
      await em.save(user)
    })
  }
}

But there doesn't appear to be a FactoryInterface nor does the Factory type appear to have .getConnection() on it.

Is this a typo in the README? Or something else?

Pass open connection?

Hey there,

Looking to see if there is a way to use an existing connection. While using in tests in a nestjs app I have a case like this ->

beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [
        ConfigModule.forRoot({ isGlobal: true }),
        MyTestModule,
        TypeOrmModule.forRoot({
          type: 'postgres',
          host: process.env.TYPEORM_HOST,
          port: Number(process.env.TYPEORM_PORT),
          username: process.env.TYPEORM_USERNAME,
          password: process.env.TYPEORM_PASSWORD,
          database: process.env.TYPEORM_DATABASE,
          logging: false,
          entities: ['src/**/*.entity{.ts,.js}'],
          synchronize: false,
        }),
      ],
    }).compile()
    app = module.createNestApplication()
    await app.init()

    // Is it possible to use the connection 'default' created by the test application
    await useRefreshDatabase()
  })

Basically looking to avoid AlreadyHasActiveConnectionError: Cannot create a new connection named "default", because connection with such name already exist and it now has an active connection session.

Is there a way to use an existing connection, or do I just need to make a new one for typeorm-seeding? If so where would I specify a name for that.

Use cli without ormconfig file

Is it possible to use the current cli without a ormconfig file? I normally initiate my database connection as follow, this way I can keep all the code on typescript side and avoid having an extra configuration file

import path from 'path';
import { createConnection, Connection } from 'typeorm';

import { env } from './env';

const { DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME } = env;

export const createDbConnection = async (): Promise<Connection> => {
  try {
    const entitiesPath = path.resolve(process.cwd(), 'src/db/entities/*{.ts,.js}');

    return await createConnection({
      type: 'postgres',
      host: DB_HOST,
      port: DB_PORT,
      username: DB_USER,
      password: DB_PASSWORD,
      database: DB_NAME,
      entities: [entitiesPath],
      synchronize: true,
    });
  } catch (e) {
    throw new Error(`Unable to connect with the database, e: ${e.message}`);
  }
};

jsonb type in column throws error

Hi! I am unable to seed a jsonb type of field on a PostgreSQL 10.0 database. The error does not occur during insertion and update queries, only on seeding. This is my model:

import { IsNotEmpty } from 'class-validator';
import {
    Column, CreateDateColumn, Entity, ManyToOne, PrimaryColumn, UpdateDateColumn
} from 'typeorm';

import { Session } from './Session';

@Entity()
export class Resource {
    @PrimaryColumn('uuid')
    public id: string;

    @IsNotEmpty()
    @Column()
    public source: string;

    @IsNotEmpty()
    @Column({ type: 'jsonb'}) // Tried with `jsonb` by itself and same error.
    public data: any;

    @UpdateDateColumn({ name: 'updated_at' })
    public updatedAt: Date;

    @CreateDateColumn({ name: 'created_at' })
    public createdAt: Date;

    @ManyToOne(type => Session, session => session.resources)
    public session: Session;
}

And here is my factory:

import * as Faker from 'faker';
import { define } from 'typeorm-seeding';
import * as uuid from 'uuid';

import { Resource } from '../../../src/api/models/Resource';

define(Resource, (faker: typeof Faker) => {
    const source = faker.company.companyName();

    const resource = new Resource();
    resource.id = uuid.v1();
    resource.source = source;
    // resource.data = 12; // Works ok, but I need an object!
    // resource.data = "hello my github friends"; // Works ok, but I need an object!
    // resource.data = new Object({ foo: 'bar' }); // Does not work!
    resource.data = { foo: 'bar' }; // Does not work either!
    return resource;
});

Which throws a:

Could not run seed  Error: Could not save entity
    at EntityFactory.<anonymous> (/Users/humbertowoody/Proyectos/VR3/fetchbug-api/node_modules/typeorm-seeding/dist/typeorm-seeding.js:102:27)
    at Generator.throw (<anonymous>)
    at rejected (/Users/humbertowoody/Proyectos/VR3/fetchbug-api/node_modules/typeorm-seeding/dist/typeorm-seeding.js:30:65)
    at processTicksAndRejections (internal/process/next_tick.js:81:5)

Is there a problem on seeding jsonb type of columns? Thanks in advance!

[BUG] CLI Options --root doesn't work as expect

According to the doc cli-options shows that if your ormconfig.js is not located at the root of your project, you can use --root (or -r) to tell cli where's the path to the typeorm config file.

Say you have a ormconfig.js file located at src/config, and the folder structure would be this...

  • /src
    • /config
      • ormconfig.js

Then, you should add the option -r src/config to your script...

"seed:run": "ts-node ./node_modules/typeorm-seeding/dist/cli.js seed -r src/config"

I tried src/config, /src/config, ./src/config

After running this script, I got an error like this...

ζˆͺεœ– 2020-07-02 上午10 24 24

Therefore, the options of --root (or -r) don't seems to work!


I found that some of the users may run into the same error. #63 #75

The temporary fix to the problem is to use --name (or -n) instead of --root (or -r).

"seed:run": "ts-node ./node_modules/typeorm-seeding/dist/cli.js seed -n src/config/ormconfig.js"

Thanks to @achmadfatoni: #75 (comment)

Typeorm should be a peerDependency

Hi guys, I'm running into an issue in my project where typeorm-seeding is installing its own typeorm library on top of the one I install for my project. This causes some issues, especially surrounding typing in Typescript projects when implementing Seeders.

Typeorm should be listed as a peer-dependency in this library to avoid duplicate Typeorm libs from being installed for end users (like me).

In my specific case this is the error I hit:

import { Factory, Seeder } from 'typeorm-seeding';
import { Connection } from 'typeorm';

export class CreateStreams implements Seeder {
  public async run(factory: Factory, connection: Connection) {
  }
}

TS error displayed:

Property 'run' in type 'CreateStreams' is not assignable to the same property in base type 'Seeder'.
  Type '(factory: import("/Volumes/work_projects/slewsystems_pi67_webserver/node_modules/typeorm-seeding/dist/types").Factory, connection: import("/Volumes/work_projects/slewsystems_pi67_webserver/node_modules/typeorm/connection/Connection").Connection) => Promise<...>' is not assignable to type '(factory: import("/Volumes/work_projects/slewsystems_pi67_webserver/node_modules/typeorm-seeding/dist/types").Factory, connection: import("/Volumes/work_projects/slewsystems_pi67_webserver/node_modules/typeorm-seeding/node_modules/typeorm/connection/Connection").Connection) => Promise<...>'.
    Types of parameters 'connection' and 'connection' are incompatible.
      Type 'import("/Volumes/work_projects/slewsystems_pi67_webserver/node_modules/typeorm-seeding/node_modules/typeorm/connection/Connection").Connection' is not assignable to type 'import("/Volumes/work_projects/slewsystems_pi67_webserver/node_modules/typeorm/connection/Connection").Connection'.
        Types of property 'options' are incompatible.
          Type 'import("/Volumes/work_projects/slewsystems_pi67_webserver/node_modules/typeorm-seeding/node_modules/typeorm/connection/ConnectionOptions").ConnectionOptions' is not assignable to type 'import("/Volumes/work_projects/slewsystems_pi67_webserver/node_modules/typeorm/connection/ConnectionOptions").ConnectionOptions'.

What you'll notice is the Connection type I define is located in:
node_modules/typeorm/connection/Connection
but the typoeorm-seeding types is looking in:
node_modules/typeorm-seeding/node_modules/typeorm/connection/Connection
because I have two typeorm libraries installed.

As a workaround I've been leveraging Yarn's resolution capabilities and its autodedup like this:

{
  "dependencies": {
    "typeorm": "^0.2.17",
  },
  "devDependencies": {
    "typeorm-seeding": "^1.0.0-rc.2"
  },
  "resolutions": {
    "typeorm-seeding/typeorm": "^0.2.17"
  }
}

README is outdated

The README seems to be outdated. The seeder examples still extends Seed rather than Seeder and uses the seed method rather than run. I think this should be updated as it seems to be a bit confusing.

I could send a PR to update it

import { define } from 'typeorm-seeding'; Error

Hi @hirsch88 Awesome update, trying to make it work with my project but I get the following mysterious error!

import { define } from 'typeorm-seeding';
Β Β Β Β Β Β Β Β Β Β Β  ^
SyntaxError: Unexpected token

This is what my code looks like

import * as Faker from 'faker';
import { define } from 'typeorm-seeding';
import * as uuid from 'uuid';

import { Booking } from '../entities/Booking';

define(Booking, (faker: typeof Faker, settings: { role: string } | undefined ) => {
// tslint:disable-next-line: no-console
    console.log(settings);
    const gender = faker.random.number(1);
    const title = faker.name.firstName(gender);
    const lastName = faker.name.lastName(gender);
    const email = faker.internet.email(title, lastName);
    // const username = faker.internet.userName(title, lastName);
    const booking = new Booking();
    booking.id = uuid.v1();
    booking.title = title;
    booking.customerName = lastName;
    booking.publicNotes = email;
    // booking.fiscalName = role;
    // user.username = username;
    // user.password = '1234';
    return booking;
});

I tried also with:
import define from "typeorm-seeding";

or:
import * as define from "typeorm-seeding;

with no luck, obviously!

Hence this issue, thank you!

Usage for unit testing

First of all, thanks for the awesome lib!

I was wondering if there's some way of using the factories to seed specific data for unit testing.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.