@effect-app/infra 2.10.0 → 2.12.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 (70) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/_cjs/Model/Repository/ext.cjs +1 -1
  3. package/_cjs/Model/Repository/ext.cjs.map +1 -1
  4. package/_cjs/Model/Repository/internal/internal.cjs +245 -0
  5. package/_cjs/Model/Repository/internal/internal.cjs.map +1 -0
  6. package/_cjs/Model/Repository/legacy.cjs +0 -139
  7. package/_cjs/Model/Repository/legacy.cjs.map +1 -1
  8. package/_cjs/Model/Repository/makeRepo.cjs +2 -241
  9. package/_cjs/Model/Repository/makeRepo.cjs.map +1 -1
  10. package/_cjs/Store/Cosmos/query.cjs +9 -2
  11. package/_cjs/Store/Cosmos/query.cjs.map +1 -1
  12. package/_cjs/Store/Cosmos.cjs +49 -23
  13. package/_cjs/Store/Cosmos.cjs.map +1 -1
  14. package/_cjs/Store/Disk.cjs +5 -5
  15. package/_cjs/Store/Disk.cjs.map +1 -1
  16. package/_cjs/Store/Memory.cjs +9 -9
  17. package/_cjs/Store/Memory.cjs.map +1 -1
  18. package/_cjs/Store/codeFilter.cjs.map +1 -1
  19. package/_cjs/Store/service.cjs.map +1 -1
  20. package/_cjs/Store/utils.cjs +3 -3
  21. package/_cjs/Store/utils.cjs.map +1 -1
  22. package/dist/Model/Repository/ext.d.ts +6 -9
  23. package/dist/Model/Repository/ext.d.ts.map +1 -1
  24. package/dist/Model/Repository/ext.js +2 -2
  25. package/dist/Model/Repository/internal/internal.d.ts +61 -0
  26. package/dist/Model/Repository/internal/internal.d.ts.map +1 -0
  27. package/dist/Model/Repository/internal/internal.js +245 -0
  28. package/dist/Model/Repository/legacy.d.ts +4 -192
  29. package/dist/Model/Repository/legacy.d.ts.map +1 -1
  30. package/dist/Model/Repository/legacy.js +2 -123
  31. package/dist/Model/Repository/makeRepo.d.ts +7 -77
  32. package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
  33. package/dist/Model/Repository/makeRepo.js +3 -247
  34. package/dist/Model/Repository/service.d.ts +1 -3
  35. package/dist/Model/Repository/service.d.ts.map +1 -1
  36. package/dist/Operations.d.ts +3 -3
  37. package/dist/QueueMaker/sbqueue.d.ts +2 -2
  38. package/dist/Store/Cosmos/query.d.ts +1 -1
  39. package/dist/Store/Cosmos/query.d.ts.map +1 -1
  40. package/dist/Store/Cosmos/query.js +7 -3
  41. package/dist/Store/Cosmos.d.ts.map +1 -1
  42. package/dist/Store/Cosmos.js +43 -23
  43. package/dist/Store/Disk.d.ts +2 -3
  44. package/dist/Store/Disk.d.ts.map +1 -1
  45. package/dist/Store/Disk.js +6 -6
  46. package/dist/Store/Memory.d.ts +4 -9
  47. package/dist/Store/Memory.d.ts.map +1 -1
  48. package/dist/Store/Memory.js +12 -12
  49. package/dist/Store/codeFilter.d.ts +2 -3
  50. package/dist/Store/codeFilter.d.ts.map +1 -1
  51. package/dist/Store/codeFilter.js +1 -1
  52. package/dist/Store/service.d.ts +9 -23
  53. package/dist/Store/service.d.ts.map +1 -1
  54. package/dist/Store/service.js +1 -1
  55. package/dist/Store/utils.d.ts +1 -3
  56. package/dist/Store/utils.d.ts.map +1 -1
  57. package/dist/Store/utils.js +4 -4
  58. package/package.json +1 -1
  59. package/src/Model/Repository/ext.ts +6 -5
  60. package/src/Model/Repository/internal/internal.ts +482 -0
  61. package/src/Model/Repository/legacy.ts +4 -538
  62. package/src/Model/Repository/makeRepo.ts +11 -489
  63. package/src/Model/Repository/service.ts +1 -1
  64. package/src/Store/Cosmos/query.ts +6 -1
  65. package/src/Store/Cosmos.ts +85 -48
  66. package/src/Store/Disk.ts +20 -8
  67. package/src/Store/Memory.ts +25 -16
  68. package/src/Store/codeFilter.ts +2 -1
  69. package/src/Store/service.ts +8 -7
  70. package/src/Store/utils.ts +4 -3
