@geekmidas/testkit 0.4.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/Factory-BFVnMMCC.mjs.map +1 -1
  3. package/dist/{Factory-c16c27Y6.d.cts → Factory-BOX312yd.d.cts} +3 -2
  4. package/dist/Factory-BOX312yd.d.cts.map +1 -0
  5. package/dist/Factory-BhjUOBWN.cjs.map +1 -1
  6. package/dist/{Factory-BcGJjLc8.d.mts → Factory-SFupxRC2.d.mts} +2 -1
  7. package/dist/Factory-SFupxRC2.d.mts.map +1 -0
  8. package/dist/Factory.d.cts +2 -2
  9. package/dist/Factory.d.mts +1 -1
  10. package/dist/KyselyFactory-BFqVIn_0.cjs.map +1 -1
  11. package/dist/KyselyFactory-DMswpwji.mjs.map +1 -1
  12. package/dist/{KyselyFactory-uZ45h7YU.d.cts → KyselyFactory-Dy5zzV4B.d.cts} +4 -3
  13. package/dist/KyselyFactory-Dy5zzV4B.d.cts.map +1 -0
  14. package/dist/{KyselyFactory-Cj-EultY.d.mts → KyselyFactory-vAxYodck.d.mts} +3 -2
  15. package/dist/KyselyFactory-vAxYodck.d.mts.map +1 -0
  16. package/dist/KyselyFactory.d.cts +3 -3
  17. package/dist/KyselyFactory.d.mts +2 -2
  18. package/dist/{ObjectionFactory-DL4qkuF1.d.mts → ObjectionFactory-BWjB49-i.d.mts} +3 -2
  19. package/dist/ObjectionFactory-BWjB49-i.d.mts.map +1 -0
  20. package/dist/ObjectionFactory-BeFBYcan.cjs.map +1 -1
  21. package/dist/{ObjectionFactory-CdhzKs4f.d.cts → ObjectionFactory-CD-WFuMJ.d.cts} +4 -3
  22. package/dist/ObjectionFactory-CD-WFuMJ.d.cts.map +1 -0
  23. package/dist/ObjectionFactory-QCJ7u0Ql.mjs.map +1 -1
  24. package/dist/ObjectionFactory.d.cts +3 -3
  25. package/dist/ObjectionFactory.d.mts +2 -2
  26. package/dist/{PostgresKyselyMigrator-upT-hmrz.mjs → PostgresKyselyMigrator-6sE1KOni.mjs} +2 -2
  27. package/dist/PostgresKyselyMigrator-6sE1KOni.mjs.map +1 -0
  28. package/dist/{PostgresKyselyMigrator-CIx3AFSR.d.mts → PostgresKyselyMigrator-CBltSOq5.d.cts} +3 -2
  29. package/dist/PostgresKyselyMigrator-CBltSOq5.d.cts.map +1 -0
  30. package/dist/{PostgresKyselyMigrator-CfytARcA.cjs → PostgresKyselyMigrator-D6IbPq8t.cjs} +2 -2
  31. package/dist/PostgresKyselyMigrator-D6IbPq8t.cjs.map +1 -0
  32. package/dist/{PostgresKyselyMigrator-CQ3aUoy_.d.cts → PostgresKyselyMigrator-DrVWncqd.d.mts} +3 -2
  33. package/dist/PostgresKyselyMigrator-DrVWncqd.d.mts.map +1 -0
  34. package/dist/PostgresKyselyMigrator.cjs +2 -2
  35. package/dist/PostgresKyselyMigrator.d.cts +2 -2
  36. package/dist/PostgresKyselyMigrator.d.mts +2 -2
  37. package/dist/PostgresKyselyMigrator.mjs +2 -2
  38. package/dist/{PostgresMigrator-DbuJGAVy.mjs → PostgresMigrator-BjjenqSd.mjs} +2 -2
  39. package/dist/PostgresMigrator-BjjenqSd.mjs.map +1 -0
  40. package/dist/{PostgresMigrator-D5UkK1_K.d.cts → PostgresMigrator-Bres0U6E.d.cts} +2 -1
  41. package/dist/PostgresMigrator-Bres0U6E.d.cts.map +1 -0
  42. package/dist/{PostgresMigrator-DFcNdCvD.cjs → PostgresMigrator-D6dQn0x2.cjs} +2 -2
  43. package/dist/PostgresMigrator-D6dQn0x2.cjs.map +1 -0
  44. package/dist/{PostgresMigrator-DQaRxoaY.d.mts → PostgresMigrator-S-YYosAC.d.mts} +2 -1
  45. package/dist/PostgresMigrator-S-YYosAC.d.mts.map +1 -0
  46. package/dist/PostgresMigrator.cjs +1 -1
  47. package/dist/PostgresMigrator.d.cts +1 -1
  48. package/dist/PostgresMigrator.d.mts +1 -1
  49. package/dist/PostgresMigrator.mjs +1 -1
  50. package/dist/{PostgresObjectionMigrator-CZHHcCOv.d.cts → PostgresObjectionMigrator-CPfBAP7r.d.cts} +3 -2
  51. package/dist/PostgresObjectionMigrator-CPfBAP7r.d.cts.map +1 -0
  52. package/dist/{PostgresObjectionMigrator-BG6ymgnt.cjs → PostgresObjectionMigrator-DK8ODIHQ.cjs} +2 -2
  53. package/dist/PostgresObjectionMigrator-DK8ODIHQ.cjs.map +1 -0
  54. package/dist/{PostgresObjectionMigrator-D_hCcrQu.d.mts → PostgresObjectionMigrator-DVEqB5tp.d.mts} +3 -2
  55. package/dist/PostgresObjectionMigrator-DVEqB5tp.d.mts.map +1 -0
  56. package/dist/{PostgresObjectionMigrator-DPj2pOpX.mjs → PostgresObjectionMigrator-D_QxXbIN.mjs} +2 -2
  57. package/dist/PostgresObjectionMigrator-D_QxXbIN.mjs.map +1 -0
  58. package/dist/PostgresObjectionMigrator.cjs +2 -2
  59. package/dist/PostgresObjectionMigrator.d.cts +2 -2
  60. package/dist/PostgresObjectionMigrator.d.mts +2 -2
  61. package/dist/PostgresObjectionMigrator.mjs +2 -2
  62. package/dist/{VitestKyselyTransactionIsolator-D3EZZhjZ.d.cts → VitestKyselyTransactionIsolator-CduJlHoT.d.cts} +4 -3
  63. package/dist/VitestKyselyTransactionIsolator-CduJlHoT.d.cts.map +1 -0
  64. package/dist/{VitestKyselyTransactionIsolator-Dxlp1u0f.d.mts → VitestKyselyTransactionIsolator-Cswnnj0k.d.mts} +4 -3
  65. package/dist/VitestKyselyTransactionIsolator-Cswnnj0k.d.mts.map +1 -0
  66. package/dist/{VitestKyselyTransactionIsolator-EvDLk5zg.cjs → VitestKyselyTransactionIsolator-D7RRXOBa.cjs} +2 -2
  67. package/dist/VitestKyselyTransactionIsolator-D7RRXOBa.cjs.map +1 -0
  68. package/dist/{VitestKyselyTransactionIsolator-CNURW8y6.mjs → VitestKyselyTransactionIsolator-DceyIqr4.mjs} +2 -2
  69. package/dist/VitestKyselyTransactionIsolator-DceyIqr4.mjs.map +1 -0
  70. package/dist/VitestKyselyTransactionIsolator.cjs +1 -1
  71. package/dist/VitestKyselyTransactionIsolator.d.cts +2 -2
  72. package/dist/VitestKyselyTransactionIsolator.d.mts +2 -2
  73. package/dist/VitestKyselyTransactionIsolator.mjs +1 -1
  74. package/dist/{VitestObjectionTransactionIsolator-1TpsPqfG.d.cts → VitestObjectionTransactionIsolator-BXoR6xdG.d.cts} +4 -3
  75. package/dist/VitestObjectionTransactionIsolator-BXoR6xdG.d.cts.map +1 -0
  76. package/dist/{VitestObjectionTransactionIsolator-CM5KTAFA.cjs → VitestObjectionTransactionIsolator-CdLRrzNf.cjs} +2 -2
  77. package/dist/VitestObjectionTransactionIsolator-CdLRrzNf.cjs.map +1 -0
  78. package/dist/{VitestObjectionTransactionIsolator-jQFaCz0u.mjs → VitestObjectionTransactionIsolator-OF2osYY5.mjs} +2 -2
  79. package/dist/VitestObjectionTransactionIsolator-OF2osYY5.mjs.map +1 -0
  80. package/dist/{VitestObjectionTransactionIsolator-i9jIgU8Q.d.mts → VitestObjectionTransactionIsolator-x6hY5j4u.d.mts} +4 -3
  81. package/dist/VitestObjectionTransactionIsolator-x6hY5j4u.d.mts.map +1 -0
  82. package/dist/VitestObjectionTransactionIsolator.cjs +1 -1
  83. package/dist/VitestObjectionTransactionIsolator.d.cts +2 -2
  84. package/dist/VitestObjectionTransactionIsolator.d.mts +2 -2
  85. package/dist/VitestObjectionTransactionIsolator.mjs +1 -1
  86. package/dist/{VitestTransactionIsolator-BvR19bYn.d.mts → VitestTransactionIsolator-BNWJqh9f.d.mts} +3 -2
  87. package/dist/VitestTransactionIsolator-BNWJqh9f.d.mts.map +1 -0
  88. package/dist/VitestTransactionIsolator-CMfJXZP8.cjs.map +1 -1
  89. package/dist/{VitestTransactionIsolator-CwQaxZLP.d.cts → VitestTransactionIsolator-CSroc7Df.d.cts} +3 -2
  90. package/dist/VitestTransactionIsolator-CSroc7Df.d.cts.map +1 -0
  91. package/dist/VitestTransactionIsolator-DQ7tLqgV.mjs.map +1 -1
  92. package/dist/VitestTransactionIsolator.d.cts +1 -1
  93. package/dist/VitestTransactionIsolator.d.mts +1 -1
  94. package/dist/aws.cjs.map +1 -1
  95. package/dist/aws.d.cts +2 -0
  96. package/dist/aws.d.cts.map +1 -0
  97. package/dist/aws.d.mts +2 -0
  98. package/dist/aws.d.mts.map +1 -0
  99. package/dist/aws.mjs.map +1 -1
  100. package/dist/benchmark.cjs.map +1 -1
  101. package/dist/benchmark.d.cts +1 -0
  102. package/dist/benchmark.d.cts.map +1 -0
  103. package/dist/benchmark.d.mts +1 -0
  104. package/dist/benchmark.d.mts.map +1 -0
  105. package/dist/benchmark.mjs.map +1 -1
  106. package/dist/better-auth.cjs +29 -30
  107. package/dist/better-auth.cjs.map +1 -1
  108. package/dist/better-auth.d.cts +2 -2
  109. package/dist/better-auth.d.cts.map +1 -0
  110. package/dist/better-auth.d.mts.map +1 -0
  111. package/dist/better-auth.mjs +29 -30
  112. package/dist/better-auth.mjs.map +1 -1
  113. package/dist/directory-B-Ozljzk.mjs.map +1 -1
  114. package/dist/directory-BVC8g7cX.cjs.map +1 -1
  115. package/dist/{directory-BXavAeJZ.d.mts → directory-CVrfTq1I.d.mts} +2 -1
  116. package/dist/directory-CVrfTq1I.d.mts.map +1 -0
  117. package/dist/{directory-Mi7tdOuD.d.cts → directory-DAnMWi50.d.cts} +2 -1
  118. package/dist/directory-DAnMWi50.d.cts.map +1 -0
  119. package/dist/faker-B14IEMIN.cjs.map +1 -1
  120. package/dist/faker-BGKYFoCT.mjs.map +1 -1
  121. package/dist/{faker-DvxiCtxc.d.cts → faker-Cg76aFNO.d.cts} +3 -3
  122. package/dist/faker-Cg76aFNO.d.cts.map +1 -0
  123. package/dist/faker-DHh7xs4u.d.mts.map +1 -0
  124. package/dist/faker.d.cts +1 -1
  125. package/dist/helpers.cjs.map +1 -1
  126. package/dist/helpers.d.cts +1 -0
  127. package/dist/helpers.d.cts.map +1 -0
  128. package/dist/helpers.d.mts +1 -0
  129. package/dist/helpers.d.mts.map +1 -0
  130. package/dist/helpers.mjs.map +1 -1
  131. package/dist/kysely.cjs +3 -3
  132. package/dist/kysely.cjs.map +1 -1
  133. package/dist/kysely.d.cts +8 -7
  134. package/dist/kysely.d.cts.map +1 -0
  135. package/dist/kysely.d.mts +7 -6
  136. package/dist/kysely.d.mts.map +1 -0
  137. package/dist/kysely.mjs +3 -3
  138. package/dist/kysely.mjs.map +1 -1
  139. package/dist/logger.cjs.map +1 -1
  140. package/dist/logger.d.cts +1 -0
  141. package/dist/logger.d.cts.map +1 -0
  142. package/dist/logger.d.mts +1 -0
  143. package/dist/logger.d.mts.map +1 -0
  144. package/dist/logger.mjs.map +1 -1
  145. package/dist/objection.cjs +3 -3
  146. package/dist/objection.cjs.map +1 -1
  147. package/dist/objection.d.cts +8 -7
  148. package/dist/objection.d.cts.map +1 -0
  149. package/dist/objection.d.mts +7 -6
  150. package/dist/objection.d.mts.map +1 -0
  151. package/dist/objection.mjs +3 -3
  152. package/dist/objection.mjs.map +1 -1
  153. package/dist/os/directory.d.cts +1 -1
  154. package/dist/os/directory.d.mts +1 -1
  155. package/dist/os/index.d.cts +1 -1
  156. package/dist/os/index.d.mts +1 -1
  157. package/dist/timer.cjs.map +1 -1
  158. package/dist/timer.d.cts +2 -0
  159. package/dist/timer.d.cts.map +1 -0
  160. package/dist/timer.d.mts +2 -0
  161. package/dist/timer.d.mts.map +1 -0
  162. package/dist/timer.mjs.map +1 -1
  163. package/package.json +5 -5
  164. package/src/Factory.ts +72 -72
  165. package/src/KyselyFactory.ts +330 -330
  166. package/src/ObjectionFactory.ts +354 -355
  167. package/src/PostgresKyselyMigrator.ts +37 -37
  168. package/src/PostgresMigrator.ts +107 -107
  169. package/src/PostgresObjectionMigrator.ts +91 -91
  170. package/src/VitestKyselyTransactionIsolator.ts +27 -27
  171. package/src/VitestObjectionTransactionIsolator.ts +39 -39
  172. package/src/VitestTransactionIsolator.ts +196 -195
  173. package/src/__tests__/Factory.spec.ts +163 -155
  174. package/src/__tests__/KyselyFactory.spec.ts +443 -439
  175. package/src/__tests__/ObjectionFactory.spec.ts +563 -557
  176. package/src/__tests__/PostgresKyselyMigrator.spec.ts +641 -641
  177. package/src/__tests__/PostgresMigrator.spec.ts +341 -341
  178. package/src/__tests__/PostgresObjectionMigrator.spec.ts +578 -578
  179. package/src/__tests__/VitestObjectionTransactionIsolator.spec.ts +114 -114
  180. package/src/__tests__/benchmark.spec.ts +140 -0
  181. package/src/__tests__/better-auth.spec.ts +15 -15
  182. package/src/__tests__/faker.spec.ts +226 -137
  183. package/src/__tests__/integration.spec.ts +597 -597
  184. package/src/__tests__/utilities.spec.ts +211 -0
  185. package/src/aws.ts +104 -104
  186. package/src/benchmark.ts +12 -12
  187. package/src/better-auth.ts +286 -301
  188. package/src/faker.ts +153 -153
  189. package/src/helpers.ts +6 -6
  190. package/src/kysely.ts +33 -33
  191. package/src/logger.ts +10 -10
  192. package/src/objection.ts +31 -31
  193. package/src/os/directory.ts +11 -10
  194. package/src/timer.ts +1 -1
  195. package/test/globalSetup.ts +45 -45
  196. package/test/helpers.ts +189 -189
  197. package/test/migrations/1749664623372_user.ts +13 -13
  198. package/tsconfig.json +9 -0
  199. package/vitest.config.ts +4 -4
  200. package/dist/PostgresKyselyMigrator-CfytARcA.cjs.map +0 -1
  201. package/dist/PostgresKyselyMigrator-upT-hmrz.mjs.map +0 -1
  202. package/dist/PostgresMigrator-DFcNdCvD.cjs.map +0 -1
  203. package/dist/PostgresMigrator-DbuJGAVy.mjs.map +0 -1
  204. package/dist/PostgresObjectionMigrator-BG6ymgnt.cjs.map +0 -1
  205. package/dist/PostgresObjectionMigrator-DPj2pOpX.mjs.map +0 -1
  206. package/dist/VitestKyselyTransactionIsolator-CNURW8y6.mjs.map +0 -1
  207. package/dist/VitestKyselyTransactionIsolator-EvDLk5zg.cjs.map +0 -1
  208. package/dist/VitestObjectionTransactionIsolator-CM5KTAFA.cjs.map +0 -1
  209. package/dist/VitestObjectionTransactionIsolator-jQFaCz0u.mjs.map +0 -1
@@ -1,325 +1,310 @@
1
1
  import {
2
- type DBAdapterDebugLogOption,
3
- type Where,
4
- createAdapterFactory,
2
+ createAdapterFactory,
3
+ type DBAdapterDebugLogOption,
4
+ type Where,
5
5
  } from 'better-auth/adapters';
6
6
 
7
7
  interface MemoryAdapterConfig {
8
- debugLogs?: DBAdapterDebugLogOption;
9
- usePlural?: boolean;
10
- initialData?: Record<string, any[]>;
8
+ debugLogs?: DBAdapterDebugLogOption;
9
+ usePlural?: boolean;
10
+ initialData?: Record<string, any[]>;
11
11
  }
12
12
 
13
13
  class MemoryStore {
14
- constructor(
15
- initialData?: Record<string, any[]>,
16
- private readonly data: Map<string, any> = new Map(),
17
- ) {
18
- if (initialData) {
19
- for (const [model, records] of Object.entries(initialData)) {
20
- const modelData = new Map();
21
- for (const record of records) {
22
- modelData.set(record.id, { ...record });
23
- }
24
- this.data.set(model, modelData);
25
- }
26
- }
27
- }
28
-
29
- getModel(modelName: string): Map<string, any> {
30
- if (!this.data.has(modelName)) {
31
- this.data.set(modelName, new Map());
32
- }
33
- return this.data.get(modelName)!;
34
- }
35
-
36
- clear() {
37
- this.data.clear();
38
- }
39
-
40
- getAllData() {
41
- const result: Record<string, any[]> = {};
42
- for (const [model, records] of this.data.entries()) {
43
- result[model] = Array.from(records.values());
44
- }
45
- return result;
46
- }
14
+ constructor(
15
+ initialData?: Record<string, any[]>,
16
+ private readonly data: Map<string, any> = new Map(),
17
+ ) {
18
+ if (initialData) {
19
+ for (const [model, records] of Object.entries(initialData)) {
20
+ const modelData = new Map();
21
+ for (const record of records) {
22
+ modelData.set(record.id, { ...record });
23
+ }
24
+ this.data.set(model, modelData);
25
+ }
26
+ }
27
+ }
28
+
29
+ getModel(modelName: string): Map<string, any> {
30
+ if (!this.data.has(modelName)) {
31
+ this.data.set(modelName, new Map());
32
+ }
33
+ return this.data.get(modelName)!;
34
+ }
35
+
36
+ clear() {
37
+ this.data.clear();
38
+ }
39
+
40
+ getAllData() {
41
+ const result: Record<string, any[]> = {};
42
+ for (const [model, records] of this.data.entries()) {
43
+ result[model] = Array.from(records.values());
44
+ }
45
+ return result;
46
+ }
47
47
  }
48
48
 
49
49
  function matchesWhere(record: any, where?: Where[]): boolean {
50
- if (!where || where.length === 0) return true;
51
-
52
- let result: boolean | null = null;
53
-
54
- for (const condition of where) {
55
- const { field, value, operator = 'eq', connector = 'AND' } = condition;
56
- const recordValue = record[field];
57
-
58
- let matches = false;
59
-
60
- switch (operator) {
61
- case 'eq':
62
- matches = recordValue === value;
63
- break;
64
- case 'ne':
65
- matches = recordValue !== value;
66
- break;
67
- case 'lt':
68
- matches = value != null && recordValue < value;
69
- break;
70
- case 'lte':
71
- matches = value != null && recordValue <= value;
72
- break;
73
- case 'gt':
74
- matches = value != null && recordValue > value;
75
- break;
76
- case 'gte':
77
- matches = value != null && recordValue >= value;
78
- break;
79
- case 'in':
80
- matches =
81
- Array.isArray(value) && (value as unknown[]).includes(recordValue);
82
- break;
83
- case 'not_in':
84
- matches =
85
- Array.isArray(value) && !(value as unknown[]).includes(recordValue);
86
- break;
87
- case 'contains':
88
- matches =
89
- typeof recordValue === 'string' &&
90
- typeof value === 'string' &&
91
- recordValue.includes(value);
92
- break;
93
- case 'starts_with':
94
- matches =
95
- typeof recordValue === 'string' &&
96
- typeof value === 'string' &&
97
- recordValue.startsWith(value);
98
- break;
99
- case 'ends_with':
100
- matches =
101
- typeof recordValue === 'string' &&
102
- typeof value === 'string' &&
103
- recordValue.endsWith(value);
104
- break;
105
- default:
106
- matches = recordValue === value;
107
- }
108
-
109
- // Apply connector logic
110
- if (result === null) {
111
- result = matches;
112
- } else if (connector === 'OR') {
113
- result = result || matches;
114
- } else {
115
- // Default: AND
116
- result = result && matches;
117
- }
118
- }
119
-
120
- return result ?? true;
50
+ if (!where || where.length === 0) return true;
51
+
52
+ let result: boolean | null = null;
53
+
54
+ for (const condition of where) {
55
+ const { field, value, operator = 'eq', connector = 'AND' } = condition;
56
+ const recordValue = record[field];
57
+
58
+ let matches = false;
59
+
60
+ switch (operator) {
61
+ case 'eq':
62
+ matches = recordValue === value;
63
+ break;
64
+ case 'ne':
65
+ matches = recordValue !== value;
66
+ break;
67
+ case 'lt':
68
+ matches = value != null && recordValue < value;
69
+ break;
70
+ case 'lte':
71
+ matches = value != null && recordValue <= value;
72
+ break;
73
+ case 'gt':
74
+ matches = value != null && recordValue > value;
75
+ break;
76
+ case 'gte':
77
+ matches = value != null && recordValue >= value;
78
+ break;
79
+ case 'in':
80
+ matches =
81
+ Array.isArray(value) && (value as unknown[]).includes(recordValue);
82
+ break;
83
+ case 'not_in':
84
+ matches =
85
+ Array.isArray(value) && !(value as unknown[]).includes(recordValue);
86
+ break;
87
+ case 'contains':
88
+ matches =
89
+ typeof recordValue === 'string' &&
90
+ typeof value === 'string' &&
91
+ recordValue.includes(value);
92
+ break;
93
+ case 'starts_with':
94
+ matches =
95
+ typeof recordValue === 'string' &&
96
+ typeof value === 'string' &&
97
+ recordValue.startsWith(value);
98
+ break;
99
+ case 'ends_with':
100
+ matches =
101
+ typeof recordValue === 'string' &&
102
+ typeof value === 'string' &&
103
+ recordValue.endsWith(value);
104
+ break;
105
+ default:
106
+ matches = recordValue === value;
107
+ }
108
+
109
+ // Apply connector logic
110
+ if (result === null) {
111
+ result = matches;
112
+ } else if (connector === 'OR') {
113
+ result = result || matches;
114
+ } else {
115
+ // Default: AND
116
+ result = result && matches;
117
+ }
118
+ }
119
+
120
+ return result ?? true;
121
121
  }
122
122
  type SortBy = {
123
- field: string;
124
- direction: 'asc' | 'desc';
123
+ field: string;
124
+ direction: 'asc' | 'desc';
125
125
  };
126
126
 
127
127
  function applySorting(records: any[], sortBy?: SortBy): any[] {
128
- if (!sortBy) return records;
128
+ if (!sortBy) return records;
129
129
 
130
- const { field, direction } = sortBy;
130
+ const { field, direction } = sortBy;
131
131
 
132
- return records.sort((a, b) => {
133
- const aVal = a[field];
134
- const bVal = b[field];
132
+ return records.sort((a, b) => {
133
+ const aVal = a[field];
134
+ const bVal = b[field];
135
135
 
136
- if (aVal === bVal) return 0;
137
- if (aVal == null) return direction === 'asc' ? -1 : 1;
138
- if (bVal == null) return direction === 'asc' ? 1 : -1;
136
+ if (aVal === bVal) return 0;
137
+ if (aVal == null) return direction === 'asc' ? -1 : 1;
138
+ if (bVal == null) return direction === 'asc' ? 1 : -1;
139
139
 
140
- const comparison = aVal < bVal ? -1 : 1;
141
- return direction === 'asc' ? comparison : -comparison;
142
- });
140
+ const comparison = aVal < bVal ? -1 : 1;
141
+ return direction === 'asc' ? comparison : -comparison;
142
+ });
143
143
  }
144
144
 
145
145
  export const memoryAdapter = (
146
- config: MemoryAdapterConfig = {},
147
- store = new Map(),
146
+ config: MemoryAdapterConfig = {},
147
+ store = new Map(),
148
148
  ) => {
149
- const storeInstance = new MemoryStore(config.initialData, store);
150
-
151
- const adapterInstance = createAdapterFactory({
152
- config: {
153
- adapterId: 'memory-adapter',
154
- adapterName: 'Memory Adapter',
155
- usePlural: config.usePlural ?? false,
156
- debugLogs: config.debugLogs ?? false,
157
- supportsJSON: true,
158
- supportsDates: true,
159
- supportsBooleans: true,
160
- supportsNumericIds: false,
161
- },
162
-
163
- adapter: ({
164
- debugLog,
165
- transformInput,
166
- transformOutput,
167
- getModelName,
168
- transformWhereClause,
169
- }) => ({
170
- create: async ({ data, model, select }) => {
171
- debugLog('CREATE', { model, data });
172
- const modelName = getModelName(model);
173
- const modelData = storeInstance.getModel(modelName);
174
-
175
- const transformedData = await transformInput(data, model, 'create');
176
-
177
- if (!transformedData.id) {
178
- transformedData.id = crypto.randomUUID();
179
- }
180
-
181
- modelData.set(transformedData.id, { ...transformedData, ...data });
182
-
183
- if (data.email_address) {
184
- modelData.set(transformedData.id, {
185
- ...transformedData,
186
- email: data.email_address,
187
- });
188
- }
189
- const created = modelData.get(transformedData.id);
190
-
191
- const out = (await transformOutput(created, model, select)) as any;
192
-
193
- return out;
194
- },
195
-
196
- findOne: async ({ where, model, select }) => {
197
- debugLog('FIND_ONE', { model, where });
198
- const modelName = getModelName(model);
199
- const modelData = storeInstance.getModel(modelName);
200
- const transformedWhere = transformWhereClause({ model, where });
201
-
202
- for (const record of modelData.values()) {
203
- if (matchesWhere(record, transformedWhere)) {
204
- const t = (await transformOutput(record, model, select)) as any;
205
-
206
- return t;
207
- }
208
- }
209
- return null;
210
- },
211
-
212
- findMany: async ({ where, model, limit, offset, sortBy }) => {
213
- debugLog('FIND_MANY', { model, where });
214
-
215
- const modelName = getModelName(model);
216
- const modelData = storeInstance.getModel(modelName);
217
- const transformedWhere = transformWhereClause({ model, where });
218
-
219
- let results = Array.from(modelData.values()).filter((record) =>
220
- matchesWhere(record, transformedWhere),
221
- );
222
-
223
- if (sortBy) {
224
- results = applySorting(results, sortBy);
225
- }
226
-
227
- if (offset) {
228
- results = results.slice(offset);
229
- }
230
- if (limit) {
231
- results = results.slice(0, limit);
232
- }
233
-
234
- return Promise.all(
235
- results.map((record) => transformOutput(record, model)),
236
- ) as any;
237
- },
238
-
239
- update: async ({ where, update, model }) => {
240
- debugLog('UPDATE', { model, where });
241
-
242
- const modelName = getModelName(model);
243
- const modelData = storeInstance.getModel(modelName);
244
- const transformedWhere = transformWhereClause({ model, where });
245
-
246
- for (const [id, record] of modelData.entries()) {
247
- if (matchesWhere(record, transformedWhere)) {
248
- const transformedData = await transformInput(
249
- update as any,
250
- model,
251
- 'update',
252
- );
253
- const updated = { ...record, ...transformedData };
254
- modelData.set(id, updated);
255
- return transformOutput(updated, model) as any;
256
- }
257
- }
258
- return null;
259
- },
260
-
261
- updateMany: async ({ where, update, model }) => {
262
- debugLog('UPDATE_MANY', { model, where });
263
- const modelName = getModelName(model);
264
- const modelData = storeInstance.getModel(modelName);
265
- const transformedWhere = transformWhereClause({ model, where });
266
-
267
- let count = 0;
268
- const transformedData = await transformInput(update, model, 'update');
269
-
270
- for (const [id, record] of modelData.entries()) {
271
- if (matchesWhere(record, transformedWhere)) {
272
- modelData.set(id, { ...record, ...transformedData });
273
- count++;
274
- }
275
- }
276
- return count;
277
- },
278
-
279
- delete: async ({ where, model }) => {
280
- debugLog('DELETE', { model, where });
281
- const modelName = getModelName(model);
282
- const modelData = storeInstance.getModel(modelName);
283
-
284
- for (const [id, record] of modelData.entries()) {
285
- if (matchesWhere(record, where)) {
286
- modelData.delete(id);
287
- return;
288
- }
289
- }
290
- },
291
-
292
- deleteMany: async ({ where, model }) => {
293
- debugLog('DELETE_MANY', { model, where });
294
- const modelName = getModelName(model);
295
- const modelData = storeInstance.getModel(modelName);
296
-
297
- const toDelete: string[] = [];
298
- for (const [id, record] of modelData.entries()) {
299
- if (matchesWhere(record, where)) {
300
- toDelete.push(id);
301
- }
302
- }
303
-
304
- toDelete.forEach((id) => modelData.delete(id));
305
- return toDelete.length;
306
- },
307
-
308
- count: async ({ where, model }) => {
309
- const modelName = getModelName(model);
310
- const modelData = storeInstance.getModel(modelName);
311
-
312
- return Array.from(modelData.values()).filter((record) =>
313
- matchesWhere(record, where),
314
- ).length;
315
- },
316
- }),
317
- });
318
-
319
- // Add utility methods to the adapter
320
- return Object.assign(adapterInstance, {
321
- clear: () => store.clear(),
322
- getAllData: () => storeInstance.getAllData(),
323
- getStore: () => store,
324
- });
149
+ const storeInstance = new MemoryStore(config.initialData, store);
150
+
151
+ const adapterInstance = createAdapterFactory({
152
+ config: {
153
+ adapterId: 'memory-adapter',
154
+ adapterName: 'Memory Adapter',
155
+ usePlural: config.usePlural ?? false,
156
+ debugLogs: config.debugLogs ?? false,
157
+ supportsJSON: true,
158
+ supportsDates: true,
159
+ supportsBooleans: true,
160
+ supportsNumericIds: false,
161
+ },
162
+
163
+ // Note: The framework automatically transforms field names in both directions:
164
+ // - Input data is already transformed before reaching the adapter (e.g., email -> email_address)
165
+ // - Output data is automatically transformed after the adapter returns (e.g., email_address -> email)
166
+ // Therefore, we should NOT call transformInput or transformOutput ourselves.
167
+ adapter: ({ debugLog, getModelName, transformWhereClause }) => ({
168
+ create: async ({ data, model }) => {
169
+ debugLog('CREATE', { model, data });
170
+ const modelName = getModelName(model);
171
+ const modelData = storeInstance.getModel(modelName);
172
+
173
+ // Data is already transformed by the framework - store directly
174
+ const record = data as Record<string, unknown>;
175
+ if (!record.id) {
176
+ record.id = crypto.randomUUID();
177
+ }
178
+
179
+ const id = record.id as string;
180
+ modelData.set(id, { ...record });
181
+ return modelData.get(id);
182
+ },
183
+
184
+ findOne: async ({ where, model }) => {
185
+ debugLog('FIND_ONE', { model, where });
186
+ const modelName = getModelName(model);
187
+ const modelData = storeInstance.getModel(modelName);
188
+ const transformedWhere = transformWhereClause({ model, where });
189
+
190
+ for (const record of modelData.values()) {
191
+ if (matchesWhere(record, transformedWhere)) {
192
+ return record;
193
+ }
194
+ }
195
+ return null;
196
+ },
197
+
198
+ findMany: async ({ where, model, limit, offset, sortBy }) => {
199
+ debugLog('FIND_MANY', { model, where });
200
+
201
+ const modelName = getModelName(model);
202
+ const modelData = storeInstance.getModel(modelName);
203
+ const transformedWhere = transformWhereClause({ model, where });
204
+
205
+ let results = Array.from(modelData.values()).filter((record) =>
206
+ matchesWhere(record, transformedWhere),
207
+ );
208
+
209
+ if (sortBy) {
210
+ results = applySorting(results, sortBy);
211
+ }
212
+
213
+ if (offset) {
214
+ results = results.slice(offset);
215
+ }
216
+ if (limit) {
217
+ results = results.slice(0, limit);
218
+ }
219
+
220
+ return results;
221
+ },
222
+
223
+ update: async ({ where, update, model }) => {
224
+ debugLog('UPDATE', { model, where });
225
+
226
+ const modelName = getModelName(model);
227
+ const modelData = storeInstance.getModel(modelName);
228
+ const transformedWhere = transformWhereClause({ model, where });
229
+
230
+ for (const [id, record] of modelData.entries()) {
231
+ if (matchesWhere(record, transformedWhere)) {
232
+ // Update data is already transformed by the framework
233
+ const updated = { ...record, ...update };
234
+ modelData.set(id, updated);
235
+ return updated;
236
+ }
237
+ }
238
+ return null;
239
+ },
240
+
241
+ updateMany: async ({ where, update, model }) => {
242
+ debugLog('UPDATE_MANY', { model, where });
243
+ const modelName = getModelName(model);
244
+ const modelData = storeInstance.getModel(modelName);
245
+ const transformedWhere = transformWhereClause({ model, where });
246
+
247
+ let count = 0;
248
+
249
+ for (const [id, record] of modelData.entries()) {
250
+ if (matchesWhere(record, transformedWhere)) {
251
+ // Update data is already transformed by the framework
252
+ modelData.set(id, { ...record, ...update });
253
+ count++;
254
+ }
255
+ }
256
+ return count;
257
+ },
258
+
259
+ delete: async ({ where, model }) => {
260
+ debugLog('DELETE', { model, where });
261
+ const modelName = getModelName(model);
262
+ const modelData = storeInstance.getModel(modelName);
263
+ const transformedWhere = transformWhereClause({ model, where });
264
+
265
+ for (const [id, record] of modelData.entries()) {
266
+ if (matchesWhere(record, transformedWhere)) {
267
+ modelData.delete(id);
268
+ return;
269
+ }
270
+ }
271
+ },
272
+
273
+ deleteMany: async ({ where, model }) => {
274
+ debugLog('DELETE_MANY', { model, where });
275
+ const modelName = getModelName(model);
276
+ const modelData = storeInstance.getModel(modelName);
277
+ const transformedWhere = transformWhereClause({ model, where });
278
+
279
+ const toDelete: string[] = [];
280
+ for (const [id, record] of modelData.entries()) {
281
+ if (matchesWhere(record, transformedWhere)) {
282
+ toDelete.push(id);
283
+ }
284
+ }
285
+
286
+ for (const id of toDelete) {
287
+ modelData.delete(id);
288
+ }
289
+ return toDelete.length;
290
+ },
291
+
292
+ count: async ({ where, model }) => {
293
+ const modelName = getModelName(model);
294
+ const modelData = storeInstance.getModel(modelName);
295
+ const transformedWhere = transformWhereClause({ model, where });
296
+
297
+ return Array.from(modelData.values()).filter((record) =>
298
+ matchesWhere(record, transformedWhere),
299
+ ).length;
300
+ },
301
+ }),
302
+ });
303
+
304
+ // Add utility methods to the adapter
305
+ return Object.assign(adapterInstance, {
306
+ clear: () => store.clear(),
307
+ getAllData: () => storeInstance.getAllData(),
308
+ getStore: () => store,
309
+ });
325
310
  };