Atualmente, se quisermos usar o cache HTTP no GraphQL, devemos usar um servidor GraphQL que suporte consultas persistentes. Isso ocorre porque a consulta persistente já terá a consulta GraphQL armazenada no servidor; como tal, não precisamos fornecer essas informações em nossa solicitação.

Para que os servidores GraphQL também ofereçam suporte ao cache HTTP por meio de um único endpoint , a consulta GraphQL deve ser fornecido como um parâmetro de URL. Esperamos que a especificação GraphQL sobre HTTP atinja esse objetivo, fornecendo uma linguagem padronizada para todos os clientes, servidores e bibliotecas GraphQL para interagir uns com os outros.

Suspeito, porém, que todas as tentativas de passar uma consulta GraphQL por meio de um parâmetro de URL estarão longe do ideal. Isso ocorre porque um parâmetro de URL deve ser fornecido como um valor de linha única, então a consulta precisará ser codificada ou reformatada, dificultando a compreensão (para nós, humanos, não para máquinas).

Por exemplo, esta é a aparência de uma consulta GraphQL ao substituir todas as quebras de linha por espaços para caber em uma única linha:

 {posts (limite: 5) {id title @titleCase excerpt @default (valor:"Sem título", condição: IS_EMPTY) autor {nome} marcações {id nome} comentários (limite: 3, ordem:"data | DESC") {id data (formato:"d/m/Y") autor {nome} conteúdo}}}

Você consegue entender isso? Eu também não.

E é assim que o cliente GraphiQL codifica a consulta simples {posts {id title}} como um parâmetro de URL:

% 7B% 0A% 20% 20posts% 20% 7B% 0A% 20% 20% 20% 20id% 0A% 20% 20% 20% 20title% 0A% 20% 20% 7D% 0A% 7D

Mais uma vez, não sabemos o que está acontecendo aqui.

Ambos os exemplos evidenciam o problema: consultas GraphQL de uma linha podem funcionar do ponto de vista técnico, transmitindo as informações para o servidor, mas não é fácil para as pessoas lerem e escreverem essas consultas.

Ser capaz de operar com consultas de uma única linha teria muitos benefícios. Por exemplo, poderíamos compor a consulta diretamente na barra de endereço do navegador, dispensando a necessidade de algum cliente GraphQL.

Não é que eu não goste de clientes GraphQL-na verdade, eu amo GraphiQL. Mas não gosto da ideia de depender deles.

Em outras palavras, podemos nos beneficiar de uma sintaxe de consulta que permite às pessoas:

  • Escreva uma consulta diretamente em uma única linha
  • Compreenda rapidamente a consulta de uma linha

Este é um desafio formidável. Mas não é intransponível.

Neste artigo, apresentarei uma sintaxe alternativa, que permite ser “fácil de ler e escrever em uma única linha” por nós, humanos.

Na verdade, não estou propondo a introdução dessa sintaxe no GraphQL-entendo que isso nunca aconteceria. Mas o processo de design para esta sintaxe pode, no entanto, exemplificar o que devemos prestar atenção ao projetar a especificação GraphQL sobre HTTP.

Por que a sintaxe GraphQL é tão difícil de entender em uma única linha?

Vamos primeiro explorar qual é o problema com a sintaxe GraphQL e, em seguida, generalizá-la para outras sintaxes.

Identificando o problema

A meu ver, a dificuldade vem dos campos em uma consulta GraphQL sendo aninhados, em que o aninhamento pode avançar e retroceder ao longo da consulta. É esse comportamento de vaivém que o torna difícil de entender quando escrito em uma única linha.

Se o aninhamento na consulta apenas avançar, não será tão difícil entendê-lo. Faça esta consulta, por exemplo:

 { Postagens { eu ia título excerto comentários { eu ia data contente autor { eu ia nome url Postagens { eu ia título } } } }
}

Aqui, o aninhamento apenas prossegue:

Código de aninhamento está se movendo Avançar
Consulta GraphQL, apenas avançando.

Ao examinar a consulta sempre progressiva e digitalizá-la da esquerda para a direita, ainda podemos entender a qual entidade cada campo pertence:

 {posts {comentários do excerto do título do id {autor do conteúdo da data do id {post do url do nome do id {título do id}}}}}

Agora, considere a mesma consulta GraphQL, mas reorganizando os campos para que as folhas apareçam após as conexões:

 { Postagens { eu ia comentários { eu ia data autor { Postagens { eu ia título } eu ia nome url } contente } título excerto }
}

Nesse caso, podemos dizer que os campos avançam e também recuam:

O código GraphQL começa a avançar e depois começa a retroceder
Consulta GraphQL, avançando e retrocedendo.

Esta consulta pode ser escrita em uma única linha, como esta:

 {posts {id comentários {id data autor {posts {id title} id nome url} conteúdo} excerto do título}}

Agora, entender a consulta não é mais tão fácil. Depois de um nível de recuo (ou seja, logo após uma conexão), podemos não lembrar qual entidade veio antes dela, então não saberemos onde o campo pertence:

Código GraphQL escrito em uma única linha
A qual entidade esses campos pertencem?

(Acho que isso está relacionado ao cérebro humano ter uma memória de curto prazo limitada, capaz de manter não mais do que um alguns itens de cada vez.)

E quando há muitos níveis de avanço e retrocesso, torna-se quase impossível compreendê-lo totalmente. Esta consulta é compreensível:

 { Postagens { eu ia comentários { eu ia data crianças { eu ia autor { nome url } contente } autor { Postagens { eu ia título Tag { nome } } eu ia nome amigos { eu ia nome } url } contente } título excerto } autor { nome }
}

Mas não há como entendermos seu equivalente de linha única:

 {posts {id comentários {id data filhos {id autor {name url} conteúdo} autor {posts {id title tags {name}} id name friends {id name} url} content} title excerpt} author {name} }

Em conclusão, as consultas GraphQL não podem ser facilmente representadas em uma única linha, de forma que nós, humanos, possamos entendê-las, devido ao seu comportamento de aninhamento.

Generalizando o problema

O problema não é específico do GraphQL. Na verdade, isso acontecerá com uma sintaxe-qualquer sintaxe-onde os elementos avançam e recuam.

Pegue JSON, por exemplo:

 { "nome":"leoloso/PoP", "descrição":"PoP monorepo", "repositórios": [ { "tipo":"pacote", "pacote": { "nome":"leoloso-pop-api-wp/newsletter-subscriptions-rest-endpoints", "version":"master", "tipo":"plugin-wordpress", "fonte": { "url":"https://gist.github.com/leoloso/6588f6c1bdcce82fc317052616d3dfb4", "type":"git", "referência":"mestre" } } }, { "tipo":"pacote", "pacote": { "nome":"leoloso-pop-api-wp/disable-user-edit-profile", "versão":"0.1.1", "tipo":"plugin-wordpress", "fonte": { "url":"https://gist.github.com/leoloso/4e367eb8d8014a7aa7580567608bd5b4", "type":"git", "referência":"mestre" } } }, { "tipo":"vcs", "url":"https://github.com/leoloso/wp-muplugin-loader.git" } ], "estabilidade mínima":"dev", "prefer-stable": verdadeiro, "requer": { "php":"~ 8.0", "getpop/api-rest":"dev-master", "getpop/engine-wp-bootloader":"dev-master" }, "extra": { "branch-alias": { "dev-master":"1.0-dev" }, "tipos de instalador": [ "cliente-gráfico", "graphql-voyager" ], "caminhos do instalador": { "wordpress/wp-content/mu-plugins/{$ name}/": [ "tipo: wordpress-muplugin" ], "wordpress/wp-content/plugins/{$ name}/": [ "type: wordpress-plugin", "getpop/engine-wp-bootloader" ] } }, "config": { "sort-packages": verdadeiro }
}

