2023-01-11

[Flutter] Katana Functions

Adapter plug-ins for server integration such as Cloud Functions for Firebase.

The interface with the API is implemented and used on the client side, allowing secure interaction with the server side.

Installation

Import the following packages

flutter pub add katana_functions

If you use Cloud Functions for Firebase, import the following packages as well.

flutter pub add katana_functions_firebase

Implementation

Advance preparation

Always place the FunctionsAdapterScope widget near the root of the app.

Pass a FunctionsAdapter such as RuntimeFunctionsAdapter as the parameter of adapter.

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return FunctionsAdapterScope(
      adapter: const RuntimeFunctionsAdapter(),
      child: MaterialApp(
        home: const FunctionsPage(),
        title: "Flutter Demo",
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
      ),
    );
  }
}

Create Function

The following must be complied with as a prerequisite for creating a Function.

  • Preliminary server side has been implemented and deployed separately.
  • All input/output to/from server side is done in JsonMap (Map<String, dynamic>) .
    • No problem if it can be adjusted in FunctionsAdapter in the end.
  • Returns Exception if communication is not successful.

As long as the above is observed, any communication format such as CloudFunctions, RestAPI, GraphQL, gRPC, etc. can be used. (Differences can be absorbed by the FunctionsAdapter)

Create a Function by inheriting from the abstract classes FunctionsAction<TResponse> and FunctionsActionResponse.

Define the action name of the Function in the action of the FunctionsAction<TResponse> and define the parameters to be passed to the server side in the toMap().

Create a response based on the values returned from the server to toResponse(DynamicMap map).

class TestFunctionsAction extends FunctionsAction<TestFunctionsActionResponse> {
  const TestFunctionsAction({
    required this.responseMessage,
  });

  final String responseMessage;

  @override
  String get action => "test";

  @override
  DynamicMap? toMap() {
    return {
      "message": responseMessage,
    };
  }

  @override
  TestFunctionsActionResponse toResponse(DynamicMap map) {
    return TestFunctionsActionResponse(
      message: map["message"] as String,
    );
  }
}

class TestFunctionsActionResponse extends FunctionsActionResponse {
  const TestFunctionsActionResponse({required this.message});

  final String message;
}

Using Functions

Create a Functions object as follows and pass the FunctionAction you wish to execute to the execute method.

If the execution is successful, the response specified in the return value of execute is returned.

final functions = Functions();
final response = await functions.execute(
  TestFunctionsAction(responseMessage: "Response"),
);
print(response?.message); // "Response"

FunctionsAdapter

The following FunctionsAdapter is available

  • RuntimeFunctionsAdapter:FunctionsAdapter that completes without server processing and without error. available as a stub.
  • FirebaseFunctionsAdapter: FunctionsAdapter for using FirebaseFunctions, where action is the name of the Function.

It is also possible to link with RestAPI, GraphQL, and gRPC that you have prepared yourself by inheriting FunctionsAdapter.

GitHub Sponsors

Sponsors are always welcome. Thank you for your support!

Developed the katana/masamune framework, which has dramatically improved the overall efficiency of Flutter-based application development.
https://github.comhttps://github.com
title