@geekmidas/testkit 10.0.0-alpha.4 → 10.0.0-alpha.41

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 (295) hide show
  1. package/README.md +74 -0
  2. package/dist/Factory.cjs +51 -2
  3. package/dist/Factory.cjs.map +1 -0
  4. package/dist/Factory.d.cts +143 -3
  5. package/dist/Factory.d.cts.map +1 -0
  6. package/dist/Factory.d.mts +143 -3
  7. package/dist/Factory.d.mts.map +1 -0
  8. package/dist/Factory.mjs +50 -2
  9. package/dist/Factory.mjs.map +1 -0
  10. package/dist/KyselyFactory.cjs +237 -4
  11. package/dist/KyselyFactory.cjs.map +1 -0
  12. package/dist/KyselyFactory.d.cts +224 -4
  13. package/dist/KyselyFactory.d.cts.map +1 -0
  14. package/dist/KyselyFactory.d.mts +224 -4
  15. package/dist/KyselyFactory.d.mts.map +1 -0
  16. package/dist/KyselyFactory.mjs +236 -4
  17. package/dist/KyselyFactory.mjs.map +1 -0
  18. package/dist/ObjectionFactory.cjs +265 -4
  19. package/dist/ObjectionFactory.cjs.map +1 -0
  20. package/dist/ObjectionFactory.d.cts +237 -4
  21. package/dist/ObjectionFactory.d.cts.map +1 -0
  22. package/dist/ObjectionFactory.d.mts +237 -4
  23. package/dist/ObjectionFactory.d.mts.map +1 -0
  24. package/dist/ObjectionFactory.mjs +264 -4
  25. package/dist/ObjectionFactory.mjs.map +1 -0
  26. package/dist/PostgresKyselyMigrator.cjs +94 -3
  27. package/dist/PostgresKyselyMigrator.cjs.map +1 -0
  28. package/dist/PostgresKyselyMigrator.d.cts +80 -3
  29. package/dist/PostgresKyselyMigrator.d.cts.map +1 -0
  30. package/dist/PostgresKyselyMigrator.d.mts +80 -3
  31. package/dist/PostgresKyselyMigrator.d.mts.map +1 -0
  32. package/dist/PostgresKyselyMigrator.mjs +93 -3
  33. package/dist/PostgresKyselyMigrator.mjs.map +1 -0
  34. package/dist/{PostgresMigrator-C_QQ6q35.d.mts → PostgresMigrator-CDPnnwMJ.d.cts} +11 -5
  35. package/dist/PostgresMigrator-CDPnnwMJ.d.cts.map +1 -0
  36. package/dist/{PostgresMigrator-CeYy-eHF.d.cts → PostgresMigrator-CDPnnwMJ.d.mts} +11 -5
  37. package/dist/PostgresMigrator-CDPnnwMJ.d.mts.map +1 -0
  38. package/dist/PostgresMigrator.cjs +178 -2
  39. package/dist/PostgresMigrator.cjs.map +1 -0
  40. package/dist/PostgresMigrator.d.cts +1 -1
  41. package/dist/PostgresMigrator.d.mts +1 -1
  42. package/dist/PostgresMigrator.mjs +175 -2
  43. package/dist/PostgresMigrator.mjs.map +1 -0
  44. package/dist/PostgresObjectionMigrator.cjs +118 -3
  45. package/dist/PostgresObjectionMigrator.cjs.map +1 -0
  46. package/dist/PostgresObjectionMigrator.d.cts +75 -3
  47. package/dist/PostgresObjectionMigrator.d.cts.map +1 -0
  48. package/dist/PostgresObjectionMigrator.d.mts +75 -3
  49. package/dist/PostgresObjectionMigrator.d.mts.map +1 -0
  50. package/dist/PostgresObjectionMigrator.mjs +117 -3
  51. package/dist/PostgresObjectionMigrator.mjs.map +1 -0
  52. package/dist/VitestKyselyTransactionIsolator.cjs +66 -3
  53. package/dist/VitestKyselyTransactionIsolator.cjs.map +1 -0
  54. package/dist/VitestKyselyTransactionIsolator.d.cts +60 -3
  55. package/dist/VitestKyselyTransactionIsolator.d.cts.map +1 -0
  56. package/dist/VitestKyselyTransactionIsolator.d.mts +60 -3
  57. package/dist/VitestKyselyTransactionIsolator.d.mts.map +1 -0
  58. package/dist/VitestKyselyTransactionIsolator.mjs +65 -3
  59. package/dist/VitestKyselyTransactionIsolator.mjs.map +1 -0
  60. package/dist/VitestObjectionTransactionIsolator.cjs +62 -3
  61. package/dist/VitestObjectionTransactionIsolator.cjs.map +1 -0
  62. package/dist/VitestObjectionTransactionIsolator.d.cts +56 -3
  63. package/dist/VitestObjectionTransactionIsolator.d.cts.map +1 -0
  64. package/dist/VitestObjectionTransactionIsolator.d.mts +56 -3
  65. package/dist/VitestObjectionTransactionIsolator.d.mts.map +1 -0
  66. package/dist/VitestObjectionTransactionIsolator.mjs +61 -3
  67. package/dist/VitestObjectionTransactionIsolator.mjs.map +1 -0
  68. package/dist/VitestTransactionIsolator.cjs +187 -4
  69. package/dist/VitestTransactionIsolator.cjs.map +1 -0
  70. package/dist/VitestTransactionIsolator.d.cts +219 -2
  71. package/dist/VitestTransactionIsolator.d.cts.map +1 -0
  72. package/dist/VitestTransactionIsolator.d.mts +219 -2
  73. package/dist/VitestTransactionIsolator.d.mts.map +1 -0
  74. package/dist/VitestTransactionIsolator.mjs +184 -2
  75. package/dist/VitestTransactionIsolator.mjs.map +1 -0
  76. package/dist/aws.cjs +3 -4
  77. package/dist/aws.cjs.map +1 -1
  78. package/dist/aws.d.cts +3 -8
  79. package/dist/aws.d.cts.map +1 -1
  80. package/dist/aws.d.mts +3 -8
  81. package/dist/aws.d.mts.map +1 -1
  82. package/dist/aws.mjs +1 -2
  83. package/dist/aws.mjs.map +1 -1
  84. package/dist/benchmark.cjs +2 -2
  85. package/dist/benchmark.cjs.map +1 -1
  86. package/dist/benchmark.d.cts +4 -6
  87. package/dist/benchmark.d.cts.map +1 -1
  88. package/dist/benchmark.d.mts +4 -6
  89. package/dist/benchmark.d.mts.map +1 -1
  90. package/dist/benchmark.mjs +1 -1
  91. package/dist/benchmark.mjs.map +1 -1
  92. package/dist/better-auth.cjs +17 -8
  93. package/dist/better-auth.cjs.map +1 -1
  94. package/dist/better-auth.d.cts +13142 -5
  95. package/dist/better-auth.d.cts.map +1 -1
  96. package/dist/better-auth.d.mts +13142 -5
  97. package/dist/better-auth.d.mts.map +1 -1
  98. package/dist/better-auth.mjs +15 -6
  99. package/dist/better-auth.mjs.map +1 -1
  100. package/dist/browser.cjs +127 -0
  101. package/dist/browser.cjs.map +1 -0
  102. package/dist/browser.d.cts +47 -0
  103. package/dist/browser.d.cts.map +1 -0
  104. package/dist/browser.d.mts +47 -0
  105. package/dist/browser.d.mts.map +1 -0
  106. package/dist/browser.mjs +125 -0
  107. package/dist/browser.mjs.map +1 -0
  108. package/dist/context.cjs +80 -0
  109. package/dist/context.cjs.map +1 -0
  110. package/dist/context.d.cts +55 -0
  111. package/dist/context.d.cts.map +1 -0
  112. package/dist/context.d.mts +55 -0
  113. package/dist/context.d.mts.map +1 -0
  114. package/dist/context.mjs +73 -0
  115. package/dist/context.mjs.map +1 -0
  116. package/dist/faker.cjs +313 -8
  117. package/dist/faker.cjs.map +1 -0
  118. package/dist/faker.d.cts +169 -2
  119. package/dist/faker.d.cts.map +1 -0
  120. package/dist/faker.d.mts +169 -2
  121. package/dist/faker.d.mts.map +1 -0
  122. package/dist/faker.mjs +305 -2
  123. package/dist/faker.mjs.map +1 -0
  124. package/dist/helpers.cjs +6 -5
  125. package/dist/helpers.cjs.map +1 -1
  126. package/dist/helpers.d.cts +1 -5
  127. package/dist/helpers.d.cts.map +1 -1
  128. package/dist/helpers.d.mts +1 -5
  129. package/dist/helpers.d.mts.map +1 -1
  130. package/dist/helpers.mjs +1 -2
  131. package/dist/helpers.mjs.map +1 -1
  132. package/dist/initScript.cjs +15 -15
  133. package/dist/initScript.cjs.map +1 -1
  134. package/dist/initScript.d.cts +2 -4
  135. package/dist/initScript.d.cts.map +1 -1
  136. package/dist/initScript.d.mts +2 -4
  137. package/dist/initScript.d.mts.map +1 -1
  138. package/dist/initScript.mjs +10 -12
  139. package/dist/initScript.mjs.map +1 -1
  140. package/dist/kysely.cjs +10 -13
  141. package/dist/kysely.cjs.map +1 -1
  142. package/dist/kysely.d.cts +10 -14
  143. package/dist/kysely.d.cts.map +1 -1
  144. package/dist/kysely.d.mts +10 -14
  145. package/dist/kysely.d.mts.map +1 -1
  146. package/dist/kysely.mjs +10 -14
  147. package/dist/kysely.mjs.map +1 -1
  148. package/dist/logger.cjs +3 -4
  149. package/dist/logger.cjs.map +1 -1
  150. package/dist/logger.d.cts +1 -5
  151. package/dist/logger.d.cts.map +1 -1
  152. package/dist/logger.d.mts +1 -5
  153. package/dist/logger.d.mts.map +1 -1
  154. package/dist/logger.mjs +1 -2
  155. package/dist/logger.mjs.map +1 -1
  156. package/dist/mailbox.cjs +95 -0
  157. package/dist/mailbox.cjs.map +1 -0
  158. package/dist/mailbox.d.cts +58 -0
  159. package/dist/mailbox.d.cts.map +1 -0
  160. package/dist/mailbox.d.mts +58 -0
  161. package/dist/mailbox.d.mts.map +1 -0
  162. package/dist/mailbox.mjs +92 -0
  163. package/dist/mailbox.mjs.map +1 -0
  164. package/dist/objection.cjs +10 -13
  165. package/dist/objection.cjs.map +1 -1
  166. package/dist/objection.d.cts +10 -14
  167. package/dist/objection.d.cts.map +1 -1
  168. package/dist/objection.d.mts +10 -14
  169. package/dist/objection.d.mts.map +1 -1
  170. package/dist/objection.mjs +10 -14
  171. package/dist/objection.mjs.map +1 -1
  172. package/dist/os/directory.cjs +31 -2
  173. package/dist/os/directory.cjs.map +1 -0
  174. package/dist/os/directory.d.cts +9 -2
  175. package/dist/os/directory.d.cts.map +1 -0
  176. package/dist/os/directory.d.mts +9 -2
  177. package/dist/os/directory.d.mts.map +1 -0
  178. package/dist/os/directory.mjs +25 -2
  179. package/dist/os/directory.mjs.map +1 -0
  180. package/dist/os/index.cjs +3 -3
  181. package/dist/os/index.d.cts +1 -1
  182. package/dist/os/index.d.mts +1 -1
  183. package/dist/os/index.mjs +2 -3
  184. package/dist/requestContext.cjs +10 -11
  185. package/dist/requestContext.cjs.map +1 -1
  186. package/dist/requestContext.d.cts +4 -8
  187. package/dist/requestContext.d.cts.map +1 -1
  188. package/dist/requestContext.d.mts +4 -8
  189. package/dist/requestContext.d.mts.map +1 -1
  190. package/dist/requestContext.mjs +1 -2
  191. package/dist/requestContext.mjs.map +1 -1
  192. package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-VH7oDXx4.cjs} +8 -10
  193. package/dist/timer.cjs +2 -2
  194. package/dist/timer.cjs.map +1 -1
  195. package/dist/timer.d.cts +1 -4
  196. package/dist/timer.d.cts.map +1 -1
  197. package/dist/timer.d.mts +1 -4
  198. package/dist/timer.d.mts.map +1 -1
  199. package/dist/timer.mjs +1 -1
  200. package/dist/timer.mjs.map +1 -1
  201. package/dist/transactions.cjs +123 -0
  202. package/dist/transactions.cjs.map +1 -0
  203. package/dist/transactions.d.cts +44 -0
  204. package/dist/transactions.d.cts.map +1 -0
  205. package/dist/transactions.d.mts +44 -0
  206. package/dist/transactions.d.mts.map +1 -0
  207. package/dist/transactions.mjs +118 -0
  208. package/dist/transactions.mjs.map +1 -0
  209. package/package.json +51 -8
  210. package/dist/Factory-AWn1IulI.d.cts +0 -147
  211. package/dist/Factory-AWn1IulI.d.cts.map +0 -1
  212. package/dist/Factory-BFVnMMCC.mjs +0 -51
  213. package/dist/Factory-BFVnMMCC.mjs.map +0 -1
  214. package/dist/Factory-BhjUOBWN.cjs +0 -57
  215. package/dist/Factory-BhjUOBWN.cjs.map +0 -1
  216. package/dist/Factory-C15SSK8_.d.mts +0 -147
  217. package/dist/Factory-C15SSK8_.d.mts.map +0 -1
  218. package/dist/KyselyFactory-BFqVIn_0.cjs +0 -246
  219. package/dist/KyselyFactory-BFqVIn_0.cjs.map +0 -1
  220. package/dist/KyselyFactory-C9Snz24z.d.mts +0 -228
  221. package/dist/KyselyFactory-C9Snz24z.d.mts.map +0 -1
  222. package/dist/KyselyFactory-CxUJCi--.d.cts +0 -228
  223. package/dist/KyselyFactory-CxUJCi--.d.cts.map +0 -1
  224. package/dist/KyselyFactory-DMswpwji.mjs +0 -241
  225. package/dist/KyselyFactory-DMswpwji.mjs.map +0 -1
  226. package/dist/ObjectionFactory-BeFBYcan.cjs +0 -272
  227. package/dist/ObjectionFactory-BeFBYcan.cjs.map +0 -1
  228. package/dist/ObjectionFactory-CYvaa0kU.d.cts +0 -241
  229. package/dist/ObjectionFactory-CYvaa0kU.d.cts.map +0 -1
  230. package/dist/ObjectionFactory-Cf2WI4o_.d.mts +0 -241
  231. package/dist/ObjectionFactory-Cf2WI4o_.d.mts.map +0 -1
  232. package/dist/ObjectionFactory-QCJ7u0Ql.mjs +0 -267
  233. package/dist/ObjectionFactory-QCJ7u0Ql.mjs.map +0 -1
  234. package/dist/PostgresKyselyMigrator-B2M6Gjvv.d.cts +0 -84
  235. package/dist/PostgresKyselyMigrator-B2M6Gjvv.d.cts.map +0 -1
  236. package/dist/PostgresKyselyMigrator-BGBxjnFv.cjs +0 -101
  237. package/dist/PostgresKyselyMigrator-BGBxjnFv.cjs.map +0 -1
  238. package/dist/PostgresKyselyMigrator-CvwXycJE.d.mts +0 -84
  239. package/dist/PostgresKyselyMigrator-CvwXycJE.d.mts.map +0 -1
  240. package/dist/PostgresKyselyMigrator-PI0QhvB1.mjs +0 -95
  241. package/dist/PostgresKyselyMigrator-PI0QhvB1.mjs.map +0 -1
  242. package/dist/PostgresMigrator-C_QQ6q35.d.mts.map +0 -1
  243. package/dist/PostgresMigrator-CeYy-eHF.d.cts.map +0 -1
  244. package/dist/PostgresMigrator-DVAY04qN.mjs +0 -166
  245. package/dist/PostgresMigrator-DVAY04qN.mjs.map +0 -1
  246. package/dist/PostgresMigrator-M9jpzOvN.cjs +0 -172
  247. package/dist/PostgresMigrator-M9jpzOvN.cjs.map +0 -1
  248. package/dist/PostgresObjectionMigrator-1j6YIB1c.d.mts +0 -79
  249. package/dist/PostgresObjectionMigrator-1j6YIB1c.d.mts.map +0 -1
  250. package/dist/PostgresObjectionMigrator-DHVC9h_P.d.cts +0 -79
  251. package/dist/PostgresObjectionMigrator-DHVC9h_P.d.cts.map +0 -1
  252. package/dist/PostgresObjectionMigrator-DSaPhwjY.cjs +0 -123
  253. package/dist/PostgresObjectionMigrator-DSaPhwjY.cjs.map +0 -1
  254. package/dist/PostgresObjectionMigrator-DjPKdUbm.mjs +0 -118
  255. package/dist/PostgresObjectionMigrator-DjPKdUbm.mjs.map +0 -1
  256. package/dist/VitestKyselyTransactionIsolator-1Saieke7.mjs +0 -67
  257. package/dist/VitestKyselyTransactionIsolator-1Saieke7.mjs.map +0 -1
  258. package/dist/VitestKyselyTransactionIsolator-BjJSXryR.cjs +0 -72
  259. package/dist/VitestKyselyTransactionIsolator-BjJSXryR.cjs.map +0 -1
  260. package/dist/VitestKyselyTransactionIsolator-CwlTo6yf.d.mts +0 -64
  261. package/dist/VitestKyselyTransactionIsolator-CwlTo6yf.d.mts.map +0 -1
  262. package/dist/VitestKyselyTransactionIsolator-DJasVuIZ.d.cts +0 -64
  263. package/dist/VitestKyselyTransactionIsolator-DJasVuIZ.d.cts.map +0 -1
  264. package/dist/VitestObjectionTransactionIsolator-B_VSWFum.mjs +0 -63
  265. package/dist/VitestObjectionTransactionIsolator-B_VSWFum.mjs.map +0 -1
  266. package/dist/VitestObjectionTransactionIsolator-CTTjvTPO.d.cts +0 -60
  267. package/dist/VitestObjectionTransactionIsolator-CTTjvTPO.d.cts.map +0 -1
  268. package/dist/VitestObjectionTransactionIsolator-CyZG6nq4.d.mts +0 -60
  269. package/dist/VitestObjectionTransactionIsolator-CyZG6nq4.d.mts.map +0 -1
  270. package/dist/VitestObjectionTransactionIsolator-DDoJTu7e.cjs +0 -68
  271. package/dist/VitestObjectionTransactionIsolator-DDoJTu7e.cjs.map +0 -1
  272. package/dist/VitestTransactionIsolator-BLaw80cx.d.mts +0 -223
  273. package/dist/VitestTransactionIsolator-BLaw80cx.d.mts.map +0 -1
  274. package/dist/VitestTransactionIsolator-CvwPecpl.mjs +0 -188
  275. package/dist/VitestTransactionIsolator-CvwPecpl.mjs.map +0 -1
  276. package/dist/VitestTransactionIsolator-DyiX-QtK.cjs +0 -206
  277. package/dist/VitestTransactionIsolator-DyiX-QtK.cjs.map +0 -1
  278. package/dist/VitestTransactionIsolator-glcxyS_R.d.cts +0 -223
  279. package/dist/VitestTransactionIsolator-glcxyS_R.d.cts.map +0 -1
  280. package/dist/directory-BxjqmtCT.mjs +0 -27
  281. package/dist/directory-BxjqmtCT.mjs.map +0 -1
  282. package/dist/directory-DD_xQoSh.cjs +0 -33
  283. package/dist/directory-DD_xQoSh.cjs.map +0 -1
  284. package/dist/directory-DiQ_DkaF.d.mts +0 -13
  285. package/dist/directory-DiQ_DkaF.d.mts.map +0 -1
  286. package/dist/directory-zIEh5ZPl.d.cts +0 -13
  287. package/dist/directory-zIEh5ZPl.d.cts.map +0 -1
  288. package/dist/faker-B14IEMIN.cjs +0 -304
  289. package/dist/faker-B14IEMIN.cjs.map +0 -1
  290. package/dist/faker-B6bmbGCM.d.mts +0 -166
  291. package/dist/faker-B6bmbGCM.d.mts.map +0 -1
  292. package/dist/faker-BGKYFoCT.mjs +0 -262
  293. package/dist/faker-BGKYFoCT.mjs.map +0 -1
  294. package/dist/faker-DvxiCtxc.d.cts +0 -166
  295. package/dist/faker-DvxiCtxc.d.cts.map +0 -1
