dart_meteor_web 1.1.1

  • Readme
  • Changelog
  • Example
  • Installing
  • 63

For VM, Flutter iOS/Android (master branch)

For Flutter Web (web branch)

A Meteor DDP library for Dart/Flutter developers. #

This library makes a connection between the Meteor backend and the Flutter app simply. Design to work seamlessly with StreamBuilder and FutureBuilder.

Usage #

I just publish a post on Medium showing how to handle connection status, user authentication, and subscriptions. Please check https://medium.com/@tanutapi/writing-flutter-mobile-application-with-meteor-backend-643d2c1947d0?source=friends_link&sk=52ce2fa2603934e7395e2d19dd54e06c

A simple usage example:

First, create an instance of MeteorClient in your app global scope so that it can be used anywhere in your project.

import 'package:flutter/material.dart';
import 'package:dart_meteor/dart_meteor.dart';

MeteorClient meteor = MeteorClient.connect(url: 'https://yourdomain.com');
void main() => runApp(MyApp());

In your StatefulWidget/StatelessWidget, thanks to rxdart, you can use FutuerBuilder or StreamBuilder to build your widget base on a response from meteor's DDP server.

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _methodResult = '';

  void _callMethod() {
    meteor.call('helloMethod', []).then((result) {
      setState(() {
        _methodResult = result.toString();
      });
    }).catchError((err) {
      if (err is MeteorError) {
        setState(() {
          _methodResult = err.message;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Package dart_meteor Example'),
        ),
        body: Container(
          padding: EdgeInsets.all(8.0),
          child: Column(
            children: <Widget>[
              StreamBuilder<DdpConnectionStatus>(
                stream: meteor.status(),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    if (snapshot.data.status ==
                        DdpConnectionStatusValues.connected) {
                      return RaisedButton(
                        child: Text('Disconnect'),
                        onPressed: () {
                          meteor.disconnect();
                        },
                      );
                    }
                    return RaisedButton(
                      child: Text('Connect'),
                      onPressed: () {
                        meteor.reconnect();
                      },
                    );
                  }
                  return Container();
                },
              ),
              StreamBuilder<DdpConnectionStatus>(
                stream: meteor.status(),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Text('Meteor Status ${snapshot.data.toString()}');
                  }
                  return Text('Meteor Status: ---');
                },
              ),
              StreamBuilder(
                  stream: meteor.userId(),
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      return RaisedButton(
                        child: Text('Logout'),
                        onPressed: () {
                          meteor.logout();
                        },
                      );
                    }
                    return RaisedButton(
                      child: Text('Login'),
                      onPressed: () {
                        meteor.loginWithPassword(
                            'yourusername', 'yourpassword');
                      },
                    );
                  }),
              StreamBuilder(
                stream: meteor.user(),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Text(snapshot.data.toString());
                  }
                  return Text('User: ----');
                },
              ),
              RaisedButton(
                child: Text('Method Call'),
                onPressed: _callMethod,
              ),
              Text(_methodResult),
            ],
          ),
        ),
      ),
    );
  }
}

Making a method call to your server #

Making a method call to your server returns a Future. You MUST handle catchError to prevent your app from crashing if something went wrong. You can also use it with a FutureBuilder.

meteor.call('helloMethod', []).then((result) {
  setState(() {
    _methodResult = result.toString();
  });
}).catchError((err) {
  if (err is MeteorError) {
    setState(() {
      _methodResult = err.message;
    });
  }
});

You can found an example project inside /example.

Collections & Subscriptions #

Prepare your collections before use. You can use prepareCollection method in initState() or in your main function.

meteor.prepareCollection('your_collections');

Then access it with

meteor.collections['test']

which return rxdart's Observable that you can use it as a simple Stream. To make collections available in Flutter app you might make a subscription to your server with:

class YourWidget extends StatefulWidget {
  YourWidget() {}

  @override
  _YourWidgetState createState() => _YourWidgetState();
}

class _YourWidgetState extends State<YourWidget> {
  SubscriptionHandler _subscriptionHandler;

  @override
  void initState() {
    super.initState();
    meteor.prepareCollection('your_collection');
    _subscriptionHandler = meteor.subscribe('your_pub', []);
  }

  @override
  void dispose() {
    super.dispose();
    _subscriptionHandler.stop();
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: meteor.collections['your_collection'],
      builder:
          (context, AsyncSnapshot<Map<String, dynamic>> snapshot) {
        int docCount = 0;
        if (snapshot.hasData) {
          docCount = snapshot.data.length;
        }
        return Text('Total document count: $docCount');
      },
    );
  }
}

