tvf_flutter_schema 1.1.0 copy "tvf_flutter_schema: ^1.1.0" to clipboard
tvf_flutter_schema: ^1.1.0 copied to clipboard

KOMBU IoT System - GraphQL Schema for Flutter/Dart (Mobile-focused). Provides GraphQL queries, mutations, and a direct GraphQL client for mobile app development with AWS Amplify. Uses GraphQL directly [...]

KOMBU Flutter Schema (Mobile-focused) #

GraphQL schema package for KOMBU IoT System mobile app. This package provides GraphQL queries, mutations, and a direct GraphQL client. Uses GraphQL directly without model classes - all responses are Map<String, dynamic>.

πŸ“¦ Installation #

Add to your pubspec.yaml:

dependencies:
  tvf_flutter_schema:
    path: ../packages/flutter-schema  # Local development
    # or
    # git:
    #   url: https://github.com/your-org/kombu
    #   path: packages/flutter-schema

Then run:

flutter pub get

πŸš€ Usage #

Import #

import 'package:tvf_flutter_schema/tvf_flutter_schema.dart';

Create GraphQL Client #

// Create a GraphQL client instance
final client = GraphQLClient();

Query User #

// Get user by ID
final result = await client.query(
  document: UserQueries.getUser,
  variables: {'id': userId},
);

if (result.hasErrors) {
  print('Error: ${result.errors}');
} else {
  final user = result.data?['getUser'];
  print('User: ${user?['fullName']}');
  print('Email: ${user?['email']}');
}

List Users #

final result = await client.query(
  document: UserQueries.listUsers,
  variables: {
    'filter': {'status': {'eq': 'active'}},
    'limit': 20,
  },
);

if (!result.hasErrors) {
  final items = result.data?['listUsers']?['items'] as List?;
  for (final user in items ?? []) {
    print('User: ${user['email']}');
  }
  
  final nextToken = result.data?['listUsers']?['nextToken'];
  if (nextToken != null) {
    // Load next page
    final nextResult = await client.query(
      document: UserQueries.listUsers,
      variables: {
        'filter': {'status': {'eq': 'active'}},
        'limit': 20,
        'nextToken': nextToken,
      },
    );
  }
}

Update User Profile #

final result = await client.mutate(
  document: UserMutations.updateUser,
  variables: {
    'input': {
      'id': userId,
      'fullName': 'New Name',
      'phoneNumber': '+84123456789',
    },
  },
);

if (!result.hasErrors) {
  final updatedUser = result.data?['updateUser'];
  print('Updated: ${updatedUser?['fullName']}');
} else {
  print('Error: ${result.errors}');
}

Deactivate User (Custom Mutation) #

final result = await client.mutate(
  document: UserMutations.deactivateUser,
  variables: {
    'userId': userId, // or email if useEmail is true
    'useEmail': false,
  },
);

if (!result.hasErrors) {
  final response = result.data?['deactivateUser'];
  if (response?['success'] == true) {
    print('User deactivated successfully');
  } else {
    print('Error: ${response?['error']}');
  }
}

Reactivate User (Custom Mutation) #

final result = await client.mutate(
  document: UserMutations.reactivateUser,
  variables: {
    'userId': userId,
    'useEmail': false,
  },
);

if (!result.hasErrors) {
  final response = result.data?['reactivateUser'];
  if (response?['success'] == true) {
    print('User reactivated successfully');
  } else {
    print('Error: ${response?['error']}');
  }
}

Remove User (Custom Mutation) #

⚠️ Warning: This action is IRREVERSIBLE and will permanently delete the user.

final result = await client.mutate(
  document: UserMutations.removeUser,
  variables: {
    'userId': userId,
    'useEmail': false,
  },
);

if (!result.hasErrors) {
  final response = result.data?['removeUser'];
  if (response?['success'] == true) {
    print('User removed successfully');
  } else {
    print('Error: ${response?['error']}');
  }
}

List Devices #

final result = await client.query(
  document: DeviceQueries.listDevices,
  variables: {
    'filter': {
      'userId': {'eq': userId},
    },
    'limit': 20,
  },
);

