Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
b3ac563
basic doc for actions
0x777 Oct 6, 2019
8946ba7
wip docs
tirumaraiselvan Oct 14, 2019
05684e8
wip: custom_types, sync and async actions
0x777 Oct 15, 2019
61072b1
switch to graphql-parser-hs on github
0x777 Oct 15, 2019
04b863c
update docs
tirumaraiselvan Oct 16, 2019
afb4ac9
metadata import/export
0x777 Oct 16, 2019
a7d72ac
webhook calls are now supported
0x777 Oct 16, 2019
ca4fd66
relationships in sync actions
0x777 Oct 20, 2019
4462284
revert to lts-13 and bump graphql-parser-hs commit
0x777 Oct 20, 2019
e0570a5
lower the lts version so that the Cabal version matches that of the b…
0x777 Oct 21, 2019
4bc8106
disable -Werr on this branch
0x777 Oct 21, 2019
c86dcc4
initialise.sql is now in sync with the migration file
0x777 Oct 21, 2019
cb05dd1
fix metadata tests
0x777 Oct 21, 2019
b925752
allow specifying arguments of actions
0x777 Oct 22, 2019
ea0f8f7
fix blacklist check on check_build_worthiness job
arvi3411301 Oct 24, 2019
a40b68e
track custom_types and actions related tables
0x777 Oct 24, 2019
c33372a
handlers are now triggered on async actions
0x777 Oct 24, 2019
1ba45d1
clean up annotated relationship related code
0x777 Oct 30, 2019
2559837
default to pgjson unless a field is involved in relationships, for ge…
0x777 Oct 30, 2019
1c9819a
temporary fix for async subscriptions
0x777 Dec 3, 2019
aa02af1
use 'true' for action filter for non admin role
0x777 Dec 10, 2019
0c7b499
fix create_action_permission sql query
0x777 Dec 10, 2019
5a5ad19
drop permissions when dropping an action
0x777 Dec 10, 2019
1f6adac
add a hdb_role view (and relationships) to fetch all roles in the system
0x777 Dec 10, 2019
6944f42
fix retrieving action permission information from catalog
0x777 Dec 11, 2019
4e81961
fix error message when action webhook returns 'errors'
rakeshkky Dec 26, 2019
483ef36
rename 'webhook' key in action definition to 'handler'
rakeshkky Dec 26, 2019
7d736c2
allow templating actions wehook URLs with env vars
rakeshkky Dec 27, 2019
3fcc908
add 'update_action' /v1/query type
rakeshkky Dec 25, 2019
f58b887
Merge branch 'master' into actions
rakeshkky Jan 2, 2020
74593f5
Merge branch 'master' into actions
rakeshkky Jan 2, 2020
3a6f444
Merge branch 'master' into actions
rakeshkky Jan 6, 2020
a6b5a8c
allow forwarding client headers by setting `forward_client_headers` i…
rakeshkky Jan 6, 2020
8180674
add 'headers' configuration in action definition
rakeshkky Jan 7, 2020
694791b
handle webhook error response based on status codes
rakeshkky Jan 7, 2020
0865aac
support array relationships for custom types
rakeshkky Jan 8, 2020
d4668bf
temp: ignore errors on warnings
tirumaraiselvan Jan 9, 2020
9344d08
Merge branch 'master' into actions
rakeshkky Jan 10, 2020
f5c8071
Merge branch 'master' into actions
rakeshkky Jan 15, 2020
8323c30
implement single row mutation, see https://github.com/hasura/graphql-…
rakeshkky Jan 17, 2020
596fe2a
single row mutation: rename 'pk_columns' -> 'columns' and no-op refactor
rakeshkky Jan 20, 2020
78ab464
use top level primary key inputs for delete_by_pk & account select pe…
rakeshkky Jan 20, 2020
b2de9c0
use only REST semantics to resolve the webhook response
rakeshkky Jan 20, 2020
fb25f8e
Merge branch 'master' into actions
rakeshkky Jan 21, 2020
116ac5b
remove warnings
rakeshkky Jan 21, 2020
a2423bf
Merge branch 'master' into actions
rakeshkky Jan 22, 2020
487ee82
use 'pk_columns' instead of 'columns' for update_by_pk input
rakeshkky Jan 22, 2020
7368748
add python basic tests for single row mutations
rakeshkky Jan 22, 2020
be07e04
refactor code building actions' cache & validate presence of actions …
rakeshkky Jan 22, 2020
4e58372
add action context (name) in webhook payload
rakeshkky Jan 23, 2020
99aab8a
Merge branch 'master' into actions
rakeshkky Jan 23, 2020
b02474b
avoid '_0_root.base' hack & add async result accessible check
rakeshkky Feb 5, 2020
1becb1b
Merge branch 'master' into actions
rakeshkky Feb 5, 2020
e5b49c5
small no-op refactor in schema/cache.hs
rakeshkky Feb 5, 2020
8234626
clean nulls, empty arrays for actions, custom types in export metadata
rakeshkky Feb 5, 2020
7c2be6d
async action mutation returns only the UUID of the action
rakeshkky Feb 6, 2020
b1fff1c
Merge branch 'master' into actions
rakeshkky Feb 6, 2020
a9ef569
unit tests for URL template parser
rakeshkky Feb 6, 2020
ecbd40b
Basic sync actions python tests
rakeshkky Feb 6, 2020
2e439c2
no-op refactor
rakeshkky Feb 6, 2020
d3ffcef
fix output in async query & add async tests
rakeshkky Feb 6, 2020
5268b2a
add admin secret header in async actions python test
rakeshkky Feb 7, 2020
baf40ff
remove comments in resolve/action.hs
rakeshkky Feb 7, 2020
a0771e0
incorporate review suggestion by @0x777
rakeshkky Feb 9, 2020
a3e2805
document async action architecture in Resolve/Action.hs file
rakeshkky Feb 10, 2020
5b2de9a
remove few commented code
rakeshkky Feb 10, 2020
06b35e6
Merge branch 'master' into actions
rakeshkky Feb 10, 2020
c96dd6e
remove commented code from GraphQL/Context.hs & update graphql-parser…
rakeshkky Feb 11, 2020
57f71e8
Merge branch 'master' into actions
rakeshkky Feb 11, 2020
2e92e3a
remove a non exhaustive pattern matches
rakeshkky Feb 11, 2020
c3557ea
support actions returning array of objects
rakeshkky Feb 12, 2020
20e23a1
tests for list type response actions
rakeshkky Feb 12, 2020
e32545e
update docs with actions and custom types metadata API reference
rakeshkky Feb 13, 2020
9222cae
Merge branch 'master' into actions
rakeshkky Feb 13, 2020
8a07237
Merge branch 'master' into actions
0x777 Feb 13, 2020
12dc26e
update actions python tests as per #f8e1330
rakeshkky Feb 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .ciignore

