w3tecch / typeorm-seeding Goto Github PK
View Code? Open in Web Editor NEW๐ฑ A delightful way to seed test data into your database.
Home Page: https://www.npmjs.com/package/typeorm-seeding
License: MIT License
๐ฑ A delightful way to seed test data into your database.
Home Page: https://www.npmjs.com/package/typeorm-seeding
License: MIT License
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);
}
}
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.
Hello, I was wondering if there's a way to tell the useRefreshDatabase() function to use a TypeORM migrations file to recreate the database after it's dropped, rather than using the entities to recreate the schema. I find that recreating the schema from the entity classes is never really 100% accurate. Thank you.
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'],
};
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.
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?
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 ?
Hi,
we use the EntitySchema to specify our typeorm schema.
https://typeorm.io/#/separating-entity-definition
How is it possible to use such a EntitySchema in a factory?
Any hints will be very appreciated.
Cheers,
Gerwin
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?
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.
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?
Typeform currently supports async ormconfig. It would be good to have it in this library.
You can check it here:
typeorm/typeorm#5048
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}`);
}
};
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?
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":
typeorm-seeding/src/entity-factory.ts
Line 90 in 9e9c591
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".
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...
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...
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)
Actualy the issue is in the title
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();
}
}
Hello, it appears this library is missing the command line utility that https://github.com/LogansUA/typeorm-seed-extension offers. Is there plans to introduce that functionality into this library?
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 control which seed to run first
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
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.
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?
Is it possible to remove the seeded data via a command? and if not, how would one achieve this reliably?
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.
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:
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"] }
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
I have a ormconfig.json in the root of the project, but i get the following error, when i try to run a seed:
Error: No connection options were found in any of configurations file.
The seed is executed in the root too.
In JS typeof null
is object
!
typeorm-seeding/src/entity-factory.ts
Line 100 in 7e26b2c
When entity has attribute with null value, got exception Cannot read property 'make' of null
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.
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.
I didn't any lazy relations example in your docs. Are they supported?
TypeORM doc on lazy relations: https://github.com/typeorm/typeorm/blob/master/docs/eager-and-lazy-relations.md
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!
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.
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
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!
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
});
user.roles = ["basic"]
in user.factory.ts
factory(User)({ roles: ['admin'] })
) then the created user will have roles = ['admin']
roles = ['basic']
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?
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
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.
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');
}
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.
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"
}
}
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
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?
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!
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.