if (!result.hasErrors) {
  final items = result.data?['listDevices']?['items'] as List?;
  for (final device in items ?? []) {
    print('Device: ${device['deviceName']}');
    print('Status: ${device['status']}');
  }
}

Create Device #

final result = await client.mutate(
  document: DeviceMutations.createDevice,
  variables: {
    'input': {
      'deviceId': 'ESP32-ABC123',
      'userId': currentUserId,
      'deviceName': 'Living Room Heater',
      'deviceType': 'kombu_brewer',
      'location': 'Living Room',
      'status': 'offline',
    },
  },
);

if (!result.hasErrors) {
  final device = result.data?['createDevice'];
  print('Device created: ${device?['deviceName']}');
}

Update Device #

final result = await client.mutate(
  document: DeviceMutations.updateDevice,
  variables: {
    'input': {
      'id': deviceId,
      'deviceName': 'New Device Name',
      'location': 'Kitchen',
    },
  },
);

if (!result.hasErrors) {
  final device = result.data?['updateDevice'];
  print('Device updated: ${device?['deviceName']}');
}

Push Command to IoT Device #

// Push command using helper method (automatically handles payload stringification)
final result = await PushCommandHelper.pushCommand(
  topic: 'kombu/device-id/down/command',
  payload: {
    'command': 'setTemperature',
    'temperature': 75,
    'heater': 'f1',
  },
);

if (result.success) {
  print('Command sent successfully! Message ID: ${result.messageId}');
} else {
  print('Failed to send command: ${result.error}');
}

Option 2: Using GraphQL Client

final result = await client.mutate(
  document: DeviceMutations.pushCommand,
  variables: {
    'topic': 'kombu/device-id/down/command',
    'payload': jsonEncode({
      'command': 'setTemperature',
      'temperature': 75,
      'heater': 'f1',
    }),
  },
);

if (!result.hasErrors) {
  final response = result.data?['pushCommand'];
  if (response?['success'] == true) {
    print('Success: ${response?['messageId']}');
  } else {
    print('Error: ${response?['error']}');
  }
}

Register Device Token (Push Notification) #

final helper = PushNotificationHelper();
await helper.registerDeviceToken(userId);

This method automatically:

  • Queries existing tokens
  • Updates token if exists
  • Creates new token if not exists

Option 2: Using GraphQL Client

// Create device token
final result = await client.mutate(
  document: DeviceTokenMutations.createDeviceToken,
  variables: {
    'input': {
      'tokenId': 'token_123',
      'userId': 'user-id',
      'deviceToken': 'fcm-token',
      'platform': 'android',
      'deviceId': 'device-id',
      'isActive': true,
    },
  },
);

if (!result.hasErrors) {
  final token = result.data?['createDeviceToken'];
  print('Token created: ${token?['tokenId']}');
}

Get Notifications #

final result = await client.query(
  document: NotificationQueries.notificationsByUser,
  variables: {
    'userId': userId,
    'limit': 20,
  },
);

if (!result.hasErrors) {
  final items = result.data?['notificationsByUser']?['items'] as List?;
  for (final notification in items ?? []) {
    print('Notification: ${notification['title']}');
    print('Status: ${notification['status']}');
  }
}

Mark Notification as Read #

final result = await client.mutate(
  document: NotificationMutations.updateNotification,
  variables: {
    'input': {
      'id': notificationId,
      'status': 'read',
      'readAt': DateTime.now().toIso8601String(),
    },
  },
);

if (!result.hasErrors) {
  final notification = result.data?['updateNotification'];
  print('Notification updated: ${notification?['status']}');
}

GraphQL Subscriptions #

// Subscribe to real-time updates
final subscription = client.subscribe(
  document: '''
    subscription OnUserUpdate(\$id: ID!) {
      onUpdateUser(id: \$id) {
        id
        fullName
        email
      }
    }
  ''',
  variables: {'id': userId},
);

