@fragno-dev/db 0.2.0 → 0.2.2

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 (62) hide show
  1. package/.turbo/turbo-build.log +34 -30
  2. package/CHANGELOG.md +49 -0
  3. package/dist/adapters/generic-sql/query/where-builder.js +1 -1
  4. package/dist/db-fragment-definition-builder.d.ts +31 -39
  5. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  6. package/dist/db-fragment-definition-builder.js +20 -16
  7. package/dist/db-fragment-definition-builder.js.map +1 -1
  8. package/dist/fragments/internal-fragment.d.ts +94 -8
  9. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  10. package/dist/fragments/internal-fragment.js +56 -55
  11. package/dist/fragments/internal-fragment.js.map +1 -1
  12. package/dist/hooks/hooks.d.ts +5 -3
  13. package/dist/hooks/hooks.d.ts.map +1 -1
  14. package/dist/hooks/hooks.js +38 -37
  15. package/dist/hooks/hooks.js.map +1 -1
  16. package/dist/mod.d.ts +3 -3
  17. package/dist/mod.d.ts.map +1 -1
  18. package/dist/mod.js +4 -4
  19. package/dist/mod.js.map +1 -1
  20. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +367 -80
  21. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  22. package/dist/query/unit-of-work/execute-unit-of-work.js +448 -148
  23. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  24. package/dist/query/unit-of-work/unit-of-work.d.ts +35 -11
  25. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  26. package/dist/query/unit-of-work/unit-of-work.js +49 -19
  27. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  28. package/dist/query/value-decoding.js +1 -1
  29. package/dist/schema/create.d.ts +2 -3
  30. package/dist/schema/create.d.ts.map +1 -1
  31. package/dist/schema/create.js +2 -5
  32. package/dist/schema/create.js.map +1 -1
  33. package/dist/schema/generate-id.d.ts +20 -0
  34. package/dist/schema/generate-id.d.ts.map +1 -0
  35. package/dist/schema/generate-id.js +28 -0
  36. package/dist/schema/generate-id.js.map +1 -0
  37. package/dist/sql-driver/dialects/durable-object-dialect.d.ts.map +1 -1
  38. package/package.json +3 -3
  39. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +1 -0
  40. package/src/adapters/drizzle/drizzle-adapter-sqlite3.test.ts +41 -25
  41. package/src/adapters/generic-sql/test/generic-drizzle-adapter-sqlite3.test.ts +39 -25
  42. package/src/db-fragment-definition-builder.test.ts +58 -42
  43. package/src/db-fragment-definition-builder.ts +78 -88
  44. package/src/db-fragment-instantiator.test.ts +64 -88
  45. package/src/db-fragment-integration.test.ts +292 -142
  46. package/src/fragments/internal-fragment.test.ts +272 -266
  47. package/src/fragments/internal-fragment.ts +155 -122
  48. package/src/hooks/hooks.test.ts +268 -264
  49. package/src/hooks/hooks.ts +74 -63
  50. package/src/mod.ts +14 -4
  51. package/src/query/unit-of-work/execute-unit-of-work.test.ts +1582 -998
  52. package/src/query/unit-of-work/execute-unit-of-work.ts +1746 -343
  53. package/src/query/unit-of-work/tx-builder.test.ts +1041 -0
  54. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +269 -21
  55. package/src/query/unit-of-work/unit-of-work.test.ts +64 -0
  56. package/src/query/unit-of-work/unit-of-work.ts +65 -30
  57. package/src/schema/create.ts +2 -5
  58. package/src/schema/generate-id.test.ts +57 -0
  59. package/src/schema/generate-id.ts +38 -0
  60. package/src/shared/config.ts +0 -10
  61. package/src/shared/connection-pool.ts +0 -24
  62. package/src/shared/prisma.ts +0 -45
