@@ -13,33 +13,34 @@ extension Queries {
1313 /// The upstream query to transform
1414 let base : Base
1515 /// The transform to apply to the output
16- let transform : @Sendable ( Base . Output) throws -> Output
16+ let transform : @Sendable ( Base . Input , Base . Output) throws -> Output
1717
1818 public func execute( with input: Base . Input ) async throws -> Output {
19- try await transform ( base. execute ( with: input) )
19+ try await transform ( input , base. execute ( with: input) )
2020 }
2121
2222 public func observe( with input: Base . Input ) -> any QueryObservation < Output > {
23- return Observation ( base: base. observe ( with: input) , transform: transform)
23+ return Observation ( base: base. observe ( with: input) , input : input , transform: transform)
2424 }
2525
2626 struct Observation : QueryObservation {
2727 let base : any QueryObservation < Base . Output >
28+ let input : Base . Input
2829 /// The transform to apply to the output
29- let transform : @Sendable ( Base . Output) throws -> Output
30+ let transform : @Sendable ( Base . Input , Base . Output) throws -> Output
3031
3132 func start(
3233 onChange: @escaping @Sendable ( Output ) -> Void ,
33- onError : @escaping @Sendable ( any Error ) -> Void
34+ onComplete : @escaping @Sendable ( Error ? ) -> Void
3435 ) {
3536 base. start { upstream in
3637 do {
37- try onChange ( transform ( upstream) )
38+ try onChange ( transform ( input , upstream) )
3839 } catch {
39- onError ( error)
40+ onComplete ( error)
4041 }
41- } onError : { error in
42- onError ( error)
42+ } onComplete : { error in
43+ onComplete ( error)
4344 }
4445 }
4546
@@ -67,7 +68,7 @@ extension Queries.Map: DatabaseQuery where Base: DatabaseQuery {
6768 with input: Base . Input ,
6869 tx: borrowing Transaction
6970 ) throws -> Output {
70- return try transform ( base. execute ( with: input, tx: tx) )
71+ return try transform ( input , base. execute ( with: input, tx: tx) )
7172 }
7273}
7374
@@ -79,20 +80,43 @@ public extension Query {
7980 func map< NewOutput> (
8081 _ transform: @Sendable @escaping ( Output) throws -> NewOutput
8182 ) -> Queries . Map < Self , NewOutput > {
82- return Queries . Map ( base: self , transform : transform)
83+ return Queries . Map ( base: self ) { _ , entity in try transform ( entity ) }
8384 }
8485
8586
86- /// If a `nil` value is returned from the query, then a `FeatherError.entityWasNotFound`
87- /// will be thrown instead.
87+ /// If a `nil` value is returned from the query, then an will throw an error.
8888 ///
89+ /// The input closure for the error takes the `input` as a parameter.
90+ /// This allows for less ambiguous erros to be thrown by passing an id
91+ /// or any other identifying information.
92+ ///
93+ /// ```swift
94+ /// query.throwIfNotFound { id in NotFound(id: id) }
95+ /// ```
96+ ///
97+ /// If the `error` is `nil` then it will default to a `entityNotFound` erro
98+ /// to be thrown.
99+ ///
100+ /// - Parameter error: A closure to construct the error to be thrown.
89101 /// - Returns: A query with a non optional result type, that will throw in case of an error.
90- func throwIfNotFound< Wrapped> ( ) -> Queries . Map < Self , Wrapped > where Output == Wrapped ? {
91- return Queries . Map ( base: self ) { entity in
92- guard let entity else {
93- throw FeatherError . entityWasNotFound
94- }
95-
102+ func throwIfNotFound< Wrapped> (
103+ _ error: ( @Sendable ( Input ) -> Error ) ? = nil
104+ ) -> Queries . Map < Self , Wrapped > where Output == Wrapped ? {
105+ return Queries . Map ( base: self ) { input, entity in
106+ guard let entity else { throw error ? ( input) ?? FeatherError . entityWasNotFound }
107+ return entity
108+ }
109+ }
110+
111+ /// If a `nil` value is returned from the query, then an will throw an error.
112+ ///
113+ /// - Parameter error: The error to throw if `nil`
114+ /// - Returns: A query with a non optional result type, that will throw in case of an error.
115+ func throwIfNotFound< Wrapped> (
116+ _ error: @Sendable @autoclosure @escaping ( ) -> Error
117+ ) -> Queries . Map < Self , Wrapped > where Output == Wrapped ? {
118+ return Queries . Map ( base: self ) { input, entity in
119+ guard let entity else { throw error ( ) }
96120 return entity
97121 }
98122 }
@@ -107,7 +131,7 @@ public extension Query {
107131 func replaceNil< Wrapped> (
108132 with value: @Sendable @autoclosure @escaping ( ) -> Wrapped
109133 ) -> Queries . Map < Self , Wrapped > where Output == Wrapped ? {
110- return Queries . Map ( base: self ) { entity in
134+ return Queries . Map ( base: self ) { _ , entity in
111135 return entity ?? value ( )
112136 }
113137 }
0 commit comments