A complete Flutter example to use hypi cli

In this article, I will explain and demonstrate how to access Hypi CLI GitHub - hypi-universe/cli: Hypi CLI from Flutter application

Install Flutter
Follow the instructions here to install Flutter on your operating system

Create Flutter application
Create Flutter applications using the guidelines here
or use ready-made example GitHub - hypi-universe/hypi-cli-flutter-example

Getting Started with Hypi cli
Install Hypi cli
npm install -g @hypi/cli

Getting started
Config
This command helps you configure the CLI. If you are using the cloud version of Hypi then you don’t need to use this but if you’re on-premise then it helps you set the Hypi API URL that the CLI will send API requests to

$ hypi config https://hypi.on-premise-domain.com
$ hypi config -a=https://hypi.on-premise-domain.com
$ hypi config --api_domain=https://hypi.on-premise-domain.com

Make sure to login again after each time you change your config through the Config command

Login
The next step is to log in to your Hypi account
On the command line, go to your Flutter application folder. Login to your Hypi account using hypi login command.
hypi login Login with a user name and password
hypi login -d Login with organization namespace and Authorization token from here Hypi.Tink
After successful login, the user config file will be placed in ~/.config/hypi/config.json . In case of Windows, the file will be created in \Users\user\AppData\Local

Init
Use the init command to initialize a new hypi App and Instance in your Flutter project folder.
hypi init.hypi folder will be created with app.yaml, instance.yaml and schema.graphql files which contains information about App, Instance and the graphql schema

Make sure to write your graphql schema inside the schema.graphql file

In our example, we will use the following schema
Update /.hypi/schema.graphql with the following schema

type Product {
    title: String!
    description: String!
    price: Float
}

Sync
The next step is to sync your local schema and get the full schema.
run the following command
hypi syncafter successful sync, generated-schema.graphql file gets generated in the .hypi folder that has full hypi schema.

Generate
Now it is time to generate the Flutter graphql dart code
The first step is to create your graphql queries and mutations inside /graphql

We will add queries to get all products

  1. Find all products /graphql/products.graphql
query ProductsData($arcql: String!)
{
    find(type:Product, arcql: $arcql){
        edges {
            node{
                ... product
            }
        }
    }
}

fragment product on Product {
    hypi {
        id
    }
    title
    description
}

Now after you created the graphql queries and mutations, use the command generate to generate the Flutter graphql dart code so that you can use Hypi APIs within your project.

hypi generate flutter
hypi generate -p=flutter
hypi generate --platform=flutter

After running the command, graphql.ts files get created in the \lib\models\graphql folder.

We will use the generated files inside the flutter dart file to display a list of products.

Configuration
You have to add my_config.dart inside /lib folder, which have to contain the domain and the token

const String domain = ''; // read from .hypi/instance.yaml
const String token = 'your access token';

Configure Artemis client
You have to configure the Artemis client and set the headers with the domain and token defined in my_config.dart
/lib/auth.dart

import 'package:http/http.dart' as http;
import './my_config.dart' as config show domain, token;

class AuthenticatedClient extends http.BaseClient {
  final http.Client _inner = http.Client();

  Future<http.StreamedResponse> send(http.BaseRequest request) {
    var myData = {};
    myData["domain"] = config.domain;
    myData["token"] = config.token;

    request.headers['Authorization'] = 'Bearer ' + myData["token"];
    request.headers['hypi-domain'] = myData["domain"];
    return _inner.send(request);
  }
}

Add Products Model
Now it is time to call the hypi app to get a list of all products using Artemis client and the generated dart graphql files, we will add this inside /lib/models/products.dart

import 'package:artemis/artemis.dart';
import 'package:codegen/models/graphql/graphql.graphql.dart';
import 'package:codegen/auth.dart';

class Products {
  final List<int> _products = [];

  static Future<List<ProductsData$Query$Find$Edges>> getProducts() async {
    final client = ArtemisClient(
      'https://api.hypi.app/graphql',
      httpClient: AuthenticatedClient(),
    );

    final query = ProductsDataQuery(
      variables: ProductsDataArguments(arcql: '*'),
    );

    final response = await client.execute(query);
    client.dispose();

    if (response.hasErrors) {
      print('Error: ${response.errors.map((e) => e.message).toList()}');
      return [];
    }
    return (response?.data?.find?.edges ?? []);
  }
}

Display Products inside flutter widget

`/lib/main.dart

import 'package:flutter/material.dart';
import 'package:artemis/artemis.dart';
import 'package:codegen/models/graphql/graphql.graphql.dart';
import 'package:codegen/auth.dart';
import 'package:codegen/models/products.dart';

void main() async {
  final products = await Products.getProducts();
  runApp(
    ProductsApp(
      products: List<ListItem>.of(products.map((product) => ProductItem(product.node.title, product.node.description))),
    ),
  );
}

class ProductsApp extends StatelessWidget {
  final List<ListItem> products;

  const ProductsApp({Key key, this.products}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    const title = 'Products List';

    return MaterialApp(
      title: title,
      home: Scaffold(
        appBar: AppBar(
          title: const Text(title),
        ),
        body: ListView.builder(
          // Let the ListView know how many items it needs to build.
          itemCount: products.length,
          // Provide a builder function. This is where the magic happens.
          // Convert each item into a widget based on the type of item it is.
          itemBuilder: (context, index) {
            final item = products[index];

            return ListTile(
              title: item.buildTitle(context),
              subtitle: item.buildSubtitle(context),
            );
          },
        ),
      ),
    );
  }
}

/// The base class for the different types of items the list can contain.
abstract class ListItem {
  /// The title line to show in a list item.
  Widget buildTitle(BuildContext context);

  /// The subtitle line, if any, to show in a list item.
  Widget buildSubtitle(BuildContext context);
}

/// A ListItem that contains data to display a product.
class ProductItem implements ListItem {
  final String title;
  final String description;

  ProductItem(this.title, this.description);

  @override
  Widget buildTitle(BuildContext context) => Text(title);

  @override
  Widget buildSubtitle(BuildContext context) => Text(description);
}

After you finish, run the project and you will see a list of products