@geekmidas/testkit 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/{Factory-z2m01hMj.mjs → Factory-BFVnMMCC.mjs} +2 -2
  2. package/dist/Factory-BFVnMMCC.mjs.map +1 -0
  3. package/dist/{Factory-DE3hE0WO.d.mts → Factory-BcGJjLc8.d.mts} +24 -10
  4. package/dist/{Factory-WMhTNZ9S.cjs → Factory-BhjUOBWN.cjs} +2 -2
  5. package/dist/Factory-BhjUOBWN.cjs.map +1 -0
  6. package/dist/{Factory-pNV7ZQ7-.d.cts → Factory-IdfEkOeT.d.cts} +24 -10
  7. package/dist/Factory.cjs +1 -1
  8. package/dist/Factory.d.cts +3 -3
  9. package/dist/Factory.d.mts +3 -3
  10. package/dist/Factory.mjs +1 -1
  11. package/dist/{KyselyFactory-DaaCykWP.cjs → KyselyFactory-BFqVIn_0.cjs} +21 -4
  12. package/dist/KyselyFactory-BFqVIn_0.cjs.map +1 -0
  13. package/dist/{KyselyFactory-CPZTUuMB.d.cts → KyselyFactory-Cj-EultY.d.mts} +18 -5
  14. package/dist/{KyselyFactory-CXY5gJk2.mjs → KyselyFactory-DMswpwji.mjs} +21 -4
  15. package/dist/KyselyFactory-DMswpwji.mjs.map +1 -0
  16. package/dist/{KyselyFactory-RAyvZ8Cj.d.mts → KyselyFactory-Dxhi_ZkA.d.cts} +18 -5
  17. package/dist/KyselyFactory.cjs +2 -2
  18. package/dist/KyselyFactory.d.cts +3 -3
  19. package/dist/KyselyFactory.d.mts +3 -3
  20. package/dist/KyselyFactory.mjs +2 -2
  21. package/dist/{ObjectionFactory-BlBicEia.d.mts → ObjectionFactory-BRAkAByP.d.cts} +18 -5
  22. package/dist/{ObjectionFactory-Eb04AOnv.cjs → ObjectionFactory-BeFBYcan.cjs} +21 -4
  23. package/dist/ObjectionFactory-BeFBYcan.cjs.map +1 -0
  24. package/dist/{ObjectionFactory-BwpN4gMX.d.cts → ObjectionFactory-DL4qkuF1.d.mts} +18 -5
  25. package/dist/{ObjectionFactory-zf2fLKrL.mjs → ObjectionFactory-QCJ7u0Ql.mjs} +21 -4
  26. package/dist/ObjectionFactory-QCJ7u0Ql.mjs.map +1 -0
  27. package/dist/ObjectionFactory.cjs +2 -2
  28. package/dist/ObjectionFactory.d.cts +3 -3
  29. package/dist/ObjectionFactory.d.mts +3 -3
  30. package/dist/ObjectionFactory.mjs +2 -2
  31. package/dist/{VitestKyselyTransactionIsolator-XDL3ngs_.mjs → VitestKyselyTransactionIsolator-CNURW8y6.mjs} +2 -2
  32. package/dist/{VitestKyselyTransactionIsolator-XDL3ngs_.mjs.map → VitestKyselyTransactionIsolator-CNURW8y6.mjs.map} +1 -1
  33. package/dist/{VitestKyselyTransactionIsolator-DiskaURs.d.mts → VitestKyselyTransactionIsolator-D3EZZhjZ.d.cts} +2 -2
  34. package/dist/{VitestKyselyTransactionIsolator-BqrZDeaT.d.cts → VitestKyselyTransactionIsolator-Dxlp1u0f.d.mts} +2 -2
  35. package/dist/{VitestKyselyTransactionIsolator-DX_VPKS-.cjs → VitestKyselyTransactionIsolator-EvDLk5zg.cjs} +2 -2
  36. package/dist/{VitestKyselyTransactionIsolator-DX_VPKS-.cjs.map → VitestKyselyTransactionIsolator-EvDLk5zg.cjs.map} +1 -1
  37. package/dist/VitestKyselyTransactionIsolator.cjs +2 -2
  38. package/dist/VitestKyselyTransactionIsolator.d.cts +2 -2
  39. package/dist/VitestKyselyTransactionIsolator.d.mts +2 -2
  40. package/dist/VitestKyselyTransactionIsolator.mjs +2 -2
  41. package/dist/{VitestObjectionTransactionIsolator-CD2ucJpH.d.cts → VitestObjectionTransactionIsolator-1TpsPqfG.d.cts} +2 -2
  42. package/dist/{VitestObjectionTransactionIsolator-D_tlOtq8.cjs → VitestObjectionTransactionIsolator-CM5KTAFA.cjs} +2 -2
  43. package/dist/{VitestObjectionTransactionIsolator-D_tlOtq8.cjs.map → VitestObjectionTransactionIsolator-CM5KTAFA.cjs.map} +1 -1
  44. package/dist/{VitestObjectionTransactionIsolator-DhQ8XGva.d.mts → VitestObjectionTransactionIsolator-i9jIgU8Q.d.mts} +2 -2
  45. package/dist/{VitestObjectionTransactionIsolator-_EhJKu_O.mjs → VitestObjectionTransactionIsolator-jQFaCz0u.mjs} +2 -2
  46. package/dist/{VitestObjectionTransactionIsolator-_EhJKu_O.mjs.map → VitestObjectionTransactionIsolator-jQFaCz0u.mjs.map} +1 -1
  47. package/dist/VitestObjectionTransactionIsolator.cjs +2 -2
  48. package/dist/VitestObjectionTransactionIsolator.d.cts +2 -2
  49. package/dist/VitestObjectionTransactionIsolator.d.mts +2 -2
  50. package/dist/VitestObjectionTransactionIsolator.mjs +2 -2
  51. package/dist/{VitestTransactionIsolator-DLdQlfZ5.d.mts → VitestTransactionIsolator-BvR19bYn.d.mts} +31 -14
  52. package/dist/{VitestTransactionIsolator-BKIrj3Uy.cjs → VitestTransactionIsolator-CMfJXZP8.cjs} +52 -36
  53. package/dist/VitestTransactionIsolator-CMfJXZP8.cjs.map +1 -0
  54. package/dist/{VitestTransactionIsolator-DfA80g2M.d.cts → VitestTransactionIsolator-CwQaxZLP.d.cts} +31 -14
  55. package/dist/{VitestTransactionIsolator-BIaMs4c2.mjs → VitestTransactionIsolator-DQ7tLqgV.mjs} +52 -36
  56. package/dist/VitestTransactionIsolator-DQ7tLqgV.mjs.map +1 -0
  57. package/dist/VitestTransactionIsolator.cjs +1 -1
  58. package/dist/VitestTransactionIsolator.d.cts +2 -2
  59. package/dist/VitestTransactionIsolator.d.mts +2 -2
  60. package/dist/VitestTransactionIsolator.mjs +1 -1
  61. package/dist/benchmark.cjs +49 -0
  62. package/dist/benchmark.cjs.map +1 -0
  63. package/dist/benchmark.d.cts +35 -0
  64. package/dist/benchmark.d.mts +35 -0
  65. package/dist/benchmark.mjs +45 -0
  66. package/dist/benchmark.mjs.map +1 -0
  67. package/dist/better-auth.d.cts +2 -2
  68. package/dist/better-auth.d.mts +2 -2
  69. package/dist/{directory-Q178x53k.d.mts → directory-BXavAeJZ.d.mts} +3 -3
  70. package/dist/{faker-BSH1EMtg.d.cts → faker-CbYiF-8_.d.cts} +3 -3
  71. package/dist/{faker-D9gz7KjY.d.mts → faker-DHh7xs4u.d.mts} +3 -3
  72. package/dist/faker.d.cts +1 -1
  73. package/dist/faker.d.mts +1 -1
  74. package/dist/kysely.cjs +25 -31
  75. package/dist/kysely.cjs.map +1 -1
  76. package/dist/kysely.d.cts +39 -34
  77. package/dist/kysely.d.mts +39 -34
  78. package/dist/kysely.mjs +25 -31
  79. package/dist/kysely.mjs.map +1 -1
  80. package/dist/objection.cjs +25 -49
  81. package/dist/objection.cjs.map +1 -1
  82. package/dist/objection.d.cts +39 -52
  83. package/dist/objection.d.mts +39 -52
  84. package/dist/objection.mjs +25 -49
  85. package/dist/objection.mjs.map +1 -1
  86. package/dist/os/directory.d.mts +1 -1
  87. package/dist/os/index.d.mts +1 -1
  88. package/package.json +6 -1
  89. package/src/Factory.ts +25 -11
  90. package/src/KyselyFactory.ts +21 -4
  91. package/src/ObjectionFactory.ts +21 -4
  92. package/src/VitestTransactionIsolator.ts +67 -16
  93. package/src/__tests__/Factory.spec.ts +16 -10
  94. package/src/__tests__/KyselyFactory.spec.ts +16 -11
  95. package/src/__tests__/ObjectionFactory.spec.ts +61 -53
  96. package/src/__tests__/VitestObjectionTransactionIsolator.spec.ts +6 -3
  97. package/src/__tests__/integration.spec.ts +24 -18
  98. package/src/benchmark.ts +48 -0
  99. package/src/kysely.ts +44 -33
  100. package/src/objection.ts +42 -51
  101. package/dist/Factory-WMhTNZ9S.cjs.map +0 -1
  102. package/dist/Factory-z2m01hMj.mjs.map +0 -1
  103. package/dist/KyselyFactory-CXY5gJk2.mjs.map +0 -1
  104. package/dist/KyselyFactory-DaaCykWP.cjs.map +0 -1
  105. package/dist/ObjectionFactory-Eb04AOnv.cjs.map +0 -1
  106. package/dist/ObjectionFactory-zf2fLKrL.mjs.map +0 -1
  107. package/dist/VitestTransactionIsolator-BIaMs4c2.mjs.map +0 -1
  108. package/dist/VitestTransactionIsolator-BKIrj3Uy.cjs.map +0 -1
