diff --git a/examples/graphql-id-scalar-type/graphql_id_scalar_type.bal b/examples/graphql-id-scalar-type/graphql_id_scalar_type.bal new file mode 100644 index 0000000000..f494920082 --- /dev/null +++ b/examples/graphql-id-scalar-type/graphql_id_scalar_type.bal @@ -0,0 +1,25 @@ +import ballerina/graphql; + +// Defines a `record` type to use as an object in the GraphQL service. +public type User readonly & record {| + @graphql:ID int id; + string name; + int age; +|}; + +// Defines an in-memory table to store the users. +table key(id) users = table [ + {id: 1, name: "Walter White", age: 50}, + {id: 2, name: "Jesse Pinkman", age: 25} +]; + +service /graphql on new graphql:Listener(9090) { + + // Returns the user for the given `id`. + resource function get user(@graphql:ID int id) returns User|error { + if users.hasKey(id) { + return users.get(id); + } + return error(string `User with the ${id} not found`); + } +} diff --git a/examples/graphql-id-scalar-type/graphql_id_scalar_type.client.out b/examples/graphql-id-scalar-type/graphql_id_scalar_type.client.out new file mode 100644 index 0000000000..39868ce34d --- /dev/null +++ b/examples/graphql-id-scalar-type/graphql_id_scalar_type.client.out @@ -0,0 +1,2 @@ +$ curl -X POST -H "Content-type: application/json" -d '{ "query": "{ user(id: 1){ id name } }" }' 'http://localhost:9090/graphql' +{"data":{"user":{"id":1, "name":"Walter White"}}} diff --git a/examples/graphql-id-scalar-type/graphql_id_scalar_type.graphql b/examples/graphql-id-scalar-type/graphql_id_scalar_type.graphql new file mode 100644 index 0000000000..a77387e872 --- /dev/null +++ b/examples/graphql-id-scalar-type/graphql_id_scalar_type.graphql @@ -0,0 +1,6 @@ +{ + user(id: 1) { + id + name + } +} diff --git a/examples/graphql-id-scalar-type/graphql_id_scalar_type.md b/examples/graphql-id-scalar-type/graphql_id_scalar_type.md new file mode 100644 index 0000000000..dda56e9f7b --- /dev/null +++ b/examples/graphql-id-scalar-type/graphql_id_scalar_type.md @@ -0,0 +1,23 @@ +# GraphQL service - ID scalar type + +The Ballerina `graphql` module provides support for the `ID` scalar type in GraphQL. The `ID` type is used to represent unique identifiers within a GraphQL schema. It is a built-in scalar type that can be utilized to define input parameters for GraphQL fields. Applying the `@graphql:ID` annotation to specific fields indicates that they correspond to the GraphQL `ID` scalar type. Consequently, the generated schema will display the field type as `ID` regardless of the actual type of the field. + +::: code graphql_id_scalar_type.bal ::: + +Run the service by executing the following command. + +::: out graphql_id_scalar_type.server.out ::: + +Send the following document to the GraphQL endpoint to test the service. + +::: code graphql_id_scalar_type.graphql ::: + +To send the document, execute the following cURL command in a separate terminal. + +::: out graphql_id_scalar_type.client.out ::: + +>**Tip:** You can invoke the above service via the [GraphQL client](/learn/by-example/graphql-client-query-endpoint/). + +## Related links +- [`graphql` module - API documentation](https://lib.ballerina.io/ballerina/graphql/latest) +- [GraphQL ID scalar type - Specification](/spec/graphql/#415-id) diff --git a/examples/graphql-id-scalar-type/graphql_id_scalar_type.metatags b/examples/graphql-id-scalar-type/graphql_id_scalar_type.metatags new file mode 100644 index 0000000000..2b3e09f37e --- /dev/null +++ b/examples/graphql-id-scalar-type/graphql_id_scalar_type.metatags @@ -0,0 +1,2 @@ +description: This example demonstrates using the GraphQL ID scalar type as a unique identifier. +keywords: ballerina, ballerina by example, bbe, graphql, scalar, id diff --git a/examples/graphql-id-scalar-type/graphql_id_scalar_type.server.out b/examples/graphql-id-scalar-type/graphql_id_scalar_type.server.out new file mode 100644 index 0000000000..e9cd100c00 --- /dev/null +++ b/examples/graphql-id-scalar-type/graphql_id_scalar_type.server.out @@ -0,0 +1 @@ +$ bal run graphql_id_scalar.bal diff --git a/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.bal b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.bal new file mode 100644 index 0000000000..b1da6cf908 --- /dev/null +++ b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.bal @@ -0,0 +1,59 @@ +import ballerina/graphql; + +// Defines a `record` type to use as an object in the GraphQL service. +type User readonly & record {| + int id; + string name; + int age; +|}; + +// Defines an in-memory table to store the profiles. +table key(id) users = table [ + {id: 1, name: "Walter White", age: 50}, + {id: 2, name: "Jesse Pinkman", age: 25} +]; + +service /graphql on new graphql:Listener(9090) { + + @graphql:ResourceConfig { + cacheConfig: {} + } + resource function get user(int id) returns User|error { + if users.hasKey(id) { + return users.get(id); + } + return error(string `User with the ${id} not found`); + } + + @graphql:ResourceConfig { + cacheConfig: {} + } + resource function get users() returns User[] { + return users.toArray(); + } + + // Updates a user. + remote function updateUser(graphql:Context context, int id, string name, + int age) returns User|error { + // `invalidate()` is used to invalidate the cache for the given field. + check context.invalidate("user"); + if users.hasKey(id) { + _ = users.remove(id); + User user = {id: id, name: name, age: age}; + users.add(user); + return user; + } + return error(string `User with the ${id} not found`); + } + + // Deletes a user. + remote function deleteUser(graphql:Context context, int id) returns User|error { + // `invalidateAll()` is used to invalidate all the caches in the service. + check context.invalidateAll(); + if users.hasKey(id) { + User user = users.remove(id); + return user; + } + return error(string `User with the ${id} not found`); + } +} diff --git a/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.client.out b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.client.out new file mode 100644 index 0000000000..d7dbd69aeb --- /dev/null +++ b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.client.out @@ -0,0 +1,2 @@ +$ curl -X POST -H "Content-type: application/json" -d '{ "query": "mutation updateUser { updateUser(id: 1, name: \"Heisenberg\", age: 52){id name age} }" }' 'http://localhost:9090/graphql' +{"data":{"updateUser":{"id":1, "name":"Heisenberg", "age":52}}} diff --git a/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.graphql b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.graphql new file mode 100644 index 0000000000..baeb036976 --- /dev/null +++ b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.graphql @@ -0,0 +1,7 @@ +mutation updateUser { + updateUser(id: 1, name: "Heisenberg" age: 52) { + id + name + age + } +} diff --git a/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.md b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.md new file mode 100644 index 0000000000..cfd87fcd07 --- /dev/null +++ b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.md @@ -0,0 +1,23 @@ +# GraphQL service - Cache invalidation + +The Ballerina `graphql` module provides functionality for cache invalidation. The `invalidate()` and `invalidateAll()` APIs in the `graphql:Context` can be used to invalidate caches in a `graphql:Service`. The `invalidate()` API supports the cache invalidation of a specific field by providing the full path of the field separated by a full stop(`.`). For example, `invalidate("field.subfield.anotherSubfield")`. Conversely, the `invalidateAll()` API invalidates all caches within the `graphql:Service`. + +::: code graphql_service_cache_invalidation.bal ::: + +Run the service by executing the following command. + +::: out graphql_service_cache_invalidation.server.out ::: + +Then, send the following document to update the user. + +::: code graphql_service_cache_invalidation.graphql ::: + +To send the document, execute the following cURL command. + +::: out graphql_service_cache_invalidation.client.out ::: + +>**Tip:** You can invoke the above service via the [GraphQL client](/learn/by-example/graphql-client-query-endpoint/). + +## Related links +- [`graphql` module - API documentation](https://lib.ballerina.io/ballerina/graphql/latest) +- [GraphQL Cache invalidation - Specification](/spec/graphql/#10713-cache-invalidation) diff --git a/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.metatags b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.metatags new file mode 100644 index 0000000000..1e538ffda5 --- /dev/null +++ b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.metatags @@ -0,0 +1,2 @@ +description: This example demonstrates the cache invalidation of a GraphQL service. +keywords: ballerina, ballerina by example, graphql, cache, invalidation, server-side caching diff --git a/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.server.out b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.server.out new file mode 100644 index 0000000000..5db9078f50 --- /dev/null +++ b/examples/graphql-service-cache-invalidation/graphql_service_cache_invalidation.server.out @@ -0,0 +1 @@ +$ bal run graphql_service_cache_invalidation.bal diff --git a/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.bal b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.bal new file mode 100644 index 0000000000..40d721c00f --- /dev/null +++ b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.bal @@ -0,0 +1,30 @@ +import ballerina/graphql; + +// Defines a `record` type to use as an object in the GraphQL service. +type User readonly & record {| + int id; + string name; + int age; +|}; + +// Defines an in-memory table to store the users. +table key(id) users = table [ + {id: 1, name: "Walter White", age: 50}, + {id: 2, name: "Jesse Pinkman", age: 25} +]; + +service /graphql on new graphql:Listener(9090) { + + // The `cacheConfig` in the `graphql:ResourceConfig` annotation is used to + // configure the cache for a specific field in the GraphQL service. + // (default: {enabled: true, maxAge: 60, maxSize: 120}) + @graphql:ResourceConfig { + cacheConfig: {} + } + resource function get name(int id) returns string|error { + if users.hasKey(id) { + return users.get(id).name; + } + return error(string `User with the ${id} not found`); + } +} diff --git a/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.client.out b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.client.out new file mode 100644 index 0000000000..c943533c5b --- /dev/null +++ b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.client.out @@ -0,0 +1,2 @@ +$ curl -X POST -H "Content-type: application/json" -d '{ "query": "{ name(id: 1) }" }' 'http://localhost:9090/graphql' +{"data":{"name":"Walter White"}} diff --git a/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.graphql b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.graphql new file mode 100644 index 0000000000..320d7c1a37 --- /dev/null +++ b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.graphql @@ -0,0 +1,3 @@ +{ + name(id: 1) +} diff --git a/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.md b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.md new file mode 100644 index 0000000000..3f71ac2a32 --- /dev/null +++ b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.md @@ -0,0 +1,23 @@ +# GraphQL service - Field-level caching + +The Ballerina `graphql` module provides the capability to enable GraphQL caching, which can be applied at either the field or operation level. To enable caching at the field level, the `cacheConfig` field in the `graphql:ResourceConfig` annotation can be used on a resource method within a `graphql:Service`. By setting this configuration, caching is enabled for the specified GraphQL field, and it can override the cache configurations set at the operation level. + +::: code graphql_service_field_level_caching.bal ::: + +Run the service by executing the following command. + +::: out graphql_service_field_level_caching.server.out ::: + +Send the following document to the GraphQL endpoint to test the service. + +::: code graphql_service_field_level_caching.graphql ::: + +To send the document, execute the following cURL command. + +::: out graphql_service_field_level_caching.client.out ::: + +>**Tip:** You can invoke the above service via the [GraphQL client](/learn/by-example/graphql-client-query-endpoint/). + +## Related links +- [`graphql` module - API documentation](https://lib.ballerina.io/ballerina/graphql/latest) +- [GraphQL Field-level caching - Specification](/spec/graphql/#10712-field-level-caching) diff --git a/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.metatags b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.metatags new file mode 100644 index 0000000000..caa9607753 --- /dev/null +++ b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.metatags @@ -0,0 +1,2 @@ +description: This example demonstrates the field-level caching functionality within a GraphQL service. +keywords: ballerina, ballerina by example, graphql, cache, server-side caching diff --git a/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.server.out b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.server.out new file mode 100644 index 0000000000..e9919656ae --- /dev/null +++ b/examples/graphql-service-field-level-caching/graphql_service_field_level_caching.server.out @@ -0,0 +1 @@ +$ bal run graphql_service_field_level_caching.bal diff --git a/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.bal b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.bal new file mode 100644 index 0000000000..16268b1544 --- /dev/null +++ b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.bal @@ -0,0 +1,59 @@ +import ballerina/graphql; + +// Defines a `record` type to use as an object in the GraphQL service. +type User readonly & record {| + int id; + string name; + int age; +|}; + +// Defines an in-memory table to store the users. +table key(id) users = table [ + {id: 1, name: "Walter White", age: 50}, + {id: 2, name: "Jesse Pinkman", age: 25} +]; + +// The `cacheConfig` in the `graphql:ServiceConfig` annotation is used to +// configure the cache for the GraphQL service. +// (default: {enabled: true, maxAge: 60, maxSize: 120}) +@graphql:ServiceConfig { + cacheConfig: {} +} +service /graphql on new graphql:Listener(9090) { + + resource function get name(int id) returns string|error { + if users.hasKey(id) { + return users.get(id).name; + } + return error(string `User with the ${id} not found`); + } + + // The `enabled` field enables/disables the cache for the field. (default: true) + @graphql:ResourceConfig { + cacheConfig: { + enabled: false + } + } + resource function get user(int id) returns User|error { + if users.hasKey(id) { + return users.get(id); + } + return error(string `User with the ${id} not found`); + } + + // The `maxAge` field sets the maximum age of the cache in seconds. (default: 60) + // The `maxSize` field indicates the maximum capacity of the cache table by entries. + // (default: 120) + @graphql:ResourceConfig { + cacheConfig: { + maxAge: 600, + maxSize: 100 + } + } + resource function get age(int id) returns int|error { + if users.hasKey(id) { + return users.get(id).age; + } + return error(string `User with the ${id} not found`); + } +} diff --git a/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.client.out b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.client.out new file mode 100644 index 0000000000..c943533c5b --- /dev/null +++ b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.client.out @@ -0,0 +1,2 @@ +$ curl -X POST -H "Content-type: application/json" -d '{ "query": "{ name(id: 1) }" }' 'http://localhost:9090/graphql' +{"data":{"name":"Walter White"}} diff --git a/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.graphql b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.graphql new file mode 100644 index 0000000000..320d7c1a37 --- /dev/null +++ b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.graphql @@ -0,0 +1,3 @@ +{ + name(id: 1) +} diff --git a/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.md b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.md new file mode 100644 index 0000000000..ff8448ed24 --- /dev/null +++ b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.md @@ -0,0 +1,23 @@ +# GraphQL service - Operation-level caching + +The Ballerina `graphql` module provides the capability to enable GraphQL caching. GraphQL caching can be enabled at either the field level or the operation level. To enable caching at the operation level, the `cacheConfig` field in the `graphql:ServiceConfig` annotation can be applied to a service. This configuration will enable caching for all resource paths within the `graphql:Service`. + +::: code graphql_service_operation_level_caching.bal ::: + +Run the service by executing the following command. + +::: out graphql_service_operation_level_caching.server.out ::: + +Send the following document to the GraphQL endpoint to test the service. + +::: code graphql_service_operation_level_caching.graphql ::: + +To send the document, execute the following cURL command. + +::: out graphql_service_operation_level_caching.client.out ::: + +>**Tip:** You can invoke the above service via the [GraphQL client](/learn/by-example/graphql-client-query-endpoint/). + +## Related links +- [`graphql` module - API documentation](https://lib.ballerina.io/ballerina/graphql/latest) +- [GraphQL Operation-level caching - Specification](/spec/graphql/#10711-operation-level-caching) diff --git a/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.metatags b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.metatags new file mode 100644 index 0000000000..c8ce15f0b2 --- /dev/null +++ b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.metatags @@ -0,0 +1,2 @@ +description: This example demonstrates the caching of a GraphQL service at the operation level. +keywords: ballerina, ballerina by example, graphql, cache, server-side caching diff --git a/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.server.out b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.server.out new file mode 100644 index 0000000000..cd6a39e15d --- /dev/null +++ b/examples/graphql-service-operation-level-caching/graphql_service_operation_level_caching.server.out @@ -0,0 +1 @@ +$ bal run graphql_service_operation_level_caching.bal diff --git a/examples/index.json b/examples/index.json index 1fc98629de..5a8e01bf1a 100644 --- a/examples/index.json +++ b/examples/index.json @@ -2370,6 +2370,14 @@ "disablePlayground": true, "isLearnByExample": false }, + { + "name": "ID scalar Type", + "url": "graphql-id-scalar-type", + "verifyBuild": true, + "verifyOutput": false, + "disablePlayground": true, + "isLearnByExample": false + }, { "name": "Interfaces", "url": "graphql-interfaces", @@ -2513,6 +2521,30 @@ "verifyOutput": false, "disablePlayground": true, "isLearnByExample": false + }, + { + "name": "Operation-level caching", + "url": "graphql-service-operation-level-caching", + "verifyBuild": true, + "verifyOutput": false, + "disablePlayground": true, + "isLearnByExample": false + }, + { + "name": "Field-level caching", + "url": "graphql-service-field-level-caching", + "verifyBuild": true, + "verifyOutput": false, + "disablePlayground": true, + "isLearnByExample": false + }, + { + "name": "Cache invalidation", + "url": "graphql-service-cache-invalidation", + "verifyBuild": true, + "verifyOutput": false, + "disablePlayground": true, + "isLearnByExample": false } ] }, diff --git a/gradle.properties b/gradle.properties index 43696fd166..1e35a6f7b7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -64,7 +64,7 @@ stdlibWebsubVersion=2.10.0-20230831-211200-c6f33c4 stdlibWebsubhubVersion=1.10.0-20230831-210000-695f161 # Stdlib Level 07 -stdlibGraphqlVersion=1.10.0-20230914-151300-376b3a9 +stdlibGraphqlVersion=1.11.0-20240212-151600-33c9bfd stdlibSqlVersion=1.11.0-20230831-224400-d2491ed # Stdlib Level 08