refactor docs schema section (#3489)
@ -44,4 +44,4 @@ Follow the example at :doc:`access control basics <basics>`.
|
||||
roles-variables
|
||||
permission-rules
|
||||
common-roles-auth-examples
|
||||
|
||||
role-multiple-rules
|
||||
|
118
docs/graphql/manual/auth/authorization/role-multiple-rules.rst
Normal file
@ -0,0 +1,118 @@
|
||||
Multiple column + row permissions for the same role
|
||||
===================================================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
Use case
|
||||
--------
|
||||
|
||||
In some cases we might want to allow access to certain columns for a role only if a particular condition is met
|
||||
while allowing access to other columns based on a different condition
|
||||
i.e. have different column permissions based on different row permissions.
|
||||
|
||||
Currently it is not possible to define multiple column + row permission rules for the same role.
|
||||
|
||||
We can work around this limitation by using :ref:`views <custom_views>`.
|
||||
|
||||
**Example**
|
||||
|
||||
Let's say we have a table called ``user_info`` with columns ``(id, name, city, email, phone, address)``.
|
||||
|
||||
We want the role ``user`` to be able to access:
|
||||
|
||||
- the ``email``, ``phone`` and ``address`` columns only if the ``id`` column is the requesting user's id i.e. the current
|
||||
user is the owner of the row.
|
||||
|
||||
- the ``id``, ``name`` and ``city`` columns for all rows.
|
||||
|
||||
We can achieve this via the following steps:
|
||||
|
||||
Step 1: Create a view
|
||||
---------------------
|
||||
|
||||
Create a :ref:`view <create_views>` called ``user_private`` with columns ``(user_id, email, phone, address)``:
|
||||
|
||||
.. code-block:: SQL
|
||||
|
||||
CREATE VIEW user_private AS
|
||||
SELECT id AS user_id, email, phone, address
|
||||
FROM user_info;
|
||||
|
||||
Step 2: Create a relationship
|
||||
-----------------------------
|
||||
|
||||
For the table ``user_info``, create a :ref:`manual object relationship <create_manual_relationships>` called
|
||||
``private_info`` using ``user_info : id -> user_private : user_id``:
|
||||
|
||||
.. thumbnail:: ../../../../img/graphql/manual/auth/multiple-rules-create-manual-relationship.png
|
||||
|
||||
Step 3: Define permissions
|
||||
--------------------------
|
||||
|
||||
For the role ``user``, create the following permissions for ``select``:
|
||||
|
||||
- Table ``user_info``: allow access to ``id``, ``name`` and ``city`` without any row conditions.
|
||||
|
||||
.. thumbnail:: ../../../../img/graphql/manual/auth/multiple-rules-define-public-permissions.png
|
||||
|
||||
- View ``user_private``: allow access to ``id``, ``phone``, ``email`` and ``address`` if the ``user-id``
|
||||
passed in the session variable is equal to the row's ``user_id``.
|
||||
|
||||
.. thumbnail:: ../../../../img/graphql/manual/auth/multiple-rules-define-private-permissions.png
|
||||
|
||||
Step 4: Query with appropriate access control
|
||||
---------------------------------------------
|
||||
|
||||
Now we can fetch the required data with the appropriate access control by using the relationship.
|
||||
|
||||
If the ``X-Hasura-Role`` and the ``X-Hasura-User-Id`` session variables are set to ``user`` and ``2`` respectively, we'll get the following result:
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
query {
|
||||
user_info {
|
||||
id
|
||||
name
|
||||
city
|
||||
private_info {
|
||||
email
|
||||
phone
|
||||
address
|
||||
}
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"user_info": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Julie",
|
||||
"city": "Boston",
|
||||
"private_info": null
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Josh",
|
||||
"city": "Bangalore",
|
||||
"private_info": {
|
||||
"email": "josh@josh.com",
|
||||
"phone": "+91-9787675678",
|
||||
"address": "#141, 7th Main Road, Koramangala 3rd Block",
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "John",
|
||||
"city": "Berlin",
|
||||
"private_info": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Observe that the ``private_info`` field is returned as ``null`` for all rows without the appropriate access.
|
19
docs/graphql/manual/guides/data-modelling/index.rst
Normal file
@ -0,0 +1,19 @@
|
||||
Guides: Data modelling
|
||||
======================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
- :ref:`soft_deletes`
|
||||
- :ref:`one_to_one_modelling`
|
||||
- :ref:`one_to_many_modelling`
|
||||
- :ref:`many_to_many_modelling`
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:titlesonly:
|
||||
:hidden:
|
||||
|
||||
soft-deletes
|
@ -1,3 +1,5 @@
|
||||
.. _soft_deletes:
|
||||
|
||||
Setting up soft deletes for data
|
||||
================================
|
||||
|
||||
@ -18,7 +20,7 @@ there is a timestamp value present, the record should be treated as deleted.
|
||||
**For example:** Let's imagine that we have a simple Todo application, our ``todos`` table would resemble
|
||||
the following:
|
||||
|
||||
.. thumbnail:: ../../../img/graphql/manual/schema/soft-deletes-example-data.png
|
||||
.. thumbnail:: ../../../../img/graphql/manual/guides/soft-deletes-example-data.png
|
||||
|
||||
In this example we only have two todos, one has ``deleted_at`` with a timestamp value and the other contains a
|
||||
``null`` value. The todo with the timestamp value in ``deleted_at`` represents a deleted todo and was deleted at
|
||||
@ -72,15 +74,15 @@ Here are some typical rules we should set:
|
||||
|
||||
**Delete permissions** - remove all access
|
||||
|
||||
.. thumbnail:: ../../../img/graphql/manual/schema/soft-deletes-delete-perms.png
|
||||
.. thumbnail:: ../../../../img/graphql/manual/guides/soft-deletes-delete-perms.png
|
||||
|
||||
**Insert permissions** - remove access for inserting into ``deleted_at`` column
|
||||
|
||||
.. thumbnail:: ../../../img/graphql/manual/schema/soft-deletes-insert-perms.png
|
||||
.. thumbnail:: ../../../../img/graphql/manual/guides/soft-deletes-insert-perms.png
|
||||
|
||||
**Update permissions** - allow access for updating ``deleted_at`` column
|
||||
|
||||
.. thumbnail:: ../../../img/graphql/manual/schema/soft-deletes-update-perms.png
|
||||
.. thumbnail:: ../../../../img/graphql/manual/guides/soft-deletes-update-perms.png
|
||||
|
||||
|
||||
Step 4: Restrict access to soft-deleted records
|
||||
@ -94,7 +96,7 @@ access to the ``todos`` table.
|
||||
For example, let's say that a role ``user`` can only access non-deleted todos, we need to add the following
|
||||
permission rule to ensure this:
|
||||
|
||||
.. thumbnail:: ../../../img/graphql/manual/schema/soft-deletes-select-perms.png
|
||||
.. thumbnail:: ../../../../img/graphql/manual/guides/soft-deletes-select-perms.png
|
||||
|
||||
Now the role ``user`` can only access non-deleted ``todos``:
|
||||
|
@ -10,6 +10,7 @@ Guides / Tutorials / Resources
|
||||
:maxdepth: 2
|
||||
:titlesonly:
|
||||
|
||||
Data modelling guides <data-modelling/index>
|
||||
Deployment guides <deployment/index>
|
||||
Sample apps & boilerplates <sample-apps/index>
|
||||
Integration/migration tutorials <integrations/index>
|
||||
|
@ -326,7 +326,7 @@ A nested insert mutation is processed as follows:
|
||||
|
||||
Many-to-many relationships
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Let's say the ``articles`` has a :ref:`many-to-many relationship <many-to-many-modelling>` with the ``tags`` table via
|
||||
Let's say the ``articles`` has a :ref:`many-to-many relationship <many_to_many_modelling>` with the ``tags`` table via
|
||||
a bridge table ``article_tags``.
|
||||
|
||||
**Example:** Insert an ``article`` along with a few ``tags``.
|
||||
|
@ -15,6 +15,11 @@ The **name of the aggregate field** is of the form ``<field-name> + _aggregate``
|
||||
Common aggregation functions are ``count``, ``sum``, ``avg``, ``max``, ``min``, etc. You can see the complete
|
||||
specification of the aggregate field in the :ref:`API reference <AggregateObject>`.
|
||||
|
||||
.. note::
|
||||
|
||||
For more advanced use cases, you can use :ref:`views <custom_views>` or
|
||||
:ref:`custom SQL functions <custom_sql_functions>`.
|
||||
|
||||
Fetch aggregated data of an object
|
||||
----------------------------------
|
||||
|
||||
@ -184,4 +189,3 @@ and articles.
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,78 +0,0 @@
|
||||
Restrict access to certain fields
|
||||
=================================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
If you want to restrict access to sensitive fields in a table, you can either use views to expose only the safe fields
|
||||
or :ref:`restrict access via permissions <col-level-permissions>`.
|
||||
|
||||
The following section describes setting up a view for this purpose.
|
||||
|
||||
**For example**: Say we have a table ``user_profile (id, name, email, phone, address)``, to restrict users to
|
||||
only have access to the ``id``, ``name`` & ``email`` fields of other users, we can:
|
||||
|
||||
Step 1: Create a view
|
||||
---------------------
|
||||
Open the Hasura console and head to the ``Data -> SQL`` tab.
|
||||
|
||||
Create a view with data from only the required (or public) columns:
|
||||
|
||||
.. code-block:: SQL
|
||||
|
||||
CREATE VIEW user_public AS
|
||||
SELECT id, name, email
|
||||
FROM user_profile;
|
||||
|
||||
Step 2: Modify permissions
|
||||
--------------------------
|
||||
You will need to revoke permission (if already granted) from the source table and grant access to the newly created
|
||||
view. So, in our example, we do the following:
|
||||
|
||||
#. Remove **select** permissions from the ``user_profile`` table
|
||||
|
||||
#. Grant **select** permissions to the ``user_public`` view
|
||||
|
||||
Step 3: Query the view
|
||||
----------------------
|
||||
You can now query the newly created view like you would a regular table:
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
query {
|
||||
user_public {
|
||||
id
|
||||
name
|
||||
email
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"user_public": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Justin",
|
||||
"email": "justin@xyz.com"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Beltran",
|
||||
"email": "beltran@xyz.com"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Sidney",
|
||||
"email": "sidney@xyz.com"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Angela",
|
||||
"email": "angela@xyz.com"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -61,7 +61,4 @@ based on a typical author/article schema for reference.
|
||||
pagination
|
||||
Using multiple arguments <multiple-arguments>
|
||||
multiple-queries
|
||||
custom-functions
|
||||
derived-data
|
||||
control-access
|
||||
variables-aliases-fragments-directives
|
||||
|
@ -9,15 +9,17 @@ Computed fields
|
||||
What are computed fields?
|
||||
-------------------------
|
||||
|
||||
Computed fields are virtual values or objects that are dynamically computed and can be queried along with a table's columns.
|
||||
Computed fields are computed when requested for via SQL functions using other columns of the table and other custom inputs if needed.
|
||||
Computed fields are virtual values or objects that are dynamically computed and can be queried along with a table's
|
||||
columns. When requested for, computed fields are computed via SQL functions using the other columns of the table and
|
||||
any user inputs if needed.
|
||||
|
||||
.. note::
|
||||
|
||||
Computed fields are only exposed over the GraphQL API and the database schema is not modified on addition of a computed field.
|
||||
Computed fields are only exposed over the GraphQL API and the database schema is not modified on addition of a
|
||||
computed field.
|
||||
|
||||
Supported SQL functions
|
||||
***********************
|
||||
-----------------------
|
||||
|
||||
Only functions which satisfy the following constraints can be added as a computed field to a table.
|
||||
(*terminology from* `Postgres docs <https://www.postgresql.org/docs/current/sql-createfunction.html>`__):
|
||||
|
59
docs/graphql/manual/schema/custom-field-names.rst
Normal file
@ -0,0 +1,59 @@
|
||||
.. _custom_field_names:
|
||||
|
||||
Customise auto-generated field names
|
||||
====================================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
It is possible to override the auto-generated table and column field names exposed over the GraphQL API.
|
||||
|
||||
.. note::
|
||||
|
||||
This feature is supported in versions ``v1.0.0-beta.8`` and later.
|
||||
|
||||
Expose columns with a different name in the GraphQL API
|
||||
-------------------------------------------------------
|
||||
|
||||
.. rst-class:: api_tabs
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Console
|
||||
|
||||
Head to the ``Data -> [table-name] -> Modify``
|
||||
|
||||
.. thumbnail:: ../../../img/graphql/manual/schema/custom-field-name-column.png
|
||||
|
||||
|
||||
.. tab:: Metadata API
|
||||
|
||||
A custom field name can be set for a column via the following 2 methods:
|
||||
|
||||
- passing a :ref:`table_config` with the :ref:`CustomColumnNames` to the :ref:`track_table_v2` API while
|
||||
tracking a table
|
||||
- using the :ref:`set_table_custom_fields` API to set the :ref:`CustomColumnNames`
|
||||
|
||||
|
||||
Expose table root fields with a different name in the GraphQL API
|
||||
-----------------------------------------------------------------
|
||||
|
||||
.. rst-class:: api_tabs
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Console
|
||||
|
||||
Head to the ``Data -> [table-name] -> Modify``
|
||||
|
||||
.. thumbnail:: ../../../img/graphql/manual/schema/custom-field-name-root-fields.png
|
||||
|
||||
.. tab:: Metadata API
|
||||
|
||||
A custom field name can be set for a table root field via the following 2 methods:
|
||||
|
||||
- passing a :ref:`table_config` with the :ref:`custom_root_fields` names to the :ref:`track_table_v2` API while
|
||||
tracking a table
|
||||
- using the :ref:`set_table_custom_fields` API to set the :ref:`custom_root_fields` names
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
Query custom SQL Functions
|
||||
==========================
|
||||
.. _custom_sql_functions:
|
||||
|
||||
Customise schema with SQL functions
|
||||
===================================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
@ -9,8 +11,8 @@ Query custom SQL Functions
|
||||
What are custom SQL functions?
|
||||
------------------------------
|
||||
|
||||
Custom SQL functions are user-defined SQL functions that can be used to either encapsulate some custom business
|
||||
logic or extend the built-in SQL functions and operators.
|
||||
Custom SQL functions are `user-defined SQL functions <https://www.postgresql.org/docs/current/sql-createfunction.html>`_
|
||||
that can be used to either encapsulate some custom business logic or extend the built-in SQL functions and operators.
|
||||
|
||||
Hasura GraphQL engine lets you expose certain types of custom functions over the GraphQL API to allow querying them
|
||||
using both ``queries`` and ``subscriptions``.
|
||||
@ -43,10 +45,14 @@ Custom SQL functions can be created using SQL which can be run in the Hasura con
|
||||
create and track an empty table with the required schema to support the function before executing the above
|
||||
steps.
|
||||
|
||||
Querying custom functions using GraphQL queries
|
||||
-----------------------------------------------
|
||||
Use cases
|
||||
---------
|
||||
|
||||
Let's see how we can query custom functions using a GraphQL query as via the below examples:
|
||||
Custom functions are ideal solutions for retrieving some derived data based on some custom business logic that
|
||||
requires user input to be calculated. If your custom logic does not require any user input, you can use
|
||||
:ref:`views <custom_views>` instead.
|
||||
|
||||
Let's see a few example use cases for custom functions:
|
||||
|
||||
Example: Text-search functions
|
||||
******************************
|
||||
@ -294,6 +300,9 @@ function in our GraphQL API as follows:
|
||||
}
|
||||
}
|
||||
|
||||
Querying custom functions using GraphQL queries
|
||||
-----------------------------------------------
|
||||
|
||||
Aggregations on custom functions
|
||||
********************************
|
||||
|
||||
@ -443,7 +452,7 @@ Use the ``->>`` JSON operator to fetch the value of a session variable as shown
|
||||
Permissions for custom function queries
|
||||
---------------------------------------
|
||||
|
||||
Access control permissions configured for the ``SETOF`` table of a function are also applicable to the function itself.
|
||||
:doc:`Access control permissions <../auth/authorization/permission-rules>` configured for the ``SETOF`` table of a function are also applicable to the function itself.
|
||||
|
||||
**For example**, in our text-search example above, if the role ``user`` doesn't have the requisite permissions to view
|
||||
the table ``article``, a validation error will be thrown if the ``search_articles`` query is run using the ``user``
|
@ -14,7 +14,7 @@ purpose. If you can express your query in SQL, define a view with it and then us
|
||||
type in the GraphQL query.
|
||||
|
||||
.. note::
|
||||
Also see :doc:`aggregation-queries` to fetch aggregation data without creating a view.
|
||||
Also see :doc:`../queries/aggregation-queries` to fetch aggregation data without creating a view.
|
||||
|
||||
**For example**, let’s see how to fetch the average article rating for each author in our author/article schema:
|
||||
|
@ -25,9 +25,10 @@ Postgres constructs.
|
||||
Basics <basics>
|
||||
Relationships <relationships/index>
|
||||
Customise with views <views>
|
||||
Customise with SQL functions <custom-functions>
|
||||
Default field values <default-values/index>
|
||||
Enum type fields <enums>
|
||||
computed-fields
|
||||
custom-field-names
|
||||
Using an existing database <using-existing-database>
|
||||
Setting up soft deletes <soft-deletes>
|
||||
Export GraphQL schema <export-graphql-schema>
|
||||
|
@ -174,12 +174,12 @@ Fetch a list of authors and a nested list of each author's articles:
|
||||
}
|
||||
}
|
||||
|
||||
.. _relationships-without-fkey:
|
||||
.. _create_manual_relationships:
|
||||
|
||||
Using manual relationships
|
||||
--------------------------
|
||||
|
||||
Let's say you have a table ``author(id, name)`` and a view ``author_avg_rating(id, avg)`` which has the
|
||||
Let's say you have a table ``author (id, name)`` and a view ``author_avg_rating (id, avg)`` which has the
|
||||
average rating of articles for each author.
|
||||
|
||||
Let us now create an ``object relationship`` called ``avg_rating`` from the ``author`` table to the
|
||||
|
@ -1,4 +1,4 @@
|
||||
.. _many-to-many-modelling:
|
||||
.. _many_to_many_modelling:
|
||||
|
||||
Modelling many-to-many table relationships
|
||||
==========================================
|
||||
|
@ -1,3 +1,5 @@
|
||||
.. _one_to_many_modelling:
|
||||
|
||||
Modelling one-to-many table relationships
|
||||
=========================================
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
.. _one_to_one_modelling:
|
||||
|
||||
Modelling one-to-one table relationships
|
||||
========================================
|
||||
|
||||
|
@ -1,28 +1,28 @@
|
||||
.. _custom_views:
|
||||
|
||||
Customise schema with views
|
||||
===========================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 1
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
Use cases
|
||||
---------
|
||||
|
||||
You may want to customise your GraphQL schema to:
|
||||
What are views?
|
||||
---------------
|
||||
|
||||
- Limit scope (i.e. expose only a subset of the columns in a table)
|
||||
- Fetch derived data (aggregations like *count, average, etc.*) in queries
|
||||
`Views <https://www.postgresql.org/docs/current/sql-createview.html>`_ can be used to expose the results of a custom
|
||||
query as a virtual table. Views are not persisted physically i.e. the query defining a view is executed whenever
|
||||
data is requested from the view.
|
||||
|
||||
These kinds of use cases can be supported using database views.
|
||||
Hasura GraphQL engine lets you expose views over the GraphQL API to allow querying them using both ``queries`` and
|
||||
``subscriptions`` just like regular tables.
|
||||
|
||||
Please see the following pages for details about the above use cases:
|
||||
.. _create_views:
|
||||
|
||||
- :doc:`../queries/control-access`
|
||||
- :doc:`../queries/derived-data`
|
||||
|
||||
Creating views
|
||||
--------------
|
||||
Creating & exposing views
|
||||
-------------------------
|
||||
|
||||
Views can be created using SQL which can be run in the Hasura console:
|
||||
|
||||
@ -31,5 +31,40 @@ Views can be created using SQL which can be run in the Hasura console:
|
||||
- Select the ``Track this`` checkbox to expose the new view over the GraphQL API
|
||||
- Hit the ``Run`` button
|
||||
|
||||
Use cases
|
||||
---------
|
||||
|
||||
Views are ideal solutions for retrieving some derived data based on some custom business logic. If your custom logic
|
||||
requires any user input, you should use :ref:`custom SQL functions <custom_sql_functions>` instead.
|
||||
|
||||
Let's see a few example use cases for views:
|
||||
|
||||
Example: Group by and then aggregate
|
||||
************************************
|
||||
|
||||
Let’s see how to fetch the average article rating for each author in our author/article schema.
|
||||
|
||||
A view that averages the rating of articles for each author can be created using the following SQL query:
|
||||
|
||||
.. code-block:: SQL
|
||||
|
||||
CREATE VIEW author_average_rating AS
|
||||
SELECT author_id, avg(rating)
|
||||
FROM article
|
||||
GROUP BY author_id
|
||||
|
||||
|
||||
Example: Hide certain fields of a table
|
||||
***************************************
|
||||
|
||||
Say, we have some sensitive information in a table which we wouldn't want to expose. We can create a view that only
|
||||
exposes the non-sensitive fields.
|
||||
|
||||
Let's say our ``author`` table has the fields ``id, name, city, email, phone, address`` and we want to hide the ``email``,
|
||||
``phone`` and ``address`` fields. We can create the following view to achieve this:
|
||||
|
||||
.. code-block:: SQL
|
||||
|
||||
CREATE VIEW author_public AS
|
||||
SELECT id, name, city
|
||||
FROM author
|
||||
|
@ -157,8 +157,8 @@ Check this `sample app <https://realtime-chat.demo.hasura.app/>`__ for a working
|
||||
Subscribe to the latest value of some derived data
|
||||
--------------------------------------------------
|
||||
|
||||
In case you are interested in the latest value of some derived data, you can :doc:`create a view to query the derived
|
||||
data <../queries/derived-data>` and then use subscriptions to fetch the derived value and get its latest value
|
||||
In case you are interested in the latest value of some derived data, you can :ref:`create a view to query the derived
|
||||
data <custom_views>` and then use subscriptions to fetch the derived value and get its latest value
|
||||
whenever it updates.
|
||||
|
||||
Example: A poll dashboard
|
||||
|
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
BIN
docs/img/graphql/manual/schema/custom-field-name-column.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
docs/img/graphql/manual/schema/custom-field-name-root-fields.png
Normal file
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 2.8 KiB |