Description
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:
- Types for additional user-defined parameters are inferred whenever possible.
- 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