### Start Ballerina GraphQL Service Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/snowtooth/GraphQL Snowtooth Example with Ballerina.md Command to build and run the Snowtooth Ballerina project, which starts the GraphQL service on `http://localhost:9000/graphql`. ```Shell $bal run ``` -------------------------------- ### Git Tracker Installation and Configuration Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/simple_github_issue_tracker/Integrating Multiple Endpoints to Expose as a GraphQL API in Ballerina.md Commands to clone the Git Tracker repository, navigate into it, configure GitHub API credentials in config.toml, start a Kafka server using Docker Compose, and finally run the Ballerina service. ```bash git clone https://github.com/ballerina-platform/module-ballerina-graphql/examples/simple-github-issue-tracker.git ``` ```bash cd simple-github-issue-tracker ``` ```toml authToken = "" owner = "" ``` ```bash docker-compose -f docker-compose-kafka.yml up ``` ```bash bal run ``` -------------------------------- ### Run Ballerina GraphQL Service Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/news_alerts/A Guide on GraphQL Subscriptions with Apache Kafka in Ballerina.md Command to start the Ballerina GraphQL service from the project directory. This service will typically expose a GraphiQL client for interaction. Ensure a Kafka broker is running beforehand as a prerequisite. ```shell bal run ``` -------------------------------- ### Example: Initializing Ballerina `DefaultDataLoader` Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md This example demonstrates how to create a new instance of `dataloader:DefaultDataLoader` in Ballerina. It shows the instantiation with a reference to a batch load function, `batchBooksForAuthors`. ```ballerina dataloader:DefaultDataLoader bookLoader = new (batchBooksForAuthors); ``` -------------------------------- ### Example: Implementing a Ballerina Batch Load Function Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md This example illustrates how to write a `BatchLoadFunction` in Ballerina. It shows the function signature, type casting for input keys, and a placeholder for the actual data retrieval logic from a data source. ```ballerina isolated function batchBooksForAuthors(readonly & anydata[] ids) returns Book[][]|error { final readonly & int[] authorIds = ids; // Logic to retrieve books from the data source for the given author ids // Book[][] books = ... return books; }; ``` -------------------------------- ### Define In-Memory Data Tables in Ballerina Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/news_alerts/A Guide on GraphQL Subscriptions with Apache Kafka in Ballerina.md Provides examples of defining in-memory data sources using Ballerina's built-in `table` type for `User` and `Publisher` data. These tables serve as simple storage for the GraphQL example and can be easily adapted for relational databases. ```ballerina isolated table key(id) userTable = table []; isolated table key(id) publisherTable = table []; ``` -------------------------------- ### Combine Ballerina GraphQL Listener and Service Initialization Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/README.md Demonstrates a concise way to initialize both the `graphql:Listener` and the `graphql:Service` in a single statement, streamlining the setup process for a GraphQL endpoint. ```Ballerina service graphql:Service on new graphql:Listener(9090) { } ``` -------------------------------- ### Combine Ballerina GraphQL Listener and Service Initialization Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/ballerina/README.md Demonstrates a concise way to initialize both the `graphql:Listener` and attach the `graphql:Service` in a single, combined statement. This simplifies setup for simple GraphQL services. ```ballerina service graphql:Service on new graphql:Listener(9090) { } ``` -------------------------------- ### Create Ballerina Project with Service Template Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/news_alerts/A Guide on GraphQL Subscriptions with Apache Kafka in Ballerina.md Command to initialize a new Ballerina project named 'news_alerts' using the 'service' template. This command sets up the basic directory structure for a Ballerina service. ```shell bal new news_alerts --template service ``` -------------------------------- ### GraphQL Cache Key Format Examples Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/proposals/server-side-caching.md Illustrates examples of the generated cache key format. Cache keys combine the resource path with a Base64-encoded hash of arguments. These examples show how keys are structured for fields with and without arguments. ```text profile.name.#[(id)] profile.friends.#[(id),{...},[ids]] ``` -------------------------------- ### Implement Ballerina GraphQL Query Type with Resource Function Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/ballerina/README.md Example of a Ballerina GraphQL service defining a `get` resource function, which automatically maps to a field in the GraphQL `Query` root type. It demonstrates how to create a simple 'greeting' query that accepts a string argument and returns a string. ```ballerina import ballerina/graphql; service graphql:Service /graphql on new graphql:Listener(4000) { resource function get greeting(string name) returns string { return "Hello, " + name; } } ``` -------------------------------- ### Example GraphQL Query for Greeting Field Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/README.md Provides a sample GraphQL query demonstrating how to call the `greeting` field defined in the Ballerina GraphQL service, passing a `name` argument to retrieve a personalized greeting. ```GraphQL { greeting(name: "John") } ``` -------------------------------- ### Create Ballerina GraphQL Listener from Mutual SSL HTTP Listener Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md This example demonstrates how to create a Ballerina GraphQL listener by utilizing an existing HTTP listener that has already been configured for mutual SSL. This method simplifies the setup by inheriting the mutual SSL settings from the underlying HTTP listener. ```ballerina listener http:Listener securedHttpListener = new(9090, secureSocket = { key: { certFile: "/path/to/public.crt", keyFile: "/path/to/private.key" }, mutualSsl: { verifyClient: http:REQUIRE, cert: "/path/to/public.crt" }, protocol: { name: http:TLS, versions: ["TLSv1.2", "TLSv1.1"] }, ciphers: ["TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"] } ); listener graphql:Listener securedGraphqlListener = new (securedHttpListener); service on securedGraphqlListener { resource function get greeting() returns string { return "Hello, World!"; } } ``` -------------------------------- ### Example GraphQL Query for Lifts Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/snowtooth/GraphQL Snowtooth Example with Ballerina.md A sample GraphQL query to retrieve all open lifts. It fetches the lift's name, ID, and details about associated trail access, including trail name and difficulty. ```GraphQL { allLifts(status: OPEN) { name id trailAccess { name difficulty } } } ``` -------------------------------- ### Example GraphQL Query for Greeting Field Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/ballerina/README.md A GraphQL document demonstrating how to query the `greeting` field defined in the Ballerina GraphQL service. This query passes a 'John' argument to the `name` parameter. ```graphql { greeting(name: "John") } ``` -------------------------------- ### Ballerina Service Project Directory Structure Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/news_alerts/A Guide on GraphQL Subscriptions with Apache Kafka in Ballerina.md Illustrates the typical file and directory layout created after initializing a new Ballerina project with the 'service' template, including configuration, service code, and test files. ```shell news_alert ├── Ballerina.toml ├── service.bal └── tests └── service_test.bal ``` -------------------------------- ### GraphQL Query for Error Handling Example Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md A GraphQL query document used to test the Ballerina service that returns an error when an invalid input is provided. ```graphql { greeting(name: "") } ``` -------------------------------- ### Implement GraphQL Query Fields in Ballerina Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/news_alerts/A Guide on GraphQL Subscriptions with Apache Kafka in Ballerina.md This code illustrates how to represent GraphQL `Query` type fields in Ballerina. It uses `resource` methods with the `get` accessor to define queries for `users` and `publishers`, retrieving data from in-memory tables and ensuring thread safety with `lock`. ```ballerina resource function get users() returns readonly & User[] { lock { return from User user in userTable select user.cloneReadOnly(); } } resource function get publishers() returns readonly & Publisher[] { lock { return from Publisher publisher in publisherTable select publisher.cloneReadOnly(); } } ``` -------------------------------- ### Create Ballerina GraphQL Listener from HTTP Listener Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/README.md Shows how to create a `graphql:Listener` by wrapping an existing `http:Listener`. This approach allows for more control over the underlying HTTP server configuration and integration with existing HTTP setups. ```Ballerina import ballerina/graphql; import ballerina/http; listener http:Listener httpListener = check new(4000); listener graphql:Listener graphqlListener = check new(httpListener); ``` -------------------------------- ### Implement GraphQL Subscription Field in Ballerina Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/news_alerts/A Guide on GraphQL Subscriptions with Apache Kafka in Ballerina.md This example shows how to define a GraphQL `Subscription` type field in Ballerina using a `resource` method with the `subscribe` accessor. It demonstrates returning a `stream` by utilizing a `StreamGenerator` to provide real-time news updates based on user ID and agency, ensuring user registration before creating the stream. ```ballerina resource function subscribe news(string userId, Agency agency) returns stream|error { stream newsStream; lock { if userTable.hasKey(userId) { NewsStream newsStreamGenerator = check new (userId, agency); newsStream = new (newsStreamGenerator); } else { return error("User not registered"); } } return newsStream; } ``` -------------------------------- ### Implement GraphQL Mutation Fields in Ballerina Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/news_alerts/A Guide on GraphQL Subscriptions with Apache Kafka in Ballerina.md This snippet demonstrates how to implement GraphQL `Mutation` type fields using Ballerina's `remote` methods. It includes examples for `publish` (news updates), `registerUser`, and `registerPublisher` operations, showcasing data manipulation and the use of `lock` for concurrency control. ```ballerina remote function publish(NewsUpdate & readonly update) returns NewsRecord|error { lock { if publisherTable.hasKey(update.publisherId) { return produceNews(update).cloneReadOnly(); } } return error("Invalid publisher"); } remote function registerUser(NewUser newUser) returns User { string id = uuid:createType1AsString(); lock { User user = {id: id, ...newUser.cloneReadOnly()}; userTable.put(user); return user.cloneReadOnly(); } } remote function registerPublisher(NewPublisher newPublisher) returns Publisher { string id = uuid:createType1AsString(); lock { Publisher publisher = {id: id, ...newPublisher.cloneReadOnly()}; publisherTable.put(publisher); return publisher.cloneReadOnly(); } } ``` -------------------------------- ### Instantiate Ballerina GraphQL Service Object and Attach Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md Illustrates how to instantiate a GraphQL service using a service object, providing full control over its lifecycle. It shows attaching the service object to a listener and starting the listener in a main function. ```ballerina graphql:Service graphqlService = service object { resource function get greeting() returns string { return "Hello, world!"; } } public function main() returns error? { graphql:Listener graphqlListener = check new (9090); check graphqlListener.attach(graphqlService, "graphql"); check graphqlListener.'start(); runtime:registerListener(graphqlListener); } ``` -------------------------------- ### Generated GraphQL Schema for Ballerina Mutation Example Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/README.md Shows the GraphQL schema automatically generated from the Ballerina service, including `Query`, `Mutation`, and `Person` types. ```graphql type Query { profile: Person! } type Mutation { updateName(name: String!): Person! updateCity(city: String!): Person! } type Person { name: String! age: Int! city: String! } ``` -------------------------------- ### Configure Operation-level Caching for Ballerina GraphQL Query Operations Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md Provides examples for enabling and configuring operation-level caching for GraphQL `query` operations using the `cacheConfig` field in `@graphql:ServiceConfig`. The first example shows enabling with default values (`enabled: true`, `maxAge: 60` seconds). The second example demonstrates explicit configuration of `enabled`, `maxAge` (TTL in seconds), and `maxSize` for the server-side operation cache. ```ballerina @graphql:ServiceConfig { cacheConfig: {} } service on new graphql:Listener(9090) { // ... } ``` ```ballerina @graphql:ServiceConfig { cacheConfig: { enabled: true maxAge: 100, maxSize: 150 } } service on new graphql:Listener(9090) { // ... } ``` -------------------------------- ### Example GraphQL Query for Authors and Books Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/proposals/graphql-dataloader.md This GraphQL query demonstrates how to fetch author names and their associated book titles from the GraphQL API after DataLoader integration. It illustrates the client-side query structure. ```graphql { authors { name books { title } } } ``` -------------------------------- ### cURL Example for Multiple GraphQL File Upload Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/proposals/file-upload.md A cURL command illustrating how to upload multiple files in a single GraphQL multipart request. This example shows an array for the file variable, multiple entries in the 'map' field, and multiple file attachments. ```curl curl localhost:9090/graphql \ -F operations='{ "query": "mutation($file: [Upload!]) { filesUpload(file: $file) { link } }", "variables": { "file": [null, null] } }' \ -F map='{ "0": ["variables.file.0"], "1": ["variables.file.1"]}' \ -F 0=@file1.png -F 1=@file2.png ``` -------------------------------- ### Create Ballerina GraphQL Listener from SSL/TLS HTTP Listener Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md This example illustrates how to initialize a Ballerina GraphQL listener by passing an already SSL/TLS configured HTTP listener. This approach allows reusing existing HTTP listener security configurations for GraphQL services. ```ballerina listener http:Listener securedHttpListener = new(9090, secureSocket = { key: { certFile: "/path/to/public.crt", keyFile: "/path/to/private.key" } } ); listener graphql:Listener securedGraphqlListener = new (securedHttpListener); service on securedGraphqlListener { resource function get greeting() returns string { return "Hello, World!"; } } ``` -------------------------------- ### Registering Ballerina DataLoaders via `graphql:ContextInit` Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md This example shows how to register `DataLoader` objects within the `graphql:ContextInit` function of a Ballerina GraphQL service. Registering DataLoaders here ensures they are accessible to all resolver functions per request, as DataLoaders are meant to be used per request context. ```ballerina @graphql:ServiceConfig { contextInit: isolated function (http:RequestContext requestContext, http:Request request) returns graphql:Context { graphql:Context context = new; context.registerDataLoader("bookLoader", new dataloader:DefaultDataLoader(batchBooks)); return context; } } service on new graphql:Listener(9090) { // ... } ``` -------------------------------- ### Pull Ballerina Kafka Package Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/news_alerts/A Guide on GraphQL Subscriptions with Apache Kafka in Ballerina.md Command to pull the `ballerinax/kafka` package from Ballerina Central. This package is essential for enabling Kafka connectivity within Ballerina projects, allowing communication with Kafka brokers. ```shell bal pull ballerinax/kafka ``` -------------------------------- ### Configure Ballerina GraphQL Listener with SSL/TLS Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md This example demonstrates how to directly configure a Ballerina GraphQL listener with basic SSL/TLS encryption. It requires specifying the paths to the public certificate file (`certFile`) and private key file (`keyFile`) for secure communication. ```ballerina listener graphql:Listener securedGraphqlListener = new(9090, secureSocket = { key: { certFile: "/path/to/public.crt", keyFile: "/path/to/private.key" } } ); service on securedGraphqlListener { resource function get greeting() returns string { return "Hello, World!"; } } ``` -------------------------------- ### Set Full Height for GraphiQL Client Container Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/native/src/main/resources/graphiql.html This CSS snippet ensures that the HTML, body, and the GraphiQL container element occupy the full viewport height, preventing scrollbars and providing a consistent layout for the GraphiQL interface. ```CSS html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; } #graphiql { height: 100vh; } ``` -------------------------------- ### Example GraphQL Query for Starwars Hero Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/starwars/GraphQL Starwars API (SWAPI) in Ballerina.md A sample GraphQL query demonstrating how to fetch details about a hero from the Starwars API. It includes conditional fragments to retrieve specific information for 'Human' and 'Droid' types, such as name, home planet, and primary function of friends. ```graphql query { hero(episode: EMPIRE) { ...on Human { name homePlanet friends { ...on Droid { name primaryFunction } } } } } ``` -------------------------------- ### Ballerina GraphQL Subscription Resolver with Pipe Integration Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/proposals/subscriptions.md This snippet provides a more complete example of a Ballerina GraphQL subscription resolver. It shows the instantiation of a new `Pipe` for each subscription, adding it to a global `pipes` array, and then returning a stream consumed from that `Pipe`, enabling real-time data push to clients. ```ballerina resource function subscribe message() returns stream { Pipe pipe = new(10); pipes.push(pipe); return pipe.consumeStream(); } ``` -------------------------------- ### Invalid Ballerina GraphQL Resource Accessor (Counter Example) Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md Illustrates an invalid resource method accessor (`post`) for Ballerina GraphQL services, which will result in a compilation error as only `get` and `subscribe` are allowed. ```Ballerina resource function post greeting() returns string { // ... } ``` -------------------------------- ### Get DataLoader from graphql:Context Object Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md This example illustrates how to retrieve a registered DataLoader instance from the `graphql:Context` object using its key. If the specified key does not exist, the `getDataLoader()` method will raise a panic. ```ballerina dataloader:DataLoader authorLoader = context.getDataLoader("authorLoader"); ``` -------------------------------- ### Initialize GraphiQL Client with Dynamic Fetcher Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/native/src/main/resources/graphiql.html This JavaScript code initializes the GraphiQL client upon DOM content loaded. It defines a `createFetcher` function that dynamically determines whether to use HTTP POST for queries/mutations or WebSocket for subscriptions, based on the `WS_ENDPOINT`. It handles WebSocket client creation with retry logic and integrates with `ReactDOM` to render the GraphiQL component. ```JavaScript document.addEventListener("DOMContentLoaded", function () { // Placeholders that will be replaced dynamically const HTTP_ENDPOINT = "${url}"; const WS_ENDPOINT = "${subscriptionUrl}"; function createFetcher() { let wsClient; if (WS_ENDPOINT && WS_ENDPOINT.startsWith("ws")) { wsClient = graphqlWs.createClient({ url: WS_ENDPOINT, retryAttempts: 5, shouldRetry: () => true }); return async (graphQLParams) => { const isSubscription = graphQLParams.query.trim().startsWith("subscription"); if (isSubscription) { return { subscribe: (observer) => { const unsubscribe = wsClient.subscribe(graphQLParams, { next: observer.next, error: observer.error, complete: observer.complete, }); return { unsubscribe }; }, }; } return fetch(HTTP_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/json" }, body: JSON.stringify(graphQLParams) }).then(response => response.json()); }; } return async (graphQLParams) => { return fetch(HTTP_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", "Accept": "application/json" }, body: JSON.stringify(graphQLParams) }).then(response => response.json()); }; } const fetcher = createFetcher(); ReactDOM.createRoot(document.getElementById("graphiql")).render( React.createElement(GraphiQL, { fetcher }) ); }); ``` -------------------------------- ### Run Ballerina Starwars GraphQL Service Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/starwars/GraphQL Starwars API (SWAPI) in Ballerina.md This command is used to build and execute the Ballerina Starwars GraphQL service project. It should be run from within the 'starwars' project directory. ```shell bal run ``` -------------------------------- ### Enable Field-level Caching and Invalidation in Ballerina GraphQL Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md This example demonstrates how to enable field-level caching for a GraphQL service in Ballerina. It shows configuring `cacheConfig` for a resource function (`get friends`) and how to invalidate specific cache entries (`friends.age`) using `context.invalidate()` when data changes. It also illustrates how a field (`isMarried`) can be explicitly excluded from caching. ```ballerina import ballerina/graphql; type Friend record { readonly string name; int age; boolean isMarried; }; service /graphql on new graphql:Listener(9090) { private table key(name) friends = table [ {name: "Skyler", age: 45, isMarried: true}, {name: "Jesse Pinkman", age: 23, isMarried: false} ]; @graphql:ResourceConfig { cacheConfig: { enabled: true, maxAge 20 } } isolated resource function get friends(boolean isMarried = false) returns Person[] { if isMarried { return from Friend friend in self.friends where friend.isMarried == true select new Person(friend.name, friend.age, isMarried); } return from Friend friend in self.friends where friend.isMarried == false select new Person(friend.name, friend.age, isMarried); } isolated remote function updateAge(graphql:Context context, string name, int age) returns Person|error { check context.invalidate("friends.age"); Friend friend = self.friends.get(name); self.friends.put({name: name, age: age, isMarried: friend.isMarried}); return new Person(name, age, friend.isMarried); } } public isolated distinct service class Person { private final string name; private final int age; private final boolean isMarried; public isolated function init(string name, int age, boolean isMarried) { self.name = name; self.age = age; self.isMarried = isMarried; } isolated resource function get name() returns string { return self.name; } isolated resource function get age() returns int { return self.age; } @graphql:ResourceConfig { cacheConfig: { enabled: false } } isolated resource function get isMarried() returns boolean { return self.isMarried; } } ``` -------------------------------- ### Create Standalone Ballerina GraphQL Listener Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/ballerina/README.md Demonstrates how to initialize a `graphql:Listener` directly with a port number, setting up a new GraphQL server instance that listens for incoming requests. ```ballerina import ballerina/graphql; listener graphql:Listener graphqlListener = check new(4000); ``` -------------------------------- ### Example GraphQL Query for Repository Details Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/simple_github_issue_tracker/Integrating Multiple Endpoints to Expose as a GraphQL API in Ballerina.md A sample GraphQL query to retrieve comprehensive details for repositories, including basic information like ID, name, description, and creation date, as well as specific attributes like fork status, language, issue count, and license information. ```graphql query MyQuery { repositories { id name description fork createdAt updatedAt language hasIssues forksCount openIssuesCount lisense { name } } } ``` -------------------------------- ### Apply GraphQL Field Interceptors to a Resource Function Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/proposals/field-interceptors.md This Ballerina example demonstrates how to apply field interceptors to a specific GraphQL resource function. The `@graphql:ResourceConfig` annotation is used to specify an array of interceptor instances (`SubscriptionInterceptor1`, `SubscriptionInterceptor2`) that will be executed before and after the `get name()` resolver function. This allows for custom logic to be injected into the GraphQL execution flow for a particular field. ```Ballerina @graphql:ResourceConfig { interceptors: [new SubscriptionInterceptor1(), new SubscriptionInterceptor2()] } isolated resource function get name() returns string { } ``` -------------------------------- ### Gradle Build and Test Commands for Ballerina Module Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/README.md This section provides a collection of Gradle commands for various development tasks related to the Ballerina module. These commands cover building the package, running tests, executing specific test groups, skipping tests, and debugging with remote or Ballerina language debuggers, as well as publishing artifacts. ```bash ./gradlew clean build ``` ```bash ./gradlew clean test ``` ```bash ./gradlew clean test -Pgroups= ``` ```bash ./gradlew clean build -x test ``` ```bash ./gradlew clean build -Pdebug= ``` ```bash ./gradlew clean build -PbalJavaDebug= ``` ```bash ./gradlew clean build -PpublishToLocalCentral=true ``` ```bash ./gradlew clean build -PpublishToCentral=true ``` -------------------------------- ### Provide Inline GraphQL Service Context Initializer Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md Demonstrates how to define the `contextInit` function inline within the `@graphql:ServiceConfig` annotation for a GraphQL service. ```ballerina @graphql:ServiceConfig { contextInit: isolated function(http:RequestContext requestContext, http:Request request) returns graphql:Context|error { // ... } } ``` -------------------------------- ### Get Attribute from graphql:Context Object Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md This snippet illustrates how to retrieve an attribute from the `graphql:Context` object using its key. The `get` method returns a `graphql:Error` if the key does not exist in the context. ```ballerina value:Cloneable|isolated object {}|graphql:Error attribute = context.get("key"); ``` -------------------------------- ### Initialize Ballerina GraphQL Client Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md Demonstrates how to create a new instance of the `graphql:Client` in Ballerina, specifying the GraphQL service URL and optional configuration like timeout. This client is essential for connecting to and interacting with GraphQL services. ```ballerina graphql:Client graphqlClient = check new (“http://localhost:9090/graphql”, {timeout: 10}); ``` -------------------------------- ### Get GraphQL Subfield Names in Ballerina Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md Shows how to get the names of subfields for the currently executing GraphQL field using the `getSubfieldNames()` method of the `graphql:Field` object. An empty array is returned if no subfields exist. ```ballerina service on new graphql:Listener(9090) { resource function get profile(graphql:Field 'field) returns Profile { string[] subfieldNames = 'field.getSubfieldNames(); } } ``` -------------------------------- ### Default GraphQL Service Context Initializer Function Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md The default implementation for the `contextInit` function when it is not explicitly provided in the service configuration. It initializes and returns a new `graphql:Context`. ```APIDOC isolated function initDefaultContext(http:RequestContext requestContext, http:Request request) returns Context|error { return new; } ``` -------------------------------- ### Create Standalone Ballerina GraphQL Listener Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/README.md Demonstrates how to initialize a `graphql:Listener` by providing a port number directly. This listener is used to accept incoming GraphQL requests on the specified port. ```Ballerina import ballerina/graphql; listener graphql:Listener graphqlListener = check new(4000); ``` -------------------------------- ### Implement Basic Authentication with File User Store for Ballerina GraphQL Service Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md This example demonstrates how to set up basic authentication for a Ballerina GraphQL service using a file-based user store. It includes a Ballerina service with a custom `AuthInterceptor` to handle authentication and authorization, and a `Config.toml` file to define user credentials and roles. ```ballerina final http:ListenerFileUserStoreBasicAuthHandler handler = new; isolated function contextInit(http:RequestContext reqCtx, http:Request request) returns graphql:Context|error { string authorization = check request.getHeader("Authorization"); graphql:Context context = new; context.set("Authorization", authorization); return context; } readonly service class AuthInterceptor { *graphql:Interceptor; isolated remote function execute(graphql:Context context, graphql:Field 'field) returns anydata|error { value:Cloneable|isolated object {} authorization = check context.get("Authorization"); if authorization !is string { return error("Failed to authorize"); } auth:UserDetails|http:Unauthorized authn = handler.authenticate(authorization); if authn is http:Unauthorized { return error("Unauthorized"); } http:Forbidden? authz = handler.authorize(authn, "admin"); if authz is http:Forbidden { return error("Forbidden"); } return context.resolve('field); } } @graphql:ServiceConfig { contextInit: contextInit, interceptors: new AuthInterceptor() } service on new graphql:Listener(9090) { resource function get greeting(graphql:Context context) returns string { return "welcome"; } } ``` ```toml [[ballerina.auth.users]] username="alice" password="alice@123" scopes=["developer"] [[ballerina.auth.users]] username="bob" password="bob@123" scopes=["developer", "admin"] ``` -------------------------------- ### Handle Errors in Ballerina GraphQL Resource Functions Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/ballerina/README.md This example demonstrates how a Ballerina GraphQL `resource` or `remote` method can return an `error` type. When an error is returned, it is propagated to the GraphQL client in the standard GraphQL error format, as shown by the example query and its JSON error response. ```ballerina public type Person record {| string name; int age; }; resource function get profile(int id) returns Person|error { if (id == 1) { return { name: "Walter White", age: 51 }; } else { return error(string `Invalid ID provided: ${id}`); } } ``` ```graphql { profile(id: 5) { name } } ``` ```json { "errors": [ { "message": "Invalid ID provided: 5", "locations": [ { "line": 2, "column": 4 } ] } ] } ``` -------------------------------- ### Ballerina GraphQL Service with @graphql:ID Annotation Examples Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/proposals/scalar-type-id.md This comprehensive Ballerina code demonstrates the practical application of the `@graphql:ID` annotation within a GraphQL service. It showcases its usage on various resource function parameters (e.g., `floatId`, `decimalId`, `intId`, `uuidId`, `stringId`, `stringIds`, `floatIds`), on a record field (`Person.id`), and on a resource function's return type (`Student.id`). These examples illustrate how to designate unique identifiers for GraphQL operations in Ballerina. ```ballerina listener graphql:Listener basicListener = new (9091); service /id_annotations on basicListener { resource function get floatId(@graphql:ID float? floatId) returns string { return "Hello, World"; } resource function get decimalId(@graphql:ID decimal? decimalId) returns string { return "Hello, World"; } resource function get intIdReturnRecord(@graphql:ID int intId) returns Student { return new Student(2, "Jennifer Flackett"); } resource function get uuidArrayReturnRecord(@graphql:ID uuid:Uuid[] uuidId) returns Student { return new Student5(563, "Aretha Franklin"); } resource function get stringIdReturnRecord(@graphql:ID string stringId) returns Person { return {id: 543, name: "Marmee March", age: 12}; } resource function get stringArrayReturnRecordArray(@graphql:ID string[] stringIds) returns Person[] { return [ {id: 789, name: "Beth Match", age: 15}, {id: 678, name: "Jo March", age: 16}, {id: 543, name: "Amy March", age: 12} ]; } resource function get floatArrayReturnRecordArray(@graphql:ID float[] floatIds) returns Person[] { return [ {id: 789, name: "Beth Match", age: 15}, {id: 678, name: "Jo March", age: 16}, {id: 543, name: "Amy March", age: 12} ]; } } public type Person record { @graphql:ID int id; string name; int age; }; public distinct service class Student { final int id; final string name; function init(int id, string name) { self.id = id; self.name = name; } resource function get id() returns @graphql:ID int { return self.id; } resource function get name() returns string { return self.name; } } ``` -------------------------------- ### Implement Basic Authentication with LDAP User Store for Ballerina GraphQL Service Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md This example shows how to configure basic authentication for a Ballerina GraphQL service using an LDAP user store. It defines an `LdapUserStoreConfig` and uses an `http:ListenerLdapUserStoreBasicAuthHandler` to authenticate users against an LDAP directory, similar to the file-based approach but with LDAP integration. ```ballerina graphql:LdapUserStoreConfig config = { domainName: "bcssl.lk", connectionUrl: "ldap://localhost:389", connectionName: "cn=admin,dc=bcssl,dc=lk", connectionPassword: "bcssl123", userSearchBase: "ou=Users,dc=bcssl,dc=lk", userEntryObjectClass: "inetOrgPerson", userNameAttribute: "uid", userNameSearchFilter: "(&(objectClass=inetOrgPerson)(uid=?))", userNameListFilter: "(objectClass=inetOrgPerson)", groupSearchBase: ["ou=Groups,dc=bcssl,dc=lk"], groupEntryObjectClass: "groupOfNames", groupNameAttribute: "cn", groupNameSearchFilter: "(&(objectClass=groupOfNames)(cn=?))", groupNameListFilter: "(objectClass=groupOfNames)", membershipAttribute: "member", userRolesCacheEnabled: true, connectionPoolingEnabled: false, connectionTimeout: 5, readTimeout: 60 }; final http:ListenerLdapUserStoreBasicAuthHandler handler = new (config); isolated function contextInit(http:RequestContext reqCtx, http:Request request) returns graphql:Context|error { string authorization = check request.getHeader("Authorization"); graphql:Context context = new; context.set("Authorization", authorization); return context; } readonly service class AuthInterceptor { *graphql:Interceptor; isolated remote function execute(graphql:Context context, graphql:Field 'field) returns anydata|error { value:Cloneable|isolated object {} authorization = check context.get("Authorization"); if authorization !is string { return error("Failed to authorize"); } auth:UserDetails|http:Unauthorized authn = handler->authenticate(authorization); if authn is http:Unauthorized { return error("Unauthorized"); } http:Forbidden? authz = handler->authorize(authn, "admin"); if authz is http:Forbidden { return error("Forbidden"); } return context.resolve('field); } } @graphql:ServiceConfig { contextInit: contextInit, interceptors: new AuthInterceptor() } service on new graphql:Listener(9090) { resource function get greeting(graphql:Context context) returns string { return "welcome"; } } ``` -------------------------------- ### Utilize DataLoader with `prefetch` Method in Ballerina GraphQL Service Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md A comprehensive example demonstrating the full integration of a DataLoader with a Ballerina GraphQL service. It shows how to register a DataLoader in the service context, use the `prefetch` method (`preBooks`) to add keys to the DataLoader, and then retrieve batched data from the DataLoader in the main resource function (`books`). Includes an `isolated function` for batching. ```ballerina import ballerina/graphql; import ballerina/graphql.dataloader; import ballerina/http; @graphql:ServiceConfig { contextInit: isolated function (http:RequestContext requestContext, http:Request request) returns graphql:Context { graphql:Context context = new; context.registerDataLoader("bookLoader", new dataloader:DefaultDataLoader(batchBooksForAuthors)); return context; } } service on new graphql:Listener(9090) { resource function get authors() returns Author[] { return getAllAuthors(); } } distinct service class Author { private final int authorId; function init(int authorId) { self.authorId = authorId; } resource function get preBooks(graphql:Context ctx) { dataloader:DataLoader bookLoader = ctx.getDataLoader("bookLoader"); // Load author id to the DataLoader bookLoader.add(self.authorId); } resource function get books(graphql:Context ctx) returns Book[] { dataloader:DataLoader bookLoader = ctx.getDataLoader("bookLoader"); // Obtain the books from the DataLoader by passing the author id Book[] books = bookLoader.get(self.authorId); return books; } } isolated function batchBooksForAuthors(readonly & anydata[] ids) returns Book[][]|error { final readonly & int[] authorIds = ids; // Logic to retrieve books from the data source for the given author ids // Book[][] books = ... return books; }; ``` -------------------------------- ### GraphQL Document for Executing Mutations Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/README.md Example GraphQL mutation document to update `Person` fields (`name`, `city`) using the defined mutations and a fragment. ```graphql mutation updatePerson { updateName(name: "Mr. Lambert") { ... ProfileFragment } updateCity(city: "New Hampshire") { ... ProfileFragment } } fragment ProfileFragment on Person { name city } ``` -------------------------------- ### Valid Ballerina GraphQL Resource Accessor Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md Demonstrates a valid resource method accessor (`get`) for Ballerina GraphQL services, which maps to a Query field. ```Ballerina resource function get greeting() returns string { // ... } ``` -------------------------------- ### Define Ballerina GraphQL Service with GraphiQL Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/examples/news_alerts/A Guide on GraphQL Subscriptions with Apache Kafka in Ballerina.md This snippet demonstrates how to define a GraphQL service in Ballerina using the `ballerina/graphql` package. It shows how to enable the built-in GraphiQL client for testing purposes by configuring the `graphql:ServiceConfig` annotation with a configurable variable `ENABLE_GRAPHIQL`. ```ballerina import ballerina/graphql; configurable boolean ENABLE_GRAPHIQL = ?; @graphql:ServiceConfig { graphiql: { enabled: ENABLE_GRAPHIQL } } service /news_alert on new graphql:Listener(9090) { // Implement the resource and remote methods here } ``` -------------------------------- ### Enable and Customize GraphiQL Client for Ballerina GraphQL Service Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md Shows how to enable and configure the GraphiQL client for a GraphQL service using the `graphiql` field in `@graphql:ServiceConfig`. It demonstrates enabling the client (`enabled: true`), setting a custom access path (`path: "/ballerina/graphiql"`), and controlling whether the GraphiQL URL is printed to stdout (`printUrl: false`). By default, `enabled` is `false`, `path` is `/graphiql`, and `printUrl` is `true`. ```ballerina @graphql:ServiceConfig { graphiql: { enabled: true, path: "/ballerina/graphiql", printUrl: false } } service on new graphql:Listener(9090) { // ... } ``` -------------------------------- ### GraphQL @skip Directive Usage Example Source: https://github.com/ballerina-platform/module-ballerina-graphql/blob/master/docs/spec/spec.md Demonstrates the use of the `@skip` directive in a GraphQL query to conditionally omit a field (`name`) based on a boolean variable (`$skipName`). ```GraphQL query getProfile ($skipName: Boolean!) { profile(id: 1) { name @skip(if: $skipName) age } } ```