@geekmidas/testkit 10.0.0-alpha.2 → 10.0.0-alpha.20

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 (262) hide show
  1. package/dist/Factory.cjs +51 -2
  2. package/dist/Factory.cjs.map +1 -0
  3. package/dist/Factory.d.cts +143 -3
  4. package/dist/Factory.d.cts.map +1 -0
  5. package/dist/Factory.d.mts +143 -3
  6. package/dist/Factory.d.mts.map +1 -0
  7. package/dist/Factory.mjs +50 -2
  8. package/dist/Factory.mjs.map +1 -0
  9. package/dist/KyselyFactory.cjs +237 -4
  10. package/dist/KyselyFactory.cjs.map +1 -0
  11. package/dist/KyselyFactory.d.cts +224 -4
  12. package/dist/KyselyFactory.d.cts.map +1 -0
  13. package/dist/KyselyFactory.d.mts +224 -4
  14. package/dist/KyselyFactory.d.mts.map +1 -0
  15. package/dist/KyselyFactory.mjs +236 -4
  16. package/dist/KyselyFactory.mjs.map +1 -0
  17. package/dist/ObjectionFactory.cjs +265 -4
  18. package/dist/ObjectionFactory.cjs.map +1 -0
  19. package/dist/ObjectionFactory.d.cts +237 -4
  20. package/dist/ObjectionFactory.d.cts.map +1 -0
  21. package/dist/ObjectionFactory.d.mts +237 -4
  22. package/dist/ObjectionFactory.d.mts.map +1 -0
  23. package/dist/ObjectionFactory.mjs +264 -4
  24. package/dist/ObjectionFactory.mjs.map +1 -0
  25. package/dist/PostgresKyselyMigrator.cjs +94 -3
  26. package/dist/PostgresKyselyMigrator.cjs.map +1 -0
  27. package/dist/PostgresKyselyMigrator.d.cts +80 -3
  28. package/dist/PostgresKyselyMigrator.d.cts.map +1 -0
  29. package/dist/PostgresKyselyMigrator.d.mts +80 -3
  30. package/dist/PostgresKyselyMigrator.d.mts.map +1 -0
  31. package/dist/PostgresKyselyMigrator.mjs +93 -3
  32. package/dist/PostgresKyselyMigrator.mjs.map +1 -0
  33. package/dist/{PostgresMigrator-C_QQ6q35.d.mts → PostgresMigrator-CDPnnwMJ.d.cts} +11 -5
  34. package/dist/PostgresMigrator-CDPnnwMJ.d.cts.map +1 -0
  35. package/dist/{PostgresMigrator-CeYy-eHF.d.cts → PostgresMigrator-CDPnnwMJ.d.mts} +11 -5
  36. package/dist/PostgresMigrator-CDPnnwMJ.d.mts.map +1 -0
  37. package/dist/PostgresMigrator.cjs +178 -2
  38. package/dist/PostgresMigrator.cjs.map +1 -0
  39. package/dist/PostgresMigrator.d.cts +1 -1
  40. package/dist/PostgresMigrator.d.mts +1 -1
  41. package/dist/PostgresMigrator.mjs +175 -2
  42. package/dist/PostgresMigrator.mjs.map +1 -0
  43. package/dist/PostgresObjectionMigrator.cjs +118 -3
  44. package/dist/PostgresObjectionMigrator.cjs.map +1 -0
  45. package/dist/PostgresObjectionMigrator.d.cts +75 -3
  46. package/dist/PostgresObjectionMigrator.d.cts.map +1 -0
  47. package/dist/PostgresObjectionMigrator.d.mts +75 -3
  48. package/dist/PostgresObjectionMigrator.d.mts.map +1 -0
  49. package/dist/PostgresObjectionMigrator.mjs +117 -3
  50. package/dist/PostgresObjectionMigrator.mjs.map +1 -0
  51. package/dist/VitestKyselyTransactionIsolator.cjs +66 -3
  52. package/dist/VitestKyselyTransactionIsolator.cjs.map +1 -0
  53. package/dist/VitestKyselyTransactionIsolator.d.cts +60 -3
  54. package/dist/VitestKyselyTransactionIsolator.d.cts.map +1 -0
  55. package/dist/VitestKyselyTransactionIsolator.d.mts +60 -3
  56. package/dist/VitestKyselyTransactionIsolator.d.mts.map +1 -0
  57. package/dist/VitestKyselyTransactionIsolator.mjs +65 -3
  58. package/dist/VitestKyselyTransactionIsolator.mjs.map +1 -0
  59. package/dist/VitestObjectionTransactionIsolator.cjs +62 -3
  60. package/dist/VitestObjectionTransactionIsolator.cjs.map +1 -0
  61. package/dist/VitestObjectionTransactionIsolator.d.cts +56 -3
  62. package/dist/VitestObjectionTransactionIsolator.d.cts.map +1 -0
  63. package/dist/VitestObjectionTransactionIsolator.d.mts +56 -3
  64. package/dist/VitestObjectionTransactionIsolator.d.mts.map +1 -0
  65. package/dist/VitestObjectionTransactionIsolator.mjs +61 -3
  66. package/dist/VitestObjectionTransactionIsolator.mjs.map +1 -0
  67. package/dist/VitestTransactionIsolator.cjs +187 -4
  68. package/dist/VitestTransactionIsolator.cjs.map +1 -0
  69. package/dist/VitestTransactionIsolator.d.cts +219 -2
  70. package/dist/VitestTransactionIsolator.d.cts.map +1 -0
  71. package/dist/VitestTransactionIsolator.d.mts +219 -2
  72. package/dist/VitestTransactionIsolator.d.mts.map +1 -0
  73. package/dist/VitestTransactionIsolator.mjs +184 -2
  74. package/dist/VitestTransactionIsolator.mjs.map +1 -0
  75. package/dist/aws.cjs +3 -4
  76. package/dist/aws.cjs.map +1 -1
  77. package/dist/aws.d.cts +3 -8
  78. package/dist/aws.d.cts.map +1 -1
  79. package/dist/aws.d.mts +3 -8
  80. package/dist/aws.d.mts.map +1 -1
  81. package/dist/aws.mjs +1 -2
  82. package/dist/aws.mjs.map +1 -1
  83. package/dist/benchmark.cjs +2 -2
  84. package/dist/benchmark.cjs.map +1 -1
  85. package/dist/benchmark.d.cts +4 -6
  86. package/dist/benchmark.d.cts.map +1 -1
  87. package/dist/benchmark.d.mts +4 -6
  88. package/dist/benchmark.d.mts.map +1 -1
  89. package/dist/benchmark.mjs +1 -1
  90. package/dist/benchmark.mjs.map +1 -1
  91. package/dist/better-auth.cjs +31 -15
  92. package/dist/better-auth.cjs.map +1 -1
  93. package/dist/better-auth.d.cts +13142 -4
  94. package/dist/better-auth.d.cts.map +1 -1
  95. package/dist/better-auth.d.mts +13142 -4
  96. package/dist/better-auth.d.mts.map +1 -1
  97. package/dist/better-auth.mjs +29 -13
  98. package/dist/better-auth.mjs.map +1 -1
  99. package/dist/faker.cjs +262 -8
  100. package/dist/faker.cjs.map +1 -0
  101. package/dist/faker.d.cts +162 -2
  102. package/dist/faker.d.cts.map +1 -0
  103. package/dist/faker.d.mts +162 -2
  104. package/dist/faker.d.mts.map +1 -0
  105. package/dist/faker.mjs +255 -2
  106. package/dist/faker.mjs.map +1 -0
  107. package/dist/helpers.cjs +6 -5
  108. package/dist/helpers.cjs.map +1 -1
  109. package/dist/helpers.d.cts +1 -5
  110. package/dist/helpers.d.cts.map +1 -1
  111. package/dist/helpers.d.mts +1 -5
  112. package/dist/helpers.d.mts.map +1 -1
  113. package/dist/helpers.mjs +1 -2
  114. package/dist/helpers.mjs.map +1 -1
  115. package/dist/initScript.cjs +15 -15
  116. package/dist/initScript.cjs.map +1 -1
  117. package/dist/initScript.d.cts +2 -4
  118. package/dist/initScript.d.cts.map +1 -1
  119. package/dist/initScript.d.mts +2 -4
  120. package/dist/initScript.d.mts.map +1 -1
  121. package/dist/initScript.mjs +10 -12
  122. package/dist/initScript.mjs.map +1 -1
  123. package/dist/kysely.cjs +10 -13
  124. package/dist/kysely.cjs.map +1 -1
  125. package/dist/kysely.d.cts +10 -14
  126. package/dist/kysely.d.cts.map +1 -1
  127. package/dist/kysely.d.mts +10 -14
  128. package/dist/kysely.d.mts.map +1 -1
  129. package/dist/kysely.mjs +10 -14
  130. package/dist/kysely.mjs.map +1 -1
  131. package/dist/logger.cjs +3 -4
  132. package/dist/logger.cjs.map +1 -1
  133. package/dist/logger.d.cts +1 -5
  134. package/dist/logger.d.cts.map +1 -1
  135. package/dist/logger.d.mts +1 -5
  136. package/dist/logger.d.mts.map +1 -1
  137. package/dist/logger.mjs +1 -2
  138. package/dist/logger.mjs.map +1 -1
  139. package/dist/objection.cjs +10 -13
  140. package/dist/objection.cjs.map +1 -1
  141. package/dist/objection.d.cts +10 -14
  142. package/dist/objection.d.cts.map +1 -1
  143. package/dist/objection.d.mts +10 -14
  144. package/dist/objection.d.mts.map +1 -1
  145. package/dist/objection.mjs +10 -14
  146. package/dist/objection.mjs.map +1 -1
  147. package/dist/os/directory.cjs +31 -2
  148. package/dist/os/directory.cjs.map +1 -0
  149. package/dist/os/directory.d.cts +9 -2
  150. package/dist/os/directory.d.cts.map +1 -0
  151. package/dist/os/directory.d.mts +9 -2
  152. package/dist/os/directory.d.mts.map +1 -0
  153. package/dist/os/directory.mjs +25 -2
  154. package/dist/os/directory.mjs.map +1 -0
  155. package/dist/os/index.cjs +3 -3
  156. package/dist/os/index.d.cts +1 -1
  157. package/dist/os/index.d.mts +1 -1
  158. package/dist/os/index.mjs +2 -3
  159. package/dist/requestContext.cjs +10 -11
  160. package/dist/requestContext.cjs.map +1 -1
  161. package/dist/requestContext.d.cts +4 -8
  162. package/dist/requestContext.d.cts.map +1 -1
  163. package/dist/requestContext.d.mts +4 -8
  164. package/dist/requestContext.d.mts.map +1 -1
  165. package/dist/requestContext.mjs +1 -2
  166. package/dist/requestContext.mjs.map +1 -1
  167. package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-VH7oDXx4.cjs} +8 -10
  168. package/dist/timer.cjs +2 -2
  169. package/dist/timer.cjs.map +1 -1
  170. package/dist/timer.d.cts +1 -4
  171. package/dist/timer.d.cts.map +1 -1
  172. package/dist/timer.d.mts +1 -4
  173. package/dist/timer.d.mts.map +1 -1
  174. package/dist/timer.mjs +1 -1
  175. package/dist/timer.mjs.map +1 -1
  176. package/package.json +18 -16
  177. package/dist/Factory-BFVnMMCC.mjs +0 -51
  178. package/dist/Factory-BFVnMMCC.mjs.map +0 -1
  179. package/dist/Factory-BhjUOBWN.cjs +0 -57
  180. package/dist/Factory-BhjUOBWN.cjs.map +0 -1
  181. package/dist/Factory-CVR3GdkW.d.mts +0 -147
  182. package/dist/Factory-CVR3GdkW.d.mts.map +0 -1
  183. package/dist/Factory-Cwzho3c8.d.cts +0 -147
  184. package/dist/Factory-Cwzho3c8.d.cts.map +0 -1
  185. package/dist/KyselyFactory-BFqVIn_0.cjs +0 -246
  186. package/dist/KyselyFactory-BFqVIn_0.cjs.map +0 -1
  187. package/dist/KyselyFactory-DMswpwji.mjs +0 -241
  188. package/dist/KyselyFactory-DMswpwji.mjs.map +0 -1
  189. package/dist/KyselyFactory-DRlMv-WT.d.mts +0 -228
  190. package/dist/KyselyFactory-DRlMv-WT.d.mts.map +0 -1
  191. package/dist/KyselyFactory-hMcVtvJq.d.cts +0 -228
  192. package/dist/KyselyFactory-hMcVtvJq.d.cts.map +0 -1
  193. package/dist/ObjectionFactory-BeFBYcan.cjs +0 -272
  194. package/dist/ObjectionFactory-BeFBYcan.cjs.map +0 -1
  195. package/dist/ObjectionFactory-DW-qwnqO.d.cts +0 -241
  196. package/dist/ObjectionFactory-DW-qwnqO.d.cts.map +0 -1
  197. package/dist/ObjectionFactory-DkJUf-uM.d.mts +0 -241
  198. package/dist/ObjectionFactory-DkJUf-uM.d.mts.map +0 -1
  199. package/dist/ObjectionFactory-QCJ7u0Ql.mjs +0 -267
  200. package/dist/ObjectionFactory-QCJ7u0Ql.mjs.map +0 -1
  201. package/dist/PostgresKyselyMigrator-B2M6Gjvv.d.cts +0 -84
  202. package/dist/PostgresKyselyMigrator-B2M6Gjvv.d.cts.map +0 -1
  203. package/dist/PostgresKyselyMigrator-BGBxjnFv.cjs +0 -101
  204. package/dist/PostgresKyselyMigrator-BGBxjnFv.cjs.map +0 -1
  205. package/dist/PostgresKyselyMigrator-CvwXycJE.d.mts +0 -84
  206. package/dist/PostgresKyselyMigrator-CvwXycJE.d.mts.map +0 -1
  207. package/dist/PostgresKyselyMigrator-PI0QhvB1.mjs +0 -95
  208. package/dist/PostgresKyselyMigrator-PI0QhvB1.mjs.map +0 -1
  209. package/dist/PostgresMigrator-C_QQ6q35.d.mts.map +0 -1
  210. package/dist/PostgresMigrator-CeYy-eHF.d.cts.map +0 -1
  211. package/dist/PostgresMigrator-DVAY04qN.mjs +0 -166
  212. package/dist/PostgresMigrator-DVAY04qN.mjs.map +0 -1
  213. package/dist/PostgresMigrator-M9jpzOvN.cjs +0 -172
  214. package/dist/PostgresMigrator-M9jpzOvN.cjs.map +0 -1
  215. package/dist/PostgresObjectionMigrator-1j6YIB1c.d.mts +0 -79
  216. package/dist/PostgresObjectionMigrator-1j6YIB1c.d.mts.map +0 -1
  217. package/dist/PostgresObjectionMigrator-DHVC9h_P.d.cts +0 -79
  218. package/dist/PostgresObjectionMigrator-DHVC9h_P.d.cts.map +0 -1
  219. package/dist/PostgresObjectionMigrator-DSaPhwjY.cjs +0 -123
  220. package/dist/PostgresObjectionMigrator-DSaPhwjY.cjs.map +0 -1
  221. package/dist/PostgresObjectionMigrator-DjPKdUbm.mjs +0 -118
  222. package/dist/PostgresObjectionMigrator-DjPKdUbm.mjs.map +0 -1
  223. package/dist/VitestKyselyTransactionIsolator-1Saieke7.mjs +0 -67
  224. package/dist/VitestKyselyTransactionIsolator-1Saieke7.mjs.map +0 -1
  225. package/dist/VitestKyselyTransactionIsolator-BjJSXryR.cjs +0 -72
  226. package/dist/VitestKyselyTransactionIsolator-BjJSXryR.cjs.map +0 -1
  227. package/dist/VitestKyselyTransactionIsolator-CwlTo6yf.d.mts +0 -64
  228. package/dist/VitestKyselyTransactionIsolator-CwlTo6yf.d.mts.map +0 -1
  229. package/dist/VitestKyselyTransactionIsolator-DJasVuIZ.d.cts +0 -64
  230. package/dist/VitestKyselyTransactionIsolator-DJasVuIZ.d.cts.map +0 -1
  231. package/dist/VitestObjectionTransactionIsolator-B_VSWFum.mjs +0 -63
  232. package/dist/VitestObjectionTransactionIsolator-B_VSWFum.mjs.map +0 -1
  233. package/dist/VitestObjectionTransactionIsolator-CTTjvTPO.d.cts +0 -60
  234. package/dist/VitestObjectionTransactionIsolator-CTTjvTPO.d.cts.map +0 -1
  235. package/dist/VitestObjectionTransactionIsolator-CyZG6nq4.d.mts +0 -60
  236. package/dist/VitestObjectionTransactionIsolator-CyZG6nq4.d.mts.map +0 -1
  237. package/dist/VitestObjectionTransactionIsolator-DDoJTu7e.cjs +0 -68
  238. package/dist/VitestObjectionTransactionIsolator-DDoJTu7e.cjs.map +0 -1
  239. package/dist/VitestTransactionIsolator-BLaw80cx.d.mts +0 -223
  240. package/dist/VitestTransactionIsolator-BLaw80cx.d.mts.map +0 -1
  241. package/dist/VitestTransactionIsolator-CvwPecpl.mjs +0 -188
  242. package/dist/VitestTransactionIsolator-CvwPecpl.mjs.map +0 -1
  243. package/dist/VitestTransactionIsolator-DyiX-QtK.cjs +0 -206
  244. package/dist/VitestTransactionIsolator-DyiX-QtK.cjs.map +0 -1
  245. package/dist/VitestTransactionIsolator-glcxyS_R.d.cts +0 -223
  246. package/dist/VitestTransactionIsolator-glcxyS_R.d.cts.map +0 -1
  247. package/dist/directory-BxjqmtCT.mjs +0 -27
  248. package/dist/directory-BxjqmtCT.mjs.map +0 -1
  249. package/dist/directory-C6DuuNyc.d.cts +0 -13
  250. package/dist/directory-C6DuuNyc.d.cts.map +0 -1
  251. package/dist/directory-DD_xQoSh.cjs +0 -33
  252. package/dist/directory-DD_xQoSh.cjs.map +0 -1
  253. package/dist/directory-DiQ_DkaF.d.mts +0 -13
  254. package/dist/directory-DiQ_DkaF.d.mts.map +0 -1
  255. package/dist/faker-B14IEMIN.cjs +0 -304
  256. package/dist/faker-B14IEMIN.cjs.map +0 -1
  257. package/dist/faker-BGKYFoCT.mjs +0 -262
  258. package/dist/faker-BGKYFoCT.mjs.map +0 -1
  259. package/dist/faker-Dg3trU4a.d.cts +0 -166
  260. package/dist/faker-Dg3trU4a.d.cts.map +0 -1
  261. package/dist/faker-DsYCplsG.d.mts +0 -166
  262. package/dist/faker-DsYCplsG.d.mts.map +0 -1
