@effect-app/infra 0.199.0 → 0.199.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.
@@ -29,7 +29,8 @@ import type { FixEnv, PureEnv } from "effect-app/Pure"
29
29
  import { assignTag } from "effect-app/service"
30
30
  import { type InvalidStateError, NotFoundError, type OptimisticConcurrencyException } from "../errors.js"
31
31
  import type { FieldValues } from "../filter/types.js"
32
- import { make as makeQuery, type QAll, type Query, query, type QueryProjection } from "./query.js"
32
+ import { make as makeQuery, page, query } from "./query.js"
33
+ import type { QAll, Query, QueryEnd, QueryProjection, QueryWhere } from "./query.js"
33
34
  import { ContextMapContainer } from "./Store/ContextMapContainer.js"
34
35
  import * as Q from "./Store/filterApi/query.js"
35
36
 
@@ -94,6 +95,7 @@ export abstract class RepositoryBaseC<
94
95
  events?: Iterable<Evt>
95
96
  ) => Effect<void>
96
97
 
98
+ /** @deprecated use q2 */
97
99
  abstract readonly mapped: Mapped<PM, Omit<PM, "_etag">>
98
100
  abstract readonly q2: {
99
101
  <A, R, From extends FieldValues>(
@@ -176,7 +178,95 @@ export class RepositoryBaseC3<
176
178
  return Effect.andThen(this.get(id), (_) => this.removeAndPublish([_]))
177
179
  }
178
180
 
179
- // TODO: project inside the db.
181
+ count(filter?: Filter<PM>) {
182
+ return Effect.map(
183
+ this.projectEffect(Effect.sync(() => ({ filter }))),
184
+ (_) => NonNegativeInt(_.length)
185
+ )
186
+ }
187
+
188
+ readonly save = (...items: NonEmptyArray<T>) => this.saveAndPublish(items)
189
+
190
+ readonly saveWithEvents = (events: Iterable<Evt>) => (...items: NonEmptyArray<T>) =>
191
+ this.saveAndPublish(items, events)
192
+
193
+ readonly q2AndSaveOnePure = <A, E2, R2, T2 extends T>(
194
+ q: (q: Query<Omit<PM, "_etag">>) => Query<Omit<PM, "_etag">> | QueryEnd<Omit<PM, "_etag">>,
195
+ pure: Effect<A, E2, FixEnv<R2, Evt, T, T2>>
196
+ ) =>
197
+ this.q2(flow(q, page({ limit: 1 }))).pipe(
198
+ Effect.map(ReadonlyArray.toNonEmptyArray),
199
+ Effect.flatMap(Effect.mapError(() => new NotFoundError({ type: this.itemType, id: q }))),
200
+ Effect.andThen((_) => saveWithPure_(this, _[0], pure))
201
+ )
202
+
203
+ readonly q2AndSavePure = <A, E2, R2, T2 extends T>(
204
+ q: (q: Query<Omit<PM, "_etag">>) => Query<Omit<PM, "_etag">> | QueryEnd<Omit<PM, "_etag">>,
205
+ pure: Effect<A, E2, FixEnv<R2, Evt, readonly T[], readonly T2[]>>,
206
+ batchSize?: number
207
+ ) =>
208
+ this.q2(flow(q, page({ limit: 1 }))).pipe(
209
+ Effect.andThen((_) =>
210
+ batchSize === undefined
211
+ ? saveManyWithPure_(this, _, pure)
212
+ : saveManyWithPureBatched_(this, _, pure, batchSize)
213
+ )
214
+ )
215
+
216
+ /**
217
+ * NOTE: it's not as composable, only useful when the request is simple, and only this part needs request args.
218
+ */
219
+ readonly handleByIdAndSaveWithPure = <Req extends { id: T["id"] }, Context, R, A, E, S2 extends T>(
220
+ pure: (req: Req, ctx: Context) => Effect<A, E, FixEnv<R, Evt, T, S2>>
221
+ ) =>
222
+ (req: Req, ctx: Context) => byIdAndSaveWithPure(this, req.id)(pure(req, ctx))
223
+
224
+ saveManyWithPure = <
225
+ R,
226
+ A,
227
+ E,
228
+ S1 extends T,
229
+ S2 extends T
230
+ >(
231
+ items: Iterable<S1>,
232
+ pure: Effect<A, E, FixEnv<R, Evt, readonly S1[], readonly S2[]>>
233
+ ) =>
234
+ saveAllWithEffectInt(
235
+ this,
236
+ runTerm(pure, [...items])
237
+ )
238
+
239
+ byIdAndSaveWithPure: {
240
+ <R, A, E, S2 extends T>(
241
+ id: T["id"],
242
+ pure: Effect<A, E, FixEnv<R, Evt, T, S2>>
243
+ ): Effect<
244
+ A,
245
+ InvalidStateError | OptimisticConcurrencyException | NotFoundError<ItemType> | E,
246
+ Exclude<R, {
247
+ env: PureEnv<Evt, T, S2>
248
+ }>
249
+ >
250
+ } = (id, pure): any => get(this, id).pipe(Effect.flatMap((item) => saveWithPure_(this, item, pure)))
251
+
252
+ saveWithPure<
253
+ R,
254
+ A,
255
+ E,
256
+ S1 extends T,
257
+ S2 extends T
258
+ >(
259
+ item: S1,
260
+ pure: Effect<A, E, FixEnv<R, Evt, S1, S2>>
261
+ ) {
262
+ return saveAllWithEffectInt(
263
+ this,
264
+ runTerm(pure, item)
265
+ .pipe(Effect.map(([item, events, a]) => [[item], events, a]))
266
+ )
267
+ }
268
+
269
+ /** @deprecated use q2 */
180
270
  projectEffect<
181
271
  R,
182
272
  E,
@@ -193,6 +283,7 @@ export class RepositoryBaseC3<
193
283
  R
194
284
  >
195
285
  ): Effect<S[], E, R>