package/src/Factory.ts CHANGED
@@ -39,7 +39,7 @@ export abstract class Factory<
39
39
  *
40
40
  * @example
41
41
  * ```typescript
42
- * const userWithPostsSeed = Factory.createSeed(async (attrs, factory, db) => {
42
+ * const userWithPostsSeed = Factory.createSeed(async ({ attrs, factory, db }) => {
43
43
  * const user = await factory.insert('user', attrs);
44
44
  * return user;
45
45
  * });
@@ -86,7 +86,7 @@ export abstract class Factory<
86
86
  */
87
87
  abstract seed<K extends keyof Seeds>(
88
88
  seedName: K,
89
- attrs?: Parameters<Seeds[K]>[0],
89
+ attrs?: ExtractSeedAttrs<Seeds[K]>,
90
90
  ): ReturnType<Seeds[K]>;
91
91
  }
92
92
 
@@ -133,15 +133,16 @@ export type MixedFactoryBuilder<
133
133
  * @template Result - The type of object returned by the seed
134
134
  * @template DB - The database connection type (Kysely, Knex, etc.)
135
135
  *
136
- * @param attrs - Configuration attributes for the seed
137
- * @param factory - The factory instance for creating records
138
- * @param db - The database connection
136
+ * @param context - Object containing attrs, factory, and db
137
+ * @param context.attrs - Configuration attributes for the seed
138
+ * @param context.factory - The factory instance for creating records
139
+ * @param context.db - The database connection
139
140
  * @returns A promise resolving to the seed result
140
141
  *
141
142
  * @example
142
143
  * ```typescript
143
144
  * const userWithPostsSeed: FactorySeed<{ postCount?: number }, Factory, User, DB> =
144
- * async (attrs, factory, db) => {
145
+ * async ({ attrs, factory, db }) => {
145
146
  * const user = await factory.insert('user', attrs);
146
147
  * const postCount = attrs.postCount || 3;
147
148
  *
@@ -153,8 +154,21 @@ export type MixedFactoryBuilder<
153
154
  * };
154
155
  * ```
155
156
  */
156
- export type FactorySeed<Attrs = any, Factory = any, Result = any, DB = any> = (
157
- attrs: Attrs,
158
- factory: Factory,
159
- db: DB,
160
- ) => Promise<Result>;
157
+ export type FactorySeed<
158
+ Attrs = any,
159
+ Factory = any,
160
+ Result = any,
161
+ DB = any,
162
+ > = (context: { attrs: Attrs; factory: Factory; db: DB }) => Promise<Result>;
163
+
164
+ /**
165
+ * Helper type to extract the Attrs type from a FactorySeed function.
166
+ * Used internally by Factory implementations to correctly type the seed method parameters.
167
+ */
168
+ export type ExtractSeedAttrs<T> = T extends (context: {
169
+ attrs: infer A;
170
+ factory: any;
171
+ db: any;
172
+ }) => any
173
+ ? A
174
+ : never;
@@ -4,7 +4,7 @@ import type {
4
4
  Kysely,
5
5
  Selectable,
6
6
  } from 'kysely';
7
- import { Factory, type FactorySeed } from './Factory.ts';
7
+ import { type ExtractSeedAttrs, Factory, type FactorySeed } from './Factory.ts';
8
8
  import { type FakerFactory, faker } from './faker.ts';
9
9
 
10
10
  /**
@@ -55,8 +55,21 @@ export class KyselyFactory<
55
55
  * Inherits from the base Factory class implementation.
56
56
  *
57
57
  * @template Seed - The seed function type
58
- * @param seedFn - The seed function to wrap
58
+ * @param seedFn - The seed function to wrap (receives { attrs, factory, db } object)
59
59
  * @returns The same seed function with proper typing
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * const seeds = {
64
+ * userWithPosts: KyselyFactory.createSeed(
65
+ * async ({ attrs, factory }) => {
66
+ * const user = await factory.insert('user', attrs);
67
+ * await factory.insertMany(3, 'post', { userId: user.id });
68
+ * return user;
69
+ * },
70
+ * ),
71
+ * };
72
+ * ```
60
73
  */
61
74
  static createSeed<Seed extends FactorySeed>(seedFn: Seed): Seed {
62
75
  return Factory.createSeed(seedFn);
@@ -359,7 +372,7 @@ export class KyselyFactory<
359
372
  */
360
373
  seed<K extends keyof Seeds>(
361
374
  seedName: K,
362
- attrs?: Parameters<Seeds[K]>[0],
375
+ attrs?: ExtractSeedAttrs<Seeds[K]>,
363
376
  ): ReturnType<Seeds[K]> {
364
377
  if (!(seedName in this.seeds)) {
365
378
  throw new Error(
@@ -369,6 +382,10 @@ export class KyselyFactory<
369
382
  );
370
383
  }
371
384
 
372
- return this.seeds[seedName](attrs || {}, this, this.db);
385
+ return this.seeds[seedName]({
386
+ attrs: attrs || {},
387
+ factory: this,
388
+ db: this.db,
389
+ });
373
390
  }
374
391
  }
@@ -1,6 +1,6 @@
1
1
  import type { Knex } from 'knex';
2
2
  import type { Model } from 'objection';
3
- import { Factory, type FactorySeed } from './Factory.ts';
3
+ import { type ExtractSeedAttrs, Factory, type FactorySeed } from './Factory.ts';
4
4
  import { type FakerFactory, faker } from './faker.ts';
5
5
 
6
6
  /**
@@ -48,8 +48,21 @@ export class ObjectionFactory<
48
48
  * Inherits from the base Factory class implementation.
49
49
  *
50
50
  * @template Seed - The seed function type
51
- * @param seedFn - The seed function to wrap
51
+ * @param seedFn - The seed function to wrap (receives { attrs, factory, db } object)
52
52
  * @returns The same seed function with proper typing
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const seeds = {
57
+ * userWithPosts: ObjectionFactory.createSeed(
58
+ * async ({ attrs, factory }) => {
59
+ * const user = await factory.insert('user', attrs);
60
+ * await factory.insertMany(3, 'post', { userId: user.id });
61
+ * return user;
62
+ * },
63
+ * ),
64
+ * };
65
+ * ```
53
66
  */
54
67
  static createSeed<Seed extends FactorySeed>(seedFn: Seed): Seed {
55
68
  return Factory.createSeed(seedFn);
@@ -381,7 +394,7 @@ export class ObjectionFactory<
381
394
  */
382
395
  seed<K extends keyof Seeds>(
383
396
  seedName: K,
384
- attrs?: Parameters<Seeds[K]>[0],
397
+ attrs?: ExtractSeedAttrs<Seeds[K]>,
385
398
  ): ReturnType<Seeds[K]> {
386
399
  if (!(seedName in this.seeds)) {
387
400
  throw new Error(
@@ -391,6 +404,10 @@ export class ObjectionFactory<
391
404
  );
392
405
  }
393
406
 
394
- return this.seeds[seedName](attrs || {}, this, this.db);
407
+ return this.seeds[seedName]({
408
+ attrs: attrs || {},
409
+ factory: this,
410
+ db: this.db,
411
+ });
395
412
  }
396
413
  }
@@ -124,30 +124,59 @@ export abstract class VitestPostgresTransactionIsolator<TConn, Transaction> {
124
124
  * Creates a wrapped version of Vitest's test API that provides transaction isolation.
125
125
  * Each test will run within a database transaction that is automatically rolled back.
126
126
  *
127
- * @param conn - The database connection to use
128
- * @param setup - Optional setup function to run within the transaction before each test
129
- * @param level - The transaction isolation level (defaults to REPEATABLE_READ)
127
+ * @param options - Configuration options for transaction wrapping
130
128
  * @returns A wrapped test API with transaction support
131
129
  *
132
130
  * @example
133
131
  * ```typescript
134
- * const isolatedTest = isolator.wrapVitestWithTransaction(db, async (trx) => {
135
- * // Optional setup: create common test data
136
- * await trx.insert('settings', { key: 'test', value: 'true' });
132
+ * const isolatedTest = isolator.wrapVitestWithTransaction({
133
+ * connection: db,
134
+ * setup: async (trx) => {
135
+ * await trx.insert('settings', { key: 'test', value: 'true' });
136
+ * },
137
+ * fixtures: {
138
+ * factory: (trx) => new Factory(trx),
139
+ * },
137
140
  * });
138
141
  *
139
- * isolatedTest('test with transaction', async ({ trx }) => {
140
- * const user = await trx.insert('users', { name: 'Test' });
142
+ * isolatedTest('test with transaction', async ({ trx, factory }) => {
143
+ * const user = await factory.insert('user', { name: 'Test' });
141
144
  * expect(user).toBeDefined();
142
145
  * });
143
146
  * ```
144
147
  */
145
- wrapVitestWithTransaction(
146
- createConnection: DatabaseConnection<TConn>,
147
- setup?: (trx: Transaction) => Promise<void>,
148
- level: IsolationLevel = IsolationLevel.REPEATABLE_READ,
148
+ wrapVitestWithTransaction<Extended extends Record<string, unknown> = {}>(
149
+ options: TransactionWrapperOptions<TConn, Transaction, Extended>,
149
150
  ) {
150
- return this.api.extend<DatabaseFixtures<Transaction>>({
151
+ const {
152
+ connection,
153
+ setup,
154
+ isolationLevel = IsolationLevel.REPEATABLE_READ,
155
+ fixtures,
156
+ } = options;
157
+
158
+ // Build fixture definitions for additional fixtures that depend on trx
159
+ const additionalFixtures: Record<string, unknown> = {};
160
+ if (fixtures) {
161
+ for (const [key, creator] of Object.entries(fixtures)) {
162
+ additionalFixtures[key] = async (
163
+ { trx }: { trx: Transaction },
164
+ use: (value: unknown) => Promise<void>,
165
+ ) => {
166
+ const value = await (creator as (trx: Transaction) => unknown)(trx);
167
+ await use(value);
168
+ };
169
+ }
170
+ }
171
+
172
+ type CombinedFixtures = DatabaseFixtures<Transaction> & Extended;
173
+
174
+ // Cast to bypass Vitest's strict fixture typing which can't infer
175
+ // dynamically built fixture objects
176
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
177
+ const extendFn = this.api.extend as <T>(fixtures: any) => TestAPI<T>;
178
+
179
+ return extendFn<CombinedFixtures>({
151
180
  // This fixture automatically provides a transaction to each test
152
181
  trx: async ({}, use: (value: Transaction) => Promise<void>) => {
153
182
  // Create a custom error class for rollback
@@ -159,9 +188,9 @@ export abstract class VitestPostgresTransactionIsolator<TConn, Transaction> {
159
188
  }
160
189
 
161
190
  let testError: Error | undefined;
162
- const conn = await createConnection();
191
+ const conn = await connection();
163
192
  try {
164
- await this.transact(conn, level, async (transaction) => {
193
+ await this.transact(conn, isolationLevel, async (transaction) => {
165
194
  try {
166
195
  // Provide the transaction to the test
167
196
  await setup?.(transaction);
@@ -188,6 +217,7 @@ export abstract class VitestPostgresTransactionIsolator<TConn, Transaction> {
188
217
  await this.destroy(conn);
189
218
  }
190
219
  },
220
+ ...additionalFixtures,
191
221
  });
192
222
  }
193
223
  }
@@ -195,6 +225,24 @@ export abstract class VitestPostgresTransactionIsolator<TConn, Transaction> {
195
225
  export type DatabaseConnectionFn<Conn> = () => Conn | Promise<Conn>;
196
226
  export type DatabaseConnection<Conn> = DatabaseConnectionFn<Conn>;
197
227
 
228
+ /**
229
+ * Options for wrapping Vitest tests with database transaction isolation.
230
+ */
231
+ export interface TransactionWrapperOptions<
232
+ TConn,
233
+ Transaction,
234
+ Extended extends Record<string, unknown> = {},
235
+ > {
236
+ /** Function that creates or returns a database connection */
237
+ connection: DatabaseConnection<TConn>;
238
+ /** Optional setup function to run within the transaction before each test */
239
+ setup?: (trx: Transaction) => Promise<void>;
240
+ /** Transaction isolation level (defaults to REPEATABLE_READ) */
241
+ isolationLevel?: IsolationLevel;
242
+ /** Additional fixtures that depend on the transaction */
243
+ fixtures?: FixtureCreators<Transaction, Extended>;
244
+ }
245
+
198
246
  /**
199
247
  * Type for fixture creator functions that depend on the transaction.
200
248
  * Each function receives the transaction and returns the fixture value.
@@ -253,7 +301,10 @@ export type TestWithExtendedFixtures<
253
301
  * import { wrapVitestKyselyTransaction, extendWithFixtures } from '@geekmidas/testkit/kysely';
254
302
  *
255
303
  * // Create base wrapped test
256
- * const baseTest = wrapVitestKyselyTransaction(test, db, createTestTables);
304
+ * const baseTest = wrapVitestKyselyTransaction(test, {
305
+ * connection: db,
306
+ * setup: createTestTables,
307
+ * });
257
308
  *
258
309
  * // Extend with fixtures
259
310
  * const it = extendWithFixtures(baseTest, {
@@ -46,7 +46,11 @@ describe('Factory', () => {
46
46
 
47
47
  describe('createSeed static method', () => {
48
48
  it('should return the seed function unchanged', () => {
49
- const seedFn = async (attrs: any, factory: any, db: any) => {
49
+ const seedFn = async ({
50
+ attrs,
51
+ factory,
52
+ db,
53
+ }: { attrs: any; factory: any; db: any }) => {
50
54
  return { id: 1, name: 'test' };
51
55
  };
52
56
 
@@ -57,12 +61,14 @@ describe('Factory', () => {
57
61
  });
58
62
 
59
63
  it('should work with different seed function signatures', () => {
60
- const simpleSeed = () => Promise.resolve({ simple: true });
61
- const complexSeed = async (
62
- attrs: { name: string },
63
- factory: any,
64
- db: any,
65
- ) => {
64
+ const simpleSeed = async () => ({ simple: true });
65
+ const complexSeed = async ({
66
+ attrs,
67
+ }: {
68
+ attrs: { name: string };
69
+ factory: any;
70
+ db: any;
71
+ }) => {
66
72
  return { name: attrs.name, created: true };
67
73
  };
68
74
 
@@ -124,8 +130,8 @@ describe('Factory', () => {
124
130
  });
125
131
 
126
132
  it('should properly type FactorySeed', () => {
127
- // Test that FactorySeed requires async return
128
- const seed: FactorySeed = async (attrs, factory, db) => ({
133
+ // Test that FactorySeed requires async return with object parameter
134
+ const seed: FactorySeed = async ({ attrs, factory, db }) => ({
129
135
  seeded: true,
130
136
  });
131
137
 
@@ -155,7 +161,7 @@ describe('Factory types', () => {
155
161
  TestFactory,
156
162
  { created: number },
157
163
  any
158
- > = async (attrs, factory, db) => {
164
+ > = async ({ attrs }) => {
159
165
  return { created: attrs.count };
160
166
  };
161
167
 
@@ -7,11 +7,10 @@ import { createKyselyDb } from '../helpers';
7
7
  import { wrapVitestKyselyTransaction } from '../kysely';
8
8
 
9
9
  const db = () => createKyselyDb<TestDatabase>(TEST_DATABASE_CONFIG);
10
- const itWithTransaction = wrapVitestKyselyTransaction<TestDatabase>(
11
- it,
12
- db,
13
- createTestTables,
14
- );
10
+ const itWithTransaction = wrapVitestKyselyTransaction<TestDatabase>(it, {
11
+ connection: db,
12
+ setup: createTestTables,
13
+ });
15
14
 
16
15
  const int8TypeId = 20;
17
16
  pg.types.setTypeParser(int8TypeId, (val) => {
@@ -280,7 +279,10 @@ describe('KyselyFactory', () => {
280
279
 
281
280
  const seeds = {
282
281
  createAdminUser: KyselyFactory.createSeed(
283
- async (attrs: { name?: string }, factory: any, db: any) => {
282
+ async ({
283
+ attrs,
284
+ factory,
285
+ }: { attrs: { name?: string }; factory: any; db: any }) => {
284
286
  return await factory.insert('user', {
285
287
  name: attrs.name || 'Admin User',
286
288
  email: 'admin@example.com',
@@ -320,11 +322,14 @@ describe('KyselyFactory', () => {
320
322
 
321
323
  const seeds = {
322
324
  createCustomUser: KyselyFactory.createSeed(
323
- async (
324
- attrs: { name: string; email: string },
325
- factory: any,
326
- db: any,
327
- ) => {
325
+ async ({
326
+ attrs,
327
+ factory,
328
+ }: {
329
+ attrs: { name: string; email: string };
330
+ factory: any;
331
+ db: any;
332
+ }) => {
328
333
  return await factory.insert('user', attrs);
329
334
  },
330
335
  ),
@@ -37,11 +37,10 @@ class Comment extends Model {
37
37
  user_id!: string;
38
38
  }
39
39
 
40
- const it = wrapVitestObjectionTransaction(
41
- test,
42
- createKnexDb,
43
- createTestTablesKnex,
44
- );
40
+ const it = wrapVitestObjectionTransaction(test, {
41
+ connection: createKnexDb,
42
+ setup: createTestTablesKnex,
43
+ });
45
44
  describe('ObjectionFactory', () => {
46
45
  it('should create an ObjectionFactory instance', ({ trx }) => {
47
46
  const builders = {};
@@ -217,20 +216,22 @@ describe('ObjectionFactory', () => {
217
216
 
218
217
  const builders = { user: userBuilder };
219
218
 
220
- const createAdminSeed = async (attrs: any, factory: any, db: Knex) => {
221
- return await factory.insert('user', {
222
- name: attrs.name || 'Admin User',
223
- });
224
- };
225
-
226
219
  const seeds = {
227
- createAdmin: createAdminSeed,
220
+ createAdmin: ObjectionFactory.createSeed(
221
+ async ({
222
+ attrs,
223
+ factory,
224
+ }: { attrs: { name?: string }; factory: any; db: Knex }) => {
225
+ return await factory.insert('user', {
226
+ name: attrs.name || 'Admin User',
227
+ });
228
+ },
229
+ ),
228
230
  };
229
231
 
230
232
  const factory = new ObjectionFactory(builders, seeds, trx);
231
233
 
232
- const attrs = { name: 'Super Admin' };
233
- const result = await factory.seed('createAdmin', attrs);
234
+ const result = await factory.seed('createAdmin', { name: 'Super Admin' });
234
235
 
235
236
  expect(result).toBeInstanceOf(User);
236
237
  expect(result.name).toBe('Super Admin');
@@ -248,15 +249,15 @@ describe('ObjectionFactory', () => {
248
249
 
249
250
  const builders = { user: userBuilder };
250
251
 
251
- const createAdminSeed = async (attrs: any, factory: any, db: Knex) => {
252
- return await factory.insert('user', {
253
- name: 'Default Admin',
254
- role: 'admin',
255
- });
256
- };
257
-
258
252
  const seeds = {
259
- createAdmin: createAdminSeed,
253
+ createAdmin: ObjectionFactory.createSeed(
254
+ async ({ factory }: { attrs: any; factory: any; db: Knex }) => {
255
+ return await factory.insert('user', {
256
+ name: 'Default Admin',
257
+ role: 'admin',
258
+ });
259
+ },
260
+ ),
260
261
  };
261
262
 
262
263
  const factory = new ObjectionFactory(builders, seeds, trx);
@@ -284,25 +285,28 @@ describe('ObjectionFactory', () => {
284
285
 
285
286
  const builders = { user: userBuilder };
286
287
 
287
- const complexSeed = async (
288
- attrs: any,
289
- passedFactory: any,
290
- passedDb: Knex,
291
- ) => {
292
- // Verify that factory and db are passed correctly
293
- expect(passedFactory).toBe(factory);
294
- expect(passedDb).toBe(trx);
295
-
296
- return await passedFactory.insert('user', {
297
- name: `Complex ${attrs.data}`,
298
- });
299
- };
288
+ let factoryRef: any;
300
289
 
301
290
  const seeds = {
302
- complexSeed,
291
+ complexSeed: ObjectionFactory.createSeed(
292
+ async ({
293
+ attrs,
294
+ factory: passedFactory,
295
+ db: passedDb,
296
+ }: { attrs: { data: string }; factory: any; db: Knex }) => {
297
+ // Verify that factory and db are passed correctly
298
+ expect(passedFactory).toBe(factoryRef);
299
+ expect(passedDb).toBe(trx);
300
+
301
+ return await passedFactory.insert('user', {
302
+ name: `Complex ${attrs.data}`,
303
+ });
304
+ },
305
+ ),
303
306
  };
304
307
 
305
308
  const factory = new ObjectionFactory(builders, seeds, trx);
309
+ factoryRef = factory;
306
310
 
307
311
  const result = await factory.seed('complexSeed', { data: 'test' });
308
312
 
@@ -311,7 +315,7 @@ describe('ObjectionFactory', () => {
311
315
  });
312
316
 
313
317
  it('should return the seed function unchanged', () => {
314
- const seedFn = async (attrs: any, factory: any, db: any) => {
318
+ const seedFn = async ({ attrs }: { attrs: any; factory: any; db: any }) => {
315
319
  return { id: 1, name: 'test' };
316
320
  };
317
321
 
@@ -482,12 +486,12 @@ describe('ObjectionFactory', () => {
482
486
  });
483
487
 
484
488
  it('should handle seed function errors gracefully', async ({ trx }) => {
485
- const failingSeed = async (attrs: any, factory: any, db: Knex) => {
486
- throw new Error('Seed failed');
487
- };
488
-
489
489
  const seeds = {
490
- failingSeed,
490
+ failingSeed: ObjectionFactory.createSeed(
491
+ async ({}: { attrs: any; factory: any; db: Knex }) => {
492
+ throw new Error('Seed failed');
493
+ },
494
+ ),
491
495
  };
492
496
 
493
497
  const factory = new ObjectionFactory({}, seeds, trx);
@@ -509,18 +513,22 @@ describe('ObjectionFactory', () => {
509
513
  });
510
514
  };
511
515
 
512
- const adminSeed = async (
513
- attrs: { isSuper?: boolean },
514
- factory: any,
515
- db: Knex,
516
- ) => {
517
- return factory.insert('user', {
518
- name: 'Admin',
519
- });
520
- };
521
-
522
516
  const builders = { user: userBuilder };
523
- const seeds = { admin: adminSeed };
517
+ const seeds = {
518
+ admin: ObjectionFactory.createSeed(
519
+ async ({
520
+ factory,
521
+ }: {
522
+ attrs: { isSuper?: boolean };
523
+ factory: any;
524
+ db: Knex;
525
+ }) => {
526
+ return factory.insert('user', {
527
+ name: 'Admin',
528
+ });
529
+ },
530
+ ),
531
+ };
524
532
 
525
533
  // This should compile without type errors
526
534
  const factory = new ObjectionFactory(builders, seeds, trx);
@@ -108,9 +108,12 @@ class Comment extends Model {
108
108
  // Create database connection
109
109
 
110
110
  // Create wrapped test with transaction isolation
111
- const it = wrapVitestObjectionTransaction(base, createKnexDb, async (trx) => {
112
- // Create tables in the transaction
113
- await createTestTablesKnex(trx);
111
+ const it = wrapVitestObjectionTransaction(base, {
112
+ connection: createKnexDb,
113
+ setup: async (trx) => {
114
+ // Create tables in the transaction
115
+ await createTestTablesKnex(trx);
116
+ },
114
117
  });
115
118
 
116
119
  describe('VitestObjectionTransactionIsolator', () => {
@@ -6,11 +6,10 @@ import { createKyselyDb } from '../helpers';
6
6
  import { extendWithFixtures, wrapVitestKyselyTransaction } from '../kysely';
7
7
 
8
8
  const db = () => createKyselyDb<TestDatabase>(TEST_DATABASE_CONFIG);
9
- const it = wrapVitestKyselyTransaction<TestDatabase>(
10
- base,
11
- db,
12
- createTestTables,
13
- );
9
+ const it = wrapVitestKyselyTransaction<TestDatabase>(base, {
10
+ connection: db,
11
+ setup: createTestTables,
12
+ });
14
13
  describe('Testkit Integration Tests', () => {
15
14
  beforeAll(async () => {});
16
15
  describe('Complex Factory Scenarios', () => {
@@ -193,10 +192,14 @@ describe('Testkit Integration Tests', () => {
193
192
  // Create complex seeds
194
193
  const seeds = {
195
194
  blogWithAdminAndPosts: KyselyFactory.createSeed(
196
- async (
197
- attrs: { postCount?: number },
198
- factory: KyselyFactory<TestDatabase, typeof builders, {}>,
199
- ) => {
195
+ async ({
196
+ attrs,
197
+ factory,
198
+ }: {
199
+ attrs: { postCount?: number };
200
+ factory: KyselyFactory<TestDatabase, typeof builders, {}>;
201
+ db: any;
202
+ }) => {
200
203
  // Create admin user
201
204
  const admin = await factory.insert('user', {
202
205
  name: 'Blog Admin',
@@ -230,10 +233,14 @@ describe('Testkit Integration Tests', () => {
230
233
  ),
231
234
 
232
235
  usersWithPosts: KyselyFactory.createSeed(
233
- async (
234
- attrs: { userCount?: number; postsPerUser?: number },
235
- factory: KyselyFactory<TestDatabase, typeof builders, {}>,
236
- ) => {
236
+ async ({
237
+ attrs,
238
+ factory,
239
+ }: {
240
+ attrs: { userCount?: number; postsPerUser?: number };
241
+ factory: KyselyFactory<TestDatabase, typeof builders, {}>;
242
+ db: any;
243
+ }) => {
237
244
  const userCount = attrs.userCount || 2;
238
245
  const postsPerUser = attrs.postsPerUser || 2;
239
246
 
@@ -481,11 +488,10 @@ describe('extendWithFixtures', () => {
481
488
  };
482
489
 
483
490
  // Create base test with transaction
484
- const baseTest = wrapVitestKyselyTransaction<TestDatabase>(
485
- base,
486
- db,
487
- createTestTables,
488
- );
491
+ const baseTest = wrapVitestKyselyTransaction<TestDatabase>(base, {
492
+ connection: db,
493
+ setup: createTestTables,
494
+ });
489
495
 
490
496
  // Extend with factory fixture
491
497
  const itWithFactory = extendWithFixtures<