effect-app 4.0.0-beta.306 → 4.0.0-beta.308

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.
@@ -58,10 +58,36 @@ type ExtractFieldValuesRefined<T> = T extends QueryTogether<any, infer TFieldVal
58
58
  ? TFieldValuesRefined
59
59
  : never
60
60
  type KeysOfUnion<T> = T extends T ? keyof T : never
61
- type LiteralValue<T> = T extends { readonly literal: infer L } ? L : T
61
+ /** Peel Schema `tag`/`Literal` brands down to the underlying literal value. */
62
+ type LiteralValue<T> = T extends { readonly literal: infer L } ? L
63
+ : T extends string | number | boolean | null | bigint ? T
64
+ // Schema.tag<"x"> / withConstructorDefault wrappers are object brands whose
65
+ // nominal shape is not a PropertyKey — fall back to never so callers treat
66
+ // them via UnwrapTag below.
67
+ : never
68
+ // Last-resort: if T is a single object brand wrapping a string literal in its
69
+ // structure, treat non-union object tags as single-literal for same-tag duals.
70
+ type TagKey<T> = [LiteralValue<T>] extends [never] ? (
71
+ string extends T ? string
72
+ : [T] extends [PropertyKey] ? T
73
+ // object brand (e.g. tag<"packing">): treat as single opaque tag token
74
+ : T
75
+ )
76
+ : LiteralValue<T>
77
+ // One-directional: domain tag may be a single literal that is a member of a
78
+ // multi-tag projection (`"picking" extends "picking"|"picked"`). Bidirectional
79
+ // equality would reject every multi-tag flat projection.
62
80
  type ExtractTagged<From, Tag> = From extends { readonly _tag: infer FromTag }
63
- ? [LiteralValue<FromTag>] extends [LiteralValue<Tag>] ? From : never
81
+ ? [TagKey<FromTag>] extends [TagKey<Tag>] ? From : never
64
82
  : never
83
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never
84
+ /**
85
+ * True when `Tag` is a single tag token (string literal or opaque brand like
86
+ * Schema.tag<"packing">), not a union of tags and not bare `string`.
87
+ */
88
+ type IsSingleLiteralTag<Tag> = string extends Tag ? false
89
+ : [Tag] extends [UnionToIntersection<Tag>] ? true
90
+ : false
65
91
  /**
66
92
  * Domain shape that may supply stored fields for projection member `I`.
67
93
  *
@@ -83,37 +109,48 @@ type ProjectableSource<I, From> = I extends { readonly _tag: infer Tag } ? (
83
109
  * field types may be narrowed by the projection).
84
110
  *
85
111
  * Uses `keyof Source` (not `KeysOfUnion` of the whole domain union) so a field
86
- * owned only by some tags cannot be required on every branch.
112
+ * owned only by some tags cannot be required on every branch — except for a
113
+ * single literal tag that maps to several domain variants (same `_tag`,
114
+ * different payloads), where `KeysOfUnion` allows each variant's keys.
87
115
  */
88
116
  /**
89
117
  * Keys the domain may supply for projection member `I`.
90
- * - Tagged `I`: only keys of the matching domain state.
118
+ * - Single-literal tagged `I` (`_tag: "packing"`): keys of *any* same-tag
119
+ * domain variant (`KeysOfUnion`) — dual packing/closed shapes stay projectable.
120
+ * - Multi-tag / string-tagged `I` (`_tag: "a"|"b"` or `string`): keys of the
121
+ * *intersection* of matched domain members (`keyof` of the source union) so
122
+ * a flat multi-tag DTO cannot claim state-only fields (e.g. `batchId` on
123
+ * `initial`).
91
124
  * - Untagged `I` (plain project DTOs): keys present on *any* domain member
92
125
  * (`KeysOfUnion`), matching historical `project()` behavior.
93
126
  */