@@ -0,0 +1,482 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import type {} from "effect/Equal"
3
+ import type {} from "effect/Hash"
4
+ import type { NonEmptyReadonlyArray } from "effect-app"
5
+ import { Array, Chunk, Context, Effect, Equivalence, flow, Option, pipe, Pipeable, PubSub, S, Unify } from "effect-app"
6
+ import { toNonEmptyArray } from "effect-app/Array"
7
+ import { NotFoundError } from "effect-app/client"
8
+ import { flatMapOption } from "effect-app/Effect"
9
+ import type { Schema } from "effect-app/Schema"
10
+ import { NonNegativeInt } from "effect-app/Schema"
11
+ import { setupRequestContextFromCurrent } from "../../../api/setupRequest.js"
12
+ import type { FilterArgs, PersistenceModelType, StoreConfig } from "../../../Store.js"
13
+ import { StoreMaker } from "../../../Store.js"
14
+ import { getContextMap } from "../../../Store/ContextMapContainer.js"
15
+ import type { FieldValues } from "../../filter/types.js"
16
+ import * as Q from "../../query.js"
17
+ import type { Repository } from "../service.js"
18
+
19
+ const dedupe = Array.dedupeWith(Equivalence.string)
20
+
21
+ /**
22
+ * A base implementation to create a repository.
23
+ */
24
+ export function makeRepoInternal<
25
+ Evt = never
26
+ >() {
27
+ return <
28
+ ItemType extends string,
29
+ R,
30
+ Encoded extends FieldValues,
31
+ T,
32
+ IdKey extends keyof T & keyof Encoded
33
+ >(
34
+ name: ItemType,
35
+ schema: S.Schema<T, Encoded, R>,
36
+ mapFrom: (pm: Encoded) => Encoded,
37
+ mapTo: (e: Encoded, etag: string | undefined) => PersistenceModelType<Encoded>,
38
+ idKey: IdKey
39
+ ) => {
40
+ type PM = PersistenceModelType<Encoded>
41
+ function mapToPersistenceModel(
42
+ e: Encoded,
43
+ getEtag: (id: string) => string | undefined
44
+ ): PM {
45
+ return mapTo(e, getEtag(e[idKey]))
46
+ }
47
+
48
+ function mapReverse(
49
+ { _etag, ...e }: PM,
50
+ setEtag: (id: string, eTag: string | undefined) => void
51
+ ): Encoded {
52
+ setEtag((e as any)[idKey], _etag)
53
+ return mapFrom(e as unknown as Encoded)
54
+ }
55
+
56
+ const mkStore = makeStore<Encoded>()(name, schema, mapTo, idKey)
57
+
58
+ function make<RInitial = never, E = never, RPublish = never, RCtx = never>(
59
+ args: [Evt] extends [never] ? {
60
+ schemaContext?: Context.Context<RCtx>
61
+ makeInitial?: Effect<readonly T[], E, RInitial>
62
+ config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
63
+ partitionValue?: (a: Encoded) => string
64
+ }
65
+ }
66
+ : {
67
+ schemaContext?: Context.Context<RCtx>
68
+ publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect<void, never, RPublish>
69
+ makeInitial?: Effect<readonly T[], E, RInitial>
70
+ config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
71
+ partitionValue?: (a: Encoded) => string
72
+ }
73
+ }
74
+ ) {
75
+ return Effect
76
+ .gen(function*() {
77
+ const rctx: Context<RCtx> = args.schemaContext ?? Context.empty() as any
78
+ const provideRctx = Effect.provide(rctx)
79
+ const encodeMany = flow(
80
+ S.encode(S.Array(schema)),
81
+ provideRctx,
82
+ Effect.withSpan("encodeMany", { captureStackTrace: false })
83
+ )
84
+ const decode = flow(S.decode(schema), provideRctx)
85
+ const decodeMany = flow(
86
+ S.decode(S.Array(schema)),
87
+ provideRctx,
88
+ Effect.withSpan("decodeMany", { captureStackTrace: false })
89
+ )
90
+
91
+ const store = yield* mkStore(args.makeInitial, args.config)
92
+ const cms = Effect.andThen(getContextMap.pipe(Effect.orDie), (_) => ({
93
+ get: (id: string) => _.get(`${name}.${id}`),
94
+ set: (id: string, etag: string | undefined) => _.set(`${name}.${id}`, etag)
95
+ }))
96
+
97
+ const pub = "publishEvents" in args
98
+ ? args.publishEvents
99
+ : () => Effect.void
100
+ const changeFeed = yield* PubSub.unbounded<[T[], "save" | "remove"]>()
101
+
102
+ const allE = cms
103
+ .pipe(Effect.flatMap((cm) => Effect.map(store.all, (_) => _.map((_) => mapReverse(_, cm.set)))))
104
+
105
+ const all = Effect
106
+ .flatMap(
107
+ allE,
108
+ (_) => decodeMany(_).pipe(Effect.orDie)
109
+ )
110
+ .pipe(Effect.map((_) => _ as T[]))
111
+
112
+ const fieldsSchema = schema as unknown as { fields: any }
113
+ // assumes the id field never needs a service...
114
+ const i = ("fields" in fieldsSchema ? S.Struct(fieldsSchema["fields"]) as unknown as typeof schema : schema)
115
+ .pipe((_) => {
116
+ let ast = _.ast
117
+ if (ast._tag === "Declaration") ast = ast.typeParameters[0]!
118
+
119
+ const s = S.make(ast) as unknown as Schema<T, Encoded, R>
120
+
121
+ return ast._tag === "Union"
122
+ // we need to get the TypeLiteral, incase of class it's behind a transform...
123
+ ? S.Union(
124
+ ...ast.types.map((_) =>
125
+ (S.make(_._tag === "Transformation" ? _.from : _) as unknown as Schema<T, Encoded>)
126
+ .pipe(S.pick(idKey as any))
127
+ )
128
+ )
129
+ : s.pipe(S.pick(idKey as any))
130
+ })
131
+ const encodeId = flow(S.encode(i), provideRctx)
132
+ function findEId(id: Encoded[IdKey]) {
133
+ return Effect.flatMap(
134
+ store.find(id),
135
+ (item) =>
136
+ Effect.gen(function*() {
137
+ const { set } = yield* cms
138
+ return item.pipe(Option.map((_) => mapReverse(_, set)))
139
+ })
140
+ )
141
+ }
142
+ // TODO: select the particular field, instead of as struct
143
+ function findE(id: T[IdKey]) {
144
+ return pipe(
145
+ encodeId({ [idKey]: id } as any),
146
+ Effect.orDie,
147
+ Effect.map((_) => (_ as any)[idKey]),
148
+ Effect.flatMap(findEId)
149
+ )
150
+ }
151
+
152
+ function find(id: T[IdKey]) {
153
+ return Effect.flatMapOption(findE(id), (_) => Effect.orDie(decode(_)))
154
+ }
155
+
156
+ const saveAllE = (a: Iterable<Encoded>) =>
157
+ Effect
158
+ .flatMapOption(
159
+ Effect
160
+ .sync(() => toNonEmptyArray([...a])),
161
+ (a) =>
162
+ Effect.gen(function*() {
163
+ const { get, set } = yield* cms
164
+ const items = a.map((_) => mapToPersistenceModel(_, get))
165
+ const ret = yield* store.batchSet(items)
166
+ ret.forEach((_) => set(_[idKey], _._etag))
167
+ })
168
+ )
169
+ .pipe(Effect.asVoid)
170
+
171
+ const saveAll = (a: Iterable<T>) =>
172
+ encodeMany(Array.fromIterable(a))
173
+ .pipe(
174
+ Effect.orDie,
175
+ Effect.andThen(saveAllE)
176
+ )
177
+
178
+ const saveAndPublish = (items: Iterable<T>, events: Iterable<Evt> = []) => {
179
+ return Effect
180
+ .suspend(() => {
181
+ const it = Chunk.fromIterable(items)
182
+ return saveAll(it)
183
+ .pipe(
184
+ Effect.andThen(Effect.sync(() => toNonEmptyArray([...events]))),
185
+ // TODO: for full consistency the events should be stored within the same database transaction, and then picked up.
186
+ (_) => Effect.flatMapOption(_, pub),
187
+ Effect.andThen(changeFeed.publish([Chunk.toArray(it), "save"])),
188
+ Effect.asVoid
189
+ )
190
+ })
191
+ .pipe(Effect.withSpan("saveAndPublish", { captureStackTrace: false }))
192
+ }
193
+
194
+ function removeAndPublish(a: Iterable<T>, events: Iterable<Evt> = []) {
195
+ return Effect.gen(function*() {
196
+ const { get, set } = yield* cms
197
+ const it = [...a]
198
+ const items = yield* encodeMany(it).pipe(Effect.orDie)
199
+ // TODO: we should have a batchRemove on store so the adapter can actually batch...
200
+ for (const e of items) {
201
+ yield* store.remove(mapToPersistenceModel(e, get))
202
+ set(e[idKey], undefined)
203
+ }
204
+ yield* Effect
205
+ .sync(() => toNonEmptyArray([...events]))
206
+ // TODO: for full consistency the events should be stored within the same database transaction, and then picked up.
207
+ .pipe((_) => Effect.flatMapOption(_, pub))
208
+
209
+ yield* changeFeed.publish([it, "remove"])
210
+ })
211
+ }
212
+
213
+ const parseMany = (items: readonly PM[]) =>
214
+ Effect
215
+ .flatMap(cms, (cm) =>
216
+ decodeMany(items.map((_) => mapReverse(_, cm.set)))
217
+ .pipe(Effect.orDie, Effect.withSpan("parseMany", { captureStackTrace: false })))
218
+ const parseMany2 = <A, R>(
219
+ items: readonly PM[],
220
+ schema: S.Schema<A, Encoded, R>
221
+ ) =>
222
+ Effect
223
+ .flatMap(cms, (cm) =>
224
+ S
225
+ .decode(S.Array(schema))(
226
+ items.map((_) => mapReverse(_, cm.set))
227
+ )
228
+ .pipe(Effect.orDie, Effect.withSpan("parseMany2", { captureStackTrace: false })))
229
+ const filter = <U extends keyof Encoded = keyof Encoded>(args: FilterArgs<Encoded, U>) =>
230
+ store
231
+ .filter(
232
+ // always enforce id and _etag because they are system fields, required for etag tracking etc
233
+ {
234
+ ...args,
235
+ select: args.select
236
+ ? dedupe([...args.select, idKey, "_etag" as any])
237
+ : undefined
238
+ } as typeof args
239
+ )
240
+ .pipe(
241
+ Effect.tap((items) =>
242
+ Effect.map(cms, ({ set }) => items.forEach((_) => set((_ as Encoded)[idKey], (_ as PM)._etag)))
243
+ )
244
+ )
245
+
246
+ // TODO: For raw we should use S.from, and drop the R...
247
+ const query: {
248
+ <A, R, From extends FieldValues>(
249
+ q: Q.QueryProjection<Encoded extends From ? From : never, A, R>
250
+ ): Effect.Effect<readonly A[], S.ParseResult.ParseError, R>
251
+ <A, R, EncodedRefined extends Encoded = Encoded>(
252
+ q: Q.QAll<NoInfer<Encoded>, NoInfer<EncodedRefined>, A, R>
253
+ ): Effect.Effect<readonly A[], never, R>
254
+ } = (<A, R, EncodedRefined extends Encoded = Encoded>(q: Q.QAll<Encoded, EncodedRefined, A, R>) => {
255
+ const a = Q.toFilter(q)
256
+ const eff = a.mode === "project"
257
+ ? filter(a)
258
+ // TODO: mapFrom but need to support per field and dependencies
259
+ .pipe(
260
+ Effect.andThen(flow(S.decode(S.Array(a.schema ?? schema)), provideRctx))
261
+ )
262
+ : a.mode === "collect"
263
+ ? filter(a)
264
+ // TODO: mapFrom but need to support per field and dependencies
265
+ .pipe(
266
+ Effect.flatMap(flow(
267
+ S.decode(S.Array(a.schema)),
268
+ Effect.map(Array.getSomes),
269
+ provideRctx
270
+ ))
271
+ )
272
+ : Effect.flatMap(
273
+ filter(a),
274
+ (_) =>
275
+ Unify.unify(
276
+ a.schema
277
+ // TODO: partial may not match?
278
+ ? parseMany2(_ as any, a.schema as any)
279
+ : parseMany(_ as any)
280
+ )
281
+ )
282
+ return pipe(
283
+ a.ttype === "one"
284
+ ? Effect.andThen(
285
+ eff,
286
+ flow(
287
+ Array.head,
288
+ Effect.mapError(() => new NotFoundError({ id: "query", /* TODO */ type: name }))
289
+ )
290
+ )
291
+ : a.ttype === "count"
292
+ ? Effect
293
+ .andThen(eff, (_) => NonNegativeInt(_.length))
294
+ .pipe(Effect.catchTag("ParseError", (e) => Effect.die(e)))
295
+ : eff,
296
+ Effect.withSpan("Repository.query [effect-app/infra]", {
297
+ captureStackTrace: false,
298
+ attributes: {
299
+ "repository.model_name": name,
300
+ query: { ...a, schema: a.schema ? "__SCHEMA__" : a.schema, filter: a.filter }
301
+ }
302
+ })
303
+ )
304
+ }) as any
305
+
306
+ const r: Repository<T, Encoded, Evt, ItemType, IdKey, Exclude<R, RCtx>, RPublish> = {
307
+ changeFeed,
308
+ itemType: name,
309
+ idKey,
310
+ find,
311
+ all,
312
+ saveAndPublish,
313
+ removeAndPublish,
314
+ query(q: any) {
315
+ // eslint-disable-next-line prefer-rest-params
316
+ return query(typeof q === "function" ? Pipeable.pipeArguments(Q.make(), arguments) : q) as any
317
+ },
318
+ /**
319
+ * @internal
320
+ */
321
+ mapped: <A, R>(schema: S.Schema<A, any, R>) => {
322
+ const dec = S.decode(schema)
323
+ const encMany = S.encode(S.Array(schema))
324
+ const decMany = S.decode(S.Array(schema))
325
+ return {
326
+ all: allE.pipe(
327
+ Effect.flatMap(decMany),
328
+ Effect.map((_) => _ as any[])
329
+ ),
330
+ find: (id: T[IdKey]) => flatMapOption(findE(id), dec),
331
+ // query: (q: any) => {
332
+ // const a = Q.toFilter(q)
333
+
334
+ // return filter(a)
335
+ // .pipe(
336
+ // Effect.flatMap(decMany),
337
+ // Effect.map((_) => _ as any[]),
338
+ // Effect.withSpan("Repository.mapped.query [effect-app/infra]", {
339
+ // captureStackTrace: false,
340
+ // attributes: {
341
+ // "repository.model_name": name,
342
+ // query: { ...a, schema: a.schema ? "__SCHEMA__" : a.schema, filter: a.filter.build() }
343
+ // }
344
+ // })
345
+ // )
346
+ // },
347
+ save: (...xes: any[]) =>
348
+ Effect.flatMap(encMany(xes), (_) => saveAllE(_)).pipe(
349
+ Effect.withSpan("mapped.save", { captureStackTrace: false })
350
+ )
351
+ }
352
+ }
353
+ }
354
+ return r
355
+ })
356
+ .pipe(Effect
357
+ // .withSpan("Repository.make [effect-app/infra]", { attributes: { "repository.model_name": name } })
358
+ .withLogSpan("Repository.make: " + name))
359
+ }
360
+
361
+ return {
362
+ make,
363
+ Q: Q.make<Encoded>()
364
+ }
365
+ }
366
+ }
367
+
368
+ const pluralize = (s: string) =>
369
+ s.endsWith("s")
370
+ ? s + "es"
371
+ : s.endsWith("y")
372
+ ? s.substring(0, s.length - 1) + "ies"
373
+ : s + "s"
374
+
375
+ export function makeStore<Encoded extends FieldValues>() {
376
+ return <
377
+ ItemType extends string,
378
+ R,
379
+ E,
380
+ T,
381
+ IdKey extends keyof Encoded
382
+ >(
383
+ name: ItemType,
384
+ schema: S.Schema<T, E, R>,
385
+ mapTo: (e: E, etag: string | undefined) => Encoded,
386
+ idKey: IdKey
387
+ ) => {
388
+ function makeStore<RInitial = never, EInitial = never>(
389
+ makeInitial?: Effect<readonly T[], EInitial, RInitial>,
390
+ config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
391
+ partitionValue?: (a: Encoded) => string
392
+ }
393
+ ) {
394
+ function encodeToEncoded() {
395
+ const getEtag = () => undefined
396
+ return (t: T) =>
397
+ S.encode(schema)(t).pipe(
398
+ Effect.orDie,
399
+ Effect.map((_) => mapToPersistenceModel(_, getEtag))
400
+ )
401
+ }
402
+
403
+ function mapToPersistenceModel(
404
+ e: E,
405
+ getEtag: (id: string) => string | undefined
406
+ ): Encoded {
407
+ return mapTo(e, getEtag((e as any)[idKey] as string))
408
+ }
409
+
410
+ return Effect.gen(function*() {
411
+ const { make } = yield* StoreMaker
412
+
413
+ const store = yield* make<IdKey, Encoded, RInitial | R, EInitial>(
414
+ pluralize(name),
415
+ idKey,
416
+ makeInitial
417
+ ? makeInitial
418
+ .pipe(
419
+ Effect.flatMap(Effect.forEach(encodeToEncoded())),
420
+ setupRequestContextFromCurrent("Repository.makeInitial [effect-app/infra]", {
421
+ attributes: { "repository.model_name": name }
422
+ })
423
+ )
424
+ : undefined,
425
+ {
426
+ ...config,
427
+ partitionValue: config?.partitionValue
428
+ ?? ((_) => "primary") /*(isIntegrationEvent(r) ? r.companyId : r.id*/
429
+ }
430
+ )
431
+
432
+ return store
433
+ })
434
+ }
435
+
436
+ return makeStore
437
+ }
438
+ }
439
+
440
+ export interface Repos<
441
+ T,
442
+ Encoded extends { id: string },
443
+ RSchema,
444
+ Evt,
445
+ ItemType extends string,
446
+ IdKey extends keyof T,
447
+ RPublish
448
+ > {
449
+ make<RInitial = never, E = never, R2 = never>(
450
+ args: [Evt] extends [never] ? {
451
+ makeInitial?: Effect<readonly T[], E, RInitial>
452
+ config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
453
+ partitionValue?: (a: Encoded) => string
454
+ }
455
+ }
456
+ : {
457
+ publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect<void, never, R2>
458
+ makeInitial?: Effect<readonly T[], E, RInitial>
459
+ config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
460
+ partitionValue?: (a: Encoded) => string
461
+ }
462
+ }
463
+ ): Effect<Repository<T, Encoded, Evt, ItemType, IdKey, RSchema, RPublish>, E, StoreMaker | RInitial | R2>
464
+ makeWith<Out, RInitial = never, E = never, R2 = never>(
465
+ args: [Evt] extends [never] ? {
466
+ makeInitial?: Effect<readonly T[], E, RInitial>
467
+ config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
468
+ partitionValue?: (a: Encoded) => string
469
+ }
470
+ }
471
+ : {
472
+ publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect<void, never, R2>
473
+ makeInitial?: Effect<readonly T[], E, RInitial>
474
+ config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
475
+ partitionValue?: (a: Encoded) => string
476
+ }
477
+ },
478
+ f: (r: Repository<T, Encoded, Evt, ItemType, IdKey, RSchema, RPublish>) => Out
479
+ ): Effect<Out, E, StoreMaker | RInitial | R2>
480
+ readonly Q: ReturnType<typeof Q.make<Encoded>>
481
+ readonly type: Repository<T, Encoded, Evt, ItemType, IdKey, RSchema, RPublish>
482
+ }