@@ -1,246 +0,0 @@
1
- const require_Factory = require('./Factory-BhjUOBWN.cjs');
2
- const require_faker = require('./faker-B14IEMIN.cjs');
3
-
4
- //#region src/KyselyFactory.ts
5
- /**
6
- * Factory implementation for Kysely ORM, providing test data creation utilities.
7
- * Extends the base Factory class with Kysely-specific database operations.
8
- *
9
- * @template DB - The database schema type
10
- * @template Builders - Record of builder functions for creating entities
11
- * @template Seeds - Record of seed functions for complex test scenarios
12
- *
13
- * @example
14
- * ```typescript
15
- * // Define your database schema
16
- * interface Database {
17
- * users: UsersTable;
18
- * posts: PostsTable;
19
- * }
20
- *
21
- * // Create builders
22
- * const builders = {
23
- * user: KyselyFactory.createBuilder<Database, 'users'>('users', ({ attrs, faker }) => ({
24
- * id: faker.string.uuid(),
25
- * name: faker.person.fullName(),
26
- * email: faker.internet.email(),
27
- * ...attrs
28
- * })),
29
- * post: KyselyFactory.createBuilder<Database, 'posts'>('posts', ({ attrs }) => ({
30
- * title: 'Test Post',
31
- * content: 'Test content',
32
- * ...attrs
33
- * }))
34
- * };
35
- *
36
- * // Create factory instance
37
- * const factory = new KyselyFactory(builders, seeds, db);
38
- *
39
- * // Use in tests
40
- * const user = await factory.insert('user', { name: 'John Doe' });
41
- * ```
42
- */
43
- var KyselyFactory = class extends require_Factory.Factory {
44
- /**
45
- * Creates a typed seed function with proper type inference.
46
- * Inherits from the base Factory class implementation.
47
- *
48
- * @template Seed - The seed function type
49
- * @param seedFn - The seed function to wrap (receives { attrs, factory, db } object)
50
- * @returns The same seed function with proper typing
51
- *
52
- * @example
53
- * ```typescript
54
- * const seeds = {
55
- * userWithPosts: KyselyFactory.createSeed(
56
- * async ({ attrs, factory }) => {
57
- * const user = await factory.insert('user', attrs);
58
- * await factory.insertMany(3, 'post', { userId: user.id });
59
- * return user;
60
- * },
61
- * ),
62
- * };
63
- * ```
64
- */
65
- static createSeed(seedFn) {
66
- return require_Factory.Factory.createSeed(seedFn);
67
- }
68
- /**
69
- * Creates a new KyselyFactory instance.
70
- *
71
- * @param builders - Record of builder functions for creating individual entities
72
- * @param seeds - Record of seed functions for creating complex test scenarios
73
- * @param db - Kysely database instance or controlled transaction
74
- */
75
- constructor(builders, seeds, db) {
76
- super();
77
- this.builders = builders;
78
- this.seeds = seeds;
79
- this.db = db;
80
- }
81
- /**
82
- * Creates a typed builder function for a specific database table.
83
- * This is a utility method that helps create builders with proper type inference for Kysely.
84
- *
85
- * @template DB - The database schema type
86
- * @template TableName - The name of the table (must be a key of DB)
87
- * @template Attrs - The attributes type for the builder (defaults to Partial<Insertable>)
88
- * @template Factory - The factory instance type
89
- * @template Result - The result type (defaults to Selectable of the table)
90
- *
91
- * @param table - The name of the database table
92
- * @param defaults - Optional function to provide default values (receives destructured context)
93
- * @param autoInsert - Whether to automatically insert the record (default: true)
94
- * @returns A builder function that creates and optionally inserts records
95
- *
96
- * @example
97
- * ```typescript
98
- * // Create a simple builder with defaults - destructure only what you need
99
- * const userBuilder = KyselyFactory.createBuilder<DB, 'users'>('users',
100
- * ({ attrs, faker }) => ({
101
- * id: faker.string.uuid(),
102
- * name: faker.person.fullName(),
103
- * email: faker.internet.email(),
104
- * createdAt: new Date(),
105
- * ...attrs
106
- * })
107
- * );
108
- *
109
- * // Only need faker? Just destructure that
110
- * const leaveTypeBuilder = KyselyFactory.createBuilder<DB, 'leaveTypes'>('leaveTypes',
111
- * ({ faker }) => ({
112
- * name: faker.helpers.arrayElement(['Annual', 'Sick', 'Maternity']),
113
- * code: faker.string.alpha({ length: 3, casing: 'upper' }),
114
- * })
115
- * );
116
- *
117
- * // Create a builder that doesn't auto-insert (useful for nested inserts)
118
- * const addressBuilder = KyselyFactory.createBuilder<DB, 'addresses'>('addresses',
119
- * ({ attrs }) => ({
120
- * street: '123 Main St',
121
- * city: 'Anytown',
122
- * ...attrs
123
- * }),
124
- * false // Don't auto-insert
125
- * );
126
- * ```
127
- */
128
- static createBuilder(table, defaults, autoInsert) {
129
- return async (attrs, factory, db, fakerInstance) => {
130
- let data = { ...attrs };
131
- if (defaults) {
132
- const defaultValues = await defaults({
133
- attrs,
134
- factory,
135
- db,
136
- faker: fakerInstance
137
- });
138
- data = {
139
- ...defaultValues,
140
- ...data
141
- };
142
- }
143
- if (autoInsert !== false) {
144
- const result = await db.insertInto(table).values(data).returningAll().executeTakeFirst();
145
- if (!result) throw new Error(`Failed to insert into ${table}`);
146
- return result;
147
- } else return {
148
- table,
149
- data
150
- };
151
- };
152
- }
153
- /**
154
- * Inserts a single record into the database using the specified builder.
155
- * The builder function is responsible for generating the record data with defaults
156
- * and the factory handles the actual database insertion.
157
- *
158
- * @template K - The builder name (must be a key of Builders)
159
- * @param builderName - The name of the builder to use
160
- * @param attrs - Optional attributes to override builder defaults
161
- * @returns A promise resolving to the inserted record
162
- * @throws Error if the specified builder doesn't exist
163
- *
164
- * @example
165
- * ```typescript
166
- * // Insert with defaults
167
- * const user = await factory.insert('user');
168
- *
169
- * // Insert with overrides
170
- * const adminUser = await factory.insert('user', {
171
- * email: 'admin@example.com',
172
- * role: 'admin'
173
- * });
174
- *
175
- * // Use the inserted record
176
- * const post = await factory.insert('post', {
177
- * userId: user.id,
178
- * title: 'My First Post'
179
- * });
180
- * ```
181
- */
182
- async insert(builderName, attrs) {
183
- if (!(builderName in this.builders)) throw new Error(`Factory "${builderName}" does not exist. Make sure it is correct and registered in src/test/setup.ts`);
184
- const result = await this.builders[builderName](attrs || {}, this, this.db, require_faker.faker);
185
- if (result && typeof result === "object" && "table" in result && "data" in result) {
186
- const inserted = await this.db.insertInto(result.table).values(result.data).returningAll().executeTakeFirst();
187
- return inserted;
188
- }
189
- return result;
190
- }
191
- async insertMany(count, builderName, attrs) {
192
- if (!(builderName in this.builders)) throw new Error(`Builder "${builderName}" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`);
193
- const promises = [];
194
- for (let i = 0; i < count; i++) {
195
- const newAttrs = typeof attrs === "function" ? await attrs(i, require_faker.faker) : attrs;
196
- promises.push(this.insert(builderName, newAttrs));
197
- }
198
- return Promise.all(promises);
199
- }
200
- /**
201
- * Executes a seed function to create complex test scenarios with multiple related records.
202
- * Seeds are useful for setting up complete test environments with realistic data relationships.
203
- *
204
- * @template K - The seed name (must be a key of Seeds)
205
- * @param seedName - The name of the seed to execute
206
- * @param attrs - Optional configuration attributes for the seed
207
- * @returns The result of the seed function (typically the primary record created)
208
- * @throws Error if the specified seed doesn't exist
209
- *
210
- * @example
211
- * ```typescript
212
- * // Execute a simple seed
213
- * const user = await factory.seed('userWithProfile');
214
- *
215
- * // Execute a seed with configuration
216
- * const author = await factory.seed('authorWithBooks', {
217
- * bookCount: 5,
218
- * includeReviews: true
219
- * });
220
- *
221
- * // Use seed result in tests
222
- * const company = await factory.seed('companyWithDepartments', {
223
- * departmentCount: 3,
224
- * employeesPerDepartment: 10
225
- * });
226
- * expect(company.departments).toHaveLength(3);
227
- * ```
228
- */
229
- seed(seedName, attrs) {
230
- if (!(seedName in this.seeds)) throw new Error(`Seed "${seedName}" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`);
231
- return this.seeds[seedName]({
232
- attrs: attrs || {},
233
- factory: this,
234
- db: this.db
235
- });
236
- }
237
- };
238
-
239
- //#endregion
240
- Object.defineProperty(exports, 'KyselyFactory', {
241
- enumerable: true,
242
- get: function () {
243
- return KyselyFactory;
244
- }
245
- });
246
- //# sourceMappingURL=KyselyFactory-BFqVIn_0.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"KyselyFactory-BFqVIn_0.cjs","names":["Factory","seedFn: Seed","builders: Builders","seeds: Seeds","db: Kysely<DB> | ControlledTransaction<DB, []>","table: TableName","defaults?: (context: {\n\t\t\tattrs: Attrs;\n\t\t\tfactory: Factory;\n\t\t\tdb: Kysely<DB>;\n\t\t\tfaker: FakerFactory;\n\t\t}) =>\n\t\t\t| Partial<Insertable<DB[TableName]>>\n\t\t\t| Promise<Partial<Insertable<DB[TableName]>>>","autoInsert?: boolean","attrs: Attrs","factory: Factory","db: Kysely<DB>","fakerInstance: FakerFactory","data: Partial<Insertable<DB[TableName]>>","builderName: K","attrs?: Parameters<Builders[K]>[0]","faker","count: number","attrs?: any","promises: Promise<any>[]","seedName: K","attrs?: ExtractSeedAttrs<Seeds[K]>"],"sources":["../src/KyselyFactory.ts"],"sourcesContent":["import type {\n\tControlledTransaction,\n\tInsertable,\n\tKysely,\n\tSelectable,\n} from 'kysely';\nimport { type ExtractSeedAttrs, Factory, type FactorySeed } from './Factory';\nimport { type FakerFactory, faker } from './faker';\n\n/**\n * Factory implementation for Kysely ORM, providing test data creation utilities.\n * Extends the base Factory class with Kysely-specific database operations.\n *\n * @template DB - The database schema type\n * @template Builders - Record of builder functions for creating entities\n * @template Seeds - Record of seed functions for complex test scenarios\n *\n * @example\n * ```typescript\n * // Define your database schema\n * interface Database {\n * users: UsersTable;\n * posts: PostsTable;\n * }\n *\n * // Create builders\n * const builders = {\n * user: KyselyFactory.createBuilder<Database, 'users'>('users', ({ attrs, faker }) => ({\n * id: faker.string.uuid(),\n * name: faker.person.fullName(),\n * email: faker.internet.email(),\n * ...attrs\n * })),\n * post: KyselyFactory.createBuilder<Database, 'posts'>('posts', ({ attrs }) => ({\n * title: 'Test Post',\n * content: 'Test content',\n * ...attrs\n * }))\n * };\n *\n * // Create factory instance\n * const factory = new KyselyFactory(builders, seeds, db);\n *\n * // Use in tests\n * const user = await factory.insert('user', { name: 'John Doe' });\n * ```\n */\nexport class KyselyFactory<\n\tDB,\n\tBuilders extends Record<string, any>,\n\tSeeds extends Record<string, any>,\n> extends Factory<Builders, Seeds> {\n\t/**\n\t * Creates a typed seed function with proper type inference.\n\t * Inherits from the base Factory class implementation.\n\t *\n\t * @template Seed - The seed function type\n\t * @param seedFn - The seed function to wrap (receives { attrs, factory, db } object)\n\t * @returns The same seed function with proper typing\n\t *\n\t * @example\n\t * ```typescript\n\t * const seeds = {\n\t * userWithPosts: KyselyFactory.createSeed(\n\t * async ({ attrs, factory }) => {\n\t * const user = await factory.insert('user', attrs);\n\t * await factory.insertMany(3, 'post', { userId: user.id });\n\t * return user;\n\t * },\n\t * ),\n\t * };\n\t * ```\n\t */\n\tstatic override createSeed<Seed extends FactorySeed>(seedFn: Seed): Seed {\n\t\treturn Factory.createSeed(seedFn);\n\t}\n\n\t/**\n\t * Creates a new KyselyFactory instance.\n\t *\n\t * @param builders - Record of builder functions for creating individual entities\n\t * @param seeds - Record of seed functions for creating complex test scenarios\n\t * @param db - Kysely database instance or controlled transaction\n\t */\n\tconstructor(\n\t\tprivate builders: Builders,\n\t\tprivate seeds: Seeds,\n\t\tprivate db: Kysely<DB> | ControlledTransaction<DB, []>,\n\t) {\n\t\tsuper();\n\t}\n\n\t/**\n\t * Creates a typed builder function for a specific database table.\n\t * This is a utility method that helps create builders with proper type inference for Kysely.\n\t *\n\t * @template DB - The database schema type\n\t * @template TableName - The name of the table (must be a key of DB)\n\t * @template Attrs - The attributes type for the builder (defaults to Partial<Insertable>)\n\t * @template Factory - The factory instance type\n\t * @template Result - The result type (defaults to Selectable of the table)\n\t *\n\t * @param table - The name of the database table\n\t * @param defaults - Optional function to provide default values (receives destructured context)\n\t * @param autoInsert - Whether to automatically insert the record (default: true)\n\t * @returns A builder function that creates and optionally inserts records\n\t *\n\t * @example\n\t * ```typescript\n\t * // Create a simple builder with defaults - destructure only what you need\n\t * const userBuilder = KyselyFactory.createBuilder<DB, 'users'>('users',\n\t * ({ attrs, faker }) => ({\n\t * id: faker.string.uuid(),\n\t * name: faker.person.fullName(),\n\t * email: faker.internet.email(),\n\t * createdAt: new Date(),\n\t * ...attrs\n\t * })\n\t * );\n\t *\n\t * // Only need faker? Just destructure that\n\t * const leaveTypeBuilder = KyselyFactory.createBuilder<DB, 'leaveTypes'>('leaveTypes',\n\t * ({ faker }) => ({\n\t * name: faker.helpers.arrayElement(['Annual', 'Sick', 'Maternity']),\n\t * code: faker.string.alpha({ length: 3, casing: 'upper' }),\n\t * })\n\t * );\n\t *\n\t * // Create a builder that doesn't auto-insert (useful for nested inserts)\n\t * const addressBuilder = KyselyFactory.createBuilder<DB, 'addresses'>('addresses',\n\t * ({ attrs }) => ({\n\t * street: '123 Main St',\n\t * city: 'Anytown',\n\t * ...attrs\n\t * }),\n\t * false // Don't auto-insert\n\t * );\n\t * ```\n\t */\n\tstatic createBuilder<\n\t\tDB,\n\t\tTableName extends keyof DB & string,\n\t\tAttrs extends Partial<Insertable<DB[TableName]>> = Partial<\n\t\t\tInsertable<DB[TableName]>\n\t\t>,\n\t\tFactory = any,\n\t\tResult = Selectable<DB[TableName]>,\n\t>(\n\t\ttable: TableName,\n\t\tdefaults?: (context: {\n\t\t\tattrs: Attrs;\n\t\t\tfactory: Factory;\n\t\t\tdb: Kysely<DB>;\n\t\t\tfaker: FakerFactory;\n\t\t}) =>\n\t\t\t| Partial<Insertable<DB[TableName]>>\n\t\t\t| Promise<Partial<Insertable<DB[TableName]>>>,\n\t\tautoInsert?: boolean,\n\t): (\n\t\tattrs: Attrs,\n\t\tfactory: Factory,\n\t\tdb: Kysely<DB>,\n\t\tfaker: FakerFactory,\n\t) => Promise<Result> {\n\t\treturn async (\n\t\t\tattrs: Attrs,\n\t\t\tfactory: Factory,\n\t\t\tdb: Kysely<DB>,\n\t\t\tfakerInstance: FakerFactory,\n\t\t) => {\n\t\t\t// Start with attributes\n\t\t\tlet data: Partial<Insertable<DB[TableName]>> = { ...attrs };\n\n\t\t\t// Apply defaults\n\t\t\tif (defaults) {\n\t\t\t\tconst defaultValues = await defaults({\n\t\t\t\t\tattrs,\n\t\t\t\t\tfactory,\n\t\t\t\t\tdb,\n\t\t\t\t\tfaker: fakerInstance,\n\t\t\t\t});\n\t\t\t\tdata = { ...defaultValues, ...data };\n\t\t\t}\n\n\t\t\t// Handle insertion based on autoInsert flag\n\t\t\tif (autoInsert !== false) {\n\t\t\t\t// Auto insert is enabled by default\n\t\t\t\tconst result = await db\n\t\t\t\t\t.insertInto(table)\n\t\t\t\t\t.values(data as Insertable<DB[TableName]>)\n\t\t\t\t\t.returningAll()\n\t\t\t\t\t.executeTakeFirst();\n\n\t\t\t\tif (!result) {\n\t\t\t\t\tthrow new Error(`Failed to insert into ${table}`);\n\t\t\t\t}\n\n\t\t\t\treturn result as Result;\n\t\t\t} else {\n\t\t\t\t// Return object for factory to handle insertion\n\t\t\t\treturn { table, data } as any;\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Inserts a single record into the database using the specified builder.\n\t * The builder function is responsible for generating the record data with defaults\n\t * and the factory handles the actual database insertion.\n\t *\n\t * @template K - The builder name (must be a key of Builders)\n\t * @param builderName - The name of the builder to use\n\t * @param attrs - Optional attributes to override builder defaults\n\t * @returns A promise resolving to the inserted record\n\t * @throws Error if the specified builder doesn't exist\n\t *\n\t * @example\n\t * ```typescript\n\t * // Insert with defaults\n\t * const user = await factory.insert('user');\n\t *\n\t * // Insert with overrides\n\t * const adminUser = await factory.insert('user', {\n\t * email: 'admin@example.com',\n\t * role: 'admin'\n\t * });\n\t *\n\t * // Use the inserted record\n\t * const post = await factory.insert('post', {\n\t * userId: user.id,\n\t * title: 'My First Post'\n\t * });\n\t * ```\n\t */\n\tasync insert<K extends keyof Builders>(\n\t\tbuilderName: K,\n\t\tattrs?: Parameters<Builders[K]>[0],\n\t): Promise<Awaited<ReturnType<Builders[K]>>> {\n\t\tif (!(builderName in this.builders)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Factory \"${\n\t\t\t\t\tbuilderName as string\n\t\t\t\t}\" does not exist. Make sure it is correct and registered in src/test/setup.ts`,\n\t\t\t);\n\t\t}\n\n\t\tconst result = await this.builders[builderName](\n\t\t\tattrs || {},\n\t\t\tthis,\n\t\t\tthis.db,\n\t\t\tfaker,\n\t\t);\n\n\t\t// For Kysely, we expect the builder to return an object with table and data properties\n\t\t// or to handle the insertion itself and return the inserted record\n\t\tif (\n\t\t\tresult &&\n\t\t\ttypeof result === 'object' &&\n\t\t\t'table' in result &&\n\t\t\t'data' in result\n\t\t) {\n\t\t\t// If the builder returns {table: string, data: object}, we insert it\n\t\t\tconst inserted = await this.db\n\t\t\t\t.insertInto(result.table)\n\t\t\t\t.values(result.data)\n\t\t\t\t.returningAll()\n\t\t\t\t.executeTakeFirst();\n\n\t\t\treturn inserted as any;\n\t\t}\n\n\t\t// Otherwise, assume the builder handled the insertion itself\n\t\treturn result;\n\t}\n\n\t/**\n\t * Inserts multiple records into the database using the specified builder.\n\t * Supports both static attributes and dynamic attribute generation via a function.\n\t *\n\t * @template K - The builder name (must be a key of Builders)\n\t * @param count - The number of records to insert\n\t * @param builderName - The name of the builder to use\n\t * @param attrs - Static attributes or a function that generates attributes for each record\n\t * @returns A promise resolving to an array of inserted records\n\t * @throws Error if the specified builder doesn't exist\n\t *\n\t * @example\n\t * ```typescript\n\t * // Insert multiple with same attributes\n\t * const users = await factory.insertMany(5, 'user', { role: 'member' });\n\t *\n\t * // Insert multiple with dynamic attributes\n\t * const posts = await factory.insertMany(10, 'post', (idx, faker) => ({\n\t * title: `Post ${idx + 1}`,\n\t * content: faker.lorem.paragraph(),\n\t * publishedAt: faker.date.past()\n\t * }));\n\t *\n\t * // Create users with sequential emails\n\t * const admins = await factory.insertMany(3, 'user', (idx) => ({\n\t * email: `admin${idx + 1}@example.com`,\n\t * role: 'admin'\n\t * }));\n\t * ```\n\t */\n\t// Method overloads for better type inference\n\tasync insertMany<K extends keyof Builders>(\n\t\tcount: number,\n\t\tbuilderName: K,\n\t\tattrs?: Parameters<Builders[K]>[0],\n\t): Promise<Awaited<ReturnType<Builders[K]>>[]>;\n\tasync insertMany<K extends keyof Builders>(\n\t\tcount: number,\n\t\tbuilderName: K,\n\t\tattrs: (\n\t\t\tidx: number,\n\t\t\tfaker: FakerFactory,\n\t\t) => Parameters<Builders[K]>[0] | Promise<Parameters<Builders[K]>[0]>,\n\t): Promise<Awaited<ReturnType<Builders[K]>>[]>;\n\tasync insertMany<K extends keyof Builders>(\n\t\tcount: number,\n\t\tbuilderName: K,\n\t\tattrs?: any,\n\t): Promise<Awaited<ReturnType<Builders[K]>>[]> {\n\t\tif (!(builderName in this.builders)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Builder \"${\n\t\t\t\t\tbuilderName as string\n\t\t\t\t}\" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`,\n\t\t\t);\n\t\t}\n\n\t\tconst promises: Promise<any>[] = [];\n\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tconst newAttrs =\n\t\t\t\ttypeof attrs === 'function' ? await attrs(i, faker) : attrs;\n\t\t\tpromises.push(this.insert(builderName, newAttrs));\n\t\t}\n\n\t\treturn Promise.all(promises);\n\t}\n\n\t/**\n\t * Executes a seed function to create complex test scenarios with multiple related records.\n\t * Seeds are useful for setting up complete test environments with realistic data relationships.\n\t *\n\t * @template K - The seed name (must be a key of Seeds)\n\t * @param seedName - The name of the seed to execute\n\t * @param attrs - Optional configuration attributes for the seed\n\t * @returns The result of the seed function (typically the primary record created)\n\t * @throws Error if the specified seed doesn't exist\n\t *\n\t * @example\n\t * ```typescript\n\t * // Execute a simple seed\n\t * const user = await factory.seed('userWithProfile');\n\t *\n\t * // Execute a seed with configuration\n\t * const author = await factory.seed('authorWithBooks', {\n\t * bookCount: 5,\n\t * includeReviews: true\n\t * });\n\t *\n\t * // Use seed result in tests\n\t * const company = await factory.seed('companyWithDepartments', {\n\t * departmentCount: 3,\n\t * employeesPerDepartment: 10\n\t * });\n\t * expect(company.departments).toHaveLength(3);\n\t * ```\n\t */\n\tseed<K extends keyof Seeds>(\n\t\tseedName: K,\n\t\tattrs?: ExtractSeedAttrs<Seeds[K]>,\n\t): ReturnType<Seeds[K]> {\n\t\tif (!(seedName in this.seeds)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Seed \"${\n\t\t\t\t\tseedName as string\n\t\t\t\t}\" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`,\n\t\t\t);\n\t\t}\n\n\t\treturn this.seeds[seedName]({\n\t\t\tattrs: attrs || {},\n\t\t\tfactory: this,\n\t\t\tdb: this.db,\n\t\t});\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,IAAa,gBAAb,cAIUA,wBAAyB;;;;;;;;;;;;;;;;;;;;;;CAsBlC,OAAgB,WAAqCC,QAAoB;AACxE,SAAO,wBAAQ,WAAW,OAAO;CACjC;;;;;;;;CASD,YACSC,UACAC,OACAC,IACP;AACD,SAAO;EAJC;EACA;EACA;CAGR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiDD,OAAO,cASNC,OACAC,UAQAC,YAMoB;AACpB,SAAO,OACNC,OACAC,SACAC,IACAC,kBACI;GAEJ,IAAIC,OAA2C,EAAE,GAAG,MAAO;AAG3D,OAAI,UAAU;IACb,MAAM,gBAAgB,MAAM,SAAS;KACpC;KACA;KACA;KACA,OAAO;IACP,EAAC;AACF,WAAO;KAAE,GAAG;KAAe,GAAG;IAAM;GACpC;AAGD,OAAI,eAAe,OAAO;IAEzB,MAAM,SAAS,MAAM,GACnB,WAAW,MAAM,CACjB,OAAO,KAAkC,CACzC,cAAc,CACd,kBAAkB;AAEpB,SAAK,OACJ,OAAM,IAAI,OAAO,wBAAwB,MAAM;AAGhD,WAAO;GACP,MAEA,QAAO;IAAE;IAAO;GAAM;EAEvB;CACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BD,MAAM,OACLC,aACAC,OAC4C;AAC5C,QAAM,eAAe,KAAK,UACzB,OAAM,IAAI,OACR,WACA,YACA;EAIH,MAAM,SAAS,MAAM,KAAK,SAAS,aAClC,SAAS,CAAE,GACX,MACA,KAAK,IACLC,oBACA;AAID,MACC,iBACO,WAAW,YAClB,WAAW,UACX,UAAU,QACT;GAED,MAAM,WAAW,MAAM,KAAK,GAC1B,WAAW,OAAO,MAAM,CACxB,OAAO,OAAO,KAAK,CACnB,cAAc,CACd,kBAAkB;AAEpB,UAAO;EACP;AAGD,SAAO;CACP;CA8CD,MAAM,WACLC,OACAH,aACAI,OAC8C;AAC9C,QAAM,eAAe,KAAK,UACzB,OAAM,IAAI,OACR,WACA,YACA;EAIH,MAAMC,WAA2B,CAAE;AAEnC,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;GAC/B,MAAM,kBACE,UAAU,aAAa,MAAM,MAAM,GAAGH,oBAAM,GAAG;AACvD,YAAS,KAAK,KAAK,OAAO,aAAa,SAAS,CAAC;EACjD;AAED,SAAO,QAAQ,IAAI,SAAS;CAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BD,KACCI,UACAC,OACuB;AACvB,QAAM,YAAY,KAAK,OACtB,OAAM,IAAI,OACR,QACA,SACA;AAIH,SAAO,KAAK,MAAM,UAAU;GAC3B,OAAO,SAAS,CAAE;GAClB,SAAS;GACT,IAAI,KAAK;EACT,EAAC;CACF;AACD"}
@@ -1,241 +0,0 @@
1
- import { Factory } from "./Factory-BFVnMMCC.mjs";
2
- import { faker } from "./faker-BGKYFoCT.mjs";
3
-
4
- //#region src/KyselyFactory.ts
5
- /**
6
- * Factory implementation for Kysely ORM, providing test data creation utilities.
7
- * Extends the base Factory class with Kysely-specific database operations.
8
- *
9
- * @template DB - The database schema type
10
- * @template Builders - Record of builder functions for creating entities
11
- * @template Seeds - Record of seed functions for complex test scenarios
12
- *
13
- * @example
14
- * ```typescript
15
- * // Define your database schema
16
- * interface Database {
17
- * users: UsersTable;
18
- * posts: PostsTable;
19
- * }
20
- *
21
- * // Create builders
22
- * const builders = {
23
- * user: KyselyFactory.createBuilder<Database, 'users'>('users', ({ attrs, faker }) => ({
24
- * id: faker.string.uuid(),
25
- * name: faker.person.fullName(),
26
- * email: faker.internet.email(),
27
- * ...attrs
28
- * })),
29
- * post: KyselyFactory.createBuilder<Database, 'posts'>('posts', ({ attrs }) => ({
30
- * title: 'Test Post',
31
- * content: 'Test content',
32
- * ...attrs
33
- * }))
34
- * };
35
- *
36
- * // Create factory instance
37
- * const factory = new KyselyFactory(builders, seeds, db);
38
- *
39
- * // Use in tests
40
- * const user = await factory.insert('user', { name: 'John Doe' });
41
- * ```
42
- */
43
- var KyselyFactory = class extends Factory {
44
- /**
45
- * Creates a typed seed function with proper type inference.
46
- * Inherits from the base Factory class implementation.
47
- *
48
- * @template Seed - The seed function type
49
- * @param seedFn - The seed function to wrap (receives { attrs, factory, db } object)
50
- * @returns The same seed function with proper typing
51
- *
52
- * @example
53
- * ```typescript
54
- * const seeds = {
55
- * userWithPosts: KyselyFactory.createSeed(
56
- * async ({ attrs, factory }) => {
57
- * const user = await factory.insert('user', attrs);
58
- * await factory.insertMany(3, 'post', { userId: user.id });
59
- * return user;
60
- * },
61
- * ),
62
- * };
63
- * ```
64
- */
65
- static createSeed(seedFn) {
66
- return Factory.createSeed(seedFn);
67
- }
68
- /**
69
- * Creates a new KyselyFactory instance.
70
- *
71
- * @param builders - Record of builder functions for creating individual entities
72
- * @param seeds - Record of seed functions for creating complex test scenarios
73
- * @param db - Kysely database instance or controlled transaction
74
- */
75
- constructor(builders, seeds, db) {
76
- super();
77
- this.builders = builders;
78
- this.seeds = seeds;
79
- this.db = db;
80
- }
81
- /**
82
- * Creates a typed builder function for a specific database table.
83
- * This is a utility method that helps create builders with proper type inference for Kysely.
84
- *
85
- * @template DB - The database schema type
86
- * @template TableName - The name of the table (must be a key of DB)
87
- * @template Attrs - The attributes type for the builder (defaults to Partial<Insertable>)
88
- * @template Factory - The factory instance type
89
- * @template Result - The result type (defaults to Selectable of the table)
90
- *
91
- * @param table - The name of the database table
92
- * @param defaults - Optional function to provide default values (receives destructured context)
93
- * @param autoInsert - Whether to automatically insert the record (default: true)
94
- * @returns A builder function that creates and optionally inserts records
95
- *
96
- * @example
97
- * ```typescript
98
- * // Create a simple builder with defaults - destructure only what you need
99
- * const userBuilder = KyselyFactory.createBuilder<DB, 'users'>('users',
100
- * ({ attrs, faker }) => ({
101
- * id: faker.string.uuid(),
102
- * name: faker.person.fullName(),
103
- * email: faker.internet.email(),
104
- * createdAt: new Date(),
105
- * ...attrs
106
- * })
107
- * );
108
- *
109
- * // Only need faker? Just destructure that
110
- * const leaveTypeBuilder = KyselyFactory.createBuilder<DB, 'leaveTypes'>('leaveTypes',
111
- * ({ faker }) => ({
112
- * name: faker.helpers.arrayElement(['Annual', 'Sick', 'Maternity']),
113
- * code: faker.string.alpha({ length: 3, casing: 'upper' }),
114
- * })
115
- * );
116
- *
117
- * // Create a builder that doesn't auto-insert (useful for nested inserts)
118
- * const addressBuilder = KyselyFactory.createBuilder<DB, 'addresses'>('addresses',
119
- * ({ attrs }) => ({
120
- * street: '123 Main St',
121
- * city: 'Anytown',
122
- * ...attrs
123
- * }),
124
- * false // Don't auto-insert
125
- * );
126
- * ```
127
- */
128
- static createBuilder(table, defaults, autoInsert) {
129
- return async (attrs, factory, db, fakerInstance) => {
130
- let data = { ...attrs };
131
- if (defaults) {
132
- const defaultValues = await defaults({
133
- attrs,
134
- factory,
135
- db,
136
- faker: fakerInstance
137
- });
138
- data = {
139
- ...defaultValues,
140
- ...data
141
- };
142
- }
143
- if (autoInsert !== false) {
144
- const result = await db.insertInto(table).values(data).returningAll().executeTakeFirst();
145
- if (!result) throw new Error(`Failed to insert into ${table}`);
146
- return result;
147
- } else return {
148
- table,
149
- data
150
- };
151
- };
152
- }
153
- /**
154
- * Inserts a single record into the database using the specified builder.
155
- * The builder function is responsible for generating the record data with defaults
156
- * and the factory handles the actual database insertion.
157
- *
158
- * @template K - The builder name (must be a key of Builders)
159
- * @param builderName - The name of the builder to use
160
- * @param attrs - Optional attributes to override builder defaults
161
- * @returns A promise resolving to the inserted record
162
- * @throws Error if the specified builder doesn't exist
163
- *
164
- * @example
165
- * ```typescript
166
- * // Insert with defaults
167
- * const user = await factory.insert('user');
168
- *
169
- * // Insert with overrides
170
- * const adminUser = await factory.insert('user', {
171
- * email: 'admin@example.com',
172
- * role: 'admin'
173
- * });
174
- *
175
- * // Use the inserted record
176
- * const post = await factory.insert('post', {
177
- * userId: user.id,
178
- * title: 'My First Post'
179
- * });
180
- * ```
181
- */
182
- async insert(builderName, attrs) {
183
- if (!(builderName in this.builders)) throw new Error(`Factory "${builderName}" does not exist. Make sure it is correct and registered in src/test/setup.ts`);
184
- const result = await this.builders[builderName](attrs || {}, this, this.db, faker);
185
- if (result && typeof result === "object" && "table" in result && "data" in result) {
186
- const inserted = await this.db.insertInto(result.table).values(result.data).returningAll().executeTakeFirst();
187
- return inserted;
188
- }
189
- return result;
190
- }
191
- async insertMany(count, builderName, attrs) {
192
- if (!(builderName in this.builders)) throw new Error(`Builder "${builderName}" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`);
193
- const promises = [];
194
- for (let i = 0; i < count; i++) {
195
- const newAttrs = typeof attrs === "function" ? await attrs(i, faker) : attrs;
196
- promises.push(this.insert(builderName, newAttrs));
197
- }
198
- return Promise.all(promises);
199
- }
200
- /**
201
- * Executes a seed function to create complex test scenarios with multiple related records.
202
- * Seeds are useful for setting up complete test environments with realistic data relationships.
203
- *
204
- * @template K - The seed name (must be a key of Seeds)
205
- * @param seedName - The name of the seed to execute
206
- * @param attrs - Optional configuration attributes for the seed
207
- * @returns The result of the seed function (typically the primary record created)
208
- * @throws Error if the specified seed doesn't exist
209
- *
210
- * @example
211
- * ```typescript
212
- * // Execute a simple seed
213
- * const user = await factory.seed('userWithProfile');
214
- *
215
- * // Execute a seed with configuration
216
- * const author = await factory.seed('authorWithBooks', {
217
- * bookCount: 5,
218
- * includeReviews: true
219
- * });
220
- *
221
- * // Use seed result in tests
222
- * const company = await factory.seed('companyWithDepartments', {
223
- * departmentCount: 3,
224
- * employeesPerDepartment: 10
225
- * });
226
- * expect(company.departments).toHaveLength(3);
227
- * ```
228
- */
229
- seed(seedName, attrs) {
230
- if (!(seedName in this.seeds)) throw new Error(`Seed "${seedName}" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`);
231
- return this.seeds[seedName]({
232
- attrs: attrs || {},
233
- factory: this,
234
- db: this.db
235
- });
236
- }
237
- };
238
-
239
- //#endregion
240
- export { KyselyFactory };
241
- //# sourceMappingURL=KyselyFactory-DMswpwji.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"KyselyFactory-DMswpwji.mjs","names":["seedFn: Seed","builders: Builders","seeds: Seeds","db: Kysely<DB> | ControlledTransaction<DB, []>","table: TableName","defaults?: (context: {\n\t\t\tattrs: Attrs;\n\t\t\tfactory: Factory;\n\t\t\tdb: Kysely<DB>;\n\t\t\tfaker: FakerFactory;\n\t\t}) =>\n\t\t\t| Partial<Insertable<DB[TableName]>>\n\t\t\t| Promise<Partial<Insertable<DB[TableName]>>>","autoInsert?: boolean","attrs: Attrs","factory: Factory","db: Kysely<DB>","fakerInstance: FakerFactory","data: Partial<Insertable<DB[TableName]>>","builderName: K","attrs?: Parameters<Builders[K]>[0]","count: number","attrs?: any","promises: Promise<any>[]","seedName: K","attrs?: ExtractSeedAttrs<Seeds[K]>"],"sources":["../src/KyselyFactory.ts"],"sourcesContent":["import type {\n\tControlledTransaction,\n\tInsertable,\n\tKysely,\n\tSelectable,\n} from 'kysely';\nimport { type ExtractSeedAttrs, Factory, type FactorySeed } from './Factory';\nimport { type FakerFactory, faker } from './faker';\n\n/**\n * Factory implementation for Kysely ORM, providing test data creation utilities.\n * Extends the base Factory class with Kysely-specific database operations.\n *\n * @template DB - The database schema type\n * @template Builders - Record of builder functions for creating entities\n * @template Seeds - Record of seed functions for complex test scenarios\n *\n * @example\n * ```typescript\n * // Define your database schema\n * interface Database {\n * users: UsersTable;\n * posts: PostsTable;\n * }\n *\n * // Create builders\n * const builders = {\n * user: KyselyFactory.createBuilder<Database, 'users'>('users', ({ attrs, faker }) => ({\n * id: faker.string.uuid(),\n * name: faker.person.fullName(),\n * email: faker.internet.email(),\n * ...attrs\n * })),\n * post: KyselyFactory.createBuilder<Database, 'posts'>('posts', ({ attrs }) => ({\n * title: 'Test Post',\n * content: 'Test content',\n * ...attrs\n * }))\n * };\n *\n * // Create factory instance\n * const factory = new KyselyFactory(builders, seeds, db);\n *\n * // Use in tests\n * const user = await factory.insert('user', { name: 'John Doe' });\n * ```\n */\nexport class KyselyFactory<\n\tDB,\n\tBuilders extends Record<string, any>,\n\tSeeds extends Record<string, any>,\n> extends Factory<Builders, Seeds> {\n\t/**\n\t * Creates a typed seed function with proper type inference.\n\t * Inherits from the base Factory class implementation.\n\t *\n\t * @template Seed - The seed function type\n\t * @param seedFn - The seed function to wrap (receives { attrs, factory, db } object)\n\t * @returns The same seed function with proper typing\n\t *\n\t * @example\n\t * ```typescript\n\t * const seeds = {\n\t * userWithPosts: KyselyFactory.createSeed(\n\t * async ({ attrs, factory }) => {\n\t * const user = await factory.insert('user', attrs);\n\t * await factory.insertMany(3, 'post', { userId: user.id });\n\t * return user;\n\t * },\n\t * ),\n\t * };\n\t * ```\n\t */\n\tstatic override createSeed<Seed extends FactorySeed>(seedFn: Seed): Seed {\n\t\treturn Factory.createSeed(seedFn);\n\t}\n\n\t/**\n\t * Creates a new KyselyFactory instance.\n\t *\n\t * @param builders - Record of builder functions for creating individual entities\n\t * @param seeds - Record of seed functions for creating complex test scenarios\n\t * @param db - Kysely database instance or controlled transaction\n\t */\n\tconstructor(\n\t\tprivate builders: Builders,\n\t\tprivate seeds: Seeds,\n\t\tprivate db: Kysely<DB> | ControlledTransaction<DB, []>,\n\t) {\n\t\tsuper();\n\t}\n\n\t/**\n\t * Creates a typed builder function for a specific database table.\n\t * This is a utility method that helps create builders with proper type inference for Kysely.\n\t *\n\t * @template DB - The database schema type\n\t * @template TableName - The name of the table (must be a key of DB)\n\t * @template Attrs - The attributes type for the builder (defaults to Partial<Insertable>)\n\t * @template Factory - The factory instance type\n\t * @template Result - The result type (defaults to Selectable of the table)\n\t *\n\t * @param table - The name of the database table\n\t * @param defaults - Optional function to provide default values (receives destructured context)\n\t * @param autoInsert - Whether to automatically insert the record (default: true)\n\t * @returns A builder function that creates and optionally inserts records\n\t *\n\t * @example\n\t * ```typescript\n\t * // Create a simple builder with defaults - destructure only what you need\n\t * const userBuilder = KyselyFactory.createBuilder<DB, 'users'>('users',\n\t * ({ attrs, faker }) => ({\n\t * id: faker.string.uuid(),\n\t * name: faker.person.fullName(),\n\t * email: faker.internet.email(),\n\t * createdAt: new Date(),\n\t * ...attrs\n\t * })\n\t * );\n\t *\n\t * // Only need faker? Just destructure that\n\t * const leaveTypeBuilder = KyselyFactory.createBuilder<DB, 'leaveTypes'>('leaveTypes',\n\t * ({ faker }) => ({\n\t * name: faker.helpers.arrayElement(['Annual', 'Sick', 'Maternity']),\n\t * code: faker.string.alpha({ length: 3, casing: 'upper' }),\n\t * })\n\t * );\n\t *\n\t * // Create a builder that doesn't auto-insert (useful for nested inserts)\n\t * const addressBuilder = KyselyFactory.createBuilder<DB, 'addresses'>('addresses',\n\t * ({ attrs }) => ({\n\t * street: '123 Main St',\n\t * city: 'Anytown',\n\t * ...attrs\n\t * }),\n\t * false // Don't auto-insert\n\t * );\n\t * ```\n\t */\n\tstatic createBuilder<\n\t\tDB,\n\t\tTableName extends keyof DB & string,\n\t\tAttrs extends Partial<Insertable<DB[TableName]>> = Partial<\n\t\t\tInsertable<DB[TableName]>\n\t\t>,\n\t\tFactory = any,\n\t\tResult = Selectable<DB[TableName]>,\n\t>(\n\t\ttable: TableName,\n\t\tdefaults?: (context: {\n\t\t\tattrs: Attrs;\n\t\t\tfactory: Factory;\n\t\t\tdb: Kysely<DB>;\n\t\t\tfaker: FakerFactory;\n\t\t}) =>\n\t\t\t| Partial<Insertable<DB[TableName]>>\n\t\t\t| Promise<Partial<Insertable<DB[TableName]>>>,\n\t\tautoInsert?: boolean,\n\t): (\n\t\tattrs: Attrs,\n\t\tfactory: Factory,\n\t\tdb: Kysely<DB>,\n\t\tfaker: FakerFactory,\n\t) => Promise<Result> {\n\t\treturn async (\n\t\t\tattrs: Attrs,\n\t\t\tfactory: Factory,\n\t\t\tdb: Kysely<DB>,\n\t\t\tfakerInstance: FakerFactory,\n\t\t) => {\n\t\t\t// Start with attributes\n\t\t\tlet data: Partial<Insertable<DB[TableName]>> = { ...attrs };\n\n\t\t\t// Apply defaults\n\t\t\tif (defaults) {\n\t\t\t\tconst defaultValues = await defaults({\n\t\t\t\t\tattrs,\n\t\t\t\t\tfactory,\n\t\t\t\t\tdb,\n\t\t\t\t\tfaker: fakerInstance,\n\t\t\t\t});\n\t\t\t\tdata = { ...defaultValues, ...data };\n\t\t\t}\n\n\t\t\t// Handle insertion based on autoInsert flag\n\t\t\tif (autoInsert !== false) {\n\t\t\t\t// Auto insert is enabled by default\n\t\t\t\tconst result = await db\n\t\t\t\t\t.insertInto(table)\n\t\t\t\t\t.values(data as Insertable<DB[TableName]>)\n\t\t\t\t\t.returningAll()\n\t\t\t\t\t.executeTakeFirst();\n\n\t\t\t\tif (!result) {\n\t\t\t\t\tthrow new Error(`Failed to insert into ${table}`);\n\t\t\t\t}\n\n\t\t\t\treturn result as Result;\n\t\t\t} else {\n\t\t\t\t// Return object for factory to handle insertion\n\t\t\t\treturn { table, data } as any;\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Inserts a single record into the database using the specified builder.\n\t * The builder function is responsible for generating the record data with defaults\n\t * and the factory handles the actual database insertion.\n\t *\n\t * @template K - The builder name (must be a key of Builders)\n\t * @param builderName - The name of the builder to use\n\t * @param attrs - Optional attributes to override builder defaults\n\t * @returns A promise resolving to the inserted record\n\t * @throws Error if the specified builder doesn't exist\n\t *\n\t * @example\n\t * ```typescript\n\t * // Insert with defaults\n\t * const user = await factory.insert('user');\n\t *\n\t * // Insert with overrides\n\t * const adminUser = await factory.insert('user', {\n\t * email: 'admin@example.com',\n\t * role: 'admin'\n\t * });\n\t *\n\t * // Use the inserted record\n\t * const post = await factory.insert('post', {\n\t * userId: user.id,\n\t * title: 'My First Post'\n\t * });\n\t * ```\n\t */\n\tasync insert<K extends keyof Builders>(\n\t\tbuilderName: K,\n\t\tattrs?: Parameters<Builders[K]>[0],\n\t): Promise<Awaited<ReturnType<Builders[K]>>> {\n\t\tif (!(builderName in this.builders)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Factory \"${\n\t\t\t\t\tbuilderName as string\n\t\t\t\t}\" does not exist. Make sure it is correct and registered in src/test/setup.ts`,\n\t\t\t);\n\t\t}\n\n\t\tconst result = await this.builders[builderName](\n\t\t\tattrs || {},\n\t\t\tthis,\n\t\t\tthis.db,\n\t\t\tfaker,\n\t\t);\n\n\t\t// For Kysely, we expect the builder to return an object with table and data properties\n\t\t// or to handle the insertion itself and return the inserted record\n\t\tif (\n\t\t\tresult &&\n\t\t\ttypeof result === 'object' &&\n\t\t\t'table' in result &&\n\t\t\t'data' in result\n\t\t) {\n\t\t\t// If the builder returns {table: string, data: object}, we insert it\n\t\t\tconst inserted = await this.db\n\t\t\t\t.insertInto(result.table)\n\t\t\t\t.values(result.data)\n\t\t\t\t.returningAll()\n\t\t\t\t.executeTakeFirst();\n\n\t\t\treturn inserted as any;\n\t\t}\n\n\t\t// Otherwise, assume the builder handled the insertion itself\n\t\treturn result;\n\t}\n\n\t/**\n\t * Inserts multiple records into the database using the specified builder.\n\t * Supports both static attributes and dynamic attribute generation via a function.\n\t *\n\t * @template K - The builder name (must be a key of Builders)\n\t * @param count - The number of records to insert\n\t * @param builderName - The name of the builder to use\n\t * @param attrs - Static attributes or a function that generates attributes for each record\n\t * @returns A promise resolving to an array of inserted records\n\t * @throws Error if the specified builder doesn't exist\n\t *\n\t * @example\n\t * ```typescript\n\t * // Insert multiple with same attributes\n\t * const users = await factory.insertMany(5, 'user', { role: 'member' });\n\t *\n\t * // Insert multiple with dynamic attributes\n\t * const posts = await factory.insertMany(10, 'post', (idx, faker) => ({\n\t * title: `Post ${idx + 1}`,\n\t * content: faker.lorem.paragraph(),\n\t * publishedAt: faker.date.past()\n\t * }));\n\t *\n\t * // Create users with sequential emails\n\t * const admins = await factory.insertMany(3, 'user', (idx) => ({\n\t * email: `admin${idx + 1}@example.com`,\n\t * role: 'admin'\n\t * }));\n\t * ```\n\t */\n\t// Method overloads for better type inference\n\tasync insertMany<K extends keyof Builders>(\n\t\tcount: number,\n\t\tbuilderName: K,\n\t\tattrs?: Parameters<Builders[K]>[0],\n\t): Promise<Awaited<ReturnType<Builders[K]>>[]>;\n\tasync insertMany<K extends keyof Builders>(\n\t\tcount: number,\n\t\tbuilderName: K,\n\t\tattrs: (\n\t\t\tidx: number,\n\t\t\tfaker: FakerFactory,\n\t\t) => Parameters<Builders[K]>[0] | Promise<Parameters<Builders[K]>[0]>,\n\t): Promise<Awaited<ReturnType<Builders[K]>>[]>;\n\tasync insertMany<K extends keyof Builders>(\n\t\tcount: number,\n\t\tbuilderName: K,\n\t\tattrs?: any,\n\t): Promise<Awaited<ReturnType<Builders[K]>>[]> {\n\t\tif (!(builderName in this.builders)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Builder \"${\n\t\t\t\t\tbuilderName as string\n\t\t\t\t}\" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`,\n\t\t\t);\n\t\t}\n\n\t\tconst promises: Promise<any>[] = [];\n\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tconst newAttrs =\n\t\t\t\ttypeof attrs === 'function' ? await attrs(i, faker) : attrs;\n\t\t\tpromises.push(this.insert(builderName, newAttrs));\n\t\t}\n\n\t\treturn Promise.all(promises);\n\t}\n\n\t/**\n\t * Executes a seed function to create complex test scenarios with multiple related records.\n\t * Seeds are useful for setting up complete test environments with realistic data relationships.\n\t *\n\t * @template K - The seed name (must be a key of Seeds)\n\t * @param seedName - The name of the seed to execute\n\t * @param attrs - Optional configuration attributes for the seed\n\t * @returns The result of the seed function (typically the primary record created)\n\t * @throws Error if the specified seed doesn't exist\n\t *\n\t * @example\n\t * ```typescript\n\t * // Execute a simple seed\n\t * const user = await factory.seed('userWithProfile');\n\t *\n\t * // Execute a seed with configuration\n\t * const author = await factory.seed('authorWithBooks', {\n\t * bookCount: 5,\n\t * includeReviews: true\n\t * });\n\t *\n\t * // Use seed result in tests\n\t * const company = await factory.seed('companyWithDepartments', {\n\t * departmentCount: 3,\n\t * employeesPerDepartment: 10\n\t * });\n\t * expect(company.departments).toHaveLength(3);\n\t * ```\n\t */\n\tseed<K extends keyof Seeds>(\n\t\tseedName: K,\n\t\tattrs?: ExtractSeedAttrs<Seeds[K]>,\n\t): ReturnType<Seeds[K]> {\n\t\tif (!(seedName in this.seeds)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Seed \"${\n\t\t\t\t\tseedName as string\n\t\t\t\t}\" is not registered in this factory. Make sure it is correct and registered in src/test/setup.ts`,\n\t\t\t);\n\t\t}\n\n\t\treturn this.seeds[seedName]({\n\t\t\tattrs: attrs || {},\n\t\t\tfactory: this,\n\t\t\tdb: this.db,\n\t\t});\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,IAAa,gBAAb,cAIU,QAAyB;;;;;;;;;;;;;;;;;;;;;;CAsBlC,OAAgB,WAAqCA,QAAoB;AACxE,SAAO,QAAQ,WAAW,OAAO;CACjC;;;;;;;;CASD,YACSC,UACAC,OACAC,IACP;AACD,SAAO;EAJC;EACA;EACA;CAGR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiDD,OAAO,cASNC,OACAC,UAQAC,YAMoB;AACpB,SAAO,OACNC,OACAC,SACAC,IACAC,kBACI;GAEJ,IAAIC,OAA2C,EAAE,GAAG,MAAO;AAG3D,OAAI,UAAU;IACb,MAAM,gBAAgB,MAAM,SAAS;KACpC;KACA;KACA;KACA,OAAO;IACP,EAAC;AACF,WAAO;KAAE,GAAG;KAAe,GAAG;IAAM;GACpC;AAGD,OAAI,eAAe,OAAO;IAEzB,MAAM,SAAS,MAAM,GACnB,WAAW,MAAM,CACjB,OAAO,KAAkC,CACzC,cAAc,CACd,kBAAkB;AAEpB,SAAK,OACJ,OAAM,IAAI,OAAO,wBAAwB,MAAM;AAGhD,WAAO;GACP,MAEA,QAAO;IAAE;IAAO;GAAM;EAEvB;CACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BD,MAAM,OACLC,aACAC,OAC4C;AAC5C,QAAM,eAAe,KAAK,UACzB,OAAM,IAAI,OACR,WACA,YACA;EAIH,MAAM,SAAS,MAAM,KAAK,SAAS,aAClC,SAAS,CAAE,GACX,MACA,KAAK,IACL,MACA;AAID,MACC,iBACO,WAAW,YAClB,WAAW,UACX,UAAU,QACT;GAED,MAAM,WAAW,MAAM,KAAK,GAC1B,WAAW,OAAO,MAAM,CACxB,OAAO,OAAO,KAAK,CACnB,cAAc,CACd,kBAAkB;AAEpB,UAAO;EACP;AAGD,SAAO;CACP;CA8CD,MAAM,WACLC,OACAF,aACAG,OAC8C;AAC9C,QAAM,eAAe,KAAK,UACzB,OAAM,IAAI,OACR,WACA,YACA;EAIH,MAAMC,WAA2B,CAAE;AAEnC,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;GAC/B,MAAM,kBACE,UAAU,aAAa,MAAM,MAAM,GAAG,MAAM,GAAG;AACvD,YAAS,KAAK,KAAK,OAAO,aAAa,SAAS,CAAC;EACjD;AAED,SAAO,QAAQ,IAAI,SAAS;CAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BD,KACCC,UACAC,OACuB;AACvB,QAAM,YAAY,KAAK,OACtB,OAAM,IAAI,OACR,QACA,SACA;AAIH,SAAO,KAAK,MAAM,UAAU;GAC3B,OAAO,SAAS,CAAE;GAClB,SAAS;GACT,IAAI,KAAK;EACT,EAAC;CACF;AACD"}