effect-app 4.0.0-beta.292 → 4.0.0-beta.293

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.
@@ -55,10 +55,14 @@ type ExtractExclusiveness<T> = T extends QueryTogether<any, any, infer Exclusive
55
55
  type ExtractFieldValuesRefined<T> = T extends QueryTogether<any, infer TFieldValuesRefined, any, any, any, any, any>
56
56
  ? TFieldValuesRefined
57
57
  : never
58
+ type ProjectableField<I, From, K extends PropertyKey> = K extends keyof From ? From[K] extends I ? I
59
+ : I extends From[K] ? I
60
+ : never
61
+ : never
58
62
  type ProjectableEncoded<I, From> = I extends FieldValues ? {
59
63
  [K in keyof I]: K extends keyof (
60
64
  I extends { readonly _tag: infer Tag } ? Extract<From, { readonly _tag: Tag }> : From
61
- ) ? I[K]
65
+ ) ? ProjectableField<I[K], I extends { readonly _tag: infer Tag } ? Extract<From, { readonly _tag: Tag }> : From, K>
62
66
  : never
63
67
  }
64
68
  : never
@@ -122,74 +126,107 @@ export type ComputedProjectionMathExpression =
122
126
  readonly right: ComputedProjectionMathExpression
123
127
  }
124
128
 
