Coder Social home page Coder Social logo

realtime-dart's Introduction

realtime-dart

Warning This repository has been moved to the supabase-flutter repo.

Listens to changes in a PostgreSQL Database and via websockets.

A dart client for Supabase Realtime server.

Usage

Creating a Socket connection

You can set up one connection to be used across the whole app.

import 'package:realtime_client/realtime_client.dart';

var client = RealtimeClient(REALTIME_URL);
client.connect();

Socket Hooks

client.onOpen(() => print('Socket opened.'));
client.onClose((event) => print('Socket closed $event'));
client.onError((error) => print('Socket error: $error'));

Disconnect the socket

Call disconnect() on the socket:

client.disconnect()

Credits

License

This repo is licensed under MIT.

realtime-dart's People

Contributors

bartektartanus avatar bdlukaa avatar chimon2000 avatar dshukertjr avatar hardiksachan avatar hubtreetea avatar iagreen avatar phamhieu avatar timwhiting avatar vinzent03 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

realtime-dart's Issues

Wrong Parsing of bool values

Bug report

Describe the bug

Boolean values are wrongly transformed, resulting always in null as the value for a boolean field.

To Reproduce

  • subscribe to a table that has a column with a boolean value
  • change a row in the table
  • take a look at the resulting (raw) json string containing the new record
  • compare it with the parsed Map<String, dyanmic> in the SupabaseRealtimePayload and see that all boolean values are now null

Expected behavior

Correct parsing of boolean values.

System information

  • Flutter 2.5.3
  • Dart 2.14.4
  • realtime_client: 0.1.12

Additional context

I did find the cause of this behavior, it lies within the file transformers.dart in the method toBoolean.
There, it only checks for the cases 'f' and 't', however, the previously called .toString() on the value makes the boolean value either 'true' or 'false', which is why the default case is being used, which results in a value of null.

Int columns get converted to String on realtime listening (for one row)

Bug report

Describe the bug

If I get realtime data from my user profile (which is discriminated with the :id=eq.$userId) every column that is an int gets converted to a String in dart

To Reproduce

Pretty much said this, just need a table, and listen two only two one row, and all int columns won't be int in dart but a string

Expected behaviour

Not have an error with the type conversion

Screenshots

If applicable, add screenshots to help explain your problem.

Additional context

N/A

How to connect to Realtime server

I am trying to use the following code:

import 'package:realtime_client/realtime_client.dart';

void main() async {
  final socket = RealtimeClient('ws://SUPABASE_API_ENDPOINT/realtime/v1',
      params: {
        'apikey':
            'My API Key'
      },
      // ignore: avoid_print
      logger: (kind, msg, data) => {print('$kind $msg $data')});

  final channel = socket.channel('realtime:public'); //:classTest:chatID.eq.2
  channel.on('DELETE', (payload, {ref}) {
    print('channel delete payload: $payload');
  });
  channel.on('INSERT', (payload, {ref}) {
    print('channel insert payload: $payload');
  });

  socket.onMessage((message) => print('MESSAGE $message'));

  // on connect and subscribe
  socket.connect();
  channel.subscribe().receive('ok', (_) => print('SUBSCRIBED'));
}

But I get the following:

flutter: transport connected to ws://supabase_api_endpoint/realtime/v1/websocket?apikey=My API Key&vsn=1.0.0 null
flutter: push realtime:public ChannelEvents.join () {}
flutter: transport WebSocketChannelException: WebSocketChannelException: SocketException: Failed host lookup: 'supabase_api_endpoint' (OS Error: No such host is known.

, errno = 11001) null
flutter: channel error realtime:public null
flutter: transport close 

What RealtimeClient host can I connect to? how to resolve this problem? thanks

Stream Subscriptions die when auth token expires

We noticed will testing that after some time that our streams were unexpectedly closed.
I tested it with a 60 second expiry time on the JWT and received this exception after 60s :