This file was deleted.

26 changes: 3 additions & 23 deletions .circleci/ciignore.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ if [[ "$CIRCLE_BRANCH" = "release-"* ]]; then
exit
fi

if [[ ! -a "$ROOT/.ciignore" ]]; then
echo "Skipping check since .ciignore is not found"
exit # If .ciignore doesn't exists, just quit this script
fi

# get the diff
if [[ ! -z "$CIRCLE_COMPARE_URL" ]]; then
# CIRCLE_COMPARE_URL is not empty, use it to get the diff
Expand All @@ -39,36 +34,21 @@ if [[ ! -z "$CIRCLE_COMPARE_URL" ]]; then
COMMIT_RANGE=$(echo $CIRCLE_COMPARE_URL | sed 's:^.*/compare/::g')
fi
echo "Diff: $COMMIT_RANGE"
changes="$(git diff $COMMIT_RANGE --name-only)"
changes="$(git diff $COMMIT_RANGE --name-only -- . ':!scripts' ':!assets' ':!docs' ':!community' ':!install-manifests' ':!github' ':!*.md' ':!.ciignore' ':!.gitignore' ':!LICENSE')"
elif [[ "$CIRCLE_BRANCH" == "master" ]]; then
# CIRCLE_COMPARE_URL is not set, but branch is master, diff with last commit
echo "Diff: HEAD~1"
changes="$(git diff HEAD~1 --name-only)"
changes="$(git diff HEAD~1 --name-only -- . ':!scripts' ':!assets' ':!docs' ':!community' ':!install-manifests' ':!github' ':!*.md' ':!.ciignore' ':!.gitignore' ':!LICENSE')"
else
# CIRCLE_COMPARE_URL is not set, branch is not master, diff with origin/master
echo "Diff: origin/master..HEAD"
changes="$(git diff-tree --no-commit-id --name-only -r origin/master..HEAD)"
changes="$(git diff-tree --no-commit-id --name-only -r origin/master..HEAD -- . ':!scripts' ':!assets' ':!docs' ':!community' ':!install-manifests' ':!github' ':!*.md' ':!.ciignore' ':!.gitignore' ':!LICENSE')"
fi