await for (final event in subscription) {
  if (!event.hasErrors) {
    final user = event.data?['onUpdateUser'];
    print('User updated: ${user?['fullName']}');
  } else {
    print('Subscription error: ${event.errors}');
  }
}

πŸ“š Available APIs #

GraphQL Client #

  • GraphQLClient() - Create a new GraphQL client instance
  • client.query() - Execute a GraphQL query
  • client.mutate() - Execute a GraphQL mutation
  • client.subscribe() - Subscribe to GraphQL subscriptions

Queries #

User

  • UserQueries.getUser - Get user by ID
  • UserQueries.listUsers - List users with pagination

Device

  • DeviceQueries.getDevice - Get device by ID
  • DeviceQueries.listDevices - List devices with filters

DeviceToken

  • DeviceTokenQueries.getDeviceToken - Get device token by ID
  • DeviceTokenQueries.listDeviceTokens - List device tokens
  • DeviceTokenQueries.tokensByUser - Query tokens by user

Notification

  • NotificationQueries.getNotification - Get notification by ID
  • NotificationQueries.listNotifications - List notifications
  • NotificationQueries.notificationsByUser - Query notifications by user (sorted by sentAt)

Mutations #

User

  • UserMutations.updateUser - Update user profile
  • UserMutations.deactivateUser - Deactivate user (custom mutation)
  • UserMutations.reactivateUser - Reactivate user (custom mutation)
  • UserMutations.removeUser - Remove user permanently (custom mutation)

Device

  • DeviceMutations.createDevice - Create new device
  • DeviceMutations.updateDevice - Update device (name, location, etc.)
  • DeviceMutations.pushCommand - Push command to AWS IoT Core topic

DeviceToken

  • DeviceTokenMutations.createDeviceToken - Register device token
  • DeviceTokenMutations.updateDeviceToken - Update device token
  • DeviceTokenMutations.deleteDeviceToken - Unregister device token

Notification

  • NotificationMutations.updateNotification - Update notification (mark as read)

Helpers #

Push Command Helper

  • PushCommandHelper.pushCommand() - Push command using helper method (recommended)
  • PushCommandHelper.pushCommandRaw() - Push command using raw GraphQL mutation (advanced)

Push Notification Helper

  • PushNotificationHelper.registerDeviceToken() - Auto register/update device token
  • PushNotificationHelper.createDeviceToken() - Create device token manually
  • PushNotificationHelper.updateDeviceToken() - Update device token manually

πŸ”’ Authentication #

All GraphQL operations require authentication via AWS Cognito. Make sure to:

  1. Initialize Amplify with Cognito configuration
  2. Sign in user before making API calls
  3. Authentication headers are handled automatically by Amplify

πŸ“ Notes #

Direct GraphQL Usage #

This package uses GraphQL directly without model classes:

  • All responses are Map<String, dynamic>
  • No need to parse JSON into model objects
  • Access data directly: result.data?['getUser']?['email']
  • More flexible and lightweight

What's NOT Included #

This mobile-focused schema does NOT include:

  • DeviceTelemetry: Use MQTT subscriptions for real-time telemetry
  • DeviceConfiguration: Backend/internal only
  • Timer: May be added in future versions
  • Alert: May be added in future versions
  • Firmware: Admin-only operations

User Creation #

User creation is handled by AWS Cognito sign-up, not GraphQL. Use Amplify.Auth.signUp() instead.

Real-time Data #

For real-time device telemetry and status updates, use MQTT subscriptions via Amplify PubSub, not GraphQL queries.

πŸ› οΈ Development #

Build #

cd packages/flutter-schema
flutter pub get
flutter analyze

Format #

dart format lib/

πŸ“„ License #

See LICENSE file for details.

0
likes
70
points
95
downloads

Publisher

unverified uploader

Weekly Downloads

KOMBU IoT System - GraphQL Schema for Flutter/Dart (Mobile-focused). Provides GraphQL queries, mutations, and a direct GraphQL client for mobile app development with AWS Amplify. Uses GraphQL directly without model classes.

Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

amplify_api, amplify_flutter, flutter, graphql

More

Packages that depend on tvf_flutter_schema