286
+ /** @deprecated use q2 */
196
287
  projectEffect<
197
288
  R,
198
289
  E,
@@ -210,6 +301,7 @@ export class RepositoryBaseC3<
210
301
  R
211
302
  >
212
303
  ): Effect<Pick<PM, U>[], E, R>
304
+ /** @deprecated use q2 */
213
305
  projectEffect<
214
306
  R,
215
307
  E,
@@ -238,6 +330,7 @@ export class RepositoryBaseC3<
238
330
  ))
239
331
  }
240
332
 
333
+ /** @deprecated use q2 */
241
334
  project<S = PM>(
242
335
  map: {
243
336
  filter?: Filter<PM>
@@ -246,6 +339,7 @@ export class RepositoryBaseC3<
246
339
  skip?: number
247
340
  }
248
341
  ): Effect<S[]>
342
+ /** @deprecated use q2 */
249
343
  project<U extends keyof PM>(
250
344
  map: {
251
345
  filter?: Q.QueryBuilder<PM>
@@ -254,6 +348,7 @@ export class RepositoryBaseC3<
254
348
  skip?: number
255
349
  }
256
350
  ): Effect<Pick<PM, U>[]>
351
+ /** @deprecated use q2 */
257
352
  project<
258
353
  U extends keyof PM,
259
354
  S = Pick<PM, U>
@@ -269,13 +364,7 @@ export class RepositoryBaseC3<
269
364
  return this.projectEffect(Effect.sync(() => map))
270
365
  }
271
366
 
272
- count(filter?: Filter<PM>) {
273
- return Effect.map(
274
- this.projectEffect(Effect.sync(() => ({ filter }))),
275
- (_) => NonNegativeInt(_.length)
276
- )
277
- }
278
-
367
+ /** @deprecated use q2 */
279
368
  queryEffect<
280
369
  R,
281
370
  E,
@@ -292,10 +381,12 @@ export class RepositoryBaseC3<
292
381
  ))
293
382
  }
294
383
 
384
+ /** @deprecated use q2 */
295
385
  queryOneEffect<R, E>(
296
386
  // TODO: think about collectPM, collectE, and collect(Parsed)
297
387
  map: Effect<{ filter?: Filter<PM> }, E, R>
298
388
  ): Effect<T, E | NotFoundError<ItemType>, R>
389
+ /** @deprecated use q2 */
299
390
  queryOneEffect<
