effect-app 4.0.0-beta.307 → 4.0.0-beta.309

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.
@@ -5,7 +5,7 @@ import * as Request from "effect/Request"
5
5
  import * as RequestResolver from "effect/RequestResolver"
6
6
  import * as Array from "../../Array.ts"
7
7
  import type { NonEmptyArray } from "../../Array.ts"
8
- import { type InvalidStateError, NotFoundError, type OptimisticConcurrencyException } from "../../client/errors.ts"
8
+ import { type DatabaseError, type InvalidStateError, NotFoundError, type OptimisticConcurrencyException } from "../../client/errors.ts"
9
9
  import * as Effect from "../../Effect.ts"
10
10
  import * as Option from "../../Option.ts"
11
11
  import { type FixEnv, type PureEnv, runTerm } from "../../Pure.ts"
@@ -89,7 +89,11 @@ export const extendRepo = <
89
89
  A
90
90
  >(
91
91
  gen: Effect.Effect<readonly [Iterable<P>, Iterable<Evt>, A], E, R>
92
- ) {
92
+ ): Effect.Effect<
93
+ A,
94
+ E | InvalidStateError | OptimisticConcurrencyException | DatabaseError,
95
+ R | RSchema | RPublish
96
+ > {
93
97
  return Effect.flatMap(gen, ([items, events, a]) => repo.saveAndPublish(items, events).pipe(Effect.map(() => a)))
94
98
  }
95
99
 
@@ -113,6 +117,8 @@ export const extendRepo = <
113
117
  )
114
118
  }
115
119
 
120
+ type PureStoreError = InvalidStateError | OptimisticConcurrencyException | DatabaseError
121
+
116
122
  const queryAndSavePure: {
117
123
  <A, E2, R2, T2 extends T>(
118
124
  q: (
@@ -121,8 +127,10 @@ export const extendRepo = <
121
127
  pure: Effect.Effect<A, E2, FixEnv<R2, Evt, T, T2>>
122
128
  ): Effect.Effect<
123
129
  A,
124
- InvalidStateError | OptimisticConcurrencyException | NotFoundError<ItemType> | E2,
125
- Exclude<R2, {
130
+ PureStoreError | NotFoundError<ItemType> | E2,
131
+ | RSchema
132
+ | RPublish
133
+ | Exclude<R2, {
126
134
  env: PureEnv<Evt, T, T2>
127
135
  }>
128
136
  >
@@ -136,7 +144,7 @@ export const extendRepo = <
136
144
  pure: Effect.Effect<A, E2, FixEnv<R2, Evt, readonly T[], readonly T2[]>>
137
145
  ): Effect.Effect<
138
146
  A,
139
- InvalidStateError | OptimisticConcurrencyException | E2,
147
+ PureStoreError | E2,
140
148
  | RSchema
141
149
  | RPublish
142
150
  | Exclude<R2, {
@@ -154,23 +162,25 @@ export const extendRepo = <
154
162
  batch: "batched" | number
155
163
  ): Effect.Effect<
156
164
  A[],
157
- InvalidStateError | OptimisticConcurrencyException | E2,
165
+ PureStoreError | E2,
158
166
  | RSchema
159
167
  | RPublish
160
168
  | Exclude<R2, {
161
169
  env: PureEnv<Evt, readonly T[], readonly T2[]>
162
170
  }>
163
171
  >
164
- } = (q, pure, batch?: "batched" | number) =>
172
+ } = ((q: any, pure: any, batch?: "batched" | number) =>
173
+ // Overload dispatch: query returns T | T[]; pure helpers are generic on item shape.
174
+ // Runtime path is query → pure term → saveAndPublish (which raises DatabaseError).
165
175
  repo.query(q).pipe(
166
176
  Effect.andThen((_) =>
167
177
  Array.isArray(_)
168
178
  ? batch === undefined
169
- ? saveManyWithPure_(_ as any, pure as any)
170
- : saveManyWithPureBatched_(_ as any, pure as any, batch === "batched" ? 100 : batch)
171
- : saveWithPure_(_ as any, pure as any)
179
+ ? saveManyWithPure_(_ as T[], pure)
180
+ : saveManyWithPureBatched_(_ as T[], pure, batch === "batched" ? 100 : batch)
181
+ : saveWithPure_(_ as T, pure)
172
182
  )
173
- ) as any
183
+ )) as typeof queryAndSavePure
174
184
 
175
185
  const saveManyWithPure: {
176
186
  <R, A, E, S1 extends T, S2 extends T>(
@@ -178,7 +188,7 @@ export const extendRepo = <
178
188
  pure: Effect.Effect<A, E, FixEnv<R, Evt, readonly S1[], readonly S2[]>>
179
189
  ): Effect.Effect<
180
190
  A,
181
- InvalidStateError | OptimisticConcurrencyException | E,
191
+ PureStoreError | E,
182
192
  | RSchema
183
193
  | RPublish
184
194
  | Exclude<R, {
@@ -191,25 +201,25 @@ export const extendRepo = <
191
201
  batch: "batched" | number
192
202
  ): Effect.Effect<
193
203
  A[],
194
- InvalidStateError | OptimisticConcurrencyException | E,
204
+ PureStoreError | E,
195
205
  | RSchema
196
206
  | RPublish
197
207
  | Exclude<R, {
198
208
  env: PureEnv<Evt, readonly S1[], readonly S2[]>
199
209
  }>
200
210
  >
201
- } = (items, pure, batch?: "batched" | number) =>
211
+ } = ((items: Iterable<T>, pure: any, batch?: "batched" | number) =>
202
212
  batch
203
213
  ? Effect.forEach(
204
- Array.chunksOf(items, batch === "batched" ? 100 : batch),
205
- (batch) =>
214
+ Array.chunksOf([...items], batch === "batched" ? 100 : batch),
215
+ (batchItems) =>
206
216
  saveAllWithEffectInt(
207
- runTerm(pure, batch)
217
+ runTerm(pure, batchItems as any)
208
218
  )
209
219
  )
210
220
  : saveAllWithEffectInt(
211
- runTerm(pure, [...items])
212
- )
221
+ runTerm(pure, [...items] as any)
222
+ )) as typeof saveManyWithPure
213
223
 
214
224
  const byIdAndSaveWithPure: {
215
225
  <R, A, E, S2 extends T>(
@@ -217,17 +227,19 @@ export const extendRepo = <
217
227
  pure: Effect.Effect<A, E, FixEnv<R, Evt, T, S2>>
218
228
  ): Effect.Effect<
219
229
  A,
220
- InvalidStateError | OptimisticConcurrencyException | NotFoundError<ItemType> | E,
230
+ PureStoreError | NotFoundError<ItemType> | E,
221
231
  | RSchema
222
232
  | RPublish
223
233
  | Exclude<R, {
224
234
  env: PureEnv<Evt, T, S2>
225
235
  }>
226
236
  >
227
- } = (id, pure): any => get(id).pipe(Effect.flatMap((item) => saveWithPure_(item, pure)))
237
+ } = (id, pure) => get(id).pipe(Effect.flatMap((item) => saveWithPure_(item, pure)))
228
238
 
239
+ // query can raise DatabaseError; NotFound is completed per-entry. Dual package
240
+ // round-trips may still surface other store errors via failCause — keep channel honest.
229
241
  type Req =
230
- & Request.Request<T, NotFoundError<ItemType>>
242
+ & Request.Request<T, NotFoundError<ItemType> | DatabaseError>
231
243
  & { _tag: `Get${ItemType}`; id: T[IdKey] }
232
244
  const _request = Request.tagged<Req>(`Get${repo.itemType}`)
233
245
 
@@ -237,9 +249,9 @@ export const extendRepo = <
237
249
  _key: unknown
238
250
  ) =>
239
251
  (repo.query(Q.where(repo.idKey as any, "in" as any, entries.map((_) => _.request.id)) as any) as Effect.Effect<
240
- readonly T[]
252
+ readonly T[],
253
+ DatabaseError
241
254
  >)
242
- // TODO
243
255
  .pipe(
244
256
  Effect.andThen((items) =>
245
257
  Effect.forEach(entries, (entry) =>
@@ -270,7 +282,7 @@ export const extendRepo = <
270
282
  * Enables chunked writes for large batches via `options.batch`.
271
283
  * Note: batching breaks transactional properties because chunks are saved independently.
272
284
  */
273
- save: ((itemOrItems: T | ReadonlyArray<T>, options?: BatchOptions) => {
285
+ save: (itemOrItems: T | ReadonlyArray<T>, options?: BatchOptions) => {
274
286
  const items = asReadonlyArray(itemOrItems)
275
287
  if (!Array.isReadonlyArrayNonEmpty(items)) {
276
288
  return Effect.void
@@ -284,23 +296,16 @@ export const extendRepo = <
284
296
  (batch) => repo.saveAndPublish(batch),
285
297
  { discard: true }
286
298
  )
287
- }) as (
288
- itemOrItems: T | ReadonlyArray<T>,
289
- options?: BatchOptions
290
- ) => Effect.Effect<
291
- void,
292
- InvalidStateError | OptimisticConcurrencyException,
293
- RSchema | RPublish
294
- >,
299
+ },
295
300
  saveWithEvents: (events: Iterable<Evt>) => (...items: NonEmptyArray<T>) => repo.saveAndPublish(items, events),
296
301
  /**
297
302
  * Enables chunked deletes for large batches via `options.batch`.
298
303
  * Note: batching breaks transactional properties because chunks are removed independently.
299
304
  */
300
- remove: ((itemOrItems: T | ReadonlyArray<T>, options?: BatchOptions) => {
305
+ remove: (itemOrItems: T | ReadonlyArray<T>, options?: BatchOptions) => {
301
306
  const items = asReadonlyArray(itemOrItems)
302
307
  if (!Array.isReadonlyArrayNonEmpty(items)) {
303
- return Effect.void
308
+ return Effect.void as Effect.Effect<void, DatabaseError, RSchema | RPublish>
304
309
  }
305
310
  const batchSize = getBatchSize(options?.batch)
306
311
  if (batchSize === undefined) {
@@ -311,18 +316,15 @@ export const extendRepo = <
311
316
  (batch) => repo.removeAndPublish(batch),
312
317
  { discard: true }
313
318
  )
314
- }) as (
315
- itemOrItems: T | ReadonlyArray<T>,
316
- options?: BatchOptions
317
- ) => Effect.Effect<void, never, RSchema | RPublish>,
319
+ },
318
320
  /**
319
321
  * Enables chunked deletes for large batches via `options.batch`.
320
322
  * Note: batching breaks transactional properties because chunks are removed independently.
321
323
  */
322
- removeById: ((idOrIds: T[IdKey] | ReadonlyArray<T[IdKey]>, options?: BatchOptions) => {
324
+ removeById: (idOrIds: T[IdKey] | ReadonlyArray<T[IdKey]>, options?: BatchOptions) => {
323
325
  const ids = asReadonlyArray(idOrIds)
324
326
  if (!Array.isReadonlyArrayNonEmpty(ids)) {
325
- return Effect.void
327
+ return Effect.void as Effect.Effect<void, DatabaseError, RSchema>
326
328
  }
327
329
  const batchSize = getBatchSize(options?.batch)
328
330
  if (batchSize === undefined) {
@@ -333,10 +335,7 @@ export const extendRepo = <
333
335
  (batch) => repo.removeById(batch),
334
336
  { discard: true }
335
337
  )
336
- }) as (
337
- idOrIds: T[IdKey] | ReadonlyArray<T[IdKey]>,
338
- options?: BatchOptions
339
- ) => Effect.Effect<void, never, RSchema>,
338
+ },
340
339
  queryAndSavePure,
341
340
  saveManyWithPure,
342
341
  byIdAndSaveWithPure,
@@ -25,8 +25,10 @@ import { type Codec, NonNegativeInt } from "../../../Schema.ts"
25
25
  import * as SchemaAST from "../../../SchemaAST.ts"
26
26
  import { setupRequestContextFromCurrent } from "../../../setupRequest.ts"
27
27
  import { type FilterArgs, getContextMap, type PersistenceModelType, type StoreConfig, storeId, StoreMaker } from "../../../Store.ts"
28
+ import type { FilterResult } from "../../filter/filterApi.ts"
28
29
  import type { FieldValues } from "../../filter/types.ts"
29
30
  import * as Q from "../../query.ts"
31
+ import { repositoryDependencyPaths } from "../dependency.ts"
30
32
  import type { ChangeFeed, ChangeFeedEvent, Repository } from "../service.ts"
31
33
  import { ValidationError, ValidationResult } from "../validation.ts"
32
34
 
@@ -147,16 +149,55 @@ export function makeRepoInternal<
147
149
  )
148
150
 
149
151
  const store = yield* mkStore(args.makeInitial, args.config)
152
+ const dependencyPaths = repositoryDependencyPaths(schema)
150
153
  const recordRead = DataDependencies.readRepo(name)
151
154
  const entityDependency = (ids: NonEmptyReadonlyArray<T[IdKey]>) =>
152
155
  DataDependencies.repo(name, [String(ids[0]), ...ids.slice(1).map(String)])
156
+ const valuesAtPath = (value: unknown, path: string): readonly unknown[] => {
157
+ if (path.length === 0) return [value]
158
+ const [head, ...tail] = path.split(".")
159
+ if (head === undefined) return [value]
160
+ if (head === "-1") {
161
+ return globalThis.Array.isArray(value)
162
+ ? value.flatMap((item) => valuesAtPath(item, tail.join(".")))
163
+ : []
164
+ }
165
+ return typeof value === "object" && value !== null
166
+ ? valuesAtPath((value as Record<string, unknown>)[head], tail.join("."))
167
+ : []
168
+ }
169
+ const dependencyIds = (item: T): NonEmptyReadonlyArray<string> => {
170
+ const configured = dependencyPaths
171
+ .flatMap((path) => valuesAtPath(item, String(path)))
172
+ .filter((value): value is string => typeof value === "string") ?? []
173
+ const ids = args.dependencyIds?.(item) ?? [String(item[idKey]), ...configured]
174
+ return [ids[0], ...ids.slice(1)]
175
+ }
153
176
  const itemDependencies = (item: T) => {
154
- const ids = args.dependencyIds?.(item) ?? [String(item[idKey])]
177
+ const ids = dependencyIds(item)
155
178
  return [
156
179
  DataDependencies.repo(name, ids),
157
180
  ...(args.additionalWriteDependencies?.(item) ?? [])
158
181
  ]
159
182
  }
183
+ const queryDependencyIds = (filter: readonly FilterResult[] | undefined): readonly string[] => {
184
+ if (!filter) return []
185
+ const paths = new Set([String(idKey), ...dependencyPaths])
186
+ const visit = (items: readonly FilterResult[]): readonly string[] => {
187
+ if (items.some((item) => item.t === "or" || item.t === "or-scope")) return []
188
+ return items.flatMap((item) => {
189
+ if ("result" in item) return visit(item.result)
190
+ if (!paths.has(item.path)) return []
191
+ const value: unknown = item.value
192
+ if (item.op === "eq" && typeof value === "string") return [value]
193
+ if (item.op === "in" && globalThis.Array.isArray(value)) {
194
+ return value.filter((entry): entry is string => typeof entry === "string")
195
+ }
196
+ return []
197
+ })
198
+ }
199
+ return [...new Set(visit(filter))]
200
+ }
160
201
  const recordEntityRead = (id: T[IdKey]) => DataDependencies.read(entityDependency([id]))
161
202
  const recordEntityWrite = (ids: NonEmptyReadonlyArray<T[IdKey]>) =>
162
203
  DataDependencies.write(entityDependency(ids))
@@ -166,12 +207,6 @@ export function makeRepoInternal<
166
207
  DataDependencies.write,
167
208
  { discard: true }
168
209
  )
169
- const recordAdditionalItemWrites = (items: ReadonlyArray<T>) =>
170
- Effect.forEach(
171
- DataDependencies.merge(new Set(items.flatMap((item) => args.additionalWriteDependencies?.(item) ?? []))),
172
- DataDependencies.write,
173
- { discard: true }
174
- )
175
210
  const cms = Effect.map(getContextMap.pipe(Effect.orDie), (_) => ({
176
211
  get: (id: string) => _.get(`${name}.${id}`),
177
212
  set: (id: string, etag: string | undefined) => _.set(`${name}.${id}`, etag)
@@ -353,7 +388,7 @@ export function makeRepoInternal<
353
388
  const it = Chunk.fromIterable(items)
354
389
  if (Chunk.isNonEmpty(it)) {
355
390
  const values = Chunk.toReadonlyArray(it)
356
- const previous = args.additionalWriteDependencies
391
+ const previous = args.additionalWriteDependencies || args.dependencyIds || dependencyPaths.length > 0
357
392
  ? yield* loadExistingItems(values.map((item) => item[idKey]))
358
393
  : []
359
394
  yield* recordItemWrite([values[0], ...values.slice(1), ...previous])
@@ -414,8 +449,9 @@ export function makeRepoInternal<
414
449
  return
415
450
  }
416
451
  yield* recordEntityWrite(ids)
417
- if (args.additionalWriteDependencies) {
418
- yield* loadExistingItems(ids).pipe(Effect.flatMap(recordAdditionalItemWrites))
452
+ if (args.additionalWriteDependencies || args.dependencyIds || dependencyPaths.length > 0) {
453
+ const previous = yield* loadExistingItems(ids)
454
+ if (Array.isReadonlyArrayNonEmpty(previous)) yield* recordItemWrite(previous)
419
455
  }
420
456
  const { set } = yield* cms
421
457
  const eids = yield* Effect.forEach(ids, (_) => encodeIdOnly(_ as any)).pipe(Effect.orDie)
@@ -485,6 +521,10 @@ export function makeRepoInternal<
485
521
  ): Effect.Effect<readonly A[], never, Exclude<R, RCtx>>
486
522
  } = (<A, R, EncodedRefined extends Encoded = Encoded>(q: Q.QAll<Encoded, EncodedRefined, A, R>) => {
487
523
  const a = Q.toFilter(q, schema)
524
+ const scopedIds = queryDependencyIds(a.filter)
525
+ const recordQueryRead = Array.isReadonlyArrayNonEmpty(scopedIds)
526
+ ? DataDependencies.read(DataDependencies.repo(name, scopedIds))
527
+ : recordRead
488
528
  // Mode dispatch — see `Q.project` JSDoc for the contract:
489
529
  // aggregate: GROUP BY + aggregate functions at DB level; decode raw rows with schema; SchemaError surfaces.
490
530
  // project : decode raw encoded rows with schema; no PM reverse-mapping; SchemaError surfaces.
@@ -563,7 +603,7 @@ export function makeRepoInternal<
563
603
  "db.response.returned_rows": Array.isArray(r) ? r.length : 1
564
604
  })
565
605
  ),
566
- Effect.tap(() => recordRead),
606
+ Effect.tap(() => recordQueryRead),
567
607
  Effect.withSpan("Repository.query", {
568
608
  kind: "client",
569
609
  attributes: { "app.entity": name }
@@ -1,3 +1,4 @@
1
+ export { repositoryDependency } from "./Repository/dependency.ts"
1
2
  export * from "./Repository/ext.ts"
2
3
  export * from "./Repository/legacy.ts"
3
4
  export { makeRepo } from "./Repository/makeRepo.ts"
@@ -707,7 +707,7 @@ export const relation = <
707
707
  expr: {
708
708
  field: (field: FieldPath<RelationElement<TFieldValues, P>>): ComputedProjectionMathExpression => ({
709
709
  _tag: "field",
710
- field: field as string
710
+ field
711
711
  }),
712
712
  mul: (
713
713
  left: ComputedProjectionMathExpression,
@@ -716,33 +716,33 @@ export const relation = <
716
716
  },
717
717
  length: (): ComputedProjectionExpression<number> => ({
718
718
  _tag: "relation-length",
719
- path: path as string
719
+ path
720
720
  }),
721
721
  count: (operation?: ComputedProjectionOperation): ComputedProjectionExpression<number> =>
722
722
  operation
723
723
  ? {
724
724
  _tag: "relation-count",
725
- path: path as string,
725
+ path,
726
726
  operation
727
727
  }
728
728
  : {
729
729
  _tag: "relation-count",
730
- path: path as string
730
+ path
731
731
  },
732
732
  any: (operation?: ComputedProjectionOperation): ComputedProjectionExpression<boolean> =>
733
733
  operation
734
734
  ? {
735
735
  _tag: "relation-any",
736
- path: path as string,
736
+ path,
737
737
  operation
738
738
  }
739
739
  : {
740
740
  _tag: "relation-any",
741
- path: path as string
741
+ path
742
742
  },
743
743
  every: (operation: ComputedProjectionOperation): ComputedProjectionExpression<boolean> => ({
744
744
  _tag: "relation-every",
745
- path: path as string,
745
+ path,
746
746
  operation
747
747
  }),
748
748
  distinctCount: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
@@ -752,14 +752,14 @@ export const relation = <
752
752
  operation
753
753
  ? {
754
754
  _tag: "relation-distinct-count",
755
- path: path as string,
756
- field: field as string,
755
+ path,
756
+ field,
757
757
  operation
758
758
  }
759
759
  : {
760
760
  _tag: "relation-distinct-count",
761
- path: path as string,
762
- field: field as string
761
+ path,
762
+ field
763
763
  },
764
764
  sum: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
765
765
  field: F,
@@ -768,14 +768,14 @@ export const relation = <
768
768
  operation
769
769
  ? {
770
770
  _tag: "relation-sum",
771
- path: path as string,
772
- field: field as string,
771
+ path,
772
+ field,
773
773
  operation
774
774
  }
775
775
  : {
776
776
  _tag: "relation-sum",
777
- path: path as string,
778
- field: field as string
777
+ path,
778
+ field
779
779
  },
780
780
  sumExpr: (
781
781
  expression: ComputedProjectionMathExpression,
@@ -784,13 +784,13 @@ export const relation = <
784
784
  operation
785
785
  ? {
786
786
  _tag: "relation-sum-expr",
787
- path: path as string,
787
+ path,
788
788
  expression,
789
789
  operation
790
790
  }
791
791
  : {
792
792
  _tag: "relation-sum-expr",
793
- path: path as string,
793
+ path,
794
794
  expression
795
795
  },
796
796
  sumExprBy: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
@@ -803,16 +803,16 @@ export const relation = <
803
803
  operation
804
804
  ? {
805
805
  _tag: "relation-sum-expr-by",
806
- path: path as string,
806
+ path,
807
807
  expression,
808
- unit: options.unit as string,
808
+ unit: options.unit,
809
809
  operation
810
810
  }
811
811
  : {
812
812
  _tag: "relation-sum-expr-by",
813
- path: path as string,
813
+ path,
814
814
  expression,
815
- unit: options.unit as string
815
+ unit: options.unit
816
816
  },
817
817
  sumExprNormalized: (
818
818
  expression: ComputedProjectionMathExpression,
@@ -826,18 +826,18 @@ export const relation = <
826
826
  operation
827
827
  ? {
828
828
  _tag: "relation-sum-expr-normalized",
829
- path: path as string,
829
+ path,
830
830
  expression,
831
- unit: options.unit as string,
831
+ unit: options.unit,
832
832
  toBase: options.toBase,
833
833
  factors: options.factors,
834
834
  operation
835
835
  }
836
836
  : {
837
837
  _tag: "relation-sum-expr-normalized",
838
- path: path as string,
838
+ path,
839
839
  expression,
840
- unit: options.unit as string,
840
+ unit: options.unit,
841
841
  toBase: options.toBase,
842
842
  factors: options.factors
843
843
  },
@@ -848,15 +848,15 @@ export const relation = <
848
848
  operation
849
849
  ? {
850
850
  _tag: "relation-collect",
851
- path: path as string,
852
- field: field as string,
851
+ path,
852
+ field,
853
853
  distinct: false,
854
854
  operation
855
855
  }
856
856
  : {
857
857
  _tag: "relation-collect",
858
- path: path as string,
859
- field: field as string,
858
+ path,
859
+ field,
860
860
  distinct: false
861
861
  },
862
862
  collectDistinct: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
@@ -866,15 +866,15 @@ export const relation = <
866
866
  operation
867
867
  ? {
868
868
  _tag: "relation-collect",
869
- path: path as string,
870
- field: field as string,
869
+ path,
870
+ field,
871
871
  distinct: true,
872
872
  operation
873
873
  }
874
874
  : {
875
875
  _tag: "relation-collect",
876
- path: path as string,
877
- field: field as string,
876
+ path,
877
+ field,
878
878
  distinct: true
879
879
  },
880
880
  collectFields: <const F extends readonly FieldPath<RelationElement<TFieldValues, P>>[]>(
@@ -886,15 +886,15 @@ export const relation = <
886
886
  operation
887
887
  ? {
888
888
  _tag: "relation-collect-fields",
889
- path: path as string,
890
- fields: fields as readonly string[],
889
+ path,
890
+ fields,
891
891
  distinct: false,
892
892
  operation
893
893
  }
894
894
  : {
895
895
  _tag: "relation-collect-fields",
896
- path: path as string,
897
- fields: fields as readonly string[],
896
+ path,
897
+ fields,
898
898
  distinct: false
899
899
  },
900
900
  collectDistinctFields: <const F extends readonly FieldPath<RelationElement<TFieldValues, P>>[]>(
@@ -906,15 +906,15 @@ export const relation = <
906
906
  operation
907
907
  ? {
908
908
  _tag: "relation-collect-fields",
909
- path: path as string,
910
- fields: fields as readonly string[],
909
+ path,
910
+ fields,
911
911
  distinct: true,
912
912
  operation
913
913
  }
914
914
  : {
915
915
  _tag: "relation-collect-fields",
916
- path: path as string,
917
- fields: fields as readonly string[],
916
+ path,
917
+ fields,
918
918
  distinct: true
919
919
  }
920
920
  })
@@ -930,7 +930,7 @@ export const relation = <
930
930
  export const expr = {
931
931
  field: <T extends FieldValues = FieldValues>(
932
932
  field: FieldPath<T>
933
- ): ComputedProjectionMathExpression => ({ _tag: "field", field: field as string }),
933
+ ): ComputedProjectionMathExpression => ({ _tag: "field", field }),
934
934
  mul: (
935
935
  left: ComputedProjectionMathExpression,
936
936
  right: ComputedProjectionMathExpression
@@ -1059,7 +1059,7 @@ export const projectComputed: {
1059
1059
  const computedProjection = typeof mapOrBuild === "function"
1060
1060
  ? mapOrBuild(makeComputedHelpers())
1061
1061
  : mapOrBuild
1062
- return new Project({ current, schema, mode, computed: computedProjection } as any)
1062
+ return new Project({ current, schema, mode, computed: computedProjection })
1063
1063
  }
1064
1064
 
1065
1065
  /**
@@ -1077,12 +1077,12 @@ export interface AggBuilder<TFieldValues extends FieldValues> {
1077
1077
  }
1078
1078
 
1079
1079
  const makeAggBuilder = <TFieldValues extends FieldValues>(): AggBuilder<TFieldValues> => ({
1080
- field: (path) => ({ _tag: "agg-field", path: path as string }),
1080
+ field: (path) => ({ _tag: "agg-field", path }),
1081
1081
  count: () => ({ _tag: "agg-count" }),
1082
1082
  countWhen: (operation) => ({ _tag: "agg-count-when", operation }),
1083
- sum: (field) => ({ _tag: "agg-sum", field: field as string }),
1084
- min: (field) => ({ _tag: "agg-min", field: field as string }),
1085
- max: (field) => ({ _tag: "agg-max", field: field as string })
1083
+ sum: (field) => ({ _tag: "agg-sum", field }),
1084
+ min: (field) => ({ _tag: "agg-min", field }),
1085
+ max: (field) => ({ _tag: "agg-max", field })
1086
1086
  })
1087
1087
 
1088
1088
  /**
@@ -316,17 +316,17 @@ const interpret = <
316
316
  case "relation-count":
317
317
  case "relation-any":
318
318
  case "relation-every":
319
- return [key, { _tag: e._tag, path: e.path, filter } as ComputedProjectionIrExpression]
319
+ return [key, { _tag: e._tag, path: e.path, filter }]
320
320
  case "relation-distinct-count":
321
321
  case "relation-sum":
322
322
  return [
323
323
  key,
324
- { _tag: e._tag, path: e.path, field: e.field, filter } as ComputedProjectionIrExpression
324
+ { _tag: e._tag, path: e.path, field: e.field, filter }
325
325
  ]
326
326
  case "relation-sum-expr":
327
327
  return [
328
328
  key,
329
- { _tag: e._tag, path: e.path, expression: e.expression, filter } as ComputedProjectionIrExpression
329
+ { _tag: e._tag, path: e.path, expression: e.expression, filter }
330
330
  ]
331
331
  case "relation-sum-expr-by":
332
332
  return [
@@ -337,7 +337,7 @@ const interpret = <
337
337
  expression: e.expression,
338
338
  unit: e.unit,
339
339
  filter
340
- } as ComputedProjectionIrExpression
340
+ }
341
341
  ]
342
342
  case "relation-sum-expr-normalized":
343
343
  return [
@@ -350,7 +350,7 @@ const interpret = <
350
350
  toBase: e.toBase,
351
351
  factors: e.factors,
352
352
  filter
353
- } as ComputedProjectionIrExpression
353
+ }
354
354
  ]
355
355
  case "relation-collect":
356
356
  return [
@@ -361,7 +361,7 @@ const interpret = <
361
361
  field: e.field,
362
362
  distinct: e.distinct,
363
363
  filter
364
- } as ComputedProjectionIrExpression
364
+ }
365
365
  ]
366
366
  case "relation-collect-fields":
367
367
  return [
@@ -372,10 +372,10 @@ const interpret = <
372
372
  fields: e.fields,
373
373
  distinct: e.distinct,
374
374
  filter
375
- } as ComputedProjectionIrExpression
375
+ }
376
376
  ]
377
377
  case "relation-length":
378
- return [key, { _tag: e._tag, path: e.path } as ComputedProjectionIrExpression]
378
+ return [key, { _tag: e._tag, path: e.path }]
379
379
  }
380
380
  })
381
381
  )
package/src/Model.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./Model/dsl.ts"
2
2
  export * as Q from "./Model/query.ts"
3
3
  export { makeRepo } from "./Model/Repository.ts"
4
+ export { repositoryDependency } from "./Model/Repository.ts"
4
5
  export { type RegisteredRepository, RepositoryRegistry, RepositoryRegistryLive } from "./Model/Repository.ts"