RFC: Implement graphql.persisted
as a stand-in value for persisted documents
#77
Labels
future 🔮
An enhancement or feature proposal that will be addressed after the next release
Summary
Currently, persisted documents are mainly achieved using two methods:
In both situations, a “manifest” is often created that contains a mapping of document IDs to GraphQL document strings (
Record<string, string>
) that can then be consumed by server-side GraphQL APIs.The latter method is often preferred in situations where GraphQL documents must compile away for security and/or obscurity purposes. When only a limited number of GraphQL documents are accepted by the API, compiling them away and keeping them out of the source reduces request payload sizes and keeps the usage of GraphQL completely private.
(This basically turns GraphQL into RPCs)
Proposed Solution
Currently,
gql.tada
sees being a runtime tool as a benefit, and compilation tools are complex to maintain and complicated tasks, like replacing allgraphql()
calls with shallow ASTs is potentially not as maintainable.Instead, we're envisioning a stand-in function to be a transparent way to integrate persisted documents.
A stand-in call would look like the following:
The
graphql.persisted
call accepts a GraphQL document as a generic and accepts a document ID as its only argument.During runtime the call returns a faux GraphQL document:
This means that:
graphql.persisted
only outputs a persisted document — not a full GraphQL document ASTquery
in our example above)query
(and all fragments it depends on) compile away, since the calls are side-effect free and are not referred to in JS values (as long as they're not part of other side-effects or assigned to other values)This has the advantage of leveraging tree-shaking for compilation, and lets users transparently assign document IDs to queries.
Non-handwritten Document IDs
Since, most commonly, documents use hashes in their IDs, GraphQLSP (and a future CLI, See #76) would be tasked to suggest replacing and/or updating the argument with a hash instead.
Requirements
graphql.persisted
call must transparently take on the type that it's passed by the generic, an act like a full documentgraphql.persisted
call must validate that the generic is a GraphQL operation document and that it receives a document ID literal{ kind: 'Document', definitions: [], documentId: string }
, wheredefinitions
is always an empty arrayExternal tasks
SHA256
)Furthermore the CLI must allow a manifest to be exported that contains a mapping of document IDs to document strings.
query
is passed to the call, e.g.typeof query
could be replaced byqueryType
(Type checker traversal needed)documentId
argument is passed i.e. if it's passed via a separate variable or property-access/import (Type checker traversal needed)Considerations
graphql.persisted
call is used. TBDdocumentId
property out-of-the-box from the faux-AST-object to send a persisted callThe text was updated successfully, but these errors were encountered: