Skip to content

Design signature of arbitrary factory parameters #252

Closed
@Quramy

Description

@Quramy

What

Like transient attributes in factory_bot, I'd like to provide feature to define and use arbitrary parameters in fabbrica.

Background

See #244 .

Points

Signature of this feature should satisfy the followings:

  1. Types for additional user-defined parameters are inferred whenever possible.
  2. New signature should be backward-compat.

Proposal for API signature

Add HOF withExtraParameters to defineModelFactory fn:

declare function withExtraParameters<TExtraParams>(defaultExtraParams: TExtraParams) => (options: UserFactoryOptions) => UserFactoryInterface<TExtraParams, UserFactoryOptions>;

defineModelFactory works not only function but also object which provides the HOF.

import { defineUserFactory } from "./__generated__/fabbrica";

export async function seed() {
  const UserFactory = defineUserFactory.withExtraParameters({ loginCount: 0 })({
    defaultData: ({ seq, loginCount }) => {
      console.log(seq, loginCount);
      return {};
    },

    traits: {
      withLoginRecords: {
        data: ({ loginCount }) => {
          console.log(loginCount);
          return {};
        },
      },
    },
  });

  await UserFactory.build({ loginCount: 100 });
  await UserFactory.build(); // UserFactory provides default value defined `withExtraParameters`(i.e. 0) as loginCount
  await UserFactory.use("withLoginRecords").build({ loginCount: 100 });
}

If you want fully example, see https://github.com/Quramy/prisma-fabbrica/blob/feature/transient_params/packages/artifact-testing/fixtures/callback/transients.ts

Why default parameters ?

Factory guarantees extra parameters existence because of default value. So developer can refer the extra parameters at implementation of defaultData or traits. ( Inspired from createContext in React) .

And default parameters object also tells to factory what kind of type for extra parameters via type inference.

Why HOF ?

The major reason is to infer types of the extra parameters and to provide the inferred type to factory definition. I also attempted the following pattern, but I can't achieve it.

  const UserFactory = defineUserFactory({
    defaultExtraParams: { loginCount: 0 },
    defaultData: ({ seq, loginCount }) => {
      console.log(seq, loginCount);
      return {};
    },
  })

Why named extraParameters ?

I think a different name would be fine. For example, transientFields or contextParameters.

Caveat

  • Developer can't define trait specified parameters. If a parameter is referred from one trait impl, it should be defined and provided the default value at the factory level

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions