Coder Social home page Coder Social logo

jorgebodega / typeorm-factory Goto Github PK

View Code? Open in Web Editor NEW
26.0 26.0 9.0 1007 KB

:seedling: A delightful way to use factories in your code.

Home Page: https://www.npmjs.com/package/@jorgebodega/typeorm-factory

License: MIT License

TypeScript 100.00%

typeorm-factory's Introduction

Hi there! I'm Jorge!

  • ๐Ÿ‹ Working as Backend Developer on Acid Tango
  • ๐Ÿ“– Learning about DDD and Hexagonal Architecture
  • ๐Ÿ‘ฏ Collaborating on typeorm-seeding, typeorm-factory and dotpyle
  • ๐Ÿบ Craft beer lover
  • ๐Ÿ‰ Former rugby player
  • โŒจ๏ธ Holy panda clicky clicky

Connect with me:

jorgebodega | Twitter jorgebodega | LinkedIn


Languages and Tools:

VSCode

Neovim

TypeScript

NodeJS

Postgresql

MongoDB

Gitkraken

Github

Gitlab

Arch Linux

typeorm-factory's People

Contributors

inossidabile avatar jorgebodega avatar piotr-skowronski-prpl avatar renovate[bot] avatar semantic-release-bot 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

Watchers

 avatar  avatar

typeorm-factory's Issues

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • chore: update dependency eslint to v9
  • chore: update wagoid/commitlint-github-action action to v6

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/commitlint.yml
  • actions/checkout v4
  • pnpm/action-setup v2
  • actions/setup-node v4
  • wagoid/commitlint-github-action v5
.github/workflows/coverage.yml
  • actions/checkout v4
  • pnpm/action-setup v2
  • actions/setup-node v4
.github/workflows/quality.yml
  • actions/checkout v4
  • pnpm/action-setup v2
  • actions/setup-node v4
  • actions/checkout v4
  • pnpm/action-setup v2
  • actions/setup-node v4
  • actions/checkout v4
  • pnpm/action-setup v2
  • actions/setup-node v4
  • actions/checkout v4
  • pnpm/action-setup v2
  • actions/setup-node v4
.github/workflows/release.yml
  • actions/checkout v4
  • pnpm/action-setup v2
  • actions/setup-node v4
  • cycjimmy/semantic-release-action v3
nodenv
.node-version
npm
package.json
  • tslib 2.6.2
  • @faker-js/faker 8.4.1
  • @tsconfig/node18-strictest 1.0.0
  • @types/jest 29.5.12
  • @types/node 20.11.29
  • @typescript-eslint/eslint-plugin 7.3.0
  • @typescript-eslint/parser 7.3.0
  • eslint 8.57.0
  • eslint-config-prettier 9.1.0
  • eslint-import-resolver-typescript 3.6.1
  • eslint-plugin-import 2.29.1
  • jest 29.7.0
  • prettier 3.2.5
  • rimraf 5.0.5
  • sqlite3 5.1.7
  • ts-jest 29.1.2
  • ts-node 10.9.2
  • typeorm 0.3.20
  • typescript 5.4.2
  • typeorm ^0.3.0
  • node >=18 <19 || >=20
  • pnpm 8.15.5

  • Check this box to trigger a request for Renovate to run again on this repository

Add code samples

Will be great to have some code samples on this library, just to improve documentation with examples

Will be great to add:

  • Simple entity
  • Two entities 1:1 related with both sides as required
  • Two entities 1:1 related, but one side is nullable
  • Two entities 1:N related
  • Two entities N:M related
  • Many entites chained

Also, will be great if all of this examples are created with factories, seeders and tests

Type *Entity* is not assignable to type Constructable<*Entity*>

When trying to recreate the examples from README, I get a type error.

Factory:

export class EquipmentFactory extends Factory<EquipmentsEntity> {
  protected entity: EquipmentsEntity; // <-- here
  protected dataSource: DataSource;
  protected attrs(): FactorizedAttrs<EquipmentsEntity> {
    return {
      title: faker.vehicle.vehicle(),
      // [...]
    };
  }
}

The error:

Type EquipmentsEntity is not assignable to type Constructable<EquipmentsEntity>

Of cause I tried wrapping the Entity with Constructable, but this results in a runtime error, when used as following:

await new EquipmentFactory().create();

Results in

this.entity is not a constructor
TypeError: this.entity is not a constructor
    at EquipmentFactory.makeEntity (.../node_modules/@jorgebodega/typeorm-factory/src/factory.ts:69:20)
    at EquipmentFactory.create (.../factory.ts:43:31)
 [...]

How to solve this? Is this a bug? At least it varies from the README.

Versions:

โ”œโ”€โ”€ @jorgebodega/[email protected]
โ”œโ”€โ”€ @nestjs/[email protected]
โ”œโ”€โ”€ @nestjs/[email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]

Add "index" dependet overrides for createMany/makeMany

It would be super helpful if I could createMany or makeMany with e.g. some kind of callback which passes the element number being created. This could easily allow seeding multiple entities with (simple) state differences

// Example 1: Seeding users, where some of them should not be active:
new UserFactory().createMany(10, (index: number) => ({ isActive: Boolean(index % 3) }));

// Example 2: Seeding products, with a "unnatural" order in database:
new ProductFactory().createMany(10, (index: number) => ({ order: 10 - (index % 5) }));

Override Params to influence SubFactory

We have the following (simplified) case:

@Entity()
export class MProductVariant extends TimestampedEntity implements ProductVariantData {
    @PrimaryColumn(UuidPrimaryColumn)
    public id!: Uuid;

    @Column({ nullable: true })
    public title?: string;

    @Column(UuidColumn)
    public productId!: Uuid;

    @ManyToOne(() => MProduct, (product) => product.variants)
    @JoinColumn({
        name: 'productId'
    })
    public product?: MProduct;
}
@Entity()
export class MProduct extends TimestampedEntity implements ProductData {
    @PrimaryColumn(UuidPrimaryColumn)
    public id!: Uuid;

    @Column()
    public title?: string;

    @OneToMany(() => MProductVariant, (variant) => variant.product, {
    })
    public variants?: MProductVariant[];
}

In the past we had the following factory, based on the context:

define(MProduct, () => {
    return new MProduct({
        id: generateTestUuid(),
        title: '[TEST] ' + faker.commerce.product()
    });
});
define(MProductVariant, (_, context: { baseProduct: MProduct } | undefined) => {
    return new MProductVariant({
        id: generateTestUuid(),
        title: productName,
        productId: context?.baseProduct.id
    });
});

If i want to replicate this with your lib, i see the possibility to use a SubFactory.
Is there a way to input parameters into the factory, that then will let you decide to form a SubFactory or use the passed parameters like that:

export class ProductVariantFactory extends Factory<MProductVariant> {
    protected entity = MProductVariant;
    protected dataSource = CoreDataSource;

    protected attrs(context): FactorizedAttrs<MProductVariant> {
        
        const product = context.product ? context.product : new SingleSubfactory(ProductFactory,{})

        return {
            id: generateTestUuid(),
            productId: product.id
        };
    }
};

Thanks for your efforts!

How to custom CollectionSubfactory

Hi, I need to create a Factory like this, field productDetails that has two children, each is one language. How can I do it, or am I missing something ?

export class ProductDetailFactory extends Factory<ProductDetail> {
  protected entity: Constructable<ProductDetail>;
  protected dataSource: DataSource;
  protected attrs(): FactorizedAttrs<ProductDetail> {
    return {
      description: faker.commerce.productDescription(),
      name: faker.commerce.productName(),
      shortDescription: faker.commerce.productDescription(),
      lang: Language.VN,
      slug: faker.commerce.productName().replace(/\s/g, '-'),
    };
  }
}

export class ProductFactory extends Factory<Product> {
  protected entity: Constructable<Product>;
  protected dataSource: DataSource;
  protected attrs(): FactorizedAttrs<Product> {
    return {
      type: ProductType.SIMPLE,
      status: ProductStatus.ACTIVE,
      isFeatured: false,
      taxStatus: ProductTaxStatus.TAXABLE,
      onSale: true,
      productDetails: [
        {lang: Language.VN,},
        {lang: Language.EN,},
      ]
    };
  }
}

Passing information into subfactories?

I have a project still way back on https://github.com/w3tecch/typeorm-seeding , and I'd like to move factories to typeorm-factory.

So I'm migrating away from using context (which was removed in your other library). Using the class-based extends factories (nice API design, btw!), I was thinking of using constructors to replace context, like this:

type FooFactoryContext = { n: number };

