Skip to content

rekabhq/fantom

Repository files navigation

Fantom

Bloc

Fantom is a cli tool for generating API layer in dart language based on OpenAPI Spec.

With fantom you can simply take an openapi file and generate all the code you need for your api. we do not impose

Get Started Quickly

  1. Install fantom
    $ dart pub global activate fantom
  2. Generate API client
    $ fantom generate openapi.yaml --dir=lib/src/network 
    Result: it will generate models in lib/src/network/model directory and APIs in lib/src/network/api directory

NOTE: you're openapi file can be in json or yaml format.

More Advanced Options

  • Separate models and APIs directories

    $ fantom generate openapi.yaml --model-dir=lib/src/model --api-dir=lib/src/network
  • Generate API layer as a standalone dart package

    $ fantom generate openapi.yaml --package=packages/network

    Note: it will generates a package called network inside packages/network from where fantom generate command runs.

Use a config file instead of cli

With fantom you can define all youre configuration once inside a fantom.yaml file or your project's pubspec.yaml file once and then every time you want to generate you're network client code you simply just run below commands

  • Define configs inside project's pubspec.yaml or create a fantom.yaml and run command
$ fantom generate 

NOTE: you can use a any yaml (or json) file to define you're fantom config in then run generate command with path to file

$ fantom generate my-config.yaml 

Here is an example of fantom config file

  • Simple fantom configuration
fantom:
  openapi: path/to/openapi/file 
  api-dir: packages/network/lib
  model-dir: packages/network/lib/models
  package-name: network
  • Fantom config for standalone network client package
fantom:
  openapi: path/to/openapi/file 
  package: path/to/export/package/
  package-name: my_network_client
  recreate-package: false # by default is true

by default recreate-package is set to true. which deletes the old generated network client package completely each time you run generate command. if you set it to false only the generated files inside the lib directory of the generated package will be removed and new one will replace them

NOTE: fantom uses the file header in generated files to recognize they are generated by fantom. same recognision method is used when deleting generated files, so try not to edit the file header by hand.

Side Note: fantom almost everywhere uses the same method to read json or yaml files the file name and extension is irrelevent to fantom just the file content should be in valid format whether it is json or yaml. you can even write your fantom config in json format if you need to

Read openapi file from URL

With fantom it is possible to path a url as the source of openapi file.

NOTE: you must also provide a path to store the downloaded file

here is how your fantom config will look like

fantom:
  openapi: https://myopenapi.com/source/of/openapi
  download-path: where/to/save/openapi.json 
  api-dir: packages/network/lib
  model-dir: packages/network/lib/models
  package-name: network

Exclude Paths and Components

you can exclude some paths and components from being generated by fantom cli. what happens is fantom will read the openapi files and then remove the paths and components you excluded so they won't be generated.

you can add the components and path you want to your fantom config to be excluded like below example

fantom:
  openapi: openapi_files/petstore.openapi.json
  package: path/to/package/
  package-name: my_api_package
  excluded-paths:
    - /pet -- [get, post] # only exclude get & post operation
    - /pet/findByStatus # when no operation specified everything gets excluded
  excluded-components:
    - components/schemas/Shalgham

Use the Generated code

Create an instance of the api class

import 'package:network/api.dart';

void createApiInstance(){
  final dio = provideDio();
  final api = FantomApi(dio);
}

Fantom uses Dio and needs an instance of Dio to operate. Note that we do not impose any custom or extra configurations to the Dio instance provided. so you can be sure you're in control of how you configure you're Dio instance

Understand Api method options

A Fantom generated api method will have extra parameters to give you more ability to customize the request you want to send

Here is an example of an api method generated

Future<Result<ChatMessageListWrapper, Exception>> getMessages({
  ...
  // define custom content type for request
  String? contentType, 
  // define custom content type for response
  String? responseContentType, 
  // useCompute will make deserialization to run on a different Isolate
  bool useCompute = false, 
  // add new or override headers
  Map<String, String>? extraHeaders,
  // path a CancelToken so you will be able to cancel request
  CancelToken? cancelToken,
}) async {

Understand return type Result

Generated api methods will have a return type of Future<Result<MODEL,Exception>> if the return type specified in openapi file is MODEL.

a Result object allows you to check whether the request was successful or not you can do that simply by

final result = await fantomApi.userApi.getUserProfile();

if (result.isSuccessful) {
  // show profile
} else {
  // show error
}

Set Exception Mapper

Fantom provide exception mapping. this feature is very usefull to map network exceptions to something that can be easily used and understood by your logic or ui layer

FantomExceptionMapping.setMapper((final Exception e, stacktrace) {
    _log(e);
    _log(stacktrace);

    if (e is SocketException) {
      return MyCustomError(S.current.noInternet, exception: e);
    }
    if (e is FormatException) {
      return MyCustomError(S.current.somethingWentWrongTryAgain, exception: e);
    }
    if (e is DioError) {
      // return something else
    }
});

Custom request body

Fantom provides each method that requires a body to be completely customzied. there are times that you need to completely customize the request body. Fantom provides this option. here is an example

final customDioRequestBody = SetPaymentRequestBody.custom({
    "method": 'credit_card',
    "price": {"amount": price, "currency": "USD"},
  });

final result = await fantomApi.paymentApi.setPayment(
  rideCode: task.ride.code,
  body: body,
);

Another example

final pictureUploadingResult = await fantomApi.userApi.uploadAvatar(
  body: UploadAvatarRequestBody.custom(
    FormData.fromMap(
      {'avatar': MultipartFile.fromFileSync(avatarFilePath)},
    ),
  ),
  extraHeaders: {
    "Authorization": "Bearer ${_currentAccessToken}",
  },
);

About

OpenAPI generator for Dart & Flutter

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages