jazz-tools 0.18.14 → 0.18.16

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 (63) hide show
  1. package/.turbo/turbo-build.log +45 -33
  2. package/CHANGELOG.md +23 -0
  3. package/dist/better-auth/database-adapter/index.d.ts +50 -0
  4. package/dist/better-auth/database-adapter/index.d.ts.map +1 -0
  5. package/dist/better-auth/database-adapter/index.js +920 -0
  6. package/dist/better-auth/database-adapter/index.js.map +1 -0
  7. package/dist/better-auth/database-adapter/repository/account.d.ts +24 -0
  8. package/dist/better-auth/database-adapter/repository/account.d.ts.map +1 -0
  9. package/dist/better-auth/database-adapter/repository/generic.d.ts +45 -0
  10. package/dist/better-auth/database-adapter/repository/generic.d.ts.map +1 -0
  11. package/dist/better-auth/database-adapter/repository/index.d.ts +6 -0
  12. package/dist/better-auth/database-adapter/repository/index.d.ts.map +1 -0
  13. package/dist/better-auth/database-adapter/repository/session.d.ts +29 -0
  14. package/dist/better-auth/database-adapter/repository/session.d.ts.map +1 -0
  15. package/dist/better-auth/database-adapter/repository/user.d.ts +30 -0
  16. package/dist/better-auth/database-adapter/repository/user.d.ts.map +1 -0
  17. package/dist/better-auth/database-adapter/repository/verification.d.ts +18 -0
  18. package/dist/better-auth/database-adapter/repository/verification.d.ts.map +1 -0
  19. package/dist/better-auth/database-adapter/schema.d.ts +27 -0
  20. package/dist/better-auth/database-adapter/schema.d.ts.map +1 -0
  21. package/dist/better-auth/database-adapter/tests/index.test.d.ts +2 -0
  22. package/dist/better-auth/database-adapter/tests/index.test.d.ts.map +1 -0
  23. package/dist/better-auth/database-adapter/tests/repository/account.test.d.ts +2 -0
  24. package/dist/better-auth/database-adapter/tests/repository/account.test.d.ts.map +1 -0
  25. package/dist/better-auth/database-adapter/tests/repository/generic.test.d.ts +2 -0
  26. package/dist/better-auth/database-adapter/tests/repository/generic.test.d.ts.map +1 -0
  27. package/dist/better-auth/database-adapter/tests/repository/session.test.d.ts +2 -0
  28. package/dist/better-auth/database-adapter/tests/repository/session.test.d.ts.map +1 -0
  29. package/dist/better-auth/database-adapter/tests/repository/user.test.d.ts +2 -0
  30. package/dist/better-auth/database-adapter/tests/repository/user.test.d.ts.map +1 -0
  31. package/dist/better-auth/database-adapter/tests/repository/verification.test.d.ts +2 -0
  32. package/dist/better-auth/database-adapter/tests/repository/verification.test.d.ts.map +1 -0
  33. package/dist/better-auth/database-adapter/tests/sync-utils.d.ts +16 -0
  34. package/dist/better-auth/database-adapter/tests/sync-utils.d.ts.map +1 -0
  35. package/dist/better-auth/database-adapter/tests/utils.test.d.ts +2 -0
  36. package/dist/better-auth/database-adapter/tests/utils.test.d.ts.map +1 -0
  37. package/dist/better-auth/database-adapter/utils.d.ts +16 -0
  38. package/dist/better-auth/database-adapter/utils.d.ts.map +1 -0
  39. package/dist/worker/edge-wasm.d.ts +2 -0
  40. package/dist/worker/edge-wasm.d.ts.map +1 -0
  41. package/dist/worker/edge-wasm.js +5 -0
  42. package/dist/worker/edge-wasm.js.map +1 -0
  43. package/jazz-tools-0.18.6.tgz +0 -0
  44. package/package.json +15 -5
  45. package/src/better-auth/database-adapter/index.ts +228 -0
  46. package/src/better-auth/database-adapter/repository/account.ts +131 -0
  47. package/src/better-auth/database-adapter/repository/generic.ts +297 -0
  48. package/src/better-auth/database-adapter/repository/index.ts +5 -0
  49. package/src/better-auth/database-adapter/repository/session.ts +190 -0
  50. package/src/better-auth/database-adapter/repository/user.ts +158 -0
  51. package/src/better-auth/database-adapter/repository/verification.ts +37 -0
  52. package/src/better-auth/database-adapter/schema.ts +222 -0
  53. package/src/better-auth/database-adapter/tests/index.test.ts +690 -0
  54. package/src/better-auth/database-adapter/tests/repository/account.test.ts +149 -0
  55. package/src/better-auth/database-adapter/tests/repository/generic.test.ts +183 -0
  56. package/src/better-auth/database-adapter/tests/repository/session.test.ts +419 -0
  57. package/src/better-auth/database-adapter/tests/repository/user.test.ts +673 -0
  58. package/src/better-auth/database-adapter/tests/repository/verification.test.ts +101 -0
  59. package/src/better-auth/database-adapter/tests/sync-utils.ts +127 -0
  60. package/src/better-auth/database-adapter/tests/utils.test.ts +787 -0
  61. package/src/better-auth/database-adapter/utils.ts +178 -0
  62. package/src/worker/edge-wasm.ts +5 -0
  63. package/tsup.config.ts +8 -0