export class FooFactory extends Factory<Foo> {
  constructor(private ctx?: FooFactoryContext) {
    super();
  }
  protected entity = Foo;
  protected dataSource = dataSource;
  protected attrs(): FactorizedAttrs<Foo> {
    return {
      description: `item number ${this.ctx?.n || faker.datatype.number(10)}`,
      user: new SingleSubfactory(UserFactory),
    };
  }
}

new FooFactory().make({ description: "stuff" });
new FooFactory({ n: 5 }).make();

Is something like this what you had in mind as a replacement for context?

I hit a wall with a pattern in our old usage that I'm struggling to replace. We're passing information from one factory's context into a subfactory's context, like this:

define<Foo, FooFactoryContext>(Foo, (_, context) => {
  const foo = new Foo();
  foo.title = faker.random.words(3);
  foo.bar = BarFactory({stuff: context?.stuff}) as any;

If I continue down the path of using constructors, I think what I need is, a way to pass in a constructed factory into a subfactory, instead of passing in a constructible. Something like this:

protected attrs: FactorizedAttrs<User> = {
  country: new SingleSubfactory(new CountryFactory({customStuff:"here"})),
}

Or maybe, alternatively, instead of using constructors, I could pass in some "synthetic" attrs that don't have corresponding properties on the Entity:

protected attrs: FactorizedAttrs<User> = {
  country: new SingleSubfactory(CountryFactory, {
    name: faker.address.country(),
    extraThing: "this doesn't exist on the entity, but could be used by factories"
  }),
}

Maybe this is what is meant by "Attributes objects are superset from the original entity attributes." ? (ref) Does this happen to already work? (TypeScript errors discouraged me, but I haven't tried it interactively)

Do either of these options seem viable? Is there another way to achieve what I'm after?

Thanks for the libraries!

SyntaxError: Unexpected token 'export'

When trying to recreate the examples from README, I get a type error.

Facatory:

import {
  CollectionSubfactory,
  Factory,
  LazyInstanceAttribute,
  FactorizedAttrs,
} from '@jorgebodega/typeorm-factory';
import { Document } from '../../../src/modules/documents/entities/document.entity';
import { faker } from '@faker-js/faker';
import { ContentType, Status } from '../../../src/modules/common/enums';
import { TagFactory } from '../commons/tags.factory';
import dataSource from '../../../src/modules/configuration/database/datasource';

export class DocumentFactory extends Factory<Document> {
  protected entity = Document;

  protected dataSource = dataSource;

  protected attrs(): FactorizedAttrs<Document> {
    return {
      title: faker.string.sample,
      thumbnail: faker.string.uuid,
      file: faker.string.uuid,
      slug: faker.string.sample,
      description: faker.string.sample,
      contentType: ContentType.ARTICLE,
      status: Status.ARCHIVED,
      tags: new LazyInstanceAttribute(
        () => new CollectionSubfactory(TagFactory, 1),
      ),
    };
  }
}

The error

SyntaxError: Unexpected token 'export'

Full stack trace (expand) ```
    โ— Test suite failed to run
  
      Jest encountered an unexpected token
  
      Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
  
      Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
  
      By default "node_modules" folder is ignored by transformers.
  
      Here's what you can do:
       โ€ข If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
       โ€ข If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
       โ€ข To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
       โ€ข If you need a custom transformation specify a "transform" option in your config.
       โ€ข If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
  
      You'll find more details and examples of these config options in the docs:
      https://jestjs.io/docs/configuration
      For information about custom transformations, see:
      https://jestjs.io/docs/code-transformation
  
      Details:
  
      /Users/adinan.paiva/projects/sanar/learning-api/node_modules/@jorgebodega/typeorm-factory/dist/index.js:1
      ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export * from './factory';
                                                                                        ^^^^^^
  
      SyntaxError: Unexpected token 'export'
  
      > 1 | import {
          | ^
        2 |   CollectionSubfactory,
        3 |   Factory,
        4 |   LazyInstanceAttribute,
  
        at Runtime.createScriptFromCode (../node_modules/jest-runtime/build/index.js:1796:14)
        at Object.<anonymous> (../test/factories/assets/document.factory.ts:1:1)
```

Versions:

โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ [email protected]
โ”œโ”€โ”€ @jorgebodega/[email protected]
โ”œโ”€โ”€ @nestjs/[email protected]

This is a bug or a miss configuration?

Let me see if you need more reproducible information to help me.

Thanks

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.