@@ -1,4 +1,237 @@
1
- import "./faker-B6bmbGCM.mjs";
2
- import "./Factory-C15SSK8_.mjs";
3
- import { ObjectionFactory } from "./ObjectionFactory-Cf2WI4o_.mjs";
4
- export { ObjectionFactory };
1
+ import { FakerFactory } from "./faker.mjs";
2
+ import { ExtractSeedAttrs, FactorySeed } from "./Factory.mjs";
3
+ import { Knex } from "knex";
4
+ import { Model } from "objection";
5
+ //#region src/ObjectionFactory.d.ts
6
+ /**
7
+ * Factory implementation for Objection.js ORM, providing test data creation utilities.
8
+ * Extends the base Factory class with Objection.js-specific database operations.
9
+ *
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 models with Objection.js
16
+ * class User extends Model {
17
+ * static tableName = 'users';
18
+ * }
19
+ *
20
+ * // Create builders
21
+ * const builders = {
22
+ * user: ObjectionFactory.createBuilder(User, ({ attrs, faker }) => ({
23
+ * id: faker.string.uuid(),
24
+ * name: faker.person.fullName(),
25
+ * email: faker.internet.email(),
26
+ * ...attrs
27
+ * })),
28
+ * post: ObjectionFactory.createBuilder(Post, ({ attrs }) => ({
29
+ * title: 'Test Post',
30
+ * content: 'Test content',
31
+ * ...attrs
32
+ * })),
33
+ * };
34
+ *
35
+ * // Create factory instance
36
+ * const factory = new ObjectionFactory(builders, seeds, knex);
37
+ *
38
+ * // Use in tests
39
+ * const user = await factory.insert('user', { name: 'John Doe' });
40
+ * ```
41
+ */
42
+ export declare class ObjectionFactory<Builders extends Record<string, any>, Seeds extends Record<string, any>> extends Factory<Builders, Seeds> {
43
+ private builders;
44
+ private seeds;
45
+ private db;
46
+ /**
47
+ * Creates a typed seed function with proper type inference.
48
+ * Inherits from the base Factory class implementation.
49
+ *
50
+ * @template Seed - The seed function type
51
+ * @param seedFn - The seed function to wrap (receives { attrs, factory, db } object)
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
+ * ```
66
+ */
67
+ static createSeed<Seed extends FactorySeed>(seedFn: Seed): Seed;
68
+ /**
69
+ * Creates a typed builder function for Objection.js models.
70
+ * This is a utility method that helps create builders with proper type inference.
71
+ *
72
+ * @template TModel - The Objection.js Model class type
73
+ * @template Attrs - The attributes type for the builder (defaults to Partial of model)
74
+ * @template Factory - The factory instance type
75
+ * @template Result - The result type (defaults to the model instance)
76
+ *
77
+ * @param ModelClass - The Objection.js Model class
78
+ * @param defaults - Optional function to provide default values (receives destructured context)
79
+ * @param autoInsert - Whether to automatically insert the record (default: true)
80
+ * @returns A builder function that creates and optionally inserts records
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * // Create a simple builder with defaults - destructure only what you need
85
+ * const userBuilder = ObjectionFactory.createBuilder(User,
86
+ * ({ attrs, faker }) => ({
87
+ * id: faker.string.uuid(),
88
+ * name: faker.person.fullName(),
89
+ * email: faker.internet.email(),
90
+ * createdAt: new Date(),
91
+ * ...attrs
92
+ * })
93
+ * );
94
+ *
95
+ * // Only need faker? Just destructure that
96
+ * const leaveTypeBuilder = ObjectionFactory.createBuilder(LeaveType,
97
+ * ({ faker }) => ({
98
+ * name: faker.helpers.arrayElement(['Annual', 'Sick', 'Maternity']),
99
+ * code: faker.string.alpha({ length: 3, casing: 'upper' }),
100
+ * })
101
+ * );
102
+ *
103
+ * // Create a builder that doesn't auto-insert (useful for nested inserts)
104
+ * const addressBuilder = ObjectionFactory.createBuilder(Address,
105
+ * ({ attrs }) => ({
106
+ * street: '123 Main St',
107
+ * city: 'Anytown',
108
+ * ...attrs
109
+ * }),
110
+ * false // Don't auto-insert
111
+ * );
112
+ *
113
+ * // Use with relations
114
+ * const postBuilder = ObjectionFactory.createBuilder(Post,
115
+ * async ({ attrs, factory, faker }) => ({
116
+ * title: faker.lorem.sentence(),
117
+ * content: faker.lorem.paragraphs(),
118
+ * authorId: attrs.authorId || (await factory.insert('user')).id,
119
+ * ...attrs
120
+ * })
121
+ * );
122
+ * ```
123
+ */
124
+ static createBuilder<TModel extends typeof Model, Attrs extends Partial<InstanceType<TModel>> = Partial<InstanceType<TModel>>, Factory = any, Result = InstanceType<TModel>>(ModelClass: TModel, defaults?: (context: {
125
+ attrs: Attrs;
126
+ factory: Factory;
127
+ db: Knex;
128
+ faker: FakerFactory;
129
+ }) => Partial<InstanceType<TModel>> | Promise<Partial<InstanceType<TModel>>>, autoInsert?: boolean): (attrs: Attrs, factory: Factory, db: Knex, faker: FakerFactory) => Promise<Result>;
130
+ /**
131
+ * Creates a new ObjectionFactory instance.
132
+ *
133
+ * @param builders - Record of builder functions for creating individual entities
134
+ * @param seeds - Record of seed functions for creating complex test scenarios
135
+ * @param db - Knex database connection instance
136
+ */
137
+ constructor(builders: Builders, seeds: Seeds, db: Knex);
138
+ /**
139
+ * Inserts a single record into the database using the specified builder.
140
+ * Uses Objection.js's insertGraph method to handle nested relations.
141
+ *
142
+ * @template K - The builder name (must be a key of Builders)
143
+ * @param builderName - The name of the builder to use
144
+ * @param attrs - Optional attributes to override builder defaults
145
+ * @returns A promise resolving to the inserted record with all relations
146
+ * @throws Error if the specified builder doesn't exist
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * // Insert with defaults
151
+ * const user = await factory.insert('user');
152
+ *
153
+ * // Insert with overrides
154
+ * const adminUser = await factory.insert('user', {
155
+ * email: 'admin@example.com',
156
+ * role: 'admin'
157
+ * });
158
+ *
159
+ * // Insert with nested relations
160
+ * const userWithProfile = await factory.insert('user', {
161
+ * name: 'John Doe',
162
+ * profile: {
163
+ * bio: 'Software Developer',
164
+ * avatar: 'avatar.jpg'
165
+ * }
166
+ * });
167
+ * ```
168
+ */
169
+ insert<K extends keyof Builders>(builderName: K, attrs?: Parameters<Builders[K]>[0]): Promise<Awaited<ReturnType<Builders[K]>>>;
170
+ /**
171
+ * Inserts multiple records into the database using the specified builder.
172
+ * Supports both static attributes and dynamic attribute generation via a function.
173
+ *
174
+ * @param count - The number of records to insert
175
+ * @param builderName - The name of the builder to use
176
+ * @param attrs - Static attributes or a function that generates attributes for each record
177
+ * @returns A promise resolving to an array of inserted records
178
+ * @throws Error if the specified builder doesn't exist
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * // Insert multiple with same attributes
183
+ * const users = await factory.insertMany(5, 'user', { role: 'member' });
184
+ *
185
+ * // Insert multiple with dynamic attributes
186
+ * const posts = await factory.insertMany(10, 'post', (idx) => ({
187
+ * title: `Post ${idx + 1}`,
188
+ * content: `Content for post ${idx + 1}`,
189
+ * publishedAt: new Date()
190
+ * }));
191
+ *
192
+ * // Create users with sequential emails
193
+ * const admins = await factory.insertMany(3, 'user', (idx) => ({
194
+ * email: `admin${idx + 1}@example.com`,
195
+ * role: 'admin'
196
+ * }));
197
+ * ```
198
+ */
199
+ insertMany<K extends keyof Builders>(count: number, builderName: K, attrs?: Parameters<Builders[K]>[0]): Promise<Awaited<ReturnType<Builders[K]>>[]>;
200
+ insertMany<K extends keyof Builders>(count: number, builderName: K, attrs: (idx: number, faker: FakerFactory) => Parameters<Builders[K]>[0]): Promise<Awaited<ReturnType<Builders[K]>>[]>;
201
+ /**
202
+ * Executes a seed function to create complex test scenarios with multiple related records.
203
+ * Seeds are useful for setting up complete test environments with realistic data relationships.
204
+ *
205
+ * @template K - The seed name (must be a key of Seeds)
206
+ * @param seedName - The name of the seed to execute
207
+ * @param attrs - Optional configuration attributes for the seed
208
+ * @returns The result of the seed function (typically the primary record created)
209
+ * @throws Error if the specified seed doesn't exist
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * // Execute a simple seed
214
+ * const user = await factory.seed('userWithProfile');
215
+ *
216
+ * // Execute a seed with configuration
217
+ * const author = await factory.seed('authorWithBooks', {
218
+ * bookCount: 5,
219
+ * includeReviews: true
220
+ * });
221
+ *
222
+ * // Use seed result in tests with Objection.js relations
223
+ * const company = await factory.seed('companyWithDepartments', {
224
+ * departmentCount: 3,
225
+ * employeesPerDepartment: 10
226
+ * });
227
+ *
228
+ * // Access eager loaded relations
229
+ * const companyWithRelations = await Company.query()
230
+ * .findById(company.id)
231
+ * .withGraphFetched('[departments.employees]');
232
+ * ```
233
+ */
234
+ seed<K extends keyof Seeds>(seedName: K, attrs?: ExtractSeedAttrs<Seeds[K]>): ReturnType<Seeds[K]>;
235
+ }
236
+ //#endregion
237
+ //# sourceMappingURL=ObjectionFactory.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectionFactory.d.mts","names":[],"sources":["../src/ObjectionFactory.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAyCa,iBACZ,iBAAiB,qBACjB,cAAc,6BACL,QAAQ,UAAU;UA4JlB;UACA;UACA;;;;;;;;;;;;;;;;;;;;;;SAxIO,WAAW,aAAa,aAAa,QAAQ,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SA4D7D,cACN,sBAAsB,OACtB,cAAc,QAAQ,aAAa,WAAW,QAAQ,aAAa,UACnE,eACA,SAAS,aAAa,SAEtB,YAAY,QACZ,YAAY;IACX,OAAO;IACP,SAAS;IACT,IAAI;IACJ,OAAO;QAEL,QAAQ,aAAa,WACrB,QAAQ,QAAQ,aAAa,WAChC,wBAEA,OAAO,OACP,SAAS,SACT,IAAI,MACJ,OAAO,iBACH,QAAQ;;;;;;;;EAoDb,YACS,UAAU,UACV,OAAO,OACP,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoCP,OAAO,gBAAgB,UAC5B,aAAa,GACb,QAAQ,WAAW,SAAS,SAC1B,QAAQ,QAAQ,WAAW,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+DjC,WAAW,gBAAgB,UAChC,eACA,aAAa,GACb,QAAQ,WAAW,SAAS,SAC1B,QAAQ,QAAQ,WAAW,SAAS;EACjC,WAAW,gBAAgB,UAChC,eACA,aAAa,GACb,QAAQ,aAAa,OAAO,iBAAiB,WAAW,SAAS,SAC/D,QAAQ,QAAQ,WAAW,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgFvC,KAAK,gBAAgB,OACpB,UAAU,GACV,QAAQ,iBAAiB,MAAM,MAC7B,WAAW,MAAM"}
@@ -1,5 +1,265 @@
1
- import "./Factory-BFVnMMCC.mjs";
2
- import "./faker-BGKYFoCT.mjs";
3
- import { ObjectionFactory } from "./ObjectionFactory-QCJ7u0Ql.mjs";
1
+ import { Factory } from "./Factory.mjs";
2
+ import { faker } from "./faker.mjs";
3
+ //#region src/ObjectionFactory.ts
4
+ /**
5
+ * Factory implementation for Objection.js ORM, providing test data creation utilities.
6
+ * Extends the base Factory class with Objection.js-specific database operations.
7
+ *
8
+ * @template Builders - Record of builder functions for creating entities
9
+ * @template Seeds - Record of seed functions for complex test scenarios
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // Define your models with Objection.js
14
+ * class User extends Model {
15
+ * static tableName = 'users';
16
+ * }
17
+ *
18
+ * // Create builders
19
+ * const builders = {
20
+ * user: ObjectionFactory.createBuilder(User, ({ attrs, faker }) => ({
21
+ * id: faker.string.uuid(),
22
+ * name: faker.person.fullName(),
23
+ * email: faker.internet.email(),
24
+ * ...attrs
25
+ * })),
26
+ * post: ObjectionFactory.createBuilder(Post, ({ attrs }) => ({
27
+ * title: 'Test Post',
28
+ * content: 'Test content',
29
+ * ...attrs
30
+ * })),
31
+ * };
32
+ *
33
+ * // Create factory instance
34
+ * const factory = new ObjectionFactory(builders, seeds, knex);
35
+ *
36
+ * // Use in tests
37
+ * const user = await factory.insert('user', { name: 'John Doe' });
38
+ * ```
39
+ */
40
+ var ObjectionFactory = class extends Factory {
41
+ builders;
42
+ seeds;
43
+ db;
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: ObjectionFactory.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 typed builder function for Objection.js models.
70
+ * This is a utility method that helps create builders with proper type inference.
71
+ *
72
+ * @template TModel - The Objection.js Model class type
73
+ * @template Attrs - The attributes type for the builder (defaults to Partial of model)
74
+ * @template Factory - The factory instance type
75
+ * @template Result - The result type (defaults to the model instance)
76
+ *
77
+ * @param ModelClass - The Objection.js Model class
78
+ * @param defaults - Optional function to provide default values (receives destructured context)
79
+ * @param autoInsert - Whether to automatically insert the record (default: true)
80
+ * @returns A builder function that creates and optionally inserts records
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * // Create a simple builder with defaults - destructure only what you need
85
+ * const userBuilder = ObjectionFactory.createBuilder(User,
86
+ * ({ attrs, faker }) => ({
87
+ * id: faker.string.uuid(),
88
+ * name: faker.person.fullName(),
89
+ * email: faker.internet.email(),
90
+ * createdAt: new Date(),
91
+ * ...attrs
92
+ * })
93
+ * );
94
+ *
95
+ * // Only need faker? Just destructure that
96
+ * const leaveTypeBuilder = ObjectionFactory.createBuilder(LeaveType,
97
+ * ({ faker }) => ({
98
+ * name: faker.helpers.arrayElement(['Annual', 'Sick', 'Maternity']),
99
+ * code: faker.string.alpha({ length: 3, casing: 'upper' }),
100
+ * })
101
+ * );
102
+ *
103
+ * // Create a builder that doesn't auto-insert (useful for nested inserts)
104
+ * const addressBuilder = ObjectionFactory.createBuilder(Address,
105
+ * ({ attrs }) => ({
106
+ * street: '123 Main St',
107
+ * city: 'Anytown',
108
+ * ...attrs
109
+ * }),
110
+ * false // Don't auto-insert
111
+ * );
112
+ *
113
+ * // Use with relations
114
+ * const postBuilder = ObjectionFactory.createBuilder(Post,
115
+ * async ({ attrs, factory, faker }) => ({
116
+ * title: faker.lorem.sentence(),
117
+ * content: faker.lorem.paragraphs(),
118
+ * authorId: attrs.authorId || (await factory.insert('user')).id,
119
+ * ...attrs
120
+ * })
121
+ * );
122
+ * ```
123
+ */
124
+ static createBuilder(ModelClass, defaults, autoInsert) {
125
+ return async (attrs, factory, db, fakerInstance) => {
126
+ let data = { ...attrs };
127
+ if (defaults) data = {
128
+ ...await defaults({
129
+ attrs,
130
+ factory,
131
+ db,
132
+ faker: fakerInstance
133
+ }),
134
+ ...data
135
+ };
136
+ const model = ModelClass.fromJson(data);
137
+ if (autoInsert !== false) {
138
+ const insertData = Object.entries(model).reduce((acc, [key, value]) => {
139
+ if (value !== void 0 && key !== "id") acc[key] = value;
140
+ return acc;
141
+ }, {});
142
+ return await ModelClass.query(db).insert(insertData);
143
+ } else return model;
144
+ };
145
+ }
146
+ /**
147
+ * Creates a new ObjectionFactory instance.
148
+ *
149
+ * @param builders - Record of builder functions for creating individual entities
150
+ * @param seeds - Record of seed functions for creating complex test scenarios
151
+ * @param db - Knex database connection instance
152
+ */
153
+ constructor(builders, seeds, db) {
154
+ super();
155
+ this.builders = builders;
156
+ this.seeds = seeds;
157
+ this.db = db;
158
+ }
159
+ /**
160
+ * Inserts a single record into the database using the specified builder.
161
+ * Uses Objection.js's insertGraph method to handle nested relations.
162
+ *
163
+ * @template K - The builder name (must be a key of Builders)
164
+ * @param builderName - The name of the builder to use
165
+ * @param attrs - Optional attributes to override builder defaults
166
+ * @returns A promise resolving to the inserted record with all relations
167
+ * @throws Error if the specified builder doesn't exist
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * // Insert with defaults
172
+ * const user = await factory.insert('user');
173
+ *
174
+ * // Insert with overrides
175
+ * const adminUser = await factory.insert('user', {
176
+ * email: 'admin@example.com',
177
+ * role: 'admin'
178
+ * });
179
+ *
180
+ * // Insert with nested relations
181
+ * const userWithProfile = await factory.insert('user', {
182
+ * name: 'John Doe',
183
+ * profile: {
184
+ * bio: 'Software Developer',
185
+ * avatar: 'avatar.jpg'
186
+ * }
187
+ * });
188
+ * ```
189
+ */
190
+ async insert(builderName, attrs) {
191
+ 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`);
192
+ const result = await this.builders[builderName](attrs || {}, this, this.db, faker);
193
+ if (result && typeof result.$query === "function") {
194
+ const insertData = Object.entries(result).reduce((acc, [key, value]) => {
195
+ if (value !== void 0 && key !== "id") acc[key] = value;
196
+ return acc;
197
+ }, {});
198
+ return await result.constructor.query(this.db).insert(insertData);
199
+ }
200
+ return result;
201
+ }
202
+ async insertMany(count, builderName, attrs) {
203
+ 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`);
204
+ const records = [];
205
+ for (let i = 0; i < count; i++) {
206
+ const newAttrs = typeof attrs === "function" ? await attrs(i, faker) : attrs;
207
+ records.push(this.builders[builderName](newAttrs, this, this.db, faker).then((record) => {
208
+ if (record && typeof record.$query === "function") {
209
+ const insertData = Object.entries(record).reduce((acc, [key, value]) => {
210
+ if (value !== void 0 && key !== "id") acc[key] = value;
211
+ return acc;
212
+ }, {});
213
+ return record.constructor.query(this.db).insert(insertData);
214
+ }
215
+ return record;
216
+ }));
217
+ }
218
+ return Promise.all(records);
219
+ }
220
+ /**
221
+ * Executes a seed function to create complex test scenarios with multiple related records.
222
+ * Seeds are useful for setting up complete test environments with realistic data relationships.
223
+ *
224
+ * @template K - The seed name (must be a key of Seeds)
225
+ * @param seedName - The name of the seed to execute
226
+ * @param attrs - Optional configuration attributes for the seed
227
+ * @returns The result of the seed function (typically the primary record created)
228
+ * @throws Error if the specified seed doesn't exist
229
+ *
230
+ * @example
231
+ * ```typescript
232
+ * // Execute a simple seed
233
+ * const user = await factory.seed('userWithProfile');
234
+ *
235
+ * // Execute a seed with configuration
236
+ * const author = await factory.seed('authorWithBooks', {
237
+ * bookCount: 5,
238
+ * includeReviews: true
239
+ * });
240
+ *
241
+ * // Use seed result in tests with Objection.js relations
242
+ * const company = await factory.seed('companyWithDepartments', {
243
+ * departmentCount: 3,
244
+ * employeesPerDepartment: 10
245
+ * });
246
+ *
247
+ * // Access eager loaded relations
248
+ * const companyWithRelations = await Company.query()
249
+ * .findById(company.id)
250
+ * .withGraphFetched('[departments.employees]');
251
+ * ```
252
+ */
253
+ seed(seedName, attrs) {
254
+ 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`);
255
+ return this.seeds[seedName]({
256
+ attrs: attrs || {},
257
+ factory: this,
258
+ db: this.db
259
+ });
260
+ }
261
+ };
262
+ //#endregion
263
+ export { ObjectionFactory };
4
264
 
5
- export { ObjectionFactory };
265
+ //# sourceMappingURL=ObjectionFactory.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectionFactory.mjs","names":[],"sources":["../src/ObjectionFactory.ts"],"sourcesContent":["import type { Knex } from 'knex';\nimport type { Model } from 'objection';\nimport { type ExtractSeedAttrs, Factory, type FactorySeed } from './Factory';\nimport { type FakerFactory, faker } from './faker';\n\n/**\n * Factory implementation for Objection.js ORM, providing test data creation utilities.\n * Extends the base Factory class with Objection.js-specific database operations.\n *\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 models with Objection.js\n * class User extends Model {\n * static tableName = 'users';\n * }\n *\n * // Create builders\n * const builders = {\n * user: ObjectionFactory.createBuilder(User, ({ attrs, faker }) => ({\n * id: faker.string.uuid(),\n * name: faker.person.fullName(),\n * email: faker.internet.email(),\n * ...attrs\n * })),\n * post: ObjectionFactory.createBuilder(Post, ({ attrs }) => ({\n * title: 'Test Post',\n * content: 'Test content',\n * ...attrs\n * })),\n * };\n *\n * // Create factory instance\n * const factory = new ObjectionFactory(builders, seeds, knex);\n *\n * // Use in tests\n * const user = await factory.insert('user', { name: 'John Doe' });\n * ```\n */\nexport class ObjectionFactory<\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: ObjectionFactory.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 typed builder function for Objection.js models.\n\t * This is a utility method that helps create builders with proper type inference.\n\t *\n\t * @template TModel - The Objection.js Model class type\n\t * @template Attrs - The attributes type for the builder (defaults to Partial of model)\n\t * @template Factory - The factory instance type\n\t * @template Result - The result type (defaults to the model instance)\n\t *\n\t * @param ModelClass - The Objection.js Model class\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 = ObjectionFactory.createBuilder(User,\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 = ObjectionFactory.createBuilder(LeaveType,\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 = ObjectionFactory.createBuilder(Address,\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 * // Use with relations\n\t * const postBuilder = ObjectionFactory.createBuilder(Post,\n\t * async ({ attrs, factory, faker }) => ({\n\t * title: faker.lorem.sentence(),\n\t * content: faker.lorem.paragraphs(),\n\t * authorId: attrs.authorId || (await factory.insert('user')).id,\n\t * ...attrs\n\t * })\n\t * );\n\t * ```\n\t */\n\tstatic createBuilder<\n\t\tTModel extends typeof Model,\n\t\tAttrs extends Partial<InstanceType<TModel>> = Partial<InstanceType<TModel>>,\n\t\tFactory = any,\n\t\tResult = InstanceType<TModel>,\n\t>(\n\t\tModelClass: TModel,\n\t\tdefaults?: (context: {\n\t\t\tattrs: Attrs;\n\t\t\tfactory: Factory;\n\t\t\tdb: Knex;\n\t\t\tfaker: FakerFactory;\n\t\t}) =>\n\t\t\t| Partial<InstanceType<TModel>>\n\t\t\t| Promise<Partial<InstanceType<TModel>>>,\n\t\tautoInsert?: boolean,\n\t): (\n\t\tattrs: Attrs,\n\t\tfactory: Factory,\n\t\tdb: Knex,\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: Knex,\n\t\t\tfakerInstance: FakerFactory,\n\t\t) => {\n\t\t\t// Start with attributes\n\t\t\tlet data: Partial<InstanceType<TModel>> = { ...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// Create model instance\n\t\t\tconst model = ModelClass.fromJson(data) as InstanceType<TModel>;\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\t// Extract only defined values for insertion\n\t\t\t\tconst insertData = Object.entries(model).reduce((acc, [key, value]) => {\n\t\t\t\t\tif (value !== undefined && key !== 'id') {\n\t\t\t\t\t\tacc[key] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn acc;\n\t\t\t\t}, {} as any);\n\n\t\t\t\t// Use static query method to insert data directly\n\t\t\t\tconst result = await ModelClass.query(db).insert(insertData);\n\t\t\t\treturn result as Result;\n\t\t\t} else {\n\t\t\t\t// Return model for factory to handle insertion\n\t\t\t\treturn model as Result;\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Creates a new ObjectionFactory 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 - Knex database connection instance\n\t */\n\tconstructor(\n\t\tprivate builders: Builders,\n\t\tprivate seeds: Seeds,\n\t\tprivate db: Knex,\n\t) {\n\t\tsuper();\n\t}\n\n\t/**\n\t * Inserts a single record into the database using the specified builder.\n\t * Uses Objection.js's insertGraph method to handle nested relations.\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 with all relations\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 * // Insert with nested relations\n\t * const userWithProfile = await factory.insert('user', {\n\t * name: 'John Doe',\n\t * profile: {\n\t * bio: 'Software Developer',\n\t * avatar: 'avatar.jpg'\n\t * }\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// If the builder returns a model instance, insert it\n\t\tif (result && typeof result.$query === 'function') {\n\t\t\t// Extract data from model, excluding undefined values and id\n\t\t\tconst insertData = Object.entries(result).reduce((acc, [key, value]) => {\n\t\t\t\tif (value !== undefined && key !== 'id') {\n\t\t\t\t\tacc[key] = value;\n\t\t\t\t}\n\t\t\t\treturn acc;\n\t\t\t}, {} as any);\n\n\t\t\t// Use the model's constructor to get the query builder\n\t\t\treturn await result.constructor.query(this.db).insert(insertData);\n\t\t}\n\n\t\t// Otherwise, assume the builder handled insertion itself\n\t\treturn result;\n\t}\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 * @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) => ({\n\t * title: `Post ${idx + 1}`,\n\t * content: `Content for post ${idx + 1}`,\n\t * publishedAt: new Date()\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: (idx: number, faker: FakerFactory) => 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 records: any[] = [];\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tconst newAttrs =\n\t\t\t\ttypeof attrs === 'function' ? await (attrs as any)(i, faker) : attrs;\n\n\t\t\trecords.push(\n\t\t\t\tthis.builders[builderName](newAttrs, this, this.db, faker).then(\n\t\t\t\t\t(record: any) => {\n\t\t\t\t\t\t// If the builder returns a model instance, insert it\n\t\t\t\t\t\tif (record && typeof record.$query === 'function') {\n\t\t\t\t\t\t\t// Extract data from model, excluding undefined values and id\n\t\t\t\t\t\t\tconst insertData = Object.entries(record).reduce(\n\t\t\t\t\t\t\t\t(acc, [key, value]) => {\n\t\t\t\t\t\t\t\t\tif (value !== undefined && key !== 'id') {\n\t\t\t\t\t\t\t\t\t\tacc[key] = value;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn acc;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{} as any,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// Use the model's constructor to get the query builder\n\t\t\t\t\t\t\treturn record.constructor.query(this.db).insert(insertData);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Otherwise, assume the builder handled insertion itself\n\t\t\t\t\t\treturn record;\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\treturn Promise.all(records);\n\t}\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 with Objection.js relations\n\t * const company = await factory.seed('companyWithDepartments', {\n\t * departmentCount: 3,\n\t * employeesPerDepartment: 10\n\t * });\n\t *\n\t * // Access eager loaded relations\n\t * const companyWithRelations = await Company.query()\n\t * .findById(company.id)\n\t * .withGraphFetched('[departments.employees]');\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,IAAa,mBAAb,cAGU,QAAyB;CA4JzB;CACA;CACA;;;;;;;;;;;;;;;;;;;;;;CAxIT,OAAgB,WAAqC,QAAoB;EACxE,OAAO,QAAQ,WAAW,MAAM;CACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0DA,OAAO,cAMN,YACA,UAQA,YAMoB;EACpB,OAAO,OACN,OACA,SACA,IACA,kBACI;GAEJ,IAAI,OAAsC,EAAE,GAAG,MAAM;GAGrD,IAAI,UAOH,OAAO;IAAE,GAAG,MANgB,SAAS;KACpC;KACA;KACA;KACA,OAAO;IACR,CAAC;IAC0B,GAAG;GAAK;GAIpC,MAAM,QAAQ,WAAW,SAAS,IAAI;GAGtC,IAAI,eAAe,OAAO;IAGzB,MAAM,aAAa,OAAO,QAAQ,KAAK,CAAC,CAAC,QAAQ,KAAK,CAAC,KAAK,WAAW;KACtE,IAAI,UAAU,KAAA,KAAa,QAAQ,MAClC,IAAI,OAAO;KAEZ,OAAO;IACR,GAAG,CAAC,CAAQ;IAIZ,OAAO,MADc,WAAW,MAAM,EAAE,CAAC,CAAC,OAAO,UAAU;GAE5D,OAEC,OAAO;EAET;CACD;;;;;;;;CASA,YACC,UACA,OACA,IACC;EACD,MAAM;EAJE,KAAA,WAAA;EACA,KAAA,QAAA;EACA,KAAA,KAAA;CAGT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCA,MAAM,OACL,aACA,OAC4C;EAC5C,IAAI,EAAE,eAAe,KAAK,WACzB,MAAM,IAAI,MACT,YACC,YACA,8EACF;EAGD,MAAM,SAAS,MAAM,KAAK,SAAS,YAAY,CAC9C,SAAS,CAAC,GACV,MACA,KAAK,IACL,KACD;EAGA,IAAI,UAAU,OAAO,OAAO,WAAW,YAAY;GAElD,MAAM,aAAa,OAAO,QAAQ,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,KAAK,WAAW;IACvE,IAAI,UAAU,KAAA,KAAa,QAAQ,MAClC,IAAI,OAAO;IAEZ,OAAO;GACR,GAAG,CAAC,CAAQ;GAGZ,OAAO,MAAM,OAAO,YAAY,MAAM,KAAK,EAAE,CAAC,CAAC,OAAO,UAAU;EACjE;EAGA,OAAO;CACR;CAyCA,MAAM,WACL,OACA,aACA,OAC8C;EAC9C,IAAI,EAAE,eAAe,KAAK,WACzB,MAAM,IAAI,MACT,YACC,YACA,iGACF;EAGD,MAAM,UAAiB,CAAC;EACxB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;GAC/B,MAAM,WACL,OAAO,UAAU,aAAa,MAAO,MAAc,GAAG,KAAK,IAAI;GAEhE,QAAQ,KACP,KAAK,SAAS,YAAY,CAAC,UAAU,MAAM,KAAK,IAAI,KAAK,CAAC,CAAC,MACzD,WAAgB;IAEhB,IAAI,UAAU,OAAO,OAAO,WAAW,YAAY;KAElD,MAAM,aAAa,OAAO,QAAQ,MAAM,CAAC,CAAC,QACxC,KAAK,CAAC,KAAK,WAAW;MACtB,IAAI,UAAU,KAAA,KAAa,QAAQ,MAClC,IAAI,OAAO;MAEZ,OAAO;KACR,GACA,CAAC,CACF;KAGA,OAAO,OAAO,YAAY,MAAM,KAAK,EAAE,CAAC,CAAC,OAAO,UAAU;IAC3D;IAEA,OAAO;GACR,CACD,CACD;EACD;EAEA,OAAO,QAAQ,IAAI,OAAO;CAC3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCA,KACC,UACA,OACuB;EACvB,IAAI,EAAE,YAAY,KAAK,QACtB,MAAM,IAAI,MACT,SACC,SACA,iGACF;EAGD,OAAO,KAAK,MAAM,SAAS,CAAC;GAC3B,OAAO,SAAS,CAAC;GACjB,SAAS;GACT,IAAI,KAAK;EACV,CAAC;CACF;AACD"}
@@ -1,4 +1,95 @@
1
- require('./PostgresMigrator-M9jpzOvN.cjs');
2
- const require_PostgresKyselyMigrator = require('./PostgresKyselyMigrator-BGBxjnFv.cjs');
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_PostgresMigrator = require("./PostgresMigrator.cjs");
3
+ let kysely_migration = require("kysely/migration");
4
+ //#region src/PostgresKyselyMigrator.ts
5
+ /**
6
+ * Default logger instance for migration operations.
7
+ */
8
+ const logger = console;
9
+ /**
10
+ * PostgreSQL migrator implementation for Kysely ORM.
11
+ * Extends PostgresMigrator to provide Kysely-specific migration functionality.
12
+ * Automatically creates test databases and applies migrations for testing environments.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { FileMigrationProvider } from 'kysely';
17
+ * import { PostgresKyselyMigrator } from '@geekmidas/testkit';
18
+ *
19
+ * // Create migration provider
20
+ * const provider = new FileMigrationProvider({
21
+ * fs: require('fs'),
22
+ * path: require('path'),
23
+ * migrationFolder: path.join(__dirname, 'migrations')
24
+ * });
25
+ *
26
+ * // Create Kysely instance
27
+ * const db = new Kysely<Database>({
28
+ * dialect: new PostgresDialect({
29
+ * pool: new Pool({ connectionString: uri })
30
+ * })
31
+ * });
32
+ *
33
+ * // Create and use migrator
34
+ * const migrator = new PostgresKyselyMigrator({
35
+ * uri: 'postgresql://localhost:5432/test_db',
36
+ * db,
37
+ * provider
38
+ * });
39
+ *
40
+ * const cleanup = await migrator.start();
41
+ * // Run tests...
42
+ * await cleanup();
43
+ *
44
+ * // With afterCreate hook to create per-app users
45
+ * import { runInitScript } from '@geekmidas/testkit/postgres';
46
+ *
47
+ * const migrator = new PostgresKyselyMigrator({
48
+ * uri: 'postgresql://localhost:5432/test_db',
49
+ * db,
50
+ * provider,
51
+ * afterCreate: async (uri) => {
52
+ * await runInitScript('docker/postgres/init.sh', uri, env);
53
+ * },
54
+ * });
55
+ * ```
56
+ */
57
+ var PostgresKyselyMigrator = class extends require_PostgresMigrator.PostgresMigrator {
58
+ options;
59
+ /**
60
+ * Creates a new PostgresKyselyMigrator instance.
61
+ *
62
+ * @param options - Configuration options
63
+ * @param options.uri - PostgreSQL connection URI
64
+ * @param options.db - Kysely database instance
65
+ * @param options.provider - Migration provider for locating migration files
66
+ * @param options.afterCreate - Optional hook called after database creation but before migrations
67
+ */
68
+ constructor(options) {
69
+ super(options.uri, options.afterCreate);
70
+ this.options = options;
71
+ }
72
+ /**
73
+ * Executes Kysely migrations to the latest version.
74
+ * Implements the abstract migrate() method from PostgresMigrator.
75
+ *
76
+ * @throws Error if migrations fail to apply
77
+ * @returns Promise that resolves when all migrations are applied
78
+ */
79
+ async migrate() {
80
+ const migrations = await new kysely_migration.Migrator({
81
+ db: this.options.db,
82
+ provider: this.options.provider
83
+ }).migrateToLatest();
84
+ if (migrations.error) {
85
+ logger.error(migrations.error, `Failed to apply migrations`);
86
+ throw migrations.error;
87
+ }
88
+ await this.options.db.destroy();
89
+ logger.log(`Applied ${migrations.results?.length} migrations successfully`);
90
+ }
91
+ };
92
+ //#endregion
93
+ exports.PostgresKyselyMigrator = PostgresKyselyMigrator;
3
94
 
4
- exports.PostgresKyselyMigrator = require_PostgresKyselyMigrator.PostgresKyselyMigrator;
95
+ //# sourceMappingURL=PostgresKyselyMigrator.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresKyselyMigrator.cjs","names":["PostgresMigrator","Migrator"],"sources":["../src/PostgresKyselyMigrator.ts"],"sourcesContent":["import type { Kysely } from 'kysely';\n// `Migrator` and the `MigrationProvider` type moved from the root barrel ('kysely')\n// to the 'kysely/migration' subpath in kysely 0.29+.\nimport { type MigrationProvider, Migrator } from 'kysely/migration';\nimport { PostgresMigrator } from './PostgresMigrator';\n\n/**\n * Default logger instance for migration operations.\n */\nconst logger = console;\n\n/**\n * PostgreSQL migrator implementation for Kysely ORM.\n * Extends PostgresMigrator to provide Kysely-specific migration functionality.\n * Automatically creates test databases and applies migrations for testing environments.\n *\n * @example\n * ```typescript\n * import { FileMigrationProvider } from 'kysely';\n * import { PostgresKyselyMigrator } from '@geekmidas/testkit';\n *\n * // Create migration provider\n * const provider = new FileMigrationProvider({\n * fs: require('fs'),\n * path: require('path'),\n * migrationFolder: path.join(__dirname, 'migrations')\n * });\n *\n * // Create Kysely instance\n * const db = new Kysely<Database>({\n * dialect: new PostgresDialect({\n * pool: new Pool({ connectionString: uri })\n * })\n * });\n *\n * // Create and use migrator\n * const migrator = new PostgresKyselyMigrator({\n * uri: 'postgresql://localhost:5432/test_db',\n * db,\n * provider\n * });\n *\n * const cleanup = await migrator.start();\n * // Run tests...\n * await cleanup();\n *\n * // With afterCreate hook to create per-app users\n * import { runInitScript } from '@geekmidas/testkit/postgres';\n *\n * const migrator = new PostgresKyselyMigrator({\n * uri: 'postgresql://localhost:5432/test_db',\n * db,\n * provider,\n * afterCreate: async (uri) => {\n * await runInitScript('docker/postgres/init.sh', uri, env);\n * },\n * });\n * ```\n */\nexport class PostgresKyselyMigrator extends PostgresMigrator {\n\t/**\n\t * Creates a new PostgresKyselyMigrator instance.\n\t *\n\t * @param options - Configuration options\n\t * @param options.uri - PostgreSQL connection URI\n\t * @param options.db - Kysely database instance\n\t * @param options.provider - Migration provider for locating migration files\n\t * @param options.afterCreate - Optional hook called after database creation but before migrations\n\t */\n\tconstructor(\n\t\tprivate options: {\n\t\t\turi: string;\n\t\t\tdb: Kysely<any>;\n\t\t\tprovider: MigrationProvider;\n\t\t\tafterCreate?: (uri: string) => Promise<void>;\n\t\t},\n\t) {\n\t\tsuper(options.uri, options.afterCreate);\n\t}\n\n\t/**\n\t * Executes Kysely migrations to the latest version.\n\t * Implements the abstract migrate() method from PostgresMigrator.\n\t *\n\t * @throws Error if migrations fail to apply\n\t * @returns Promise that resolves when all migrations are applied\n\t */\n\tasync migrate(): Promise<void> {\n\t\tconst migrator = new Migrator({\n\t\t\tdb: this.options.db,\n\t\t\tprovider: this.options.provider,\n\t\t});\n\t\tconst migrations = await migrator.migrateToLatest();\n\n\t\tif (migrations.error) {\n\t\t\tlogger.error(migrations.error, `Failed to apply migrations`);\n\t\t\tthrow migrations.error;\n\t\t}\n\n\t\tawait this.options.db.destroy();\n\n\t\tlogger.log(`Applied ${migrations.results?.length} migrations successfully`);\n\t}\n}\n"],"mappings":";;;;;;;AASA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDf,IAAa,yBAAb,cAA4CA,yBAAAA,iBAAiB;CAWnD;;;;;;;;;;CADT,YACC,SAMC;EACD,MAAM,QAAQ,KAAK,QAAQ,WAAW;EAP9B,KAAA,UAAA;CAQT;;;;;;;;CASA,MAAM,UAAyB;EAK9B,MAAM,aAAa,MAAM,IAJJC,iBAAAA,SAAS;GAC7B,IAAI,KAAK,QAAQ;GACjB,UAAU,KAAK,QAAQ;EACxB,CACgC,CAAC,CAAC,gBAAgB;EAElD,IAAI,WAAW,OAAO;GACrB,OAAO,MAAM,WAAW,OAAO,4BAA4B;GAC3D,MAAM,WAAW;EAClB;EAEA,MAAM,KAAK,QAAQ,GAAG,QAAQ;EAE9B,OAAO,IAAI,WAAW,WAAW,SAAS,OAAO,yBAAyB;CAC3E;AACD"}