300
391
  R,
301
392
  E,
@@ -304,6 +395,7 @@ export class RepositoryBaseC3<
304
395
  // TODO: think about collectPM, collectE, and collect(Parsed)
305
396
  map: Effect<{ filter?: Filter<PM>; collect: (t: T) => Option<S> }, E, R>
306
397
  ): Effect<S, E | NotFoundError<ItemType>, R>
398
+ /** @deprecated use q2 */
307
399
  queryOneEffect<
308
400
  R,
309
401
  E,
@@ -331,6 +423,7 @@ export class RepositoryBaseC3<
331
423
  ))
332
424
  }
333
425
 
426
+ /** @deprecated use q2 */
334
427
  queryLegacy<S = T>(
335
428
  // TODO: think about collectPM, collectE, and collect(Parsed)
336
429
  map: { filter?: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }
@@ -338,24 +431,29 @@ export class RepositoryBaseC3<
338
431
  return this.queryEffect(Effect.sync(() => map))
339
432
  }
340
433
 
434
+ /** @deprecated use q2 */
341
435
  query(
342
436
  b: (fn: Q.FilterTest<PM>, fields: Q.Filter<PM, never>) => Q.QueryBuilder<PM>
343
437
  ) {
344
438
  return this.queryEffect(Effect.sync(() => ({ filter: anyQb((_, fields) => b(_, fields as any)) })))
345
439
  }
346
440
 
441
+ /** @deprecated use q2 */
347
442
  queryOne<S = T>(
348
443
  map: { filter?: Filter<PM>; collect: (t: T) => Option<S> }
349
444
  ): Effect<S, NotFoundError<ItemType>>
445
+ /** @deprecated use q2 */
350
446
  queryOne(
351
447
  map: { filter?: Filter<PM> }
352
448
  ): Effect<T, NotFoundError<ItemType>>
449
+ /** @deprecated use q2 */
353
450
  queryOne<S = T>(
354
451
  map: { filter?: Filter<PM>; collect?: (t: T) => Option<S> }
355
452
  ) {
356
453
  return this.queryOneEffect(Effect.sync(() => map))
357
454
  }
358
455
 
456
+ /** @deprecated */
359
457
  queryAndSaveOnePureEffect<
360
458
  R,
361
459
  E,
@@ -372,6 +470,7 @@ export class RepositoryBaseC3<
372
470
  env: PureEnv<Evt, S, S2>
373
471
  }>
374
472
  >
473
+ /** @deprecated */
375
474
  queryAndSaveOnePureEffect<
376
475
  R,
377
476
  E
@@ -387,12 +486,13 @@ export class RepositoryBaseC3<
387
486
  env: PureEnv<Evt, T, T2>
388
487
  }>
389
488
  >
489
+ /** @deprecated */
390
490
  queryAndSaveOnePureEffect(
391
491
  map: any
392
492
  ) {
393
493
  return (pure: any) => Effect.flatMap(queryOneEffect(this, map), (_) => saveWithPure_(this, _, pure))
394
494
  }
395
-
495
+ /** @deprecated */
396
496
  queryAndSaveOnePure<
397
497
  S extends T = T
398
498
  >(
@@ -404,6 +504,7 @@ export class RepositoryBaseC3<
404
504
  env: PureEnv<Evt, S, S2>
405
505
  }>
406
506
  >
507
+ /** @deprecated */
407
508
  queryAndSaveOnePure(
408
509
  map: { filter: Filter<PM> }
409
510
  ): <R2, A, E2, T2>(pure: Effect<A, E2, FixEnv<R2, Evt, T, T2>>) => Effect<
@@ -413,12 +514,13 @@ export class RepositoryBaseC3<
413
514
  env: PureEnv<Evt, T, T2>
414
515
  }>
415
516
  >
517
+ /** @deprecated */
416
518
  queryAndSaveOnePure<S = T>(
417
519
  map: { filter: Filter<PM>; collect: (t: T) => Option<S> }
418
520
  ) {
419
521
  return this.queryAndSaveOnePureEffect(Effect.sync(() => map))
420
522
  }
421
-
523
+ /** @deprecated */
422
524
  queryAndSavePureEffect<