[sentry.runZonedGuarded] [error] Uncaught zone error
[sentry.runZonedGuarded] _CastError (type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String?' in type cast)
[sentry.runZonedGuarded] #0      RealtimeSubscription.onError.<anonymous closure> 		package:realtime_client/src/realtime_subscription.dart:97
#1      RealtimeSubscription.trigger													package:realtime_client/src/realtime_subscription.dart:221
#2      RealtimeClient.onConnMessage.<anonymous closure>.<anonymous closure>			package:realtime_client/src/realtime_client.dart:265
#3      Iterable.forEach (dart:core/iterable.dart:279:35)
#4      RealtimeClient.onConnMessage.<anonymous closure>								package:realtime_client/src/realtime_client.dart:264
#5      new RealtimeClient.<anonymous closure>											package:realtime_client/src/realtime_client.dart:86
#6      RealtimeClient.onConnMessage													package:realtime_client/src/realtime_client.dart:249
#7      RealtimeClient.connect.<anonymous closure>										package:realtime_client/src/realtime_client.dart:108
#8      _rootRunUnary (dart:async/zone.dart:1436:47)
#9      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#10     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#11     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#12     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#13     _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11)
#14     _HandleErrorStream._handleData (dart:async/stream_pipe.dart:253:10)
#15     _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13)
#16     _rootRunUnary (dart:async/zone.dart:1436:47)
#17     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#18     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#20     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#21     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
#22     _StreamController._add (dart:async/stream_controller.dart:607:7)
#23     _rootRunUnary (dart:async/zone.dart:1436:47)
#24     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#25     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#26     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#27     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#28     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
#29     _StreamController._add (dart:async/stream_controller.dart:607:7)
#30     _StreamController.add (dart:async/stream_controller.dart:554:5)
#31     new _WebSocketImpl._fromSocket.<anonymous closure> (dart:_http/websocket_impl.dart:1144:21)
#32     _rootRunUnary (dart:async/zone.dart:1436:47)
#33     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#34     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#35     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#36     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#37     _SinkTransformerStreamSubscription._add (dart:async/stream_transformers.dart:63:11)
#38     _EventSinkWrapper.add (dart:async/stream_transformers.dart:13:11)
#39     _WebSocketProtocolTransformer._messageFrameEnd (dart:_http/websocket_impl.dart:332:23)
#40     _WebSocketProtocolTransformer.add (dart:_http/websocket_impl.dart:226:46)
#41     _SinkTransformerStreamSubscription._handleData (dart:async/stream_transformers.dart:111:24)
#42     _rootRunUnary (dart:async/zone.dart:1436:47)
#43     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#44     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#45     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#46     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#47     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
#48     _StreamController._add (dart:async/stream_controller.dart:607:7)
#49     _StreamController.add (dart:async/stream_controller.dart:554:5)
#50     _Socket._onData (dart:io-patch/socket_patch.dart:2302:41)
#51     _rootRunUnary (dart:async/zone.dart:1436:47)
#52     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#53     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#54     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#55     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#56     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
#57     _StreamController._add (dart:async/stream_controller.dart:607:7)
#58     _StreamController.add (dart:async/stream_controller.dart:554:5)
#59     _RawSecureSocket._sendReadEvent (dart:io/secure_socket.dart:1000:19)
#60     _rootRun (dart:async/zone.dart:1420:47)
#61     _CustomZone.run (dart:async/zone.dart:1328:19)
#62     _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
#63     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
#64     _rootRun (dart:async/zone.dart:1428:13)
#65     _CustomZone.run (dart:async/zone.dart:1328:19)
#66     _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1260:23)
#67     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
#68     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:395:19)
#69     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:426:5)
#70     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)

It might be related to this issue #28

Logger name conflict

Using the official logging package will result in name conflicts with the Logger function from realtime_client.

As always the first solution would be adding a prefix to its import but im a friend of avoiding name conflicts in first place. Maybe you could discuss an alternative name?

The error message is the following:
The name 'Logger' is defined in the libraries 'package:logging/src/logger.dart (via package:logging/logging.dart)' and 'package:realtime_client/src/realtime_client.dart'. (Documentation) Try using 'as prefix' for one of the import directives, or hiding the name from all but one of the imports.

casting error in `RealtimeSubscription`

I'm enable to reproduce the error but it has occurred with me several times already.

The debugger shows that the error is caused by the casting at line 97 below:

https://github.com/supabase-community/realtime-dart/blob/9f068255d159c4717cf51e0d8efbfe838987ff54/lib/src/realtime_subscription.dart#L94-L98

Full error message:

[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String?' in type cast
#0      RealtimeSubscription.onError.<anonymous closure>
#1      RealtimeSubscription.trigger
#2      RealtimeClient.onConnMessage.<anonymous closure>.<anonymous closure>
#3      Iterable.forEach (dart:core/iterable.dart:279:35)
#4      RealtimeClient.onConnMessage.<anonymous closure>
#5      new RealtimeClient.<anonymous closure>
#6      RealtimeClient.onConnMessage
#7      RealtimeClient.connect.<anonymous closure>
#8      _rootRunUnary (dart:async/zone.dart:1436:47)
#9      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#10     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#11     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#12     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#13     _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11)
#14     _HandleErrorStream._handleData (dart:async/stream_pipe.dart:253:10)
#15     _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13)
#16     _rootRunUnary (dart:async/zone.dart:1436:47)
#17     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#18     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#19     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#20     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#21     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
#22     _StreamController._add (dart:async/stream_controller.dart:607:7)
#23     _rootRunUnary (dart:async/zone.dart:1436:47)
#24     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#25     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#26     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#27     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#28     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
#29     _StreamController._add (dart:async/stream_controller.dart:607:7)
#30     _StreamController.add (dart:async/stream_controller.dart:554:5)
#31     new _WebSocketImpl._fromSocket.<anonymous closure> (dart:_http/websocket_impl.dart:1144:21)
#32     _rootRunUnary (dart:async/zone.dart:1436:47)
#33     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#34     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#35     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#36     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#37     _SinkTransformerStreamSubscription._add (dart:async/stream_transformers.dart:63:11)
#38     _EventSinkWrapper.add (dart:async/stream_transformers.dart:13:11)
#39     _WebSocketProtocolTransformer._messageFrameEnd (dart:_http/websocket_impl.dart:332:23)
#40     _WebSocketProtocolTransformer.add (dart:_http/websocket_impl.dart:226:46)
#41     _SinkTransformerStreamSubscription._handleData (dart:async/stream_transformers.dart:111:24)
#42     _rootRunUnary (dart:async/zone.dart:1436:47)
#43     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#44     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#45     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#46     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#47     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
#48     _StreamController._add (dart:async/stream_controller.dart:607:7)
#49     _StreamController.add (dart:async/stream_controller.dart:554:5)
#50     _Socket._onData (dart:io-patch/socket_patch.dart:2302:41)
#51     _rootRunUnary (dart:async/zone.dart:1444:13)
#52     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#53     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#54     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#55     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#56     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:733:19)
#57     _StreamController._add (dart:async/stream_controller.dart:607:7)
#58     _StreamController.add (dart:async/stream_controller.dart:554:5)
#59     new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1830:33)
#60     _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1314:14)
#61     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#62     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

Feedback

Hey, I think you could add a link for supabase-dart and postgres-dart as they are related and anyone falling into this page might not know they exist.

Also, I just want to do a Firestore.stream. Is that possible? It could mention how to achieve this (or if it is not possible) for users coming from it to have the right expectations.

Listening to realtime events on varchar[] column always returns ['archa'] and not the actual array content

Bug report

Describe the bug

Listening to realtime events on a column with varchar[] type always returns ['archa'] no matter what you enter as the value within the payload. It also seems like other array types are not returning the correct values either.

Mentioned supabase/supabase-dart#44

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Create a table with column of varchar[] type
  2. Start listening to realtime events of the table
  3. Make modification to the table so that realtime event fires
  4. Receive ['archa'] as the value for varchar[] type column

Expected behavior

Should receive the actual array content as payload

Send Valid User Access Token to Realtime Server

Feature request

Realtime server is now checking every minute to verify the validity of the user access token and storing updated user information from the JWT to Realtime's subscription table (used by Realtime WALRUS).

Describe the solution you'd like

  1. Realtime client pushes the user access token to all channels every heartbeat, which defaults to 30 seconds (see ref, ref, and ref).
  2. Supabase client sends latest and valid user access token on auth events SIGNED_IN and TOKEN_REFRESHED (see ref)*.
  3. Supabase client removes all subscriptions on auth event SIGNED_OUT (see ref)*.

*fix: improve auth for realtime row level security #303

Additional context

Realtime Security (WALRUS) will be launched very soon so we'll mention that additional Supabase client libs, like this one, will be compatible with the new Realtime some time in the near future.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.