94
- type ProjectableDomainKeys<I, From> = I extends { readonly _tag: any } ? keyof ProjectableSource<I, From>
127
+ type ProjectableDomainKeys<I, From> = I extends { readonly _tag: infer Tag } ? (
128
+ IsSingleLiteralTag<Tag> extends true ? KeysOfUnion<ProjectableSource<I, From>>
129
+ : keyof ProjectableSource<I, From>
130
+ )
95
131
  : KeysOfUnion<From>
96
132
 
97
- type ProjectableEncodedMember<
98
- I,
99
- From,
100
- ExtraKeys extends PropertyKey = never
101
- > = I extends FieldValues ? {
102
- // Keep `I[K]` (key presence only). Requiring domain field types would reject
103
- // legitimate projections that narrow nested shapes (e.g. package views).
104
- [K in keyof I]-?: K extends ExtraKeys ? I[K]
105
- : K extends ProjectableDomainKeys<I, From> ? I[K]
106
- : never
107
- }
108
- : never
133
+ /**
134
+ * Keys on projection member `I` that are neither computed (`ExtraKeys`) nor
135
+ * present on the matching domain source. Key presence only — nested field
136
+ * types may be narrowed by the projection, and optional domain/projection
137
+ * keys must not fail via `{ k?: T } extends { k: T }` (the old `-?` mapped
138
+ * assignability check rejected legitimate optionalKey fields like closed.batchId).
139
+ */
140
+ type UnprojectableKeys<I, From, ExtraKeys extends PropertyKey> = {
141
+ [K in keyof I]-?: K extends ExtraKeys ? never
142
+ : K extends ProjectableDomainKeys<I, From> ? never
143
+ : K
144
+ }[keyof I]
109
145
 
110
146
  /**
111
147
  * Distribute over tagged-union projection Encoded types. A non-distributive
112
- * `[I] extends [...]` check against a union only sees `keyof (A|B)` (key
113
- * intersection) and misses branch-only fields like cancel-only omissions.
148
+ * check against a union only sees `keyof (A|B)` (key intersection) and misses
149
+ * branch-only fields like cancel-only omissions.
114
150
  */
115
- type IsProjectableMember<I, From, ExtraKeys extends PropertyKey> = [I] extends
116
- [ProjectableEncodedMember<I, From, ExtraKeys>] ? true : false
151
+ type IsProjectableMember<I, From, ExtraKeys extends PropertyKey> = [I] extends [FieldValues]
152
+ ? ([UnprojectableKeys<I, From, ExtraKeys>] extends [never] ? true : false)
153
+ : false
117
154
 