423
525
  R,
424
526
  E,
@@ -426,10 +528,10 @@ export class RepositoryBaseC3<
426
528
  >(
427
529
  map: Effect<{ filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }, E, R>
428
530
  ) {
429
- return <R2, A, E2, S2 extends T>(pure: Effect<A, E2, FixEnv<R2, Evt, S[], S2[]>>) =>
430
- Effect.flatMap(queryEffect(this, map), (_) => this.saveManyWithPure_(_, pure))
531
+ return <R2, A, E2, S2 extends T>(pure: Effect<A, E2, FixEnv<R2, Evt, readonly S[], readonly S2[]>>) =>
532
+ Effect.flatMap(queryEffect(this, map), (_) => this.saveManyWithPure(_, pure))
431
533
  }
432
-
534
+ /** @deprecated */
433
535
  queryAndSavePure<
434
536
  S extends T = T
435
537
  >(
@@ -438,92 +540,7 @@ export class RepositoryBaseC3<
438
540
  return this.queryAndSavePureEffect(Effect.sync(() => map))
439
541
  }
440
542
 
441
- get saveManyWithPure() {
442
- return <R, A, E, S1 extends T, S2 extends T>(pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>) =>
443
- (items: Iterable<S1>) => saveManyWithPure_(this, items, pure)
444
- }
445
-
446
- byIdAndSaveWithPure(
447
- id: T["id"]
448
- ): <R, A, E, S2 extends T>(
449
- pure: Effect<A, E, FixEnv<R, Evt, T, S2>>
450
- ) => Effect<
451
- A,
452
- InvalidStateError | OptimisticConcurrencyException | NotFoundError<ItemType> | E,
453
- Exclude<R, {
454
- env: PureEnv<Evt, T, S2>
455
- }>
456
- >
457
- byIdAndSaveWithPure<R, A, E, S2 extends T>(
458
- id: T["id"],
459
- pure: Effect<A, E, FixEnv<R, Evt, T, S2>>
460
- ): Effect<
461
- A,
462
- InvalidStateError | OptimisticConcurrencyException | NotFoundError<ItemType> | E,
463
- Exclude<R, {
464
- env: PureEnv<Evt, T, S2>
465
- }>
466
- >
467
- byIdAndSaveWithPure<R, A, E, S2 extends T>(id: T["id"], pure?: Effect<A, E, FixEnv<R, Evt, T, S2>>) {
468
- if (pure) return get(this, id).pipe(Effect.flatMap((item) => saveWithPure_(this, item, pure)))
469
- return (pure: Effect<A, E, FixEnv<R, Evt, T, S2>>) =>
470
- get(this, id).pipe(Effect.flatMap((item) => saveWithPure_(this, item, pure)))
471
- }
472
-
473
- /**
474
- * NOTE: it's not as composable, only useful when the request is simple, and only this part needs request args.
475
- */
476
- get handleByIdAndSaveWithPure() {
477
- return <Req extends { id: T["id"] }, Context, R, A, E, S2 extends T>(
478
- pure: (req: Req, ctx: Context) => Effect<A, E, FixEnv<R, Evt, T, S2>>
479
- ) =>
480
- (req: Req, ctx: Context) => byIdAndSaveWithPure(this, req.id)(pure(req, ctx))
481
- }
482
-
483
- saveManyWithPure_<
484
- R,
485
- A,
486
- E,
487
- S1 extends T,
488
- S2 extends T
489
- >(
490
- items: Iterable<S1>,
491
- pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>
492
- ) {
493
- return saveAllWithEffectInt(
494
- this,
495
- runTerm(pure, [...items])
496
- )
497
- }
498
-
499
- saveWithPure_<
500
- R,
501
- A,
502
- E,
503
- S1 extends T,
504
- S2 extends T
505
- >(
506
- item: S1,
507
- pure: Effect<A, E, FixEnv<R, Evt, S1, S2>>
508
- ) {
509
- return saveAllWithEffectInt(
510
- this,
511
- runTerm(pure, item)
512
- .pipe(Effect.map(([item, events, a]) => [[item], events, a]))
513
- )
514
- }
515
-
516
- saveAllWithEffectInt<
517
- P extends T,
518
- R,
519
- E,
520
- A
521
- >(
522
- gen: Effect<readonly [Iterable<P>, Iterable<Evt>, A], E, R>
523
- ) {
524
- return Effect.flatMap(gen, ([items, events, a]) => Effect.map(this.saveAndPublish(items, events), () => a))
525
- }
526
-
543
+ /** @deprecated use q2 */
527
544
  queryAndSavePureEffectBatched<
