@effect-app/infra 4.0.0-beta.305 → 4.0.0-beta.306
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.
- package/CHANGELOG.md +8 -0
- package/package.json +2 -2
- package/test/query.test.ts +96 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @effect-app/infra
|
|
2
2
|
|
|
3
|
+
## 4.0.0-beta.306
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0fe925d: Tag-aware `ProjectableFromDomain` for `projectComputed`: projection Encoded fields must exist on the matching domain tagged state (or be computed). Prevents Overview.List SchemaErrors when cancel states omit workflow lock fields like `activeRequest`.
|
|
8
|
+
- Updated dependencies [0fe925d]
|
|
9
|
+
- effect-app@4.0.0-beta.306
|
|
10
|
+
|
|
3
11
|
## 4.0.0-beta.305
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-app/infra",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.306",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"proper-lockfile": "^4.1.2",
|
|
16
16
|
"pure-rand": "8.4.0",
|
|
17
17
|
"query-string": "^9.4.0",
|
|
18
|
-
"effect-app": "4.0.0-beta.
|
|
18
|
+
"effect-app": "4.0.0-beta.306"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@azure/cosmos": "^4.9.3",
|
package/test/query.test.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import * as Context from "effect-app/Context"
|
|
5
5
|
import * as Effect from "effect-app/Effect"
|
|
6
6
|
import * as Layer from "effect-app/Layer"
|
|
7
|
-
import { and, computed, count, expr, make, one, or, order, page, project, projectComputed, type QueryEnd, type QueryProjection, type QueryWhere, relation, toFilter, where } from "effect-app/Model/query"
|
|
7
|
+
import { and, computed, count, expr, make, one, or, order, page, project, type ProjectableFromDomain, projectComputed, type QueryEnd, type QueryProjection, type QueryWhere, relation, toFilter, where } from "effect-app/Model/query"
|
|
8
8
|
import { makeRepo } from "effect-app/Model/Repository"
|
|
9
9
|
import { RepositoryRegistryLive } from "effect-app/Model/Repository/Registry"
|
|
10
10
|
import * as Option from "effect-app/Option"
|
|
@@ -662,9 +662,11 @@ it("projectComputed constrains projection schema to encoded repo fields and comp
|
|
|
662
662
|
)
|
|
663
663
|
|
|
664
664
|
make<Encoded>().pipe(
|
|
665
|
+
// @ts-expect-error missingField is neither an encoded repo field nor a computed projection
|
|
665
666
|
projectComputed(S.Struct({ missingField: S.String }), computed({}))
|
|
666
667
|
)
|
|
667
668
|
|
|
669
|
+
// Key presence only (not Encoded value types) — name: number is still projectable.
|
|
668
670
|
make<Encoded>().pipe(
|
|
669
671
|
projectComputed(
|
|
670
672
|
S.Struct({ name: S.Number }),
|
|
@@ -672,6 +674,8 @@ it("projectComputed constrains projection schema to encoded repo fields and comp
|
|
|
672
674
|
)
|
|
673
675
|
)
|
|
674
676
|
|
|
677
|
+
// Computed field *value* types are not yet constrained against the expression
|
|
678
|
+
// result (only key presence). Keeping this as a documentation call site.
|
|
675
679
|
make<Encoded>().pipe(
|
|
676
680
|
projectComputed(
|
|
677
681
|
S.Struct({ itemCount: S.String }),
|
|
@@ -737,12 +741,103 @@ it("projectComputed supports union projection schemas", () => {
|
|
|
737
741
|
])
|
|
738
742
|
})
|
|
739
743
|
|
|
744
|
+
/**
|
|
745
|
+
* MACS-SCANNER-API-KS class of bug: domain cancel omits pack/print ownership
|
|
746
|
+
* (`activeRequest`); a hand-built overview projection that still requires it on
|
|
747
|
+
* every branch must fail at the `projectComputed` call site, not in prod decode.
|
|
748
|
+
*/
|
|
749
|
+
it("projectComputed rejects state-owned fields required on the wrong tagged branch", () => {
|
|
750
|
+
const domain = S.Union([
|
|
751
|
+
S.Struct({
|
|
752
|
+
_tag: S.Literal("packing"),
|
|
753
|
+
id: S.String,
|
|
754
|
+
activeRequest: S.NullOr(S.String),
|
|
755
|
+
items: S.Array(S.Struct({ articleId: S.String }))
|
|
756
|
+
}),
|
|
757
|
+
S.Struct({
|
|
758
|
+
_tag: S.Literal("cancelled"),
|
|
759
|
+
id: S.String,
|
|
760
|
+
items: S.Array(S.Struct({ articleId: S.String }))
|
|
761
|
+
})
|
|
762
|
+
])
|
|
763
|
+
type DomainEnc = S.Codec.Encoded<typeof domain>
|
|
764
|
+
|
|
765
|
+
// Good: activeRequest only on packing; cancel omits it; articleCount is computed.
|
|
766
|
+
make<DomainEnc>().pipe(
|
|
767
|
+
projectComputed(
|
|
768
|
+
S.Union([
|
|
769
|
+
S.Struct({
|
|
770
|
+
_tag: S.Literal("packing"),
|
|
771
|
+
id: S.String,
|
|
772
|
+
activeRequest: S.NullOr(S.String),
|
|
773
|
+
articleCount: S.Number
|
|
774
|
+
}),
|
|
775
|
+
S.Struct({
|
|
776
|
+
_tag: S.Literal("cancelled"),
|
|
777
|
+
id: S.String,
|
|
778
|
+
articleCount: S.Number
|
|
779
|
+
})
|
|
780
|
+
]),
|
|
781
|
+
computed({
|
|
782
|
+
articleCount: relation<DomainEnc>("items").count()
|
|
783
|
+
})
|
|
784
|
+
)
|
|
785
|
+
)
|
|
786
|
+
|
|
787
|
+
make<DomainEnc>().pipe(
|
|
788
|
+
projectComputed(
|
|
789
|
+
S.Union([
|
|
790
|
+
S.Struct({
|
|
791
|
+
_tag: S.Literal("packing"),
|
|
792
|
+
id: S.String,
|
|
793
|
+
activeRequest: S.NullOr(S.String),
|
|
794
|
+
articleCount: S.Number
|
|
795
|
+
}),
|
|
796
|
+
S.Struct({
|
|
797
|
+
_tag: S.Literal("cancelled"),
|
|
798
|
+
id: S.String,
|
|
799
|
+
activeRequest: S.NullOr(S.String),
|
|
800
|
+
articleCount: S.Number
|
|
801
|
+
})
|
|
802
|
+
]),
|
|
803
|
+
// @ts-expect-error activeRequest is not on domain cancelled — cannot project it there
|
|
804
|
+
computed({
|
|
805
|
+
articleCount: relation<DomainEnc>("items").count()
|
|
806
|
+
})
|
|
807
|
+
)
|
|
808
|
+
)
|
|
809
|
+
})
|
|
810
|
+
|
|
811
|
+
it("ProjectableFromDomain distributes over tagged union Encoded", () => {
|
|
812
|
+
type DomainEnc =
|
|
813
|
+
| { readonly _tag: "packing"; readonly id: string; readonly activeRequest: string | null }
|
|
814
|
+
| { readonly _tag: "cancelled"; readonly id: string }
|
|
815
|
+
|
|
816
|
+
type Good =
|
|
817
|
+
| { readonly _tag: "packing"; readonly id: string; readonly activeRequest: string | null; readonly n: number }
|
|
818
|
+
| { readonly _tag: "cancelled"; readonly id: string; readonly n: number }
|
|
819
|
+
|
|
820
|
+
type Bad =
|
|
821
|
+
| { readonly _tag: "packing"; readonly id: string; readonly activeRequest: string | null }
|
|
822
|
+
| { readonly _tag: "cancelled"; readonly id: string; readonly activeRequest: string | null }
|
|
823
|
+
|
|
824
|
+
type GoodCheck = ProjectableFromDomain<Good, DomainEnc, "n">
|
|
825
|
+
type BadCheck = ProjectableFromDomain<Bad, DomainEnc>
|
|
826
|
+
|
|
827
|
+
const _good: GoodCheck = undefined as unknown
|
|
828
|
+
// @ts-expect-error cancelled branch requires activeRequest not present on domain cancelled
|
|
829
|
+
const _bad: BadCheck = undefined as unknown
|
|
830
|
+
void _good
|
|
831
|
+
void _bad
|
|
832
|
+
})
|
|
833
|
+
|
|
740
834
|
it("projection schema with computed fields fails without computed map", () => {
|
|
741
835
|
const baseSchema = S.Struct({
|
|
742
836
|
id: S.String,
|
|
743
837
|
items: S.Array(S.Struct({ value: S.Number }))
|
|
744
838
|
})
|
|
745
839
|
const query = make<S.Codec.Encoded<typeof baseSchema>>().pipe(
|
|
840
|
+
// @ts-expect-error missing computed keys are rejected; also not projectable from domain alone
|
|
746
841
|
projectComputed(S.Struct({ pickedCount: S.NonNegativeInt }), computed({}))
|
|
747
842
|
)
|
|
748
843
|
expect(() => toFilter(query, baseSchema)).toThrowError("Missing computed projections for schema keys")
|