Features and bugs #

Please file feature requests and bugs at the issue tracker.

1.1.1 #

  • Allows both int and String for MeteorError.error

1.1.0 #

  • Pin rxdart to 0.24.1 and crypto to 2.1.5.

1.0.8 #

  • Allow passing email to loginWithPassword.

1.0.7 #

  • Don't use this release

1.0.5 - 1.0.6 #

  • Pin rxdart version to 0.22.6

1.0.1 - 1.0.4 #

  • Update README and example

1.0.0 - 1.0.3 #

  • Initial version.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:dart_meteor_web/dart_meteor_web.dart';

MeteorClient meteor = MeteorClient.connect(url: 'http://localhost:3000');
void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _methodResult = '';

  void _callMethod() {
    meteor.call('helloMethod', []).then((result) {
      setState(() {
        _methodResult = result.toString();
      });
    }).catchError((err) {
      if (err is MeteorError) {
        setState(() {
          _methodResult = err.message;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Package dart_meteor Example'),
        ),
        body: Container(
          padding: EdgeInsets.all(8.0),
          child: Column(
            children: <Widget>[
              StreamBuilder<DdpConnectionStatus>(
                stream: meteor.status(),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    if (snapshot.data.status ==
                        DdpConnectionStatusValues.connected) {
                      return RaisedButton(
                        child: Text('Disconnect'),
                        onPressed: () {
                          meteor.disconnect();
                        },
                      );
                    }
                    return RaisedButton(
                      child: Text('Connect'),
                      onPressed: () {
                        meteor.reconnect();
                      },
                    );
                  }
                  return Container();
                },
              ),
              StreamBuilder<DdpConnectionStatus>(
                stream: meteor.status(),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Text('Meteor Status ${snapshot.data.toString()}');
                  }
                  return Text('Meteor Status: ---');
                },
              ),
              StreamBuilder(
                  stream: meteor.userId(),
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      return RaisedButton(
                        child: Text('Logout'),
                        onPressed: () {
                          meteor.logout();
                        },
                      );
                    }
                    return RaisedButton(
                      child: Text('Login'),
                      onPressed: () {
                        meteor.loginWithPassword(
                            'yourusername', 'yourpassword');
                      },
                    );
                  }),
              StreamBuilder(
                stream: meteor.user(),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Text(snapshot.data.toString());
                  }
                  return Text('User: ----');
                },
              ),
              RaisedButton(
                child: Text('Method Call'),
                onPressed: _callMethod,
              ),
              Text(_methodResult),
            ],
          ),
        ),
      ),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  dart_meteor_web: ^1.1.1

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:dart_meteor_web/dart_meteor_web.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
25
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
63
Learn more about scoring.

We analyzed this package on Jul 6, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.13

Analysis suggestions

Package not compatible with runtime flutter-native on android

Because of the import of dart:html via the import chain package:dart_meteor_web/dart_meteor_web.dartpackage:dart_meteor_web/src/ddp_client.dartdart:html

Package not compatible with runtime flutter-native on ios

Because of the import of dart:html via the import chain package:dart_meteor_web/dart_meteor_web.dartpackage:dart_meteor_web/src/ddp_client.dartdart:html

Package not compatible with runtime flutter-native on linux

Because of the import of dart:html via the import chain package:dart_meteor_web/dart_meteor_web.dartpackage:dart_meteor_web/src/ddp_client.dartdart:html

Package not compatible with runtime flutter-native on macos

Because of the import of dart:html via the import chain package:dart_meteor_web/dart_meteor_web.dartpackage:dart_meteor_web/src/ddp_client.dartdart:html

Package not compatible with runtime flutter-native on windows

Because of the import of dart:html via the import chain package:dart_meteor_web/dart_meteor_web.dartpackage:dart_meteor_web/src/ddp_client.dartdart:html

Package not compatible with runtime native-aot

Because of the import of dart:html via the import chain package:dart_meteor_web/dart_meteor_web.dartpackage:dart_meteor_web/src/ddp_client.dartdart:html

Package not compatible with runtime native-jit

Because of the import of dart:html via the import chain package:dart_meteor_web/dart_meteor_web.dartpackage:dart_meteor_web/src/ddp_client.dartdart:html

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.5.0 <3.0.0
crypto ^2.1.5 2.1.5
intl ^0.16.1 0.16.1
rxdart ^0.24.1 0.24.1
Transitive dependencies
charcode 1.1.3
collection 1.14.13
convert 2.1.1
path 1.7.0
typed_data 1.2.0
Dev dependencies
pedantic ^1.0.0
test ^1.0.0