528
545
  R,
529
546
  E,
@@ -533,10 +550,11 @@ export class RepositoryBaseC3<
533
550
  map: Effect<{ filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }, E, R>,
534
551
  batchSize = 100
535
552
  ) {
536
- return <R2, A, E2, S2 extends T>(pure: Effect<A, E2, FixEnv<R2, Evt, S[], S2[]>>) =>
537
- Effect.flatMap(queryEffect(this, map), (_) => this.saveManyWithPureBatched_(_, pure, batchSize))
553
+ return <R2, A, E2, S2 extends T>(pure: Effect<A, E2, FixEnv<R2, Evt, readonly S[], readonly S2[]>>) =>
554
+ Effect.flatMap(queryEffect(this, map), (_) => this.saveManyWithPureBatched(_, pure, batchSize))
538
555
  }
539
556
 
557
+ /** @deprecated use q2 */
540
558
  queryAndSavePureBatched<
541
559
  S extends T = T
542
560
  >(
@@ -547,12 +565,8 @@ export class RepositoryBaseC3<
547
565
  return this.queryAndSavePureEffectBatched(Effect.sync(() => map), batchSize)
548
566
  }
549
567
 
550
- saveManyWithPureBatched(batchSize = 100) {
551
- return <R, A, E, S1 extends T, S2 extends T>(pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>) =>
552
- (items: Iterable<S1>) => saveManyWithPureBatched_(this, items, pure, batchSize)
553
- }
554
-
555
- saveManyWithPureBatched_<
568
+ /** @deprecated use q2 */
569
+ saveManyWithPureBatched<
556
570
  R,
557
571
  A,
558
572
  E,
@@ -560,7 +574,7 @@ export class RepositoryBaseC3<
560
574
  S2 extends T
561
575
  >(
562
576
  items: Iterable<S1>,
563
- pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>,
577
+ pure: Effect<A, E, FixEnv<R, Evt, readonly S1[], readonly S2[]>>,
564
578
  batchSize = 100
565
579
  ) {
566
580
  return Effect.forEach(
@@ -572,13 +586,6 @@ export class RepositoryBaseC3<
572
586
  )
573
587
  )
574
588
  }
575
-
576
- readonly save = (...items: NonEmptyArray<T>) => this.saveAndPublish(items)
577
-
578
- readonly saveWithEvents = (
579
- events: Iterable<Evt>
580
- ) =>
581
- (...items: NonEmptyArray<T>) => this.saveAndPublish(items, events)
582
589
  }
583
590
 
584
591
  type Exact<A, B> = [A] extends [B] ? [B] extends [A] ? true : false : false