@@ -0,0 +1,419 @@
1
+ import { beforeEach, describe, expect, it } from "vitest";
2
+ import { Account, co } from "jazz-tools";
3
+ import { startWorker } from "jazz-tools/worker";
4
+ import { SessionRepository } from "../../repository/session";
5
+ import { UserRepository } from "../../repository/user";
6
+ import { createJazzSchema, Database } from "../../schema";
7
+ import { createWorkerAccount, startSyncServer } from "../sync-utils.js";
8
+
9
+ describe("SessionRepository", () => {
10
+ let syncServer: any;
11
+
12
+ let databaseSchema: Database;
13
+ let databaseRoot: co.loaded<Database, { group: true }>;
14
+ let worker: Account;
15
+
16
+ beforeEach(async () => {
17
+ syncServer = await startSyncServer();
18
+
19
+ const workerAccount = await createWorkerAccount({
20
+ name: "test",
21
+ peer: `ws://localhost:${syncServer.port}`,
22
+ });
23
+
24
+ const JazzSchema = createJazzSchema({
25
+ user: {
26
+ modelName: "user",
27
+ fields: {
28
+ email: {
29
+ type: "string",
30
+ required: true,
31
+ },
32
+ },
33
+ },
34
+ session: {
35
+ modelName: "session",
36
+ fields: {
37
+ userId: {
38
+ type: "string",
39
+ required: true,
40
+ },
41
+ token: {
42
+ type: "string",
43
+ required: true,
44
+ },
45
+ },
46
+ },
47
+ });
48
+
49
+ const result = await startWorker({
50
+ AccountSchema: JazzSchema.WorkerAccount,
51
+ syncServer: `ws://localhost:${syncServer.port}`,
52
+ accountID: workerAccount.accountID,
53
+ accountSecret: workerAccount.agentSecret,
54
+ });
55
+
56
+ databaseSchema = JazzSchema.DatabaseRoot;
57
+ databaseRoot = await JazzSchema.loadDatabase(result.worker);
58
+ worker = result.worker;
59
+ });
60
+
61
+ it("should create a session repository", async () => {
62
+ const sessionRepository = new SessionRepository(
63
+ databaseSchema,
64
+ databaseRoot,
65
+ worker,
66
+ );
67
+ });
68
+
69
+ describe("create", () => {
70
+ it("should throw an error if token or userId is not provided", async () => {
71
+ const sessionRepository = new SessionRepository(
72
+ databaseSchema,
73
+ databaseRoot,
74
+ worker,
75
+ );
76
+
77
+ await expect(
78
+ sessionRepository.create("session", {
79
+ randomData: "random",
80
+ }),
81
+ ).rejects.toThrow("Token and userId are required for session creation");
82
+ });
83
+
84
+ it("should throw an error user does not exist", async () => {
85
+ const sessionRepository = new SessionRepository(
86
+ databaseSchema,
87
+ databaseRoot,
88
+ worker,
89
+ );
90
+
91
+ await expect(
92
+ sessionRepository.create("session", {
93
+ token: "test",
94
+ userId: "test",
95
+ }),
96
+ ).rejects.toThrow("User not found");
97
+ });
98
+
99
+ it("should create a session", async () => {
100
+ const userRepository = new UserRepository(
101
+ databaseSchema,
102
+ databaseRoot,
103
+ worker,
104
+ );
105
+ const user = await userRepository.create("user", {
106
+ email: "test@test.com",
107
+ });
108
+
109
+ const sessionRepository = new SessionRepository(
110
+ databaseSchema,
111
+ databaseRoot,
112
+ worker,
113
+ );
114
+
115
+ const session = await sessionRepository.create("session", {
116
+ token: "test",
117
+ userId: user.$jazz.id,
118
+ });
119
+
120
+ expect(session.token).toBe("test");
121
+ expect(session.userId).toBe(user.$jazz.id);
122
+ expect(session.$jazz.id).toBeDefined();
123
+ });
124
+
125
+ it("should create a session with a custom uniqueId", async () => {
126
+ const userRepository = new UserRepository(
127
+ databaseSchema,
128
+ databaseRoot,
129
+ worker,
130
+ );
131
+ const user = await userRepository.create("user", {
132
+ email: "test@test.com",
133
+ });
134
+
135
+ const sessionRepository = new SessionRepository(
136
+ databaseSchema,
137
+ databaseRoot,
138
+ worker,
139
+ );
140
+
141
+ const session = await sessionRepository.create("session", {
142
+ token: "test",
143
+ userId: user.$jazz.id,
144
+ });
145
+
146
+ const sessionByToken = await sessionRepository.findByUnique("session", [
147
+ {
148
+ connector: "AND",
149
+ operator: "eq",
150
+ field: "token",
151
+ value: "test",
152
+ },
153
+ ]);
154
+
155
+ expect(sessionByToken?.$jazz.id).toBe(session.$jazz.id);
156
+ });
157
+
158
+ it("should create a session inside the user object", async () => {
159
+ const userRepository = new UserRepository(
160
+ databaseSchema,
161
+ databaseRoot,
162
+ worker,
163
+ );
164
+ const user = await userRepository.create("user", {
165
+ email: "test@test.com",
166
+ });
167
+
168
+ const sessionRepository = new SessionRepository(
169
+ databaseSchema,
170
+ databaseRoot,
171
+ worker,
172
+ );
173
+
174
+ const session = await sessionRepository.create("session", {
175
+ token: "test",
176
+ userId: user.$jazz.id,
177
+ });
178
+
179
+ const { sessions } = await (
180
+ user as unknown as co.loaded<co.Map<{ sessions: co.List<co.Map<any>> }>>
181
+ ).$jazz.ensureLoaded({
182
+ resolve: {
183
+ sessions: {
184
+ $each: true,
185
+ },
186
+ },
187
+ });
188
+
189
+ expect(sessions.length).toBe(1);
190
+ expect(sessions.at(0)?.$jazz.id).toBe(session.$jazz.id);
191
+
192
+ // The generic table should be empty
193
+ const { tables } = await databaseRoot.$jazz.ensureLoaded({
194
+ resolve: {
195
+ tables: {
196
+ session: {
197
+ $each: true,
198
+ },
199
+ },
200
+ },
201
+ });
202
+
203
+ expect(tables.session.length).toBe(0);
204
+ });
205
+ });
206
+
207
+ describe("delete", () => {
208
+ it("should return 0 when trying to delete by non-existent id", async () => {
209
+ const sessionRepository = new SessionRepository(
210
+ databaseSchema,
211
+ databaseRoot,
212
+ worker,
213
+ );
214
+
215
+ const deleted = await sessionRepository.deleteValue("session", [
216
+ {
217
+ field: "id",
218
+ operator: "eq",
219
+ value: "does-not-exist",
220
+ connector: "AND",
221
+ },
222
+ ]);
223
+
224
+ expect(deleted).toBe(0);
225
+ });
226
+
227
+ it("should throw an error for unsupported where clause", async () => {
228
+ const sessionRepository = new SessionRepository(
229
+ databaseSchema,
230
+ databaseRoot,
231
+ worker,
232
+ );
233
+
234
+ await expect(
235
+ sessionRepository.deleteValue("session", [
236
+ { field: "random", operator: "eq", value: "x", connector: "AND" },
237
+ ]),
238
+ ).rejects.toThrow("Unable to find session with where:");
239
+ });
240
+
241
+ it("should delete a session by id", async () => {
242
+ const userRepository = new UserRepository(
243
+ databaseSchema,
244
+ databaseRoot,
245
+ worker,
246
+ );
247
+ const user = await userRepository.create("user", {
248
+ email: "delete-id@test.com",
249
+ });
250
+
251
+ const sessionRepository = new SessionRepository(
252
+ databaseSchema,
253
+ databaseRoot,
254
+ worker,
255
+ );
256
+
257
+ const session = await sessionRepository.create("session", {
258
+ token: "token-by-id",
259
+ userId: user.$jazz.id,
260
+ });
261
+
262
+ const deleted = await sessionRepository.deleteValue("session", [
263
+ {
264
+ field: "id",
265
+ operator: "eq",
266
+ value: session.$jazz.id,
267
+ connector: "AND",
268
+ },
269
+ ]);
270
+
271
+ expect(deleted).toBe(1);
272
+
273
+ // Validate it's removed from user's sessions
274
+ const { sessions } = await (
275
+ user as unknown as co.loaded<co.Map<{ sessions: co.List<co.Map<any>> }>>
276
+ ).$jazz.ensureLoaded({
277
+ resolve: { sessions: { $each: true } },
278
+ });
279
+ expect(sessions.length).toBe(0);
280
+
281
+ // Validate cannot be found anymore
282
+ const foundAgain = await sessionRepository.findById("session", [
283
+ {
284
+ field: "id",
285
+ operator: "eq",
286
+ value: session.$jazz.id,
287
+ connector: "AND",
288
+ },
289
+ ]);
290
+ expect(foundAgain).toBeNull();
291
+ });
292
+
293
+ it("should delete a session by token", async () => {
294
+ const userRepository = new UserRepository(
295
+ databaseSchema,
296
+ databaseRoot,
297
+ worker,
298
+ );
299
+ const user = await userRepository.create("user", {
300
+ email: "delete-token@test.com",
301
+ });
302
+
303
+ const sessionRepository = new SessionRepository(
304
+ databaseSchema,
305
+ databaseRoot,
306
+ worker,
307
+ );
308
+
309
+ const session = await sessionRepository.create("session", {
310
+ token: "token-by-token",
311
+ userId: user.$jazz.id,
312
+ });
313
+
314
+ const deleted = await sessionRepository.deleteValue("session", [
315
+ {
316
+ field: "token",
317
+ operator: "eq",
318
+ value: "token-by-token",
319
+ connector: "AND",
320
+ },
321
+ ]);
322
+
323
+ expect(deleted).toBe(1);
324
+
325
+ const { sessions } = await (
326
+ user as unknown as co.loaded<co.Map<{ sessions: co.List<co.Map<any>> }>>
327
+ ).$jazz.ensureLoaded({
328
+ resolve: { sessions: { $each: true } },
329
+ });
330
+ expect(sessions.length).toBe(0);
331
+ });
332
+
333
+ it("should delete multiple sessions by userId with optional filters", async () => {
334
+ const userRepository = new UserRepository(
335
+ databaseSchema,
336
+ databaseRoot,
337
+ worker,
338
+ );
339
+ const user = await userRepository.create("user", {
340
+ email: "delete-many@test.com",
341
+ });
342
+
343
+ const sessionRepository = new SessionRepository(
344
+ databaseSchema,
345
+ databaseRoot,
346
+ worker,
347
+ );
348
+
349
+ const s1 = await sessionRepository.create("session", {
350
+ token: "a1",
351
+ userId: user.$jazz.id,
352
+ });
353
+ const s2 = await sessionRepository.create("session", {
354
+ token: "a2",
355
+ userId: user.$jazz.id,
356
+ });
357
+ await sessionRepository.create("session", {
358
+ token: "b1",
359
+ userId: user.$jazz.id,
360
+ });
361
+
362
+ // Delete only tokens that start with 'a'
363
+ const deleted = await sessionRepository.deleteValue("session", [
364
+ {
365
+ field: "userId",
366
+ operator: "eq",
367
+ value: user.$jazz.id,
368
+ connector: "AND",
369
+ },
370
+ {
371
+ field: "token",
372
+ operator: "starts_with",
373
+ value: "a",
374
+ connector: "AND",
375
+ },
376
+ ]);
377
+
378
+ expect(deleted).toBe(2);
379
+
380
+ const { sessions } = await (
381
+ user as unknown as co.loaded<co.Map<{ sessions: co.List<co.Map<any>> }>>
382
+ ).$jazz.ensureLoaded({
383
+ resolve: { sessions: { $each: true } },
384
+ });
385
+ expect(sessions.length).toBe(1);
386
+ expect(sessions.at(0)?.token).toBe("b1");
387
+
388
+ // Verify deleted ones are gone
389
+ const again1 = await sessionRepository.findById("session", [
390
+ { field: "id", operator: "eq", value: s1.$jazz.id, connector: "AND" },
391
+ ]);
392
+ const again2 = await sessionRepository.findById("session", [
393
+ { field: "id", operator: "eq", value: s2.$jazz.id, connector: "AND" },
394
+ ]);
395
+ expect(again1).toBeNull();
396
+ expect(again2).toBeNull();
397
+ });
398
+
399
+ it("should return 0 when user not found for userId clause", async () => {
400
+ const sessionRepository = new SessionRepository(
401
+ databaseSchema,
402
+ databaseRoot,
403
+ worker,
404
+ );
405
+
406
+ const deleted = await sessionRepository.deleteValue("session", [
407
+ {
408
+ field: "userId",
409
+ operator: "eq",
410
+ value: "missing-user",
411
+ connector: "AND",
412
+ },
413
+ { field: "token", operator: "eq", value: "anything", connector: "AND" },
414
+ ]);
415
+
416
+ expect(deleted).toBe(0);
417
+ });
418
+ });
419
+ });