Convertê-lo em uma única linha torna muito difícil de compreender:

 {"nome":"leoloso/PoP","descrição":"PoP monorepo","repositórios": [{"tipo":"pacote","pacote": {"nome":"leoloso-pop-api-wp/newsletter-subscriptions-rest-endpoints","version":"master","type":"wordpress-plugin","source": {"url":"https://gist.github. com/leoloso/6588f6c1bdcce82fc317052616d3dfb4","type":"git","reference":"master"}}}, {"type":"package","package": {"name":"leoloso-pop-api-wp/disable-user-edit-profile","version":"0.1.1","type":"wordpress-plugin","source": {"url":"https://gist.github. com/leoloso/4e367eb8d8014a7aa7580567608bd5b4","type":"git","reference":"master"}}}, {"type":"vcs","url":"https://github.com/leoloso/wp-muplugin-loader.git"}],"minimum-stable":"dev","prefer-stable": true,"require": {"php":"~ 8.0","getpop/api-rest":"dev-master","getpop/engine-wp-bootloader":"dev-master"},"extra": {"branch-alias": {"dev-master":"1.0-dev"},"installer-types": ["graphiql-client","graphql-voyager"],"installer-caminhos": {"wordpress/wp-content/mu-plugins/{$ name}/": ["type: wordpress-muplugin"],"wordpress/wp-content/plugins/{$ name}/": ["type: wordpress-plugin","getpop/engine-wp-bootloader"]}},"config": {"sort-packages": true}}

Além do mais, quando a sintaxe usa espaçamento para aninhar seus elementos, nem será possível escrevê-la em uma única linha.

Esse é o caso, por exemplo, com YAML:

 serviços: _defaults: public: true autowire: true autoconfigure: true PoP \ API \ PersistedQueries \ PersistedQueryManagerInterface: classe: \ PoP \ API \ PersistedQueries \ PersistedQueryManager # Substituir o serviço PoP \ ComponentModel \ Schema \ FieldQueryInterpreterInterface: classe: \ PoP \ API \ Schema \ FieldQueryInterpreter PoP \ API \ Hooks \: recurso:'../src/Hooks/*'

Projetando uma sintaxe de consulta diferente

Descreverei o design de uma alternativa à sintaxe GraphQL: a sintaxe PQL , usado por GraphQL por PoP (o servidor GraphQL em PHP que eu criei) para aceitar consultas baseadas em URL passadas via GET .

Uma vez que o problema com a sintaxe GraphQL surge da retirada de campos aninhados, a solução parece evidente: o fluxo da consulta deve ser sempre para a frente.

Como o PQL consegue isso? Para demonstrar, vamos explorar a sintaxe PQL.

Sintaxe de campo

No GraphQL, um campo é escrito assim:

 { alias: fieldName (fieldArgs) @fieldDirective (DirectiveArgs)
}

Em PQL, um campo é escrito assim:

 fieldName (fieldArgs) [@ alias] 