@@ -49,11 +49,12 @@ describe("Internal Fragment", () => {
49
49
 
50
50
  it("should get undefined for non-existent key", async () => {
51
51
  const result = await fragment.inContext(async function () {
52
- return await this.uow(async ({ executeRetrieve }) => {
53
- const valuePromise = fragment.services.settingsService.get(SETTINGS_NAMESPACE, "test-key");
54
- await executeRetrieve();
55
- return await valuePromise;
56
- });
52
+ return await this.handlerTx()
53
+ .withServiceCalls(
54
+ () => [fragment.services.settingsService.get(SETTINGS_NAMESPACE, "test-key")] as const,
55
+ )
56
+ .transform(({ serviceResult: [value] }) => value)
57
+ .execute();
57
58
  });
58
59
 
59
60
  expect(result).toBeUndefined();
@@ -61,23 +62,20 @@ describe("Internal Fragment", () => {
61
62
 
62
63
  it("should set and get a value", async () => {
63
64
  await fragment.inContext(async function () {
64
- return await this.uow(async ({ executeMutate }) => {
65
- const setPromise = fragment.services.settingsService.set(
66
- SETTINGS_NAMESPACE,
67
- "test-key",
68
- "test-value",
69
- );
70
- await executeMutate();
71
- await setPromise;
72
- });
65
+ await this.handlerTx()
66
+ .withServiceCalls(() => [
67
+ fragment.services.settingsService.set(SETTINGS_NAMESPACE, "test-key", "test-value"),
68
+ ])
69
+ .execute();
73
70
  });
74
71
 
75
72
  const result = await fragment.inContext(async function () {
76
- return await this.uow(async ({ executeRetrieve }) => {
77
- const valuePromise = fragment.services.settingsService.get(SETTINGS_NAMESPACE, "test-key");
78
- await executeRetrieve();
79
- return await valuePromise;
80
- });
73
+ return await this.handlerTx()
74
+ .withServiceCalls(
75
+ () => [fragment.services.settingsService.get(SETTINGS_NAMESPACE, "test-key")] as const,
76
+ )
77
+ .transform(({ serviceResult: [value] }) => value)
78
+ .execute();
81
79
  });
82
80
 
83
81
  expect(result).toMatchObject({
@@ -88,23 +86,27 @@ describe("Internal Fragment", () => {
88
86
 
89
87
  it("should update an existing value", async () => {
90
88
  await fragment.inContext(async function () {
91
- return await this.uow(async ({ executeMutate }) => {
92
- const setPromise = fragment.services.settingsService.set(
93
- SETTINGS_NAMESPACE,
94
- "test-key",
95
- "updated-value",
96
- );
97
- await executeMutate();
98
- await setPromise;
99
- });
89
+ await this.handlerTx()
90
+ .withServiceCalls(
91
+ () =>
92
+ [
93
+ fragment.services.settingsService.set(
94
+ SETTINGS_NAMESPACE,
95
+ "test-key",
96
+ "updated-value",
97
+ ),
98
+ ] as const,
99
+ )
100
+ .execute();
100
101
  });
101
102
 
102
103
  const result = await fragment.inContext(async function () {
103
- return await this.uow(async ({ executeRetrieve }) => {
104
- const valuePromise = fragment.services.settingsService.get(SETTINGS_NAMESPACE, "test-key");
105
- await executeRetrieve();
106
- return await valuePromise;
107
- });
104
+ return await this.handlerTx()
105
+ .withServiceCalls(
106
+ () => [fragment.services.settingsService.get(SETTINGS_NAMESPACE, "test-key")] as const,
107
+ )
108
+ .transform(({ serviceResult: [value] }) => value)
109
+ .execute();
108
110
  });
109
111
 
110
112
  expect(result).toMatchObject({
@@ -116,31 +118,31 @@ describe("Internal Fragment", () => {
116
118
  it("should delete a value", async () => {
117
119
  // First get the ID
118
120
  const setting = await fragment.inContext(async function () {
119
- return await this.uow(async ({ executeRetrieve }) => {
120
- const valuePromise = fragment.services.settingsService.get(SETTINGS_NAMESPACE, "test-key");
121
- await executeRetrieve();
122
- return await valuePromise;
123
- });
121
+ return await this.handlerTx()
122
+ .withServiceCalls(
123
+ () => [fragment.services.settingsService.get(SETTINGS_NAMESPACE, "test-key")] as const,
124
+ )
125
+ .transform(({ serviceResult: [value] }) => value)
126
+ .execute();
124
127
  });
125
128
 
126
129
  expect(setting).toBeDefined();
127
130
 
128
131
  // Delete it
129
132
  await fragment.inContext(async function () {
130
- return await this.uow(async ({ executeMutate }) => {
131
- const deletePromise = fragment.services.settingsService.delete(setting!.id);
132
- await executeMutate();
133
- await deletePromise;
134
- });
133
+ await this.handlerTx()
134
+ .withServiceCalls(() => [fragment.services.settingsService.delete(setting!.id)] as const)
135
+ .execute();
135
136
  });
136
137
 
137
138
  // Verify it's gone
138
139
  const result = await fragment.inContext(async function () {
139
- return await this.uow(async ({ executeRetrieve }) => {
140
- const valuePromise = fragment.services.settingsService.get(SETTINGS_NAMESPACE, "test-key");
141
- await executeRetrieve();
142
- return await valuePromise;
143
- });
140
+ return await this.handlerTx()
141
+ .withServiceCalls(
142
+ () => [fragment.services.settingsService.get(SETTINGS_NAMESPACE, "test-key")] as const,
143
+ )
144
+ .transform(({ serviceResult: [value] }) => value)
145
+ .execute();
144
146
  });
145
147
 
146
148
  expect(result).toBeUndefined();
@@ -188,42 +190,44 @@ describe("Hook Service", () => {
188
190
  const nonce = "test-nonce-1";
189
191
 
190
192
  await fragment.inContext(async function () {
191
- return await this.uow(async ({ forSchema, executeMutate }) => {
192
- const uow = forSchema(internalSchema);
193
- uow.create("fragno_hooks", {
194
- namespace: "test-namespace",
195
- hookName: "onTest",
196
- payload: { test: "data" },
197
- status: "pending",
198
- attempts: 0,
199
- maxAttempts: 5,
200
- lastAttemptAt: null,
201
- nextRetryAt: null,
202
- error: null,
203
- nonce,
204
- });
205
- uow.create("fragno_hooks", {
206
- namespace: "test-namespace",
207
- hookName: "onTest",
208
- payload: { test: "already-completed-data" },
209
- status: "completed",
210
- attempts: 0,
211
- maxAttempts: 5,
212
- lastAttemptAt: null,
213
- nextRetryAt: null,
214
- error: null,
215
- nonce,
216
- });
217
- await executeMutate();
218
- });
193
+ await this.handlerTx()
194
+ .mutate(({ forSchema }) => {
195
+ const uow = forSchema(internalSchema);
196
+ uow.create("fragno_hooks", {
197
+ namespace: "test-namespace",
198
+ hookName: "onTest",
199
+ payload: { test: "data" },
200
+ status: "pending",
201
+ attempts: 0,
202
+ maxAttempts: 5,
203
+ lastAttemptAt: null,
204
+ nextRetryAt: null,
205
+ error: null,
206
+ nonce,
207
+ });
208
+ uow.create("fragno_hooks", {
209
+ namespace: "test-namespace",
210
+ hookName: "onTest",
211
+ payload: { test: "already-completed-data" },
212
+ status: "completed",
213
+ attempts: 0,
214
+ maxAttempts: 5,
215
+ lastAttemptAt: null,
216
+ nextRetryAt: null,
217
+ error: null,
218
+ nonce,
219
+ });
220
+ })
221
+ .execute();
219
222
  });
220
223
 
221
224
  const events = await fragment.inContext(async function () {
222
- return await this.uow(async ({ executeRetrieve }) => {
223
- const eventsPromise = fragment.services.hookService.getPendingHookEvents("test-namespace");
224
- await executeRetrieve();
225
- return await eventsPromise;
226
- });
225
+ return await this.handlerTx()
226
+ .withServiceCalls(
227
+ () => [fragment.services.hookService.getPendingHookEvents("test-namespace")] as const,
228
+ )
229
+ .transform(({ serviceResult: [result] }) => result)
230
+ .execute();
227
231
  });
228
232
 
229
233
  expect(events).toHaveLength(1);
@@ -232,7 +236,7 @@ describe("Hook Service", () => {
232
236
  payload: { test: "data" },
233
237
  attempts: 0,
234
238
  maxAttempts: 5,
235
- nonce,
239
+ idempotencyKey: nonce,
236
240
  });
237
241
  });
238
242
 
@@ -241,41 +245,36 @@ describe("Hook Service", () => {
241
245
  let eventId: FragnoId;
242
246
 
243
247
  await fragment.inContext(async function () {
244
- return await this.uow(async ({ forSchema, executeMutate }) => {
245
- const uow = forSchema(internalSchema);
246
- eventId = uow.create("fragno_hooks", {
247
- namespace: "test-namespace",
248
- hookName: "onComplete",
249
- payload: { test: "data" },
250
- status: "pending",
251
- attempts: 0,
252
- maxAttempts: 5,
253
- lastAttemptAt: null,
254
- nextRetryAt: null,
255
- error: null,
256
- nonce,
257
- });
258
- await executeMutate();
259
- });
248
+ await this.handlerTx()
249
+ .mutate(({ forSchema }) => {
250
+ const uow = forSchema(internalSchema);
251
+ eventId = uow.create("fragno_hooks", {
252
+ namespace: "test-namespace",
253
+ hookName: "onComplete",
254
+ payload: { test: "data" },
255
+ status: "pending",
256
+ attempts: 0,
257
+ maxAttempts: 5,
258
+ lastAttemptAt: null,
259
+ nextRetryAt: null,
260
+ error: null,
261
+ nonce,
262
+ });
263
+ })
264
+ .execute();
260
265
  });
261
266
 
262
267
  await fragment.inContext(async function () {
263
- return await this.uow(async ({ executeMutate }) => {
264
- fragment.services.hookService.markHookCompleted(eventId);
265
- await executeMutate();
266
- });
268
+ await this.handlerTx()
269
+ .withServiceCalls(() => [fragment.services.hookService.markHookCompleted(eventId)] as const)
270
+ .execute();
267
271
  });
268
272
 
269
273
  const result = await fragment.inContext(async function () {
270
- return await this.uow(async ({ forSchema, executeRetrieve }) => {
271
- const uow = forSchema(internalSchema);
272
- const findUow = uow.find("fragno_hooks", (b) =>
273
- b.whereIndex("primary", (eb) => eb("id", "=", eventId)),
274
- );
275
- await executeRetrieve();
276
- const [events] = await findUow.retrievalPhase;
277
- return events?.[0];
278
- });
274
+ return await this.handlerTx()
275
+ .withServiceCalls(() => [fragment.services.hookService.getHookById(eventId)] as const)
276
+ .transform(({ serviceResult: [event] }) => event)
277
+ .execute();
279
278
  });
280
279
 
281
280
  expect(result).toBeDefined();
@@ -288,41 +287,38 @@ describe("Hook Service", () => {
288
287
  let eventId: FragnoId;
289
288
 
290
289
  await fragment.inContext(async function () {
291
- return await this.uow(async ({ forSchema, executeMutate }) => {
292
- const uow = forSchema(internalSchema);
293
- eventId = uow.create("fragno_hooks", {
294
- namespace: "test-namespace",
295
- hookName: "onProcess",
296
- payload: { test: "data" },
297
- status: "pending",
298
- attempts: 0,
299
- maxAttempts: 5,
300
- lastAttemptAt: null,
301
- nextRetryAt: null,
302
- error: null,
303
- nonce,
304
- });
305
- await executeMutate();
306
- });
290
+ return this.handlerTx()
291
+ .mutate(({ forSchema }) => {
292
+ const uow = forSchema(internalSchema);
293
+ eventId = uow.create("fragno_hooks", {
294
+ namespace: "test-namespace",
295
+ hookName: "onProcess",
296
+ payload: { test: "data" },
297
+ status: "pending",
298
+ attempts: 0,
299
+ maxAttempts: 5,
300
+ lastAttemptAt: null,
301
+ nextRetryAt: null,
302
+ error: null,
303
+ nonce,
304
+ });
305
+ })
306
+ .execute();
307
307
  });
308
308
 
309
309
  await fragment.inContext(async function () {
310
- return await this.uow(async ({ executeMutate }) => {
311
- fragment.services.hookService.markHookProcessing(eventId);
312
- await executeMutate();
313
- });
310
+ await this.handlerTx()
311
+ .withServiceCalls(
312
+ () => [fragment.services.hookService.markHookProcessing(eventId)] as const,
313
+ )
314
+ .execute();
314
315
  });
315
316
 
316
317
  const result = await fragment.inContext(async function () {
317
- return await this.uow(async ({ forSchema, executeRetrieve }) => {
318
- const uow = forSchema(internalSchema);
319
- const findUow = uow.find("fragno_hooks", (b) =>
320
- b.whereIndex("primary", (eb) => eb("id", "=", eventId)),
321
- );
322
- await executeRetrieve();
323
- const [events] = await findUow.retrievalPhase;
324
- return events?.[0];
325
- });
318
+ return await this.handlerTx()
319
+ .withServiceCalls(() => [fragment.services.hookService.getHookById(eventId)] as const)
320
+ .transform(({ serviceResult: [event] }) => event)
321
+ .execute();
326
322
  });
327
323
 
328
324
  expect(result).toBeDefined();
@@ -335,43 +331,44 @@ describe("Hook Service", () => {
335
331
  let eventId: FragnoId;
336
332
 
337
333
  await fragment.inContext(async function () {
338
- return await this.uow(async ({ forSchema, executeMutate }) => {
339
- const uow = forSchema(internalSchema);
340
- eventId = uow.create("fragno_hooks", {
341
- namespace: "test-namespace",
342
- hookName: "onFail",
343
- payload: { test: "data" },
344
- status: "pending",
345
- attempts: 0,
346
- maxAttempts: 5,
347
- lastAttemptAt: null,
348
- nextRetryAt: null,
349
- error: null,
350
- nonce,
351
- });
352
- await executeMutate();
353
- });
334
+ const createdId = await this.handlerTx()
335
+ .mutate(({ forSchema }) => {
336
+ const uow = forSchema(internalSchema);
337
+ return uow.create("fragno_hooks", {
338
+ namespace: "test-namespace",
339
+ hookName: "onFail",
340
+ payload: { test: "data" },
341
+ status: "pending",
342
+ attempts: 0,
343
+ maxAttempts: 5,
344
+ lastAttemptAt: null,
345
+ nextRetryAt: null,
346
+ error: null,
347
+ nonce,
348
+ });
349
+ })
350
+ .execute();
351
+ eventId = createdId;
354
352
  });
355
353
 
356
354
  const retryPolicy = new ExponentialBackoffRetryPolicy({ maxRetries: 3 });
357
355
 
358
356
  await fragment.inContext(async function () {
359
- return await this.uow(async ({ executeMutate }) => {
360
- fragment.services.hookService.markHookFailed(eventId, "Test error", 0, retryPolicy);
361
- await executeMutate();
362
- });
357
+ await this.handlerTx()
358
+ .withServiceCalls(
359
+ () =>
360
+ [
361
+ fragment.services.hookService.markHookFailed(eventId, "Test error", 0, retryPolicy),
362
+ ] as const,
363
+ )
364
+ .execute();
363
365
  });
364
366
 
365
367
  const result = await fragment.inContext(async function () {
366
- return await this.uow(async ({ forSchema, executeRetrieve }) => {
367
- const uow = forSchema(internalSchema);
368
- const findUow = uow.find("fragno_hooks", (b) =>
369
- b.whereIndex("primary", (eb) => eb("id", "=", eventId)),
370
- );
371
- await executeRetrieve();
372
- const [events] = await findUow.retrievalPhase;
373
- return events?.[0];
374
- });
368
+ return await this.handlerTx()
369
+ .withServiceCalls(() => [fragment.services.hookService.getHookById(eventId)] as const)
370
+ .transform(({ serviceResult: [event] }) => event)
371
+ .execute();
375
372
  });
376
373
 
377
374
  expect(result).toBeDefined();
@@ -387,48 +384,49 @@ describe("Hook Service", () => {
387
384
  let eventId: FragnoId;
388
385
 
389
386
  await fragment.inContext(async function () {
390
- return await this.uow(async ({ forSchema, executeMutate }) => {
391
- const uow = forSchema(internalSchema);
392
- eventId = uow.create("fragno_hooks", {
393
- namespace: "test-namespace",
394
- hookName: "onMaxFail",
395
- payload: { test: "data" },
396
- status: "pending",
397
- attempts: 0,
398
- maxAttempts: 1,
399
- lastAttemptAt: null,
400
- nextRetryAt: null,
401
- error: null,
402
- nonce,
403
- });
404
- await executeMutate();
405
- });
387
+ const createdId = await this.handlerTx()
388
+ .mutate(({ forSchema }) => {
389
+ const uow = forSchema(internalSchema);
390
+ return uow.create("fragno_hooks", {
391
+ namespace: "test-namespace",
392
+ hookName: "onMaxFail",
393
+ payload: { test: "data" },
394
+ status: "pending",
395
+ attempts: 0,
396
+ maxAttempts: 1,
397
+ lastAttemptAt: null,
398
+ nextRetryAt: null,
399
+ error: null,
400
+ nonce,
401
+ });
402
+ })
403
+ .execute();
404
+ eventId = createdId;
406
405
  });
407
406
 
408
407
  const retryPolicy = new NoRetryPolicy();
409
408
 
410
409
  await fragment.inContext(async function () {
411
- return await this.uow(async ({ executeMutate }) => {
412
- fragment.services.hookService.markHookFailed(
413
- eventId,
414
- "Max attempts reached",
415
- 0,
416
- retryPolicy,
417
- );
418
- await executeMutate();
419
- });
410
+ await this.handlerTx()
411
+ .withServiceCalls(
412
+ () =>
413
+ [
414
+ fragment.services.hookService.markHookFailed(
415
+ eventId,
416
+ "Max attempts reached",
417
+ 0,
418
+ retryPolicy,
419
+ ),
420
+ ] as const,
421
+ )
422
+ .execute();
420
423
  });
421
424
 
422
425
  const result = await fragment.inContext(async function () {
423
- return await this.uow(async ({ forSchema, executeRetrieve }) => {
424
- const uow = forSchema(internalSchema);
425
- const findUow = uow.find("fragno_hooks", (b) =>
426
- b.whereIndex("primary", (eb) => eb("id", "=", eventId)),
427
- );
428
- await executeRetrieve();
429
- const [events] = await findUow.retrievalPhase;
430
- return events?.[0];
431
- });
426
+ return await this.handlerTx()
427
+ .withServiceCalls(() => [fragment.services.hookService.getHookById(eventId)] as const)
428
+ .transform(({ serviceResult: [event] }) => event)
429
+ .execute();
432
430
  });
433
431
 
434
432
  expect(result).toBeDefined();
@@ -444,30 +442,33 @@ describe("Hook Service", () => {
444
442
  const pastTime = new Date(Date.now() - 10000);
445
443
 
446
444
  await fragment.inContext(async function () {
447
- return await this.uow(async ({ forSchema, executeMutate }) => {
448
- const uow = forSchema(internalSchema);
449
- eventId = uow.create("fragno_hooks", {
450
- namespace: "test-namespace",
451
- hookName: "onStale",
452
- payload: { test: "stale" },
453
- status: "pending",
454
- attempts: 1,
455
- maxAttempts: 5,
456
- lastAttemptAt: pastTime,
457
- nextRetryAt: pastTime,
458
- error: "Previous error",
459
- nonce,
460
- });
461
- await executeMutate();
462
- });
445
+ const createdId = await this.handlerTx()
446
+ .mutate(({ forSchema }) => {
447
+ const uow = forSchema(internalSchema);
448
+ return uow.create("fragno_hooks", {
449
+ namespace: "test-namespace",
450
+ hookName: "onStale",
451
+ payload: { test: "stale" },
452
+ status: "pending",
453
+ attempts: 1,
454
+ maxAttempts: 5,
455
+ lastAttemptAt: pastTime,
456
+ nextRetryAt: pastTime,
457
+ error: "Previous error",
458
+ nonce,
459
+ });
460
+ })
461
+ .execute();
462
+ eventId = createdId;
463
463
  });
464
464
 
465
465
  const events = await fragment.inContext(async function () {
466
- return await this.uow(async ({ executeRetrieve }) => {
467
- const eventsPromise = fragment.services.hookService.getPendingHookEvents("test-namespace");
468
- await executeRetrieve();
469
- return await eventsPromise;
470
- });
466
+ return await this.handlerTx()
467
+ .withServiceCalls(
468
+ () => [fragment.services.hookService.getPendingHookEvents("test-namespace")] as const,
469
+ )
470
+ .transform(({ serviceResult: [result] }) => result)
471
+ .execute();
471
472
  });
472
473
 
473
474
  const staleEvent = events.find((e) => e.id.externalId === eventId.externalId);
@@ -480,30 +481,32 @@ describe("Hook Service", () => {
480
481
  const nonce = "test-nonce-7";
481
482
 
482
483
  await fragment.inContext(async function () {
483
- return await this.uow(async ({ forSchema, executeMutate }) => {
484
- const uow = forSchema(internalSchema);
485
- uow.create("fragno_hooks", {
486
- namespace: "other-namespace",
487
- hookName: "onOther",
488
- payload: { test: "other" },
489
- status: "pending",
490
- attempts: 0,
491
- maxAttempts: 5,
492
- lastAttemptAt: null,
493
- nextRetryAt: null,
494
- error: null,
495
- nonce,
496
- });
497
- await executeMutate();
498
- });
484
+ await this.handlerTx()
485
+ .mutate(({ forSchema }) => {
486
+ const uow = forSchema(internalSchema);
487
+ uow.create("fragno_hooks", {
488
+ namespace: "other-namespace",
489
+ hookName: "onOther",
490
+ payload: { test: "other" },
491
+ status: "pending",
492
+ attempts: 0,
493
+ maxAttempts: 5,
494
+ lastAttemptAt: null,
495
+ nextRetryAt: null,
496
+ error: null,
497
+ nonce,
498
+ });
499
+ })
500
+ .execute();
499
501
  });
500
502
 
501
503
  const events = await fragment.inContext(async function () {
502
- return await this.uow(async ({ executeRetrieve }) => {
503
- const eventsPromise = fragment.services.hookService.getPendingHookEvents("test-namespace");
504
- await executeRetrieve();
505
- return await eventsPromise;
506
- });
504
+ return await this.handlerTx()
505
+ .withServiceCalls(
506
+ () => [fragment.services.hookService.getPendingHookEvents("test-namespace")] as const,
507
+ )
508
+ .transform(({ serviceResult: [result] }) => result)
509
+ .execute();
507
510
  });
508
511
 
509
512
  const otherEvent = events.find((e) => e.hookName === "onOther");
@@ -517,30 +520,33 @@ describe("Hook Service", () => {
517
520
  const futureTime = new Date(Date.now() + 60000);
518
521
 
519
522
  await fragment.inContext(async function () {
520
- return await this.uow(async ({ forSchema, executeMutate }) => {
521
- const uow = forSchema(internalSchema);
522
- eventId = uow.create("fragno_hooks", {
523
- namespace: "test-namespace",
524
- hookName: "onFuture",
525
- payload: { test: "future" },
526
- status: "pending",
527
- attempts: 1,
528
- maxAttempts: 5,
529
- lastAttemptAt: new Date(),
530
- nextRetryAt: futureTime,
531
- error: "Previous error",
532
- nonce,
533
- });
534
- await executeMutate();
535
- });
523
+ const createdId = await this.handlerTx()
524
+ .mutate(({ forSchema }) => {
525
+ const uow = forSchema(internalSchema);
526
+ return uow.create("fragno_hooks", {
527
+ namespace: "test-namespace",
528
+ hookName: "onFuture",
529
+ payload: { test: "future" },
530
+ status: "pending",
531
+ attempts: 1,
532
+ maxAttempts: 5,
533
+ lastAttemptAt: new Date(),
534
+ nextRetryAt: futureTime,
535
+ error: "Previous error",
536
+ nonce,
537
+ });
538
+ })
539
+ .execute();
540
+ eventId = createdId;
536
541
  });
537
542
 
538
543
  const events = await fragment.inContext(async function () {
539
- return await this.uow(async ({ executeRetrieve }) => {
540
- const eventsPromise = fragment.services.hookService.getPendingHookEvents("test-namespace");
541
- await executeRetrieve();
542
- return await eventsPromise;
543
- });
544
+ return await this.handlerTx()
545
+ .withServiceCalls(
546
+ () => [fragment.services.hookService.getPendingHookEvents("test-namespace")] as const,
547
+ )
548
+ .transform(({ serviceResult: [result] }) => result)
549
+ .execute();
544
550
  });
545
551
 
546
552
  const futureEvent = events.find((e) => e.id.externalId === eventId.externalId);