118
155
  /**
119
156
  * `unknown` when every member of projection Encoded `I` is projectable from
@@ -670,7 +707,7 @@ export const relation = <
670
707
  expr: {
671
708
  field: (field: FieldPath<RelationElement<TFieldValues, P>>): ComputedProjectionMathExpression => ({
672
709
  _tag: "field",
673
- field: field as string
710
+ field
674
711
  }),
675
712
  mul: (
676
713
  left: ComputedProjectionMathExpression,
@@ -679,33 +716,33 @@ export const relation = <
679
716
  },
680
717
  length: (): ComputedProjectionExpression<number> => ({
681
718
  _tag: "relation-length",
682
- path: path as string
719
+ path
683
720
  }),
684
721
  count: (operation?: ComputedProjectionOperation): ComputedProjectionExpression<number> =>
685
722
  operation
686
723
  ? {
687
724
  _tag: "relation-count",
688
- path: path as string,
725
+ path,
689
726
  operation
690
727
  }
691
728
  : {
692
729
  _tag: "relation-count",
693
- path: path as string
730
+ path
694
731
  },
695
732
  any: (operation?: ComputedProjectionOperation): ComputedProjectionExpression<boolean> =>
696
733
  operation
697
734
  ? {
698
735
  _tag: "relation-any",
699
- path: path as string,
736
+ path,
700
737
  operation
701
738
  }
702
739
  : {
703
740
  _tag: "relation-any",
704
- path: path as string
741
+ path
705
742
  },
706
743
  every: (operation: ComputedProjectionOperation): ComputedProjectionExpression<boolean> => ({
707
744
  _tag: "relation-every",
708
- path: path as string,
745
+ path,
709
746
  operation
710
747
  }),
711
748
  distinctCount: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
@@ -715,14 +752,14 @@ export const relation = <
715
752
  operation
716
753
  ? {
717
754
  _tag: "relation-distinct-count",
718
- path: path as string,
719
- field: field as string,
755
+ path,
756
+ field,
720
757
  operation
721
758
  }
722
759
  : {
723
760
  _tag: "relation-distinct-count",
724
- path: path as string,
725
- field: field as string
761
+ path,
762
+ field
726
763
  },
727
764
  sum: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
728
765
  field: F,
@@ -731,14 +768,14 @@ export const relation = <
731
768
  operation
732
769
  ? {
733
770
  _tag: "relation-sum",
734
- path: path as string,
735
- field: field as string,
771
+ path,
772
+ field,
736
773
  operation
737
774
  }
738
775
  : {
739
776
  _tag: "relation-sum",
740
- path: path as string,
741
- field: field as string
777
+ path,
778
+ field
742
779
  },
743
780
  sumExpr: (
744
781
  expression: ComputedProjectionMathExpression,
@@ -747,13 +784,13 @@ export const relation = <
747
784
  operation
748
785
  ? {
749
786
  _tag: "relation-sum-expr",
750
- path: path as string,
787
+ path,
751
788
  expression,
752
789
  operation
753
790
  }
754
791
  : {
755
792
  _tag: "relation-sum-expr",
756
- path: path as string,
793
+ path,
757
794
  expression
758
795
  },
759
796
  sumExprBy: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
@@ -766,16 +803,16 @@ export const relation = <
766
803
  operation
767
804
  ? {
768
805
  _tag: "relation-sum-expr-by",
769
- path: path as string,
806
+ path,
770
807
  expression,
771
- unit: options.unit as string,
808
+ unit: options.unit,
772
809
  operation
773
810
  }
774
811
  : {
775
812
  _tag: "relation-sum-expr-by",
776
- path: path as string,
813
+ path,
777
814
  expression,
778
- unit: options.unit as string
815
+ unit: options.unit
779
816
  },
780
817
  sumExprNormalized: (
781
818
  expression: ComputedProjectionMathExpression,
@@ -789,18 +826,18 @@ export const relation = <
789
826
  operation
790
827
  ? {
791
828
  _tag: "relation-sum-expr-normalized",
792
- path: path as string,
829
+ path,
793
830
  expression,
794
- unit: options.unit as string,
831
+ unit: options.unit,
795
832
  toBase: options.toBase,
796
833
  factors: options.factors,
797
834
  operation
798
835
  }
799
836
  : {
800
837
  _tag: "relation-sum-expr-normalized",
801
- path: path as string,
838
+ path,
802
839
  expression,
803
- unit: options.unit as string,
840
+ unit: options.unit,
804
841
  toBase: options.toBase,
805
842
  factors: options.factors
806
843
  },
@@ -811,15 +848,15 @@ export const relation = <
811
848
  operation
812
849
  ? {
813
850
  _tag: "relation-collect",
814
- path: path as string,
815
- field: field as string,
851
+ path,
852
+ field,
816
853
  distinct: false,
817
854
  operation
818
855
  }
819
856
  : {
820
857
  _tag: "relation-collect",
821
- path: path as string,
822
- field: field as string,
858
+ path,
859
+ field,
823
860
  distinct: false
824
861
  },
825
862
  collectDistinct: <const F extends FieldPath<RelationElement<TFieldValues, P>>>(
@@ -829,15 +866,15 @@ export const relation = <
829
866
  operation
830
867
  ? {
831
868
  _tag: "relation-collect",
832
- path: path as string,
833
- field: field as string,
869
+ path,
870
+ field,
834
871
  distinct: true,
835
872
  operation
836
873
  }
837
874
  : {
838
875
  _tag: "relation-collect",
839
- path: path as string,
840
- field: field as string,
876
+ path,
877
+ field,
841
878
  distinct: true
842
879
  },
843
880
  collectFields: <const F extends readonly FieldPath<RelationElement<TFieldValues, P>>[]>(
@@ -849,15 +886,15 @@ export const relation = <
849
886
  operation
850
887
  ? {
851
888
  _tag: "relation-collect-fields",
852
- path: path as string,
853
- fields: fields as readonly string[],
889
+ path,
890
+ fields,
854
891
  distinct: false,
855
892
  operation
856
893
  }
857
894
  : {
858
895
  _tag: "relation-collect-fields",
859
- path: path as string,
860
- fields: fields as readonly string[],
896
+ path,
897
+ fields,
861
898
  distinct: false
862
899
  },
863
900
  collectDistinctFields: <const F extends readonly FieldPath<RelationElement<TFieldValues, P>>[]>(
@@ -869,15 +906,15 @@ export const relation = <
869
906
  operation
870
907
  ? {
871
908
  _tag: "relation-collect-fields",
872
- path: path as string,
873
- fields: fields as readonly string[],
909
+ path,
910
+ fields,
874
911
  distinct: true,
875
912
  operation
876
913
  }
877
914
  : {
878
915
  _tag: "relation-collect-fields",
879
- path: path as string,
880
- fields: fields as readonly string[],
916
+ path,
917
+ fields,
881
918
  distinct: true
882
919
  }
883
920
  })
@@ -893,7 +930,7 @@ export const relation = <
893
930
  export const expr = {
894
931
  field: <T extends FieldValues = FieldValues>(
895
932
  field: FieldPath<T>
896
- ): ComputedProjectionMathExpression => ({ _tag: "field", field: field as string }),
933
+ ): ComputedProjectionMathExpression => ({ _tag: "field", field }),
897
934
  mul: (
898
935
  left: ComputedProjectionMathExpression,
899
936
  right: ComputedProjectionMathExpression
@@ -1022,7 +1059,7 @@ export const projectComputed: {
1022
1059
  const computedProjection = typeof mapOrBuild === "function"
1023
1060
  ? mapOrBuild(makeComputedHelpers())
1024
1061
  : mapOrBuild
1025
- return new Project({ current, schema, mode, computed: computedProjection } as any)
1062
+ return new Project({ current, schema, mode, computed: computedProjection })
1026
1063
  }
1027
1064
 
1028
1065
  /**
@@ -1040,12 +1077,12 @@ export interface AggBuilder<TFieldValues extends FieldValues> {
1040
1077
  }
1041
1078
 
1042
1079
  const makeAggBuilder = <TFieldValues extends FieldValues>(): AggBuilder<TFieldValues> => ({
1043
- field: (path) => ({ _tag: "agg-field", path: path as string }),
1080
+ field: (path) => ({ _tag: "agg-field", path }),
1044
1081
  count: () => ({ _tag: "agg-count" }),
1045
1082
  countWhen: (operation) => ({ _tag: "agg-count-when", operation }),
1046
- sum: (field) => ({ _tag: "agg-sum", field: field as string }),
1047
- min: (field) => ({ _tag: "agg-min", field: field as string }),
1048
- 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 })
1049
1086
  })
1050
1087
 
1051
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/ids.ts CHANGED
@@ -28,7 +28,7 @@ export const RequestId = extendM(
28
28
  function make(input: string, options?: S.MakeOptions): NonEmptyString255
29
29
  function make(input?: string, options?: S.MakeOptions): NonEmptyString255 {
30
30
  const id = input === undefined ? StringId.make() : StringId.make(input, options)
31
- return id as NonEmptyString255
31
+ return id
32
32
  }
33
33
  return ({
34
34
  make,
package/tsconfig.json CHANGED
@@ -14,7 +14,12 @@
14
14
  "isolatedModules": true,
15
15
  "esModuleInterop": true,
16
16
  "skipLibCheck": true,
17
- "plugins": [],
17
+ "plugins": [
18
+ {
19
+ "name": "@effect/language-service",
20
+ "diagnostics": false
21
+ }
22
+ ],
18
23
  "module": "Node16",
19
24
  "lib": [
20
25
  "ES2023"