Portanto, é bastante semelhante, mas existem algumas diferenças:

  1. O alias não é colocado antes do campo, mas depois do campo
  2. O alias é identificado não com : , mas com @ (e, opcionalmente, cercado por [...] (para “ favoritos ”, explicado mais tarde)
  3. A diretiva não é identificada com @ , mas entre <...>

Essas diferenças estão diretamente relacionadas ao fluxo sempre avançado necessário para a consulta.

Na minha própria experiência, ao escrever consultas diretamente na barra de endereço do navegador, sempre penso na necessidade do alias depois de ter escrito o nome do campo, não antes. Portanto, usando a ordem como em GraphQL, tive que voltar para essa posição (pressionando a tecla de seta para a esquerda), adicionar o alias e voltar para a posição final (pressionando a tecla de seta para a direita).

Isso foi bastante complicado. Fazia muito mais sentido colocar o alias após o nome do campo, tornando-o um fluxo natural.

Ao definir o alias após o nome do campo, não faz mais sentido usar : . Este símbolo é usado pelo GraphQL para que a resposta JSON respeite o formato da consulta. Uma vez que a ordem entre o campo e o alias é invertida, usar @ parece um ajuste natural.

Isso, por sua vez, significava que não podíamos mais usar @ para identificar diretivas. Em vez disso, escolhi uma sintaxe envolvente <...> (por exemplo, ) para que as diretivas também possam ser aninhadas (por exemplo, > ), possibilitando que GraphQL por PoP ofereça suporte a recurso de diretivas composíveis .

Campos

No GraphQL, podemos adicionar dois ou mais campos adicionando um espaço ou quebra de linha entre eles:

 { foo bar
}

Em PQL, usamos o caractere | para separar campos:

 foo | bar

Já podemos visualizar como a consulta é composta em uma única linha:

  • Não há {} caracteres
  • Não há espaços ou quebras de linha

Também podemos apreciar que a consulta pode ser composta diretamente no navegador, passada através do parâmetro de URL query .

Por exemplo, o URL para executar a consulta id | __typename é: $ {endpoint}? query=id | __typename .

Usando DevTools, podemos ver como o cache HTTP é compatível com o ponto de extremidade único GraphQL:

Site DevTool inspecionando cache de HTTP para GraphQL
Cache HTTP para o único endpoint GraphQL.

Para todas as consultas demonstradas abaixo, haverá um link Executar consulta no navegador . Clique neles para visualizar como o PQL funciona em um site real em produção.

Fazer consultas visualmente atraentes

Semelhante ao GraphQL , novas linhas (e também espaços) não adicionam nenhum significado semântico. Assim, podemos adicionar quebras de linha de forma conveniente para ajudar a visualizar a consulta:

 foo |
bar

Ao usar o Firefox, esta consulta pode ser copiada (de um editor de texto, uma página da web, etc.) e colada na barra de endereço do navegador, e todas as quebras de linha serão removidas automaticamente, criando a consulta de linha única equivalente.

Navegador Firefox usado para remover quebras de linha e criar código de linha única
Copiar/colar consulta no Firefox.

Conexões

GraphQL usa caracteres {} para definir dados para conexões:

 { Postagens { autor { eu ia } }
}

Em PQL, a consulta apenas avança, nunca recua. Portanto, há um equivalente para {, que é . , mas não há equivalente para } , pois não será necessário.

 posts. autor. eu ia

Execute a consulta no navegador .

Podemos combinar | e . para buscar vários campos para qualquer entidade. Considere esta consulta GraphQL:

 { Postagens { eu ia título autor { eu ia nome url } }
}

Seu equivalente em PQL seria:

 posts. id | título | autor. id | nome | url

Executar consulta no navegador .

Nesse ponto, podemos enfrentar o desafio: como o PQL aceita apenas campos de avanço?

Sintaxe para um fluxo apenas de avanço

As consultas vistas acima estavam sempre avançando. Vamos agora abordar as consultas que também precisam ser retiradas, como esta consulta GraphQL:

 { Postagens { eu ia autor { eu ia nome url } comentários { eu ia contente } }
}

PQL usa o caractere , para unir elementos. É semelhante a | para unir campos, mas com uma diferença fundamental: o campo à direita de , começa a percorrer o gráfico novamente a partir da raiz.

Então, a consulta acima tem este equivalente em PQL:

 posts. id | autor. id | nome | url,
Postagens. comentários. id | contente

Executar consulta no navegador .

Observe como, para torná-lo visualmente atraente, name | e url têm o mesmo preenchimento à esquerda, já que | mantém o mesmo caminho posts.author. . Mas não há preenchimento à esquerda logo após , porque a consulta começa novamente a partir da raiz.

Podemos pensar que esta consulta também recua:

O código em PQL está avançando, depois para trás e para a frente
Avanço e retrocesso de consulta em PQL.

No entanto, isso não é tanto um recuo, mas um”reset”. No GraphQL, podemos voltar à posição anterior na consulta-ou seja, o nó pai no gráfico-quantas vezes forem os níveis inferiores que percorremos. No PQL, porém, não podemos: sempre voltamos até a raiz do gráfico.

Começando da raiz novamente, devemos mais uma vez especificar o caminho completo para o nó para continuar adicionando campos. Isso torna a consulta mais detalhada. Por exemplo, o caminho posts na consulta acima aparece uma vez no GraphQL, mas duas vezes no PQL.

Essa redundância força os humanos a recriar o caminho ao ler e escrever a consulta para cada nível do gráfico. Isso nos permite entender a consulta quando expressa em uma única linha:

 posts.id | author.id | nome | url, posts.comments.id | conteúdo

Como estamos recriando o caminho em nossas cabeças, não sofremos o problema de memória de curto prazo que nos faz perder ao olhar para a consulta GraphQL.

Marcadores para remover verbosidade

Ter que recriar todo o caminho para o nó pode se tornar um incômodo.

Considere esta consulta GraphQL:

 { Comercial { Postagens { autor { eu ia nome } comentários { eu ia contente } } }
}

E seu equivalente em PQL:

usuários

. Postagens. autor. id | nome,
Comercial. Postagens. comentários. id | contente

Executar consulta no navegador .

Para recuperar o campo comentários , novamente precisamos adicionar users.posts. . Quanto mais o nível abaixo no gráfico, mais longo o caminho para replicar.

Para resolver esse problema, o PQL apresenta um novo conceito: um”marcador”, que fornece um atalho para um caminho já percorrido para que possamos continuar carregando dados de maneira conveniente a partir desse ponto.

Definimos um favorito colocando seu nome entre [...] ao iterar por algum caminho, e então esse caminho é automaticamente recuperado ao fazer referência a seu favorito, novamente colocando seu nome entre [...] , a partir da raiz da consulta.

Na consulta acima, podemos marcar users.posts como [userposts] :

usuários

. postagens [postagens do usuário]. autor. id | nome,
[postagens do usuário]. comentários. id | contente

Execute a consulta no navegador .

Para facilitar a visualização, também podemos adicionar o preenchimento equivalente à esquerda do marcador aplicado, correspondendo ao mesmo preenchimento de seu caminho (de forma que comentários apareça abaixo de posts ):

usuários

. postagens [postagens do usuário]. autor. id | nome, [postagens do usuário]. comentários. id | contente

Com os favoritos, ainda podemos entender a consulta quando expressa em uma única linha:

 users.posts [userposts].author.id | name, [userposts].comments.id | content

Se precisarmos definir um favorito e um alias, podemos ter o símbolo @ embutido no [...] :

usuários

. posts [@userposts]. autor. id | nome, [postagens do usuário]. comments.id | contente

Executar consulta no navegador .

Simplificando os argumentos de campo

No GraphQL, os valores String em argumentos de campo devem ser colocados entre aspas "...":

 { Postagens { eu ia título data (formato:"d/m/Y") }
}

Ter que digitar essas aspas ao compor a consulta no navegador provou ser muito chato; Muitas vezes eu os esquecia e precisava navegar para a esquerda e para a direita com as teclas de seta para adicioná-los.

Portanto, em PQL, as aspas de string podem ser omitidas:

 posts. id | título | data (formato: d/m/Y)

Executar consulta no navegador .

Aspas de string são necessárias quando a consulta seria interrompida de outra forma:

 posts. id | título | data (formato:"d M, Y")

Execute a consulta no navegador .

Além disso, o argumento do campo às vezes pode ser tornado implícito; por exemplo, quando o campo tem apenas um argumento de campo. Nesse caso, o PQL permite omiti-lo:

 posts. id | título | data (d/m/A)

Executar consulta no navegador .

Variáveis ​​

No GraphQL, as variáveis ​​são definidas no corpo da solicitação como um JSON codificado:

 { "query":"query ($ format: String) { Postagens { eu ia título data (formato: $ format) } }", "variáveis":"{ \"format \": \"d/m/Y \" }"
}

Em vez disso, o PQL usa as entradas padrão HTTP, passando variáveis ​​via $ _GET ou $ _POST :

? query= Postagens. id | título | data (formato $)
& format=d/m/Y

Executar consulta no navegador .

Também podemos passar variáveis ​​nas variáveis ​​ de entrada:

? query= Postagens. id | título | data (formato $)
& variáveis ​​[formato]=d/m/Y

Execute a consulta no navegador .

Fragmentos

GraphQL emprega fragmentos para reutilizar seções de consulta:

 { Comercial { ...dados do usuário Postagens { comentários { autor { ...dados do usuário } } } }
} fragmento userData no usuário { eu ia nome url
}

Em PQL, os fragmentos seguem o mesmo método das variáveis ​​para sua definição: como entradas em $ _GET ou $ _POST . Eles são referenciados com -:

? query= Comercial. --userData | Postagens. comentários. autor. --dados do usuário
& userData= id | nome | url

Execute a consulta no navegador .

O fragmento também pode ser definido em fragmentos de entrada:

? query= Comercial. --userData | Postagens. comentários. autor. --dados do usuário
& fragmentos [userData]= id | nome | url

Execute a consulta no navegador .

Conversão de consultas entre as sintaxes GraphQL e PQL

PQL é um superconjunto da sintaxe de consulta GraphQL. Portanto, qualquer consulta escrita usando a sintaxe GraphQL padrão também pode ser escrita em PQL.

Por outro lado, nem todas as consultas escritas em PQL podem ser escritas usando a sintaxe GraphQL, porque PQL suporta recursos como campos composíveis e composíveis diretivas que não são suportadas pelo GraphQL.

PQL compreende a maioria dos mesmos elementos:

  • Campos e argumentos de campo
  • Diretivas e argumentos diretivos
  • Aliases
  • fragmentos
  • Variáveis ​​

Os elementos que não suporta são:

  • Operação
  • Nome da operação, definições de variáveis ​​e variáveis ​​padrão
  • O elemento on , para indicar em qual tipo/interface um fragmento deve ser aplicado

Mesmo que esses elementos não sejam compatíveis, sua funcionalidade subjacente é compatível por meio de um método diferente.

A operação está faltando porque não há mais necessidade dela: agora temos a opção de solicitar a consulta usando GET (para consultas) ou POST (para mutações ).

The operation name is only needed in GraphQL when the document contains many operations, and we need to specify which one to execute, or maybe execute several of them together, tying them via @export.

In the previous case, there’s no need for it for PQL — we only pass the query that must be executed, not all of them.

In the latter case, the multiple operations can be executed together in a single request, while guaranteeing their execution order, by joining them with ; like so:

posts. author. id| name| url; posts. comments. id| content

Execute query in browser.

In GraphQL, the variable definition is used to define the type of the variable, enabling clients like GraphiQL to show an error whenever the type is different. This is a nice-to-have, but not really needed for executing the query itself.

Default variable values can be defined like any variable: via a URL param.

The on element is not needed since we can instead use the directive @include, passing a composable field isType as argument, to find out the type of the object and, based on this value, apply the intended fragment or not.

For instance, take this GraphQL query:

{ customPosts { __typename ... on Post { título } }
}

This the PQL equivalent:

customPosts. __typename| title

Execute query in browser.

Converting the introspection query

Let’s convert the introspection query used by GraphiQL (and other clients) to obtain the schema metadata from the GraphQL syntax to PQL.

The introspection query is this one:

query IntrospectionQuery { __schema { queryType { nome } mutationType { nome } subscriptionType { nome } types { ...FullType } directives { nome Descrição Localizações args { ...InputValue } } }
} fragment FullType on __Type { Gentil nome Descrição fields(includeDeprecated: true) { nome Descrição args { ...InputValue } type { ...TypeRef } isDeprecated deprecationReason } inputFields { ...InputValue } interfaces { ...TypeRef } enumValues(includeDeprecated: true) { nome Descrição isDeprecated deprecationReason } possibleTypes { ...TypeRef }
} fragment InputValue on __InputValue { nome Descrição type { ...TypeRef } defaultValue
} fragment TypeRef on __Type { Gentil nome ofType { Gentil nome ofType { Gentil nome ofType { Gentil nome ofType { Gentil nome ofType { Gentil nome ofType { Gentil nome ofType { Gentil nome } } } } } } }
}

Its equivalent PQL query is this one:

?query= __schema[schema]. queryType. name, [schema]. mutationType. name, [schema]. subscriptionType. name, [schema]. types. --FullType, [schema]. directives. name| description| locations| args. --InputValue
&fragments[FullType]= kind| name| description| fields(includeDeprecated: true)[@fields]. name| description| args. --InputValue, [fields]. type. --TypeRef, [fields]. isDeprecated| deprecationReason, [fields]. inputFields. --InputValue, [fields]. interfaces. --TypeRef, [fields]. enumValues(includeDeprecated: true)@enumValues. name| description| isDeprecated| deprecationReason, [fields]. possibleTypes. --TypeRef
&fragments[InputValue]= name| description| defaultValue| type. --TypeRef
&fragments[TypeRef]= kind| name| ofType. kind| name| ofType. kind| name| ofType. kind| name| ofType. kind| name| ofType. kind| name| ofType. kind| name| ofType. kind| nome

Execute query in browser. (Note that the query in this link is slightly different than the one above since I still need to add support for the , token within fragments.)

And this is the query written in a single line:

?query=__schema[schema].queryType.name,[schema].mutationType.name,[schema].subscriptionType.name,[schema].types.--FullType,[schema].directives.name|description|locations|args.--InputValue&fragments[FullType]=kind|name|description|fields(includeDeprecated: true)[@fields].name|description|args.--InputValue,[fields].type.--TypeRef,[fields].isDeprecated|deprecationReason,[fields].inputFields.--InputValue,[fields].interfaces.--TypeRef,[fields].enumValues(includeDeprecated: true)@enumValues.name|description|isDeprecated|deprecationReason,[fields].possibleTypes.--TypeRef&fragments[InputValue]=name|description|defaultValue|type.--TypeRef&fragments[TypeRef]=kind|name|ofType.kind|name|ofType.kind|name|ofType.kind|name|ofType.kind|name|ofType.kind|name|ofType.kind|name|ofType.kind|name

Some more examples

This query has a fragment containing nested paths, variables, directives, and other fragments:

?query= posts(limit:$limit, order:$order). --postData| author. posts(limit:$limit). --postData
&postData= id| title| --nestedPostData| date(format:$format)
&nestedPostData= comments. id| content
&format=d/m/Y
&include=true
&limit=3
&order=title

Execute query in browser.

This query applies a directive to a fragment, which is consequently applied on all the fields within the fragment:

?query= posts. id| --props
&fragments[props]= title| data

Execute query in browser.

Finally, there are many examples of single-line queries embedded directly as a URL param, and containing additional properties from the PQL syntax (not described in this article), in this blog post.

Conclusion

In order to support HTTP caching, we must currently use GraphQL servers that support persisted queries.

But what about the GraphQL single endpoint? Could it also support HTTP caching? And if so, could it be done in a way that people can write the query instead of having to depend on a client or library?

The response to these questions is: yes, it can be done. However, the GraphQL syntax currently stands in the way due to its nesting behavior.

In this article I demonstrated an alternative syntax, called PQL, that would enable GraphQL servers to accept the query via the URL param, while enabling people to read and write the query in a single line, even directly in the browser’s address bar.

The post Designing a URL-based query syntax for GraphQL appeared first on LogRocket Blog.