125
- export type ComputedProjectionExpression =
126
- | {
127
- readonly _tag: "relation-count"
128
- readonly path: string
129
- readonly operation?: ComputedProjectionOperation
130
- }
131
- | {
132
- readonly _tag: "relation-any"
133
- readonly path: string
134
- readonly operation?: ComputedProjectionOperation
135
- }
136
- | {
137
- readonly _tag: "relation-every"
138
- readonly path: string
139
- readonly operation: ComputedProjectionOperation
140
- }
141
- | {
142
- readonly _tag: "relation-distinct-count"
143
- readonly path: string
144
- readonly field: string
145
- readonly operation?: ComputedProjectionOperation
146
- }
147
- | {
148
- readonly _tag: "relation-sum"
149
- readonly path: string
150
- readonly field: string
151
- readonly operation?: ComputedProjectionOperation
152
- }
153
- | {
154
- readonly _tag: "relation-sum-expr"
155
- readonly path: string
156
- readonly expression: ComputedProjectionMathExpression
157
- readonly operation?: ComputedProjectionOperation
158
- }
159
- | {
160
- readonly _tag: "relation-sum-expr-by"
161
- readonly path: string
162
- readonly expression: ComputedProjectionMathExpression
163
- readonly unit: string
164
- readonly operation?: ComputedProjectionOperation
165
- }
166
- | {
167
- readonly _tag: "relation-sum-expr-normalized"
168
- readonly path: string
169
- readonly expression: ComputedProjectionMathExpression
170
- readonly unit: string
171
- readonly toBase: string
172
- readonly factors: Readonly<Record<string, number>>
173
- readonly operation?: ComputedProjectionOperation
174
- }
175
- | {
176
- readonly _tag: "relation-collect"
177
- readonly path: string
178
- readonly field: string
179
- readonly distinct: boolean
180
- readonly operation?: ComputedProjectionOperation
181
- }
182
- | {
183
- readonly _tag: "relation-collect-fields"
184
- readonly path: string
185
- readonly fields: readonly string[]
186
- readonly distinct: boolean
187
- readonly operation?: ComputedProjectionOperation
188
- }
189
- | {
190
- readonly _tag: "relation-length"
191
- readonly path: string
129
+ declare const ComputedProjectionExpressionTypeId: unique symbol
130
+
131
+ type ComputedProjectionOutput<A> = {
132
+ readonly [ComputedProjectionExpressionTypeId]?: Covariant<A>
133
+ }
134
+
135
+ export type ComputedProjectionExpression<A = unknown> =
136
+ & ComputedProjectionOutput<A>
137
+ & (
138
+ | {
139
+ readonly _tag: "relation-count"
140
+ readonly path: string
141
+ readonly operation?: ComputedProjectionOperation
142
+ }
143
+ | {
144
+ readonly _tag: "relation-any"
145
+ readonly path: string
146
+ readonly operation?: ComputedProjectionOperation
147
+ }
148
+ | {
149
+ readonly _tag: "relation-every"
150
+ readonly path: string
151
+ readonly operation: ComputedProjectionOperation
152
+ }
153
+ | {
154
+ readonly _tag: "relation-distinct-count"
155
+ readonly path: string
156
+ readonly field: string
157
+ readonly operation?: ComputedProjectionOperation
158
+ }
159
+ | {
160
+ readonly _tag: "relation-sum"
161
+ readonly path: string
162
+ readonly field: string
163
+ readonly operation?: ComputedProjectionOperation
164
+ }
165
+ | {
166
+ readonly _tag: "relation-sum-expr"
167
+ readonly path: string
168
+ readonly expression: ComputedProjectionMathExpression
169
+ readonly operation?: ComputedProjectionOperation
170
+ }
171
+ | {
172
+ readonly _tag: "relation-sum-expr-by"
173
+ readonly path: string
174
+ readonly expression: ComputedProjectionMathExpression
175
+ readonly unit: string
176
+ readonly operation?: ComputedProjectionOperation
177
+ }
178
+ | {
179
+ readonly _tag: "relation-sum-expr-normalized"
180
+ readonly path: string
181
+ readonly expression: ComputedProjectionMathExpression
182
+ readonly unit: string
183
+ readonly toBase: string
184
+ readonly factors: Readonly<Record<string, number>>
185
+ readonly operation?: ComputedProjectionOperation
186
+ }
187
+ | {
188
+ readonly _tag: "relation-collect"
189
+ readonly path: string
190
+ readonly field: string
191
+ readonly distinct: boolean
192
+ readonly operation?: ComputedProjectionOperation
193
+ }
194
+ | {
195
+ readonly _tag: "relation-collect-fields"
196
+ readonly path: string
197
+ readonly fields: readonly string[]
198
+ readonly distinct: boolean
199
+ readonly operation?: ComputedProjectionOperation
200
+ }
201
+ | {
202
+ readonly _tag: "relation-length"
203
+ readonly path: string
204
+ }
205
+ )
206
+
207
+ type ComputedProjectionOutputOf<T> = T extends ComputedProjectionExpression<infer A> ? A : never
208
+
209
+ type ComputedProjectionShape<M extends ComputedProjectionMap> = {
210
+ readonly [K in keyof M]: ComputedProjectionOutputOf<M[K]>
211
+ }
212
+
213
+ type ProjectableComputedEncoded<I, From, M extends ComputedProjectionMap> = I extends FieldValues ? {
214
+ [K in keyof I]: K extends keyof M ? ComputedProjectionShape<M>[K]
215
+ : K extends keyof (
216
+ I extends { readonly _tag: infer Tag } ? Extract<From, { readonly _tag: Tag }> : From
217
+ ) ? ProjectableField<
218
+ I[K],
219
+ I extends { readonly _tag: infer Tag } ? Extract<From, { readonly _tag: Tag }> : From,
220
+ K
221
+ >
222
+ : never
192
223
  }
224
+ : never
225
+
226
+ type KeysOfUnion<T> = T extends T ? keyof T : never
227
+
228
+ type NoExtraComputedKeys<M extends ComputedProjectionMap, I> = Exclude<keyof M, KeysOfUnion<I>> extends never ? unknown
229
+ : never
193
230
 
194
231
  /**
195
232
  * An expression that aggregates values across documents (for use with {@link aggregate}).
@@ -629,11 +666,11 @@ export const relation = <
629
666
  right: ComputedProjectionMathExpression
630
667
  ): ComputedProjectionMathExpression => ({ _tag: "mul", left, right })
631
668
  },
632
- length: (): ComputedProjectionExpression => ({
669
+ length: (): ComputedProjectionExpression<number> => ({
633
670
  _tag: "relation-length",
634
671
  path: path as string
635
672
  }),
636
- count: (operation?: ComputedProjectionOperation): ComputedProjectionExpression =>
673
+ count: (operation?: ComputedProjectionOperation): ComputedProjectionExpression<number> =>
637
674
  operation
638
675
  ? {
639
676
  _tag: "relation-count",
@@ -644,7 +681,7 @@ export const relation = <
644
681
  _tag: "relation-count",
645
682
  path: path as string
646
683
  },
647
- any: (operation?: ComputedProjectionOperation): ComputedProjectionExpression =>
684
+ any: (operation?: ComputedProjectionOperation): ComputedProjectionExpression<boolean> =>
648
685
  operation
649
686
  ? {
650
687
  _tag: "relation-any",
@@ -655,15 +692,15 @@ export const relation = <
655
692
  _tag: "relation-any",
656
693
  path: path as string
657
694
  },
658
- every: (operation: ComputedProjectionOperation): ComputedProjectionExpression => ({
695
+ every: (operation: ComputedProjectionOperation): ComputedProjectionExpression<boolean> => ({
659
696
  _tag: "relation-every",
660
697
  path: path as string,
661
698
  operation
662
699
  }),
663
- distinctCount: (
664
- field: FieldPath<RelationElement<TFieldValues, P>>,
700
+ distinctCount: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
701
+ field: F,
665
702
  operation?: ComputedProjectionOperation
666
- ): ComputedProjectionExpression =>
703
+ ): ComputedProjectionExpression<number> =>
667
704
  operation
668
705
  ? {
669
706
  _tag: "relation-distinct-count",
@@ -676,10 +713,10 @@ export const relation = <
676
713
  path: path as string,
677
714
  field: field as string
678
715
  },
679
- sum: (
680
- field: FieldPath<RelationElement<TFieldValues, P>>,
716
+ sum: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
717
+ field: F,
681
718
  operation?: ComputedProjectionOperation
682
- ): ComputedProjectionExpression =>
719
+ ): ComputedProjectionExpression<number> =>
683
720
  operation
684
721
  ? {
685
722
  _tag: "relation-sum",
@@ -695,7 +732,7 @@ export const relation = <
695
732
  sumExpr: (
696
733
  expression: ComputedProjectionMathExpression,
697
734
  operation?: ComputedProjectionOperation
698
- ): ComputedProjectionExpression =>
735
+ ): ComputedProjectionExpression<number> =>
699
736
  operation
700
737
  ? {
701
738
  _tag: "relation-sum-expr",
@@ -708,11 +745,13 @@ export const relation = <
708
745
  path: path as string,
709
746
  expression
710
747
  },
711
- sumExprBy: (
748
+ sumExprBy: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
712
749
  expression: ComputedProjectionMathExpression,
713
- options: { unit: FieldPath<RelationElement<TFieldValues, P>> },
750
+ options: { unit: F },
714
751
  operation?: ComputedProjectionOperation
715
- ): ComputedProjectionExpression =>
752
+ ): ComputedProjectionExpression<
753
+ ReadonlyArray<{ readonly unit: FieldPathValue<RelationElement<TFieldValues, P>, F>; readonly total: number }>
754
+ > =>
716
755
  operation
717
756
  ? {
718
757
  _tag: "relation-sum-expr-by",
@@ -735,7 +774,7 @@ export const relation = <
735
774
  factors: Readonly<Record<string, number>>
736
775
  },
737
776
  operation?: ComputedProjectionOperation
738
- ): ComputedProjectionExpression =>
777
+ ): ComputedProjectionExpression<number> =>
739
778
  operation
740
779
  ? {
741
780
  _tag: "relation-sum-expr-normalized",
@@ -754,10 +793,10 @@ export const relation = <
754
793
  toBase: options.toBase,
755
794
  factors: options.factors
756
795
  },
757
- collect: (
758
- field: FieldPath<RelationElement<TFieldValues, P>>,
796
+ collect: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
797
+ field: F,
759
798
  operation?: ComputedProjectionOperation
760
- ): ComputedProjectionExpression =>
799
+ ): ComputedProjectionExpression<ReadonlyArray<FieldPathValue<RelationElement<TFieldValues, P>, F>>> =>
761
800
  operation
762
801
  ? {
763
802
  _tag: "relation-collect",
@@ -772,10 +811,10 @@ export const relation = <
772
811
  field: field as string,
773
812
  distinct: false
774
813
  },
775
- collectDistinct: (
776
- field: FieldPath<RelationElement<TFieldValues, P>>,
814
+ collectDistinct: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
815
+ field: F,
777
816
  operation?: ComputedProjectionOperation
778
- ): ComputedProjectionExpression =>
817
+ ): ComputedProjectionExpression<ReadonlyArray<FieldPathValue<RelationElement<TFieldValues, P>, F>>> =>
779
818
  operation
780
819
  ? {
781
820
  _tag: "relation-collect",
@@ -790,10 +829,12 @@ export const relation = <
790
829
  field: field as string,
791
830
  distinct: true
792
831
  },
793
- collectFields: (
794
- fields: readonly FieldPath<RelationElement<TFieldValues, P>>[],
832
+ collectFields: <const F extends readonly FieldPath<RelationElement<TFieldValues, P>>[]>(
833
+ fields: F,
795
834
  operation?: ComputedProjectionOperation
796
- ): ComputedProjectionExpression =>
835
+ ): ComputedProjectionExpression<
836
+ ReadonlyArray<FieldPathValue<RelationElement<TFieldValues, P>, F[number]>>
837
+ > =>
797
838
  operation
798
839
  ? {
799
840
  _tag: "relation-collect-fields",
@@ -808,10 +849,12 @@ export const relation = <
808
849
  fields: fields as readonly string[],
809
850
  distinct: false
810
851
  },
811
- collectDistinctFields: (
812
- fields: readonly FieldPath<RelationElement<TFieldValues, P>>[],
852
+ collectDistinctFields: <const F extends readonly FieldPath<RelationElement<TFieldValues, P>>[]>(
853
+ fields: F,
813
854
  operation?: ComputedProjectionOperation
814
- ): ComputedProjectionExpression =>
855
+ ): ComputedProjectionExpression<
856
+ ReadonlyArray<FieldPathValue<RelationElement<TFieldValues, P>, F[number]>>
857
+ > =>
815
858
  operation
816
859
  ? {
817
860
  _tag: "relation-collect-fields",
@@ -865,13 +908,16 @@ const makeComputedHelpers = <TFieldValues extends FieldValues>(): ComputedHelper
865
908
  export const projectComputed: {
866
909
  <
867
910
  Q extends Query<any> | QueryWhere<any, any, any> | QueryEnd<any, "one" | "many", any>,
868
- I extends Record<string, unknown>,
911
+ I extends FieldValues,
912
+ M extends ComputedProjectionMap,
869
913
  A = ExtractFieldValuesRefined<Q>,
870
914
  R = never,
871
915
  E extends boolean = ExtractExclusiveness<Q>
872
916
  >(
873
- schema: S.Codec<Option.Option<A>, I, R>,
874
- build: (helpers: ComputedHelpers<ExtractFieldValuesRefined<Q>>) => ComputedProjectionMap,
917
+ schema:
918
+ & S.Codec<Option.Option<A>, I, R>
919
+ & S.Codec<Option.Option<A>, ProjectableComputedEncoded<I, ExtractFieldValuesRefined<Q>, M>, R>,
920
+ build: (helpers: ComputedHelpers<ExtractFieldValuesRefined<Q>>) => M & NoExtraComputedKeys<M, I>,
875
921
  mode: "collect"
876
922
  ): (
877
923
  current: Q
@@ -879,13 +925,16 @@ export const projectComputed: {
879
925
 
880
926
  <
881
927
  Q extends Query<any> | QueryWhere<any, any, any> | QueryEnd<any, "one" | "many", any>,
882
- I extends Record<string, unknown>,
928
+ I extends FieldValues,
929
+ M extends ComputedProjectionMap,
883
930
  A = ExtractFieldValuesRefined<Q>,
884
931
  R = never,
885
932
  E extends boolean = ExtractExclusiveness<Q>
886
933
  >(
887
- schema: S.Codec<A, I, R>,
888
- build: (helpers: ComputedHelpers<ExtractFieldValuesRefined<Q>>) => ComputedProjectionMap,
934
+ schema:
935
+ & S.Codec<A, I, R>
936
+ & S.Codec<A, ProjectableComputedEncoded<I, ExtractFieldValuesRefined<Q>, M>, R>,
937
+ build: (helpers: ComputedHelpers<ExtractFieldValuesRefined<Q>>) => M & NoExtraComputedKeys<M, I>,
889
938
  mode?: "project"
890
939
  ): (
891
940
  current: Q
@@ -893,13 +942,16 @@ export const projectComputed: {
893
942
 
894
943
  <
895
944
  Q extends Query<any> | QueryWhere<any, any, any> | QueryEnd<any, "one" | "many", any>,
896
- I extends Record<string, unknown>,
945
+ I extends FieldValues,
946
+ M extends ComputedProjectionMap,
897
947
  A = ExtractFieldValuesRefined<Q>,
898
948
  R = never,
899
949
  E extends boolean = ExtractExclusiveness<Q>
900
950
  >(
901
- schema: S.Codec<Option.Option<A>, I, R>,
902
- computedProjection: ComputedProjectionMap,
951
+ schema:
952
+ & S.Codec<Option.Option<A>, I, R>
953
+ & S.Codec<Option.Option<A>, ProjectableComputedEncoded<I, ExtractFieldValuesRefined<Q>, M>, R>,
954
+ computedProjection: M & NoExtraComputedKeys<M, I>,
903
955
  mode: "collect"
904
956
  ): (
905
957
  current: Q
@@ -907,13 +959,16 @@ export const projectComputed: {
907
959
 
908
960
  <
909
961
  Q extends Query<any> | QueryWhere<any, any, any> | QueryEnd<any, "one" | "many", any>,
910
- I extends Record<string, unknown>,
962
+ I extends FieldValues,
963
+ M extends ComputedProjectionMap,
911
964
  A = ExtractFieldValuesRefined<Q>,
912
965
  R = never,
913
966
  E extends boolean = ExtractExclusiveness<Q>
914
967
  >(
915
- schema: S.Codec<A, I, R>,
916
- computedProjection: ComputedProjectionMap,
968
+ schema:
969
+ & S.Codec<A, I, R>
970
+ & S.Codec<A, ProjectableComputedEncoded<I, ExtractFieldValuesRefined<Q>, M>, R>,
971
+ computedProjection: M & NoExtraComputedKeys<M, I>,
917
972
  mode?: "project"
918
973
  ): (
919
974
  current: Q
@@ -357,6 +357,21 @@ const walkTransformation = (t: S.AST.AST): S.AST.AST => {
357
357
  return t
358
358
  }
359
359
 
360
+ const objectAsts = (ast: S.AST.AST): readonly S.AST.Objects[] => {
361
+ const t = walkTransformation(ast)
362
+ if (S.AST.isObjects(t)) {
363
+ return [t]
364
+ }
365
+ if (S.AST.isUnion(t)) {
366
+ return t.types.flatMap(objectAsts)
367
+ }
368
+ return []
369
+ }
370
+
371
+ const objectKeys = (ast: S.AST.AST): readonly string[] => [
372
+ ...new Set(objectAsts(ast).flatMap((object) => object.propertySignatures.map((_) => _.name as string)))
373
+ ]
374
+
360
375
  export const toFilter = <
361
376
  TFieldValues extends FieldValues,
362
377
  A,
@@ -399,9 +414,10 @@ export const toFilter = <
399
414
  // TODO: support more complex (nested) schemas?
400
415
  if (schema) {
401
416
  const t = walkTransformation(SchemaAST.toEncoded(schema.ast))
402
- if (S.AST.isObjects(t)) {
403
- select = t.propertySignatures.map((_) => _.name as string)
404
- for (const prop of t.propertySignatures) {
417
+ const objects = [...objectAsts(t)]
418
+ if (Array.isArrayNonEmpty(objects)) {
419
+ select = [...objectKeys(t)]
420
+ for (const prop of objects.flatMap((_) => _.propertySignatures)) {
405
421
  if (S.AST.isArrays(prop.type)) {
406
422
  // make sure we only select when there are actually type literals in the tuple...
407
423
  // otherwise we might be dealing with strings etc.
@@ -411,8 +427,7 @@ export const toFilter = <
411
427
  subKeys: Array.flatMap(
412
428
  prop.type.rest,
413
429
  (x) => {
414
- const t = walkTransformation(x)
415
- return S.AST.isObjects(t) ? t.propertySignatures.map((y) => y.name as string) : []
430
+ return objectKeys(x)
416
431
  }
417
432
  )
418
433
  }
@@ -443,10 +458,7 @@ export const toFilter = <
443
458
  return [] as string[]
444
459
  }
445
460
  const encoded = walkTransformation(SchemaAST.toEncoded(baseSchema.ast))
446
- if (!S.AST.isObjects(encoded)) {
447
- return [] as string[]
448
- }
449
- const encodedKeys = encoded.propertySignatures.map((_) => _.name as string)
461
+ const encodedKeys = objectKeys(encoded)
450
462
  return schemaKeys.filter((key) => !encodedKeys.includes(key))
451
463
  })()
452
464
  const missingComputedKeys = nonEncodedSchemaKeys.filter((key) => !(computed && key in computed))