- 
                Notifications
    
You must be signed in to change notification settings  - Fork 2.8k
 
allow custom mutations through actions #3042
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
          
     Merged
      
      
    
  
     Merged
                    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 8946ba7
              
                wip docs
              
              
                tirumaraiselvan 05684e8
              
                wip: custom_types, sync and async actions
              
              
                0x777 61072b1
              
                switch to graphql-parser-hs on github
              
              
                0x777 04b863c
              
                update docs
              
              
                tirumaraiselvan afb4ac9
              
                metadata import/export
              
              
                0x777 a7d72ac
              
                webhook calls are now supported
              
              
                0x777 ca4fd66
              
                relationships in sync actions
              
              
                0x777 4462284
              
                revert to lts-13 and bump graphql-parser-hs commit
              
              
                0x777 e0570a5
              
                lower the lts version so that the Cabal version matches that of the b…
              
              
                0x777 4bc8106
              
                disable -Werr on this branch
              
              
                0x777 c86dcc4
              
                initialise.sql is now in sync with the migration file
              
              
                0x777 cb05dd1
              
                fix metadata tests
              
              
                0x777 b925752
              
                allow specifying arguments of actions
              
              
                0x777 ea0f8f7
              
                fix blacklist check on check_build_worthiness job
              
              
                arvi3411301 a40b68e
              
                track custom_types and actions related tables
              
              
                0x777 c33372a
              
                handlers are now triggered on async actions
              
              
                0x777 1ba45d1
              
                clean up annotated relationship related code
              
              
                0x777 2559837
              
                default to pgjson unless a field is involved in relationships, for ge…
              
              
                0x777 1c9819a
              
                temporary fix for async subscriptions
              
              
                0x777 aa02af1
              
                use 'true' for action filter for non admin role
              
              
                0x777 0c7b499
              
                fix create_action_permission sql query
              
              
                0x777 5a5ad19
              
                drop permissions when dropping an action
              
              
                0x777 1f6adac
              
                add a hdb_role view (and relationships) to fetch all roles in the system
              
              
                0x777 6944f42
              
                fix retrieving action permission information from catalog
              
              
                0x777 4e81961
              
                fix error message when action webhook returns 'errors'
              
              
                rakeshkky 483ef36
              
                rename 'webhook' key in action definition to 'handler'
              
              
                rakeshkky 7d736c2
              
                allow templating actions wehook URLs with env vars
              
              
                rakeshkky 3fcc908
              
                add 'update_action' /v1/query type
              
              
                rakeshkky f58b887
              
                Merge branch 'master' into actions
              
              
                rakeshkky 74593f5
              
                Merge branch 'master' into actions
              
              
                rakeshkky 3a6f444
              
                Merge branch 'master' into actions
              
              
                rakeshkky a6b5a8c
              
                allow forwarding client headers by setting `forward_client_headers` i…
              
              
                rakeshkky 8180674
              
                add 'headers' configuration in action definition
              
              
                rakeshkky 694791b
              
                handle webhook error response based on status codes
              
              
                rakeshkky 0865aac
              
                support array relationships for custom types
              
              
                rakeshkky d4668bf
              
                temp: ignore errors on warnings
              
              
                tirumaraiselvan 9344d08
              
                Merge branch 'master' into actions
              
              
                rakeshkky f5c8071
              
                Merge branch 'master' into actions
              
              
                rakeshkky 8323c30
              
                implement single row mutation, see https://github.com/hasura/graphql-…
              
              
                rakeshkky 596fe2a
              
                single row mutation: rename 'pk_columns' -> 'columns' and no-op refactor
              
              
                rakeshkky 78ab464
              
                use top level primary key inputs for delete_by_pk & account select pe…
              
              
                rakeshkky b2de9c0
              
                use only REST semantics to resolve the webhook response
              
              
                rakeshkky fb25f8e
              
                Merge branch 'master' into actions
              
              
                rakeshkky 116ac5b
              
                remove warnings
              
              
                rakeshkky a2423bf
              
                Merge branch 'master' into actions
              
              
                rakeshkky 487ee82
              
                use 'pk_columns' instead of 'columns' for update_by_pk input
              
              
                rakeshkky 7368748
              
                add python basic tests for single row mutations
              
              
                rakeshkky be07e04
              
                refactor code building actions' cache & validate presence of actions …
              
              
                rakeshkky 4e58372
              
                add action context (name) in webhook payload
              
              
                rakeshkky 99aab8a
              
                Merge branch 'master' into actions
              
              
                rakeshkky b02474b
              
                avoid '_0_root.base' hack & add async result accessible check
              
              
                rakeshkky 1becb1b
              
                Merge branch 'master' into actions
              
              
                rakeshkky e5b49c5
              
                small no-op refactor in schema/cache.hs
              
              
                rakeshkky 8234626
              
                clean nulls, empty arrays for actions, custom types in export metadata
              
              
                rakeshkky 7c2be6d
              
                async action mutation returns only the UUID of the action
              
              
                rakeshkky b1fff1c
              
                Merge branch 'master' into actions
              
              
                rakeshkky a9ef569
              
                unit tests for URL template parser
              
              
                rakeshkky ecbd40b
              
                Basic sync actions python tests
              
              
                rakeshkky 2e439c2
              
                no-op refactor
              
              
                rakeshkky d3ffcef
              
                fix output in async query & add async tests
              
              
                rakeshkky 5268b2a
              
                add admin secret header in async actions python test
              
              
                rakeshkky baf40ff
              
                remove comments in resolve/action.hs
              
              
                rakeshkky a0771e0
              
                incorporate review suggestion by @0x777
              
              
                rakeshkky a3e2805
              
                document async action architecture in Resolve/Action.hs file
              
              
                rakeshkky 5b2de9a
              
                remove few commented code
              
              
                rakeshkky 06b35e6
              
                Merge branch 'master' into actions
              
              
                rakeshkky c96dd6e
              
                remove commented code from GraphQL/Context.hs & update graphql-parser…
              
              
                rakeshkky 57f71e8
              
                Merge branch 'master' into actions
              
              
                rakeshkky 2e92e3a
              
                remove a non exhaustive pattern matches
              
              
                rakeshkky c3557ea
              
                support actions returning array of objects
              
              
                rakeshkky 20e23a1
              
                tests for list type response actions
              
              
                rakeshkky e32545e
              
                update docs with actions and custom types metadata API reference
              
              
                rakeshkky 9222cae
              
                Merge branch 'master' into actions
              
              
                rakeshkky 8a07237
              
                Merge branch 'master' into actions
              
              
                0x777 12dc26e
              
                update actions python tests as per #f8e1330
              
              
                rakeshkky File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
There are no files selected for viewing
This file was deleted.
      
      Oops, something went wrong.
      
    
  
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | 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 | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | 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. | ||
| 
     | 
||
| 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 | ||
| } | ||
| } | ||
| } | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | 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! | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | 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> | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | 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! | ||
| } | ||
| 
     | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | 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. | ||
| 
     | 
      
      Oops, something went wrong.
        
    
  
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
There was a problem hiding this comment.
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
idbeing made available through the GraphQL schema when attempting to subscribe to my action - as opposed to theaction_idstated here.