echo "Changes in this build:"
echo $changes
echo

# Load the patterns we want to skip into an array
mapfile -t blacklist < "$ROOT/.ciignore"

for i in "${blacklist[@]}"
do
# Remove the current pattern from the list of changes
changes=( ${changes[@]/$i/} )

if [[ ${#changes[@]} -eq 0 ]]; then
# If we've exhausted the list of changes before we've finished going
# through patterns, that's okay, just quit the loop
break
fi
done

if [[ ${#changes[@]} -gt 0 ]]; then
# If there's still changes left, then we have stuff to build, leave the commit alone.
echo "Files that are not ignored present in commits, need to build, succeed the job"
Expand Down
36 changes: 36 additions & 0 deletions docs/graphql/manual/actions/action-handlers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Action handlers
===============


.. contents:: Table of contents
:backlinks: none
:depth: 1
:local:

WORK IN PROGRESS

Actions need to be backed by custom business logic. This business logic can be defined in different types of handlers.


HTTP handler
------------

WIP

Postgres functions
------------------

WIP

Postgres PLV8
----

Similar to postgres functions but in nodejs.


Managing and deploying action handlers
--------------------------------------

HTTP handlers in serverless functions, micoservice APIs etc

Postgres functions as migrations, etc
35 changes: 35 additions & 0 deletions docs/graphql/manual/actions/async-actions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Async Actions
=============


.. contents:: Table of contents
:backlinks: none
:depth: 1
:local:

WORK IN PROGRESS

Sometimes you may not want to wait for an action to complete (say if the business logic takes a long time). In such cases you can create an **asynchronous** action, which returns an ``action_id`` immediately to the client before contacting the webhook.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this feature! In trying this, I noticed that when running an async mutation, I am seeing id being made available through the GraphQL schema when attempting to subscribe to my action - as opposed to the action_id stated here.


If you mark an action as **asynchronous**, graphql-engine also generates a query and a subscription field for the action so that you can query/subscribe to its status. In the above example, let's say ``place_order`` is an asnychronous action, your client code looks something like this:

.. code-block:: graphql

mutation place_order($order_input: place_order_input!) {
place_order(input: $order_input) {
action_id
}
}

.. code-block:: graphql

subscription order_status($action_id: uuid!) {
place_order(action_id: $action_id) {
order {
id
payment_url
total_amount
discount
}
}
}
69 changes: 69 additions & 0 deletions docs/graphql/manual/actions/getting-started.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
Getting Started with Actions
============================


.. contents:: Table of contents
:backlinks: none
:depth: 1
:local:

WORK IN PROGRESS

Let's say you are building an ecommerce application where you need to provide a mutation for placing an 'order', ``place_order``.

Example
-------

WORK IN PROGRESS

First, you will need to first define the input types for this mutation in the console:

.. code-block:: graphql

enum payment_method {
stripe
paypal
}

input type place_order_input {
selected_payment_mode payment_method!
items [order_item_input!]!
address_id uuid!
coupon_code String
}

input order_item_input {
skuId uuid!
quantity Int!
}

type place_order_response {
order_id uuid!
}

You will then define an action called ``place_order`` with ``place_order_input`` as the **input** type, ``place_order_response`` as the **output** type.

Once you have the action setup, you'll have to define the permissions for the role for which you want to allow this action. For all such roles, this action will be exposed as a mutation. The client can then execute this mutation as follows:

.. code-block:: graphql

mutation place_order($order_input: place_order_input!) {
place_order(input: $order_input) {
response {
order_id
}
}
}


But how is this action executed? An action can be linked to different types of handlers (see: :doc:`Action handlers <action-handlers>`) . In this example, let's use a HTTP handler which will be invoked when this action is called by the client. The logic of this handler could look something like this:

.. code-block:: python

def place_order(payload):
input_args = payload['input']
session_variables = payload['session_variables']
order_id = validate_and_insert_order(input_args, session_variables) # some business logic code
return {"order_id": order_id}

And that's it. You have created your first action!
40 changes: 40 additions & 0 deletions docs/graphql/manual/actions/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Actions
=======

.. contents:: Table of contents
:backlinks: none
:depth: 1
:local:


WORK IN PROGRESS

Actions are user defined mutations with custom business logic. Actions can be added to Hasura to handle various use cases such as data validation, data enrichment and other complex business logic.

When the permissions system isn't enough to specify the required constraints, you would typically add such mutation through a remote schema. However actions can handle these use cases better because of the following reasons:

1. No need to write a remote schema. Actions can be executed in ordinary webhooks or postgres itself.

2. Return graphql-engine's types without writing any extra code. You might want to return the new "state" after a mutation.

3. Can be executed asynchronously for building powerful event-driven apps.

Architecture Diagram
--------------------

WORK IN PROGRESS


Learn more
----------

.. toctree::
:maxdepth: 1
:titlesonly:

Getting started <getting-started>
Input types <input-types>
Response types <response-types>
Action handlers <action-handlers>
Async actions <async-actions>
Sample use cases <use-cases>
45 changes: 45 additions & 0 deletions docs/graphql/manual/actions/input-types.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
Action Input Types
==================

.. contents:: Table of contents
:backlinks: none
:depth: 1
:local:

WORK IN PROGRESS

Reference for creating different input types.


Scalar Input Types
------------------

WORK IN PROGRESS

.. code-block:: graphql

enum payment_method {
stripe
paytm
}


Object Input Types
------------------

WORK IN PROGRESS

.. code-block:: graphql

input type place_order_input {
selected_payment_mode payment_method!
items [order_item_input!]!
address_id uuid!
coupon_code String
}

input order_item_input {
skuId uuid!
quantity Int!
}

67 changes: 67 additions & 0 deletions docs/graphql/manual/actions/response-types.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
Action Response Types
=====================


.. contents:: Table of contents
:backlinks: none
:depth: 1
:local:


WORK IN PROGRESS

You can return different types of responses when an action is executed.

Basic Response
--------------

WORK IN PROGRESS

.. code-block:: graphql


mutation place_order($order_input: place_order_input!) {
place_order(input: $order_input) {
response {
order_id
}
}
}

Complex response with relationships
-----------------------------------

WORK IN PROGRESS

.. code-block:: graphql

mutation place_order($order_input: place_order_input!) {
place_order(input: $order_input) {
response {
order {
id
payment_url
total_amount
discount
}
}
}
}

You can fetch relationships of the ``order`` like you would when you query the ``order`` table. Thus with actions you can write the minimum needed code that is needed to validate the mutation and still not lose out on the powerful query fields that graphql-engine generates.

Async response
--------------

WORK IN PROGRESS

.. code-block:: graphql

mutation place_order($order_input: place_order_input!) {
place_order(input: $order_input) {
action_id
}
}

Where ``action_id`` is a unique id generated for every async action that has been performed.

Loading