@geekmidas/testkit 0.2.0 → 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 (71) 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-Cmr3s3-s.d.mts → Factory-BcGJjLc8.d.mts} +23 -9
  4. package/dist/{Factory-WMhTNZ9S.cjs → Factory-BhjUOBWN.cjs} +2 -2
  5. package/dist/Factory-BhjUOBWN.cjs.map +1 -0
  6. package/dist/{Factory-D7oHtI2D.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 +2 -2
  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-BTdygZ-i.d.mts → KyselyFactory-Cj-EultY.d.mts} +17 -4
  14. package/dist/{KyselyFactory-CXY5gJk2.mjs → KyselyFactory-DMswpwji.mjs} +21 -4
  15. package/dist/KyselyFactory-DMswpwji.mjs.map +1 -0
  16. package/dist/{KyselyFactory-dYdviox2.d.cts → 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 +2 -2
  20. package/dist/KyselyFactory.mjs +2 -2
  21. package/dist/{ObjectionFactory-0gUdx8bB.d.cts → 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-BagGjikT.d.mts → ObjectionFactory-DL4qkuF1.d.mts} +17 -4
  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 +2 -2
  30. package/dist/ObjectionFactory.mjs +2 -2
  31. package/dist/benchmark.cjs +49 -0
  32. package/dist/benchmark.cjs.map +1 -0
  33. package/dist/benchmark.d.cts +35 -0
  34. package/dist/benchmark.d.mts +35 -0
  35. package/dist/benchmark.mjs +45 -0
  36. package/dist/benchmark.mjs.map +1 -0
  37. package/dist/better-auth.d.cts +2 -2
  38. package/dist/{directory-BUcnztHI.d.cts → directory-Mi7tdOuD.d.cts} +3 -3
  39. package/dist/{faker-Dg3trU4a.d.cts → faker-CbYiF-8_.d.cts} +3 -3
  40. package/dist/faker.d.cts +1 -1
  41. package/dist/kysely.cjs +2 -2
  42. package/dist/kysely.cjs.map +1 -1
  43. package/dist/kysely.d.cts +4 -4
  44. package/dist/kysely.d.mts +3 -3
  45. package/dist/kysely.mjs +2 -2
  46. package/dist/kysely.mjs.map +1 -1
  47. package/dist/objection.cjs +2 -2
  48. package/dist/objection.cjs.map +1 -1
  49. package/dist/objection.d.cts +4 -4
  50. package/dist/objection.d.mts +3 -3
  51. package/dist/objection.mjs +2 -2
  52. package/dist/objection.mjs.map +1 -1
  53. package/dist/os/directory.d.cts +1 -1
  54. package/dist/os/index.d.cts +1 -1
  55. package/package.json +6 -1
  56. package/src/Factory.ts +25 -11
  57. package/src/KyselyFactory.ts +21 -4
  58. package/src/ObjectionFactory.ts +21 -4
  59. package/src/__tests__/Factory.spec.ts +16 -10
  60. package/src/__tests__/KyselyFactory.spec.ts +12 -6
  61. package/src/__tests__/ObjectionFactory.spec.ts +57 -48
  62. package/src/__tests__/integration.spec.ts +16 -8
  63. package/src/benchmark.ts +48 -0
  64. package/src/kysely.ts +1 -0
  65. package/src/objection.ts +1 -0
  66. package/dist/Factory-WMhTNZ9S.cjs.map +0 -1
  67. package/dist/Factory-z2m01hMj.mjs.map +0 -1
  68. package/dist/KyselyFactory-CXY5gJk2.mjs.map +0 -1
  69. package/dist/KyselyFactory-DaaCykWP.cjs.map +0 -1
  70. package/dist/ObjectionFactory-Eb04AOnv.cjs.map +0 -1
  71. package/dist/ObjectionFactory-zf2fLKrL.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"objection.cjs","names":["api: TestAPI","options: ObjectionTransactionOptions<Extended>","VitestObjectionTransactionIsolator","extendWithFixtures","wrappedTest: T","fixtures: FixtureCreators<Knex.Transaction, Extended>"],"sources":["../src/objection.ts"],"sourcesContent":["import type { Knex } from 'knex';\nimport type { TestAPI } from 'vitest';\nimport { VitestObjectionTransactionIsolator } from './VitestObjectionTransactionIsolator';\nimport {\n type DatabaseConnection,\n type FixtureCreators,\n type IsolationLevel,\n extendWithFixtures as baseExtendWithFixtures,\n} from './VitestTransactionIsolator';\n\n/**\n * Objection.js-specific exports for test utilities.\n * Provides factory implementation for creating test data with Objection.js ORM\n * and transaction isolation for test suites.\n */\n\nexport { ObjectionFactory } from './ObjectionFactory';\nexport { VitestObjectionTransactionIsolator } from './VitestObjectionTransactionIsolator';\nexport { IsolationLevel } from './VitestTransactionIsolator';\nexport { PostgresObjectionMigrator } from './PostgresObjectionMigrator';\nexport type {\n DatabaseFixtures,\n ExtendedDatabaseFixtures,\n FixtureCreators,\n TestWithExtendedFixtures,\n TransactionWrapperOptions,\n} from './VitestTransactionIsolator';\n\n/**\n * Objection.js-specific options for transaction wrapping.\n */\nexport interface ObjectionTransactionOptions<\n Extended extends Record<string, unknown> = {},\n> {\n /** Function that creates or returns a Knex database connection */\n connection: DatabaseConnection<Knex>;\n /** Optional setup function to run within the transaction before each test */\n setup?: (trx: Knex.Transaction) => Promise<void>;\n /** Transaction isolation level (defaults to REPEATABLE_READ) */\n isolationLevel?: IsolationLevel;\n /** Additional fixtures that depend on the transaction */\n fixtures?: FixtureCreators<Knex.Transaction, Extended>;\n}\n\n// Re-export faker and FakerFactory for type portability in declaration files\nexport { faker, type FakerFactory } from './faker';\n\n/**\n * Creates a wrapped Vitest test API with automatic transaction rollback for Objection.js.\n * Each test runs in an isolated database transaction that is rolled back after completion.\n * This ensures tests don't affect each other's data and run faster than truncating tables.\n *\n * @template Extended - Additional fixtures to provide\n * @param api - The Vitest test API (usually `test` from vitest)\n * @param options - Configuration options for transaction wrapping\n * @returns A wrapped test API that provides transaction isolation\n *\n * @example\n * ```typescript\n * import { test } from 'vitest';\n * import { wrapVitestObjectionTransaction } from '@geekmidas/testkit/objection';\n * import { knex } from './database';\n * import { User } from './models';\n *\n * // Create isolated test with automatic rollback\n * const isolatedTest = wrapVitestObjectionTransaction(test, {\n * connection: knex,\n * });\n *\n * // Use in tests - each test gets its own transaction\n * isolatedTest('should create user', async ({ trx }) => {\n * const user = await User.query(trx)\n * .insert({ name: 'Test User', email: 'test@example.com' });\n *\n * expect(user).toBeDefined();\n * });\n *\n * // With fixtures for factories\n * const it = wrapVitestObjectionTransaction<{ factory: Factory }>(test, {\n * connection: knex,\n * fixtures: {\n * factory: (trx) => new Factory(trx),\n * },\n * });\n *\n * it('should create user with factory', async ({ trx, factory }) => {\n * const user = await factory.insert('user', { name: 'Test' });\n * expect(user.id).toBeDefined();\n * });\n * ```\n */\nexport function wrapVitestObjectionTransaction<\n Extended extends Record<string, unknown> = {},\n>(api: TestAPI, options: ObjectionTransactionOptions<Extended>) {\n const wrapper = new VitestObjectionTransactionIsolator(api);\n\n return wrapper.wrapVitestWithTransaction(options);\n}\n\n/**\n * Extends an Objection.js transaction-wrapped test with additional fixtures.\n * Each fixture receives the transaction and can create dependencies like factories or repositories.\n *\n * @template Extended - The type of additional fixtures to provide\n * @param wrappedTest - The base wrapped test from wrapVitestObjectionTransaction\n * @param fixtures - Object mapping fixture names to creator functions\n * @returns An extended test API with both trx and the additional fixtures\n *\n * @example\n * ```typescript\n * import { test } from 'vitest';\n * import { wrapVitestObjectionTransaction, extendWithFixtures, ObjectionFactory } from '@geekmidas/testkit/objection';\n * import { User } from './models';\n *\n * // Define your builders\n * const builders = {\n * user: ObjectionFactory.createBuilder(User, ({ faker }) => ({\n * name: faker.person.fullName(),\n * email: faker.internet.email(),\n * })),\n * };\n *\n * // Create base wrapped test\n * const baseTest = wrapVitestObjectionTransaction(test, {\n * connection: knex,\n * setup: createTestTables,\n * });\n *\n * // Extend with fixtures - each fixture receives the transaction\n * const it = extendWithFixtures<{ factory: ObjectionFactory<typeof builders, {}> }>(\n * baseTest,\n * {\n * factory: (trx) => new ObjectionFactory(builders, {}, trx),\n * }\n * );\n *\n * // Use in tests - both trx and factory are available\n * it('should create user with factory', async ({ trx, factory }) => {\n * const user = await factory.insert('user', { name: 'Test User' });\n * expect(user.id).toBeDefined();\n *\n * // Verify in database\n * const found = await User.query(trx).findById(user.id);\n * expect(found?.name).toBe('Test User');\n * });\n * ```\n */\nexport function extendWithFixtures<\n Extended extends Record<string, unknown>,\n T extends ReturnType<TestAPI['extend']> = ReturnType<TestAPI['extend']>,\n>(wrappedTest: T, fixtures: FixtureCreators<Knex.Transaction, Extended>) {\n return baseExtendWithFixtures<Knex.Transaction, Extended, T>(\n wrappedTest,\n fixtures,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FA,SAAgB,+BAEdA,KAAcC,SAAgD;CAC9D,MAAM,UAAU,IAAIC,8EAAmC;AAEvD,QAAO,QAAQ,0BAA0B,QAAQ;AAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDD,SAAgBC,qBAGdC,aAAgBC,UAAuD;AACvE,QAAO,qDACL,aACA,SACD;AACF"}
1
+ {"version":3,"file":"objection.cjs","names":["api: TestAPI","options: ObjectionTransactionOptions<Extended>","VitestObjectionTransactionIsolator","extendWithFixtures","wrappedTest: T","fixtures: FixtureCreators<Knex.Transaction, Extended>"],"sources":["../src/objection.ts"],"sourcesContent":["import type { Knex } from 'knex';\nimport type { TestAPI } from 'vitest';\nimport { VitestObjectionTransactionIsolator } from './VitestObjectionTransactionIsolator';\nimport {\n type DatabaseConnection,\n type FixtureCreators,\n type IsolationLevel,\n extendWithFixtures as baseExtendWithFixtures,\n} from './VitestTransactionIsolator';\n\n/**\n * Objection.js-specific exports for test utilities.\n * Provides factory implementation for creating test data with Objection.js ORM\n * and transaction isolation for test suites.\n */\n\nexport { ObjectionFactory } from './ObjectionFactory';\nexport type { ExtractSeedAttrs, FactorySeed } from './Factory';\nexport { VitestObjectionTransactionIsolator } from './VitestObjectionTransactionIsolator';\nexport { IsolationLevel } from './VitestTransactionIsolator';\nexport { PostgresObjectionMigrator } from './PostgresObjectionMigrator';\nexport type {\n DatabaseFixtures,\n ExtendedDatabaseFixtures,\n FixtureCreators,\n TestWithExtendedFixtures,\n TransactionWrapperOptions,\n} from './VitestTransactionIsolator';\n\n/**\n * Objection.js-specific options for transaction wrapping.\n */\nexport interface ObjectionTransactionOptions<\n Extended extends Record<string, unknown> = {},\n> {\n /** Function that creates or returns a Knex database connection */\n connection: DatabaseConnection<Knex>;\n /** Optional setup function to run within the transaction before each test */\n setup?: (trx: Knex.Transaction) => Promise<void>;\n /** Transaction isolation level (defaults to REPEATABLE_READ) */\n isolationLevel?: IsolationLevel;\n /** Additional fixtures that depend on the transaction */\n fixtures?: FixtureCreators<Knex.Transaction, Extended>;\n}\n\n// Re-export faker and FakerFactory for type portability in declaration files\nexport { faker, type FakerFactory } from './faker';\n\n/**\n * Creates a wrapped Vitest test API with automatic transaction rollback for Objection.js.\n * Each test runs in an isolated database transaction that is rolled back after completion.\n * This ensures tests don't affect each other's data and run faster than truncating tables.\n *\n * @template Extended - Additional fixtures to provide\n * @param api - The Vitest test API (usually `test` from vitest)\n * @param options - Configuration options for transaction wrapping\n * @returns A wrapped test API that provides transaction isolation\n *\n * @example\n * ```typescript\n * import { test } from 'vitest';\n * import { wrapVitestObjectionTransaction } from '@geekmidas/testkit/objection';\n * import { knex } from './database';\n * import { User } from './models';\n *\n * // Create isolated test with automatic rollback\n * const isolatedTest = wrapVitestObjectionTransaction(test, {\n * connection: knex,\n * });\n *\n * // Use in tests - each test gets its own transaction\n * isolatedTest('should create user', async ({ trx }) => {\n * const user = await User.query(trx)\n * .insert({ name: 'Test User', email: 'test@example.com' });\n *\n * expect(user).toBeDefined();\n * });\n *\n * // With fixtures for factories\n * const it = wrapVitestObjectionTransaction<{ factory: Factory }>(test, {\n * connection: knex,\n * fixtures: {\n * factory: (trx) => new Factory(trx),\n * },\n * });\n *\n * it('should create user with factory', async ({ trx, factory }) => {\n * const user = await factory.insert('user', { name: 'Test' });\n * expect(user.id).toBeDefined();\n * });\n * ```\n */\nexport function wrapVitestObjectionTransaction<\n Extended extends Record<string, unknown> = {},\n>(api: TestAPI, options: ObjectionTransactionOptions<Extended>) {\n const wrapper = new VitestObjectionTransactionIsolator(api);\n\n return wrapper.wrapVitestWithTransaction(options);\n}\n\n/**\n * Extends an Objection.js transaction-wrapped test with additional fixtures.\n * Each fixture receives the transaction and can create dependencies like factories or repositories.\n *\n * @template Extended - The type of additional fixtures to provide\n * @param wrappedTest - The base wrapped test from wrapVitestObjectionTransaction\n * @param fixtures - Object mapping fixture names to creator functions\n * @returns An extended test API with both trx and the additional fixtures\n *\n * @example\n * ```typescript\n * import { test } from 'vitest';\n * import { wrapVitestObjectionTransaction, extendWithFixtures, ObjectionFactory } from '@geekmidas/testkit/objection';\n * import { User } from './models';\n *\n * // Define your builders\n * const builders = {\n * user: ObjectionFactory.createBuilder(User, ({ faker }) => ({\n * name: faker.person.fullName(),\n * email: faker.internet.email(),\n * })),\n * };\n *\n * // Create base wrapped test\n * const baseTest = wrapVitestObjectionTransaction(test, {\n * connection: knex,\n * setup: createTestTables,\n * });\n *\n * // Extend with fixtures - each fixture receives the transaction\n * const it = extendWithFixtures<{ factory: ObjectionFactory<typeof builders, {}> }>(\n * baseTest,\n * {\n * factory: (trx) => new ObjectionFactory(builders, {}, trx),\n * }\n * );\n *\n * // Use in tests - both trx and factory are available\n * it('should create user with factory', async ({ trx, factory }) => {\n * const user = await factory.insert('user', { name: 'Test User' });\n * expect(user.id).toBeDefined();\n *\n * // Verify in database\n * const found = await User.query(trx).findById(user.id);\n * expect(found?.name).toBe('Test User');\n * });\n * ```\n */\nexport function extendWithFixtures<\n Extended extends Record<string, unknown>,\n T extends ReturnType<TestAPI['extend']> = ReturnType<TestAPI['extend']>,\n>(wrappedTest: T, fixtures: FixtureCreators<Knex.Transaction, Extended>) {\n return baseExtendWithFixtures<Knex.Transaction, Extended, T>(\n wrappedTest,\n fixtures,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4FA,SAAgB,+BAEdA,KAAcC,SAAgD;CAC9D,MAAM,UAAU,IAAIC,8EAAmC;AAEvD,QAAO,QAAQ,0BAA0B,QAAQ;AAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDD,SAAgBC,qBAGdC,aAAgBC,UAAuD;AACvE,QAAO,qDACL,aACA,SACD;AACF"}
@@ -1,6 +1,6 @@
1
- import { FakerFactory, faker } from "./faker-Dg3trU4a.cjs";
2
- import "./Factory-D7oHtI2D.cjs";
3
- import { ObjectionFactory } from "./ObjectionFactory-0gUdx8bB.cjs";
1
+ import { FakerFactory, faker } from "./faker-CbYiF-8_.cjs";
2
+ import { ExtractSeedAttrs, FactorySeed } from "./Factory-IdfEkOeT.cjs";
3
+ import { ObjectionFactory } from "./ObjectionFactory-BRAkAByP.cjs";
4
4
  import "./PostgresMigrator-D5UkK1_K.cjs";
5
5
  import { PostgresObjectionMigrator } from "./PostgresObjectionMigrator-CZHHcCOv.cjs";
6
6
  import { DatabaseConnection, DatabaseFixtures, ExtendedDatabaseFixtures, FixtureCreators, IsolationLevel, TestWithExtendedFixtures, TransactionWrapperOptions } from "./VitestTransactionIsolator-CwQaxZLP.cjs";
@@ -118,5 +118,5 @@ declare function wrapVitestObjectionTransaction<Extended extends Record<string,
118
118
  */
119
119
  declare function extendWithFixtures<Extended extends Record<string, unknown>, T extends ReturnType<TestAPI['extend']> = ReturnType<TestAPI['extend']>>(wrappedTest: T, fixtures: FixtureCreators<Knex.Transaction, Extended>): TestWithExtendedFixtures<Knex.Transaction<any, any[]>, Extended, T>;
120
120
  //#endregion
121
- export { DatabaseFixtures, ExtendedDatabaseFixtures, FakerFactory, FixtureCreators, IsolationLevel, ObjectionFactory, ObjectionTransactionOptions, PostgresObjectionMigrator, TestWithExtendedFixtures, TransactionWrapperOptions, VitestObjectionTransactionIsolator, extendWithFixtures, faker, wrapVitestObjectionTransaction };
121
+ export { DatabaseFixtures, ExtendedDatabaseFixtures, ExtractSeedAttrs, FactorySeed, FakerFactory, FixtureCreators, IsolationLevel, ObjectionFactory, ObjectionTransactionOptions, PostgresObjectionMigrator, TestWithExtendedFixtures, TransactionWrapperOptions, VitestObjectionTransactionIsolator, extendWithFixtures, faker, wrapVitestObjectionTransaction };
122
122
  //# sourceMappingURL=objection.d.cts.map
@@ -1,6 +1,6 @@
1
1
  import { FakerFactory, faker } from "./faker-DHh7xs4u.mjs";
2
- import "./Factory-Cmr3s3-s.mjs";
3
- import { ObjectionFactory } from "./ObjectionFactory-BagGjikT.mjs";
2
+ import { ExtractSeedAttrs, FactorySeed } from "./Factory-BcGJjLc8.mjs";
3
+ import { ObjectionFactory } from "./ObjectionFactory-DL4qkuF1.mjs";
4
4
  import "./PostgresMigrator-DQaRxoaY.mjs";
5
5
  import { PostgresObjectionMigrator } from "./PostgresObjectionMigrator-D_hCcrQu.mjs";
6
6
  import { DatabaseConnection, DatabaseFixtures, ExtendedDatabaseFixtures, FixtureCreators, IsolationLevel, TestWithExtendedFixtures, TransactionWrapperOptions } from "./VitestTransactionIsolator-BvR19bYn.mjs";
@@ -118,5 +118,5 @@ declare function wrapVitestObjectionTransaction<Extended extends Record<string,
118
118
  */
119
119
  declare function extendWithFixtures<Extended extends Record<string, unknown>, T extends ReturnType<TestAPI['extend']> = ReturnType<TestAPI['extend']>>(wrappedTest: T, fixtures: FixtureCreators<Knex.Transaction, Extended>): TestWithExtendedFixtures<Knex.Transaction<any, any[]>, Extended, T>;
120
120
  //#endregion
121
- export { DatabaseFixtures, ExtendedDatabaseFixtures, FakerFactory, FixtureCreators, IsolationLevel, ObjectionFactory, ObjectionTransactionOptions, PostgresObjectionMigrator, TestWithExtendedFixtures, TransactionWrapperOptions, VitestObjectionTransactionIsolator, extendWithFixtures, faker, wrapVitestObjectionTransaction };
121
+ export { DatabaseFixtures, ExtendedDatabaseFixtures, ExtractSeedAttrs, FactorySeed, FakerFactory, FixtureCreators, IsolationLevel, ObjectionFactory, ObjectionTransactionOptions, PostgresObjectionMigrator, TestWithExtendedFixtures, TransactionWrapperOptions, VitestObjectionTransactionIsolator, extendWithFixtures, faker, wrapVitestObjectionTransaction };
122
122
  //# sourceMappingURL=objection.d.mts.map
@@ -1,6 +1,6 @@
1
- import "./Factory-z2m01hMj.mjs";
1
+ import "./Factory-BFVnMMCC.mjs";
2
2
  import { faker } from "./faker-BGKYFoCT.mjs";
3
- import { ObjectionFactory } from "./ObjectionFactory-zf2fLKrL.mjs";
3
+ import { ObjectionFactory } from "./ObjectionFactory-QCJ7u0Ql.mjs";
4
4
  import "./PostgresMigrator-DbuJGAVy.mjs";
5
5
  import { PostgresObjectionMigrator } from "./PostgresObjectionMigrator-DPj2pOpX.mjs";
6
6
  import { IsolationLevel, extendWithFixtures } from "./VitestTransactionIsolator-DQ7tLqgV.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"objection.mjs","names":["api: TestAPI","options: ObjectionTransactionOptions<Extended>","extendWithFixtures","wrappedTest: T","fixtures: FixtureCreators<Knex.Transaction, Extended>"],"sources":["../src/objection.ts"],"sourcesContent":["import type { Knex } from 'knex';\nimport type { TestAPI } from 'vitest';\nimport { VitestObjectionTransactionIsolator } from './VitestObjectionTransactionIsolator';\nimport {\n type DatabaseConnection,\n type FixtureCreators,\n type IsolationLevel,\n extendWithFixtures as baseExtendWithFixtures,\n} from './VitestTransactionIsolator';\n\n/**\n * Objection.js-specific exports for test utilities.\n * Provides factory implementation for creating test data with Objection.js ORM\n * and transaction isolation for test suites.\n */\n\nexport { ObjectionFactory } from './ObjectionFactory';\nexport { VitestObjectionTransactionIsolator } from './VitestObjectionTransactionIsolator';\nexport { IsolationLevel } from './VitestTransactionIsolator';\nexport { PostgresObjectionMigrator } from './PostgresObjectionMigrator';\nexport type {\n DatabaseFixtures,\n ExtendedDatabaseFixtures,\n FixtureCreators,\n TestWithExtendedFixtures,\n TransactionWrapperOptions,\n} from './VitestTransactionIsolator';\n\n/**\n * Objection.js-specific options for transaction wrapping.\n */\nexport interface ObjectionTransactionOptions<\n Extended extends Record<string, unknown> = {},\n> {\n /** Function that creates or returns a Knex database connection */\n connection: DatabaseConnection<Knex>;\n /** Optional setup function to run within the transaction before each test */\n setup?: (trx: Knex.Transaction) => Promise<void>;\n /** Transaction isolation level (defaults to REPEATABLE_READ) */\n isolationLevel?: IsolationLevel;\n /** Additional fixtures that depend on the transaction */\n fixtures?: FixtureCreators<Knex.Transaction, Extended>;\n}\n\n// Re-export faker and FakerFactory for type portability in declaration files\nexport { faker, type FakerFactory } from './faker';\n\n/**\n * Creates a wrapped Vitest test API with automatic transaction rollback for Objection.js.\n * Each test runs in an isolated database transaction that is rolled back after completion.\n * This ensures tests don't affect each other's data and run faster than truncating tables.\n *\n * @template Extended - Additional fixtures to provide\n * @param api - The Vitest test API (usually `test` from vitest)\n * @param options - Configuration options for transaction wrapping\n * @returns A wrapped test API that provides transaction isolation\n *\n * @example\n * ```typescript\n * import { test } from 'vitest';\n * import { wrapVitestObjectionTransaction } from '@geekmidas/testkit/objection';\n * import { knex } from './database';\n * import { User } from './models';\n *\n * // Create isolated test with automatic rollback\n * const isolatedTest = wrapVitestObjectionTransaction(test, {\n * connection: knex,\n * });\n *\n * // Use in tests - each test gets its own transaction\n * isolatedTest('should create user', async ({ trx }) => {\n * const user = await User.query(trx)\n * .insert({ name: 'Test User', email: 'test@example.com' });\n *\n * expect(user).toBeDefined();\n * });\n *\n * // With fixtures for factories\n * const it = wrapVitestObjectionTransaction<{ factory: Factory }>(test, {\n * connection: knex,\n * fixtures: {\n * factory: (trx) => new Factory(trx),\n * },\n * });\n *\n * it('should create user with factory', async ({ trx, factory }) => {\n * const user = await factory.insert('user', { name: 'Test' });\n * expect(user.id).toBeDefined();\n * });\n * ```\n */\nexport function wrapVitestObjectionTransaction<\n Extended extends Record<string, unknown> = {},\n>(api: TestAPI, options: ObjectionTransactionOptions<Extended>) {\n const wrapper = new VitestObjectionTransactionIsolator(api);\n\n return wrapper.wrapVitestWithTransaction(options);\n}\n\n/**\n * Extends an Objection.js transaction-wrapped test with additional fixtures.\n * Each fixture receives the transaction and can create dependencies like factories or repositories.\n *\n * @template Extended - The type of additional fixtures to provide\n * @param wrappedTest - The base wrapped test from wrapVitestObjectionTransaction\n * @param fixtures - Object mapping fixture names to creator functions\n * @returns An extended test API with both trx and the additional fixtures\n *\n * @example\n * ```typescript\n * import { test } from 'vitest';\n * import { wrapVitestObjectionTransaction, extendWithFixtures, ObjectionFactory } from '@geekmidas/testkit/objection';\n * import { User } from './models';\n *\n * // Define your builders\n * const builders = {\n * user: ObjectionFactory.createBuilder(User, ({ faker }) => ({\n * name: faker.person.fullName(),\n * email: faker.internet.email(),\n * })),\n * };\n *\n * // Create base wrapped test\n * const baseTest = wrapVitestObjectionTransaction(test, {\n * connection: knex,\n * setup: createTestTables,\n * });\n *\n * // Extend with fixtures - each fixture receives the transaction\n * const it = extendWithFixtures<{ factory: ObjectionFactory<typeof builders, {}> }>(\n * baseTest,\n * {\n * factory: (trx) => new ObjectionFactory(builders, {}, trx),\n * }\n * );\n *\n * // Use in tests - both trx and factory are available\n * it('should create user with factory', async ({ trx, factory }) => {\n * const user = await factory.insert('user', { name: 'Test User' });\n * expect(user.id).toBeDefined();\n *\n * // Verify in database\n * const found = await User.query(trx).findById(user.id);\n * expect(found?.name).toBe('Test User');\n * });\n * ```\n */\nexport function extendWithFixtures<\n Extended extends Record<string, unknown>,\n T extends ReturnType<TestAPI['extend']> = ReturnType<TestAPI['extend']>,\n>(wrappedTest: T, fixtures: FixtureCreators<Knex.Transaction, Extended>) {\n return baseExtendWithFixtures<Knex.Transaction, Extended, T>(\n wrappedTest,\n fixtures,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FA,SAAgB,+BAEdA,KAAcC,SAAgD;CAC9D,MAAM,UAAU,IAAI,mCAAmC;AAEvD,QAAO,QAAQ,0BAA0B,QAAQ;AAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDD,SAAgBC,qBAGdC,aAAgBC,UAAuD;AACvE,QAAO,mBACL,aACA,SACD;AACF"}
1
+ {"version":3,"file":"objection.mjs","names":["api: TestAPI","options: ObjectionTransactionOptions<Extended>","extendWithFixtures","wrappedTest: T","fixtures: FixtureCreators<Knex.Transaction, Extended>"],"sources":["../src/objection.ts"],"sourcesContent":["import type { Knex } from 'knex';\nimport type { TestAPI } from 'vitest';\nimport { VitestObjectionTransactionIsolator } from './VitestObjectionTransactionIsolator';\nimport {\n type DatabaseConnection,\n type FixtureCreators,\n type IsolationLevel,\n extendWithFixtures as baseExtendWithFixtures,\n} from './VitestTransactionIsolator';\n\n/**\n * Objection.js-specific exports for test utilities.\n * Provides factory implementation for creating test data with Objection.js ORM\n * and transaction isolation for test suites.\n */\n\nexport { ObjectionFactory } from './ObjectionFactory';\nexport type { ExtractSeedAttrs, FactorySeed } from './Factory';\nexport { VitestObjectionTransactionIsolator } from './VitestObjectionTransactionIsolator';\nexport { IsolationLevel } from './VitestTransactionIsolator';\nexport { PostgresObjectionMigrator } from './PostgresObjectionMigrator';\nexport type {\n DatabaseFixtures,\n ExtendedDatabaseFixtures,\n FixtureCreators,\n TestWithExtendedFixtures,\n TransactionWrapperOptions,\n} from './VitestTransactionIsolator';\n\n/**\n * Objection.js-specific options for transaction wrapping.\n */\nexport interface ObjectionTransactionOptions<\n Extended extends Record<string, unknown> = {},\n> {\n /** Function that creates or returns a Knex database connection */\n connection: DatabaseConnection<Knex>;\n /** Optional setup function to run within the transaction before each test */\n setup?: (trx: Knex.Transaction) => Promise<void>;\n /** Transaction isolation level (defaults to REPEATABLE_READ) */\n isolationLevel?: IsolationLevel;\n /** Additional fixtures that depend on the transaction */\n fixtures?: FixtureCreators<Knex.Transaction, Extended>;\n}\n\n// Re-export faker and FakerFactory for type portability in declaration files\nexport { faker, type FakerFactory } from './faker';\n\n/**\n * Creates a wrapped Vitest test API with automatic transaction rollback for Objection.js.\n * Each test runs in an isolated database transaction that is rolled back after completion.\n * This ensures tests don't affect each other's data and run faster than truncating tables.\n *\n * @template Extended - Additional fixtures to provide\n * @param api - The Vitest test API (usually `test` from vitest)\n * @param options - Configuration options for transaction wrapping\n * @returns A wrapped test API that provides transaction isolation\n *\n * @example\n * ```typescript\n * import { test } from 'vitest';\n * import { wrapVitestObjectionTransaction } from '@geekmidas/testkit/objection';\n * import { knex } from './database';\n * import { User } from './models';\n *\n * // Create isolated test with automatic rollback\n * const isolatedTest = wrapVitestObjectionTransaction(test, {\n * connection: knex,\n * });\n *\n * // Use in tests - each test gets its own transaction\n * isolatedTest('should create user', async ({ trx }) => {\n * const user = await User.query(trx)\n * .insert({ name: 'Test User', email: 'test@example.com' });\n *\n * expect(user).toBeDefined();\n * });\n *\n * // With fixtures for factories\n * const it = wrapVitestObjectionTransaction<{ factory: Factory }>(test, {\n * connection: knex,\n * fixtures: {\n * factory: (trx) => new Factory(trx),\n * },\n * });\n *\n * it('should create user with factory', async ({ trx, factory }) => {\n * const user = await factory.insert('user', { name: 'Test' });\n * expect(user.id).toBeDefined();\n * });\n * ```\n */\nexport function wrapVitestObjectionTransaction<\n Extended extends Record<string, unknown> = {},\n>(api: TestAPI, options: ObjectionTransactionOptions<Extended>) {\n const wrapper = new VitestObjectionTransactionIsolator(api);\n\n return wrapper.wrapVitestWithTransaction(options);\n}\n\n/**\n * Extends an Objection.js transaction-wrapped test with additional fixtures.\n * Each fixture receives the transaction and can create dependencies like factories or repositories.\n *\n * @template Extended - The type of additional fixtures to provide\n * @param wrappedTest - The base wrapped test from wrapVitestObjectionTransaction\n * @param fixtures - Object mapping fixture names to creator functions\n * @returns An extended test API with both trx and the additional fixtures\n *\n * @example\n * ```typescript\n * import { test } from 'vitest';\n * import { wrapVitestObjectionTransaction, extendWithFixtures, ObjectionFactory } from '@geekmidas/testkit/objection';\n * import { User } from './models';\n *\n * // Define your builders\n * const builders = {\n * user: ObjectionFactory.createBuilder(User, ({ faker }) => ({\n * name: faker.person.fullName(),\n * email: faker.internet.email(),\n * })),\n * };\n *\n * // Create base wrapped test\n * const baseTest = wrapVitestObjectionTransaction(test, {\n * connection: knex,\n * setup: createTestTables,\n * });\n *\n * // Extend with fixtures - each fixture receives the transaction\n * const it = extendWithFixtures<{ factory: ObjectionFactory<typeof builders, {}> }>(\n * baseTest,\n * {\n * factory: (trx) => new ObjectionFactory(builders, {}, trx),\n * }\n * );\n *\n * // Use in tests - both trx and factory are available\n * it('should create user with factory', async ({ trx, factory }) => {\n * const user = await factory.insert('user', { name: 'Test User' });\n * expect(user.id).toBeDefined();\n *\n * // Verify in database\n * const found = await User.query(trx).findById(user.id);\n * expect(found?.name).toBe('Test User');\n * });\n * ```\n */\nexport function extendWithFixtures<\n Extended extends Record<string, unknown>,\n T extends ReturnType<TestAPI['extend']> = ReturnType<TestAPI['extend']>,\n>(wrappedTest: T, fixtures: FixtureCreators<Knex.Transaction, Extended>) {\n return baseExtendWithFixtures<Knex.Transaction, Extended, T>(\n wrappedTest,\n fixtures,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4FA,SAAgB,+BAEdA,KAAcC,SAAgD;CAC9D,MAAM,UAAU,IAAI,mCAAmC;AAEvD,QAAO,QAAQ,0BAA0B,QAAQ;AAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDD,SAAgBC,qBAGdC,aAAgBC,UAAuD;AACvE,QAAO,mBACL,aACA,SACD;AACF"}
@@ -1,2 +1,2 @@
1
- import { DirectoryFixtures, itWithDir } from "../directory-BUcnztHI.cjs";
1
+ import { DirectoryFixtures, itWithDir } from "../directory-Mi7tdOuD.cjs";
2
2
  export { DirectoryFixtures, itWithDir };
@@ -1,2 +1,2 @@
1
- import { itWithDir } from "../directory-BUcnztHI.cjs";
1
+ import { itWithDir } from "../directory-Mi7tdOuD.cjs";
2
2
  export { itWithDir };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekmidas/testkit",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -43,6 +43,11 @@
43
43
  "types": "./dist/better-auth.d.ts",
44
44
  "import": "./dist/better-auth.mjs",
45
45
  "require": "./dist/better-auth.cjs"
46
+ },
47
+ "./benchmark": {
48
+ "types": "./dist/benchmark.d.ts",
49
+ "import": "./dist/benchmark.mjs",
50
+ "require": "./dist/benchmark.cjs"
46
51
  }
47
52
  },
48
53
  "dependencies": {
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
  }
@@ -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
 
@@ -279,7 +279,10 @@ describe('KyselyFactory', () => {
279
279
 
280
280
  const seeds = {
281
281
  createAdminUser: KyselyFactory.createSeed(
282
- async (attrs: { name?: string }, factory: any, db: any) => {
282
+ async ({
283
+ attrs,
284
+ factory,
285
+ }: { attrs: { name?: string }; factory: any; db: any }) => {
283
286
  return await factory.insert('user', {
284
287
  name: attrs.name || 'Admin User',
285
288
  email: 'admin@example.com',
@@ -319,11 +322,14 @@ describe('KyselyFactory', () => {
319
322
 
320
323
  const seeds = {
321
324
  createCustomUser: KyselyFactory.createSeed(
322
- async (
323
- attrs: { name: string; email: string },
324
- factory: any,
325
- db: any,
326
- ) => {
325
+ async ({
326
+ attrs,
327
+ factory,
328
+ }: {
329
+ attrs: { name: string; email: string };
330
+ factory: any;
331
+ db: any;
332
+ }) => {
327
333
  return await factory.insert('user', attrs);
328
334
  },
329
335
  ),
@@ -216,20 +216,22 @@ describe('ObjectionFactory', () => {
216
216
 
217
217
  const builders = { user: userBuilder };
218
218
 
219
- const createAdminSeed = async (attrs: any, factory: any, db: Knex) => {
220
- return await factory.insert('user', {
221
- name: attrs.name || 'Admin User',
222
- });
223
- };
224
-
225
219
  const seeds = {
226
- 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
+ ),
227
230
  };
228
231
 
229
232
  const factory = new ObjectionFactory(builders, seeds, trx);
230
233
 
231
- const attrs = { name: 'Super Admin' };
232
- const result = await factory.seed('createAdmin', attrs);
234
+ const result = await factory.seed('createAdmin', { name: 'Super Admin' });
233
235
 
234
236
  expect(result).toBeInstanceOf(User);
235
237
  expect(result.name).toBe('Super Admin');
@@ -247,15 +249,15 @@ describe('ObjectionFactory', () => {
247
249
 
248
250
  const builders = { user: userBuilder };
249
251
 
250
- const createAdminSeed = async (attrs: any, factory: any, db: Knex) => {
251
- return await factory.insert('user', {
252
- name: 'Default Admin',
253
- role: 'admin',
254
- });
255
- };
256
-
257
252
  const seeds = {
258
- 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
+ ),
259
261
  };
260
262
 
261
263
  const factory = new ObjectionFactory(builders, seeds, trx);
@@ -283,25 +285,28 @@ describe('ObjectionFactory', () => {
283
285
 
284
286
  const builders = { user: userBuilder };
285
287
 
286
- const complexSeed = async (
287
- attrs: any,
288
- passedFactory: any,
289
- passedDb: Knex,
290
- ) => {
291
- // Verify that factory and db are passed correctly
292
- expect(passedFactory).toBe(factory);
293
- expect(passedDb).toBe(trx);
294
-
295
- return await passedFactory.insert('user', {
296
- name: `Complex ${attrs.data}`,
297
- });
298
- };
288
+ let factoryRef: any;
299
289
 
300
290
  const seeds = {
301
- 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
+ ),
302
306
  };
303
307
 
304
308
  const factory = new ObjectionFactory(builders, seeds, trx);
309
+ factoryRef = factory;
305
310
 
306
311
  const result = await factory.seed('complexSeed', { data: 'test' });
307
312
 
@@ -310,7 +315,7 @@ describe('ObjectionFactory', () => {
310
315
  });
311
316
 
312
317
  it('should return the seed function unchanged', () => {
313
- const seedFn = async (attrs: any, factory: any, db: any) => {
318
+ const seedFn = async ({ attrs }: { attrs: any; factory: any; db: any }) => {
314
319
  return { id: 1, name: 'test' };
315
320
  };
316
321
 
@@ -481,12 +486,12 @@ describe('ObjectionFactory', () => {
481
486
  });
482
487
 
483
488
  it('should handle seed function errors gracefully', async ({ trx }) => {
484
- const failingSeed = async (attrs: any, factory: any, db: Knex) => {
485
- throw new Error('Seed failed');
486
- };
487
-
488
489
  const seeds = {
489
- failingSeed,
490
+ failingSeed: ObjectionFactory.createSeed(
491
+ async ({}: { attrs: any; factory: any; db: Knex }) => {
492
+ throw new Error('Seed failed');
493
+ },
494
+ ),
490
495
  };
491
496
 
492
497
  const factory = new ObjectionFactory({}, seeds, trx);
@@ -508,18 +513,22 @@ describe('ObjectionFactory', () => {
508
513
  });
509
514
  };
510
515
 
511
- const adminSeed = async (
512
- attrs: { isSuper?: boolean },
513
- factory: any,
514
- db: Knex,
515
- ) => {
516
- return factory.insert('user', {
517
- name: 'Admin',
518
- });
519
- };
520
-
521
516
  const builders = { user: userBuilder };
522
- 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
+ };
523
532
 
524
533
  // This should compile without type errors
525
534
  const factory = new ObjectionFactory(builders, seeds, trx);
@@ -192,10 +192,14 @@ describe('Testkit Integration Tests', () => {
192
192
  // Create complex seeds
193
193
  const seeds = {
194
194
  blogWithAdminAndPosts: KyselyFactory.createSeed(
195
- async (
196
- attrs: { postCount?: number },
197
- factory: KyselyFactory<TestDatabase, typeof builders, {}>,
198
- ) => {
195
+ async ({
196
+ attrs,
197
+ factory,
198
+ }: {
199
+ attrs: { postCount?: number };
200
+ factory: KyselyFactory<TestDatabase, typeof builders, {}>;
201
+ db: any;
202
+ }) => {
199
203
  // Create admin user
200
204
  const admin = await factory.insert('user', {
201
205
  name: 'Blog Admin',
@@ -229,10 +233,14 @@ describe('Testkit Integration Tests', () => {
229
233
  ),
230
234
 
231
235
  usersWithPosts: KyselyFactory.createSeed(
232
- async (
233
- attrs: { userCount?: number; postsPerUser?: number },
234
- factory: KyselyFactory<TestDatabase, typeof builders, {}>,
235
- ) => {
236
+ async ({
237
+ attrs,
238
+ factory,
239
+ }: {
240
+ attrs: { userCount?: number; postsPerUser?: number };
241
+ factory: KyselyFactory<TestDatabase, typeof builders, {}>;
242
+ db: any;
243
+ }) => {
236
244
  const userCount = attrs.userCount || 2;
237
245
  const postsPerUser = attrs.postsPerUser || 2;
238
246
 
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Generates an array of test records for benchmark data sets.
3
+ *
4
+ * @param count - Number of records to generate
5
+ * @returns Array of test data objects
6
+ */
7
+ export function generateTestData(
8
+ count: number,
9
+ ): Array<{ id: string; name: string; value: number }> {
10
+ return Array.from({ length: count }, (_, i) => ({
11
+ id: `id-${i}`,
12
+ name: `Item ${i}`,
13
+ value: Math.random() * 1000,
14
+ }));
15
+ }
16
+
17
+ /**
18
+ * Generates unique keys for cache benchmarks to avoid collisions.
19
+ *
20
+ * @param prefix - Key prefix
21
+ * @param count - Number of keys to generate
22
+ * @returns Array of unique cache keys
23
+ */
24
+ export function generateCacheKeys(prefix: string, count: number): string[] {
25
+ return Array.from({ length: count }, (_, i) => `${prefix}:${i}`);
26
+ }
27
+
28
+ /**
29
+ * Generates IP addresses for rate limit benchmarks.
30
+ *
31
+ * @param count - Number of IPs to generate
32
+ * @param subnet - Subnet prefix (default: '192.168.1')
33
+ * @returns Array of IP addresses
34
+ */
35
+ export function generateIpAddresses(
36
+ count: number,
37
+ subnet: string = '192.168.1',
38
+ ): string[] {
39
+ return Array.from({ length: count }, (_, i) => `${subnet}.${i % 256}`);
40
+ }
41
+
42
+ /**
43
+ * Creates a random IP address for rate limit benchmarks.
44
+ */
45
+ export function randomIpAddress(): string {
46
+ const octet = () => Math.floor(Math.random() * 256);
47
+ return `${octet()}.${octet()}.${octet()}.${octet()}`;
48
+ }
package/src/kysely.ts CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  */
15
15
 
16
16
  export { KyselyFactory } from './KyselyFactory';
17
+ export type { ExtractSeedAttrs, FactorySeed } from './Factory';
17
18
  export { PostgresKyselyMigrator } from './PostgresKyselyMigrator';
18
19
  export { VitestKyselyTransactionIsolator } from './VitestKyselyTransactionIsolator';
19
20
  export { IsolationLevel } from './VitestTransactionIsolator';