Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better typing for payload #113

Closed
d-exclaimation opened this issue Dec 20, 2022 · 1 comment · Fixed by #115
Closed

Better typing for payload #113

d-exclaimation opened this issue Dec 20, 2022 · 1 comment · Fixed by #115
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@d-exclaimation
Copy link
Owner

Is your feature request related to a problem? Please describe.
It's not a pleasant experience having to work with Map for the WebSocket payload, especially if the user already know what to expect.

Describe the solution you'd like
2 approach:

  • Allow user to specify what type they are expecting which might require a breaking change
  • Extends Map with functionalities to be parsed to other types
@d-exclaimation d-exclaimation added the enhancement New feature or request label Dec 20, 2022
@d-exclaimation d-exclaimation added this to the Version 1 milestone Dec 20, 2022
@d-exclaimation d-exclaimation self-assigned this Dec 20, 2022
@d-exclaimation
Copy link
Owner Author

d-exclaimation commented Dec 21, 2022

A draft on how I could do the second approach:

import enum GraphQL.Map
import class JSONEncoder
import class JSONDecoder

extension Map {
    public func into<T: Decodable>(_ dataType: T.Type) throws -> T {
        let data = try JSONEncoder().encode(self)
        return try JSONDecoder().decode(dataType, from: data)
    }
}


// ...

server.vaporMiddleware(
    websocketContext: { req, payload, gql in
        let myPayload = payload.into(MyPayload.self)
        // do something with it
    }
)

With this I can have somewhat implement the first with

public typealias VaporCustomWebSocketContext<P: Decodable> = @Sendable (Request, P, GraphQLRequest) async throws -> Context

public typealias VaporCustomWebSocketGuard<P: Decodable> = @Sendable (Request, P) async throws -> Void

public func vaporMiddleware<CustomPayload: Decodable>(
    ...,
    websocketContext: VaporCustomWebSocketContext<CustomPayload>,
    websocketGuard: VaporCustomWebSocketGuard<CustomPayload>
) -> VaporGraphQLMiddleware {
    vaporMiddleware(
        ...,
        websocketContext: { req, payload, gql in 
            let custom = payload.into(CustomPayload.self) 
            return try await websocketContext(req, custom, gql)
        },
        websocketGuard: { req, payload in 
            let custom = payload.into(CustomPayload.self) 
            return try await websocketGuard(req, custom)
        }
    )
}

I am not particularly a big fan of the above, as I feel if I were to do the first, I need to somewhat rewrite the WebSocket client so that it doesn't have to re-parse the payload for each websocket operation, maybe that advantage of the websocket guard to compute the payload object.

I think the best way is to implement the Map.into(_) first and later see if I can do the first without adding breaking changes

@d-exclaimation d-exclaimation linked a pull request Dec 22, 2022 that will close this issue
d-exclaimation added a commit that referenced this issue Dec 22, 2022
`Map.decode(_)` and Documentation fixed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

1 participant