@@ -1026,6 +1033,7 @@ export interface RepoFunctions<T extends { id: unknown }, PM extends { id: strin
1026
1033
  save: (...items: T[]) => Effect<void, InvalidStateError | OptimisticConcurrencyException, Service>
1027
1034
  get: (id: T["id"]) => Effect<T, NotFoundError<ItemType>, Service>
1028
1035
 
1036
+ /** @deprecated use q2 */
1029
1037
  query: (b: (fn: Q.FilterTest<PM>, fields: Q.Filter<PM, never>) => Q.QueryBuilder<PM>) => Effect<T[], never, Service>
1030
1038
  queryLegacy: <S = T>(map: {
1031
1039
  filter?: Filter<PM>
@@ -1034,8 +1042,64 @@ export interface RepoFunctions<T extends { id: unknown }, PM extends { id: strin
1034
1042
  skip?: number
1035
1043
  }) => Effect<S[], never, Service>
1036
1044
 
1045
+ /** @deprecated use q2 */
1037
1046
  mapped: MM<Service, PM, Omit<PM, "_etag">>
1038
1047
 
1048
+ byIdAndSaveWithPure: {
1049
+ <R, A, E, S2 extends T>(
1050
+ id: T["id"],
1051
+ pure: Effect<A, E, FixEnv<R, never, T, S2>>
1052
+ ): Effect<
1053
+ A,
1054
+ InvalidStateError | OptimisticConcurrencyException | E | NotFoundError<ItemType>,
1055
+ | Service
1056
+ | Exclude<R, {
1057
+ env: PureEnv<never, T, S2>
1058
+ }>
1059
+ >
1060
+ }
1061
+
1062
+ q2AndSaveOnePure: {
1063
+ <
1064
+ R2,
1065
+ A,
1066
+ E2,
1067
+ T2 extends T
1068
+ >(
1069
+ q: (initial: Query<Omit<PM, "_etag">>) =>
1070
+ | Query<Omit<PM, "_etag">>
1071
+ | QueryWhere<Omit<PM, "_etag">>,
1072
+ pure: Effect<A, E2, FixEnv<R2, Evt, T, T2>>
1073
+ ): Effect<
1074
+ A,
1075
+ InvalidStateError | OptimisticConcurrencyException | E2 | NotFoundError<ItemType>,
1076
+ | Service
1077
+ | Exclude<R2, {
1078
+ env: PureEnv<Evt, T, T2>
1079
+ }>
1080
+ >
1081
+ }
1082
+ q2AndSavePure: {
1083
+ <
1084
+ R2,
1085
+ A,
1086
+ E2,
1087
+ T2 extends T
1088
+ >(
1089
+ q: (initial: Query<Omit<PM, "_etag">>) =>
1090
+ | Query<Omit<PM, "_etag">>
1091
+ | QueryWhere<Omit<PM, "_etag">>,
1092
+ pure: Effect<A, E2, FixEnv<R2, Evt, readonly T[], readonly T2[]>>
1093
+ ): Effect<
1094
+ A,
1095
+ InvalidStateError | OptimisticConcurrencyException | E2,
1096
+ | Service
1097
+ | Exclude<R2, {
1098
+ env: PureEnv<Evt, readonly T[], readonly T2[]>
1099
+ }>
1100
+ >
1101
+ }
1102
+
1039
1103
  readonly q2: {
1040
1104
  <A, R, From extends FieldValues>(
1041
1105
  q: (initial: Query<Omit<PM, "_etag">>) => QueryProjection<Omit<PM, "_etag"> extends From ? From : never, A, R>
@@ -1053,14 +1117,39 @@ export interface RepoFunctions<T extends { id: unknown }, PM extends { id: strin
1053
1117
 
1054
1118
  const makeRepoFunctions = (tag: any) => {
1055
1119
  const { all } = Effect.serviceConstants(tag) as any
1056
- const { find, get, q2, query, queryLegacy, removeAndPublish, removeById, save, saveAndPublish } = Effect
1057
- .serviceFunctions(
1058
- tag
1059
- ) as any
1120
+ const {
1121
+ byIdAndSaveWithPure,
1122
+ find,
1123
+ get,
1124
+ q2,
1125
+ q2AndSaveOnePure,
1126
+ q2AndSavePure,
1127
+ query,
1128
+ queryLegacy,
1129
+ removeAndPublish,
1130
+ removeById,
1131
+ save,
1132
+ saveAndPublish
1133
+ } = Effect.serviceFunctions(tag) as any
1060
1134
 
1061
1135
  const mapped = (s: any) => tag.map((_: any) => _.mapped(s))
1062
1136
 
1063
- return { all, find, removeById, saveAndPublish, removeAndPublish, save, get, query, queryLegacy, q2, mapped }
1137
+ return {
1138
+ all,
1139
+ byIdAndSaveWithPure,
1140
+ find,
1141
+ removeById,
1142
+ saveAndPublish,
1143
+ removeAndPublish,
1144
+ save,
1145
+ get,
1146
+ query,
1147
+ queryLegacy,
1148
+ q2,
1149
+ mapped,
1150
+ q2AndSaveOnePure,
1151
+ q2AndSavePure
1152
+ }
1064
1153
  }
1065
1154
 
1066
1155
  export const RepositoryBaseImpl = <Service>() => {