Skip to content

Commit

Permalink
Merge pull request #348 from ably/refactor/named-constructors
Browse files Browse the repository at this point in the history
Refactor of ClientOptions
  • Loading branch information
ikurek committed Mar 22, 2022
2 parents 37e40bf + 1554692 commit d005726
Show file tree
Hide file tree
Showing 29 changed files with 366 additions and 219 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ Authenticating using [basic authentication/ API key](https://ably.com/documentat
```dart
// Specify your apiKey with `flutter run --dart-define=ABLY_API_KEY=replace_your_api_key`
final String ablyApiKey = const String.fromEnvironment("ABLY_API_KEY");
final clientOptions = ably.ClientOptions.fromKey(ablyApiKey);
final clientOptions = ably.ClientOptions(key: ablyApiKey);
clientOptions.logLevel = ably.LogLevel.verbose; // optional
```

Expand Down
29 changes: 17 additions & 12 deletions example/lib/ui/ably_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,26 @@ class AblyService {

AblyService({required this.apiKeyProvision}) {
realtime = ably.Realtime(
options: ably.ClientOptions.fromKey(apiKeyProvision.key)
..clientId = Constants.clientId
..logLevel = ably.LogLevel.verbose
..environment = apiKeyProvision.source == ApiKeySource.env
options: ably.ClientOptions(
key: apiKeyProvision.key,
clientId: Constants.clientId,
logLevel: ably.LogLevel.verbose,
environment: apiKeyProvision.source == ApiKeySource.env
? null
: Constants.sandboxEnvironment
..autoConnect = false,
: Constants.sandboxEnvironment,
autoConnect: false,
),
);
rest = ably.Rest(
options: ably.ClientOptions.fromKey(apiKeyProvision.key)
..clientId = Constants.clientId
..logLevel = ably.LogLevel.verbose
..environment = apiKeyProvision.source == ApiKeySource.env
? null
: Constants.sandboxEnvironment);
options: ably.ClientOptions(
key: apiKeyProvision.key,
clientId: Constants.clientId,
logLevel: ably.LogLevel.verbose,
environment: apiKeyProvision.source == ApiKeySource.env
? null
: Constants.sandboxEnvironment,
),
);
pushNotificationService = PushNotificationService(realtime, rest);
}
}
Expand Down
44 changes: 30 additions & 14 deletions lib/src/authentication/src/auth_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,6 @@ import 'package:ably_flutter/ably_flutter.dart';
///
/// https://docs.ably.com/client-lib-development-guide/features/#AO1
abstract class AuthOptions {
/// initializes an instance without any defaults
AuthOptions();

/// Convenience constructor, to create an AuthOptions based
/// on the key string obtained from the application dashboard.
/// param [key]: the full key string as obtained from the dashboard
AuthOptions.fromKey(String key) {
if (key.contains(':')) {
this.key = key;
} else {
tokenDetails = TokenDetails(key);
}
}

/// A function which is called when a new token is required.
///
/// The role of the callback is to either generate a signed [TokenRequest]
Expand Down Expand Up @@ -83,6 +69,36 @@ abstract class AuthOptions {

// TODO(tiholic) missing token attribute here
// see: https://docs.ably.com/client-lib-development-guide/features/#AO2h

/// Initializes an instance without any defaults
AuthOptions({
this.authCallback,
this.authUrl,
this.authMethod,
this.key,
this.tokenDetails,
this.authHeaders,
this.authParams,
this.queryTime,
this.useTokenAuth,
}) {
if (key != null && !key!.contains(':')) {
tokenDetails = TokenDetails(key);
key = null;
}
}

/// Convenience constructor, to create an AuthOptions based
/// on the key string obtained from the application dashboard.
/// param [key]: the full key string as obtained from the dashboard
@Deprecated("Use AuthOptions constructor with named 'key' parameter instead")
AuthOptions.fromKey(String key) {
if (key.contains(':')) {
this.key = key;
} else {
tokenDetails = TokenDetails(key);
}
}
}

/// Function-type alias implemented by a function that provides either tokens,
Expand Down
85 changes: 77 additions & 8 deletions lib/src/authentication/src/client_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,6 @@ import 'package:ably_flutter/ably_flutter.dart';
///
/// https://docs.ably.com/client-lib-development-guide/features/#TO1
class ClientOptions extends AuthOptions {
/// Set fields on [ClientOptions] to configure it.
ClientOptions();

/// initializes [ClientOptions] with a key and log level set to info
///
/// See [AuthOptions.fromKey] for more details
ClientOptions.fromKey(String key) : super.fromKey(key);

/// Optional clientId that can be used to specify the identity for this client
///
/// In most cases it is preferable to instead specific a clientId in the token
Expand Down Expand Up @@ -195,6 +187,83 @@ class ClientOptions extends AuthOptions {
/// https://docs.ably.com/client-lib-development-guide/features/#TO3l7
int channelRetryTimeout = 15000;

/// Initializes an instance with defaults
ClientOptions({
AuthCallback? authCallback,
String? authUrl,
String? authMethod,
String? key,
TokenDetails? tokenDetails,
Map<String, String>? authHeaders,
Map<String, String>? authParams,
bool? queryTime,
bool? useTokenAuth,
this.clientId,
this.logHandler,
LogLevel? logLevel,
this.restHost,
this.realtimeHost,
this.port,
bool? tls,
this.tlsPort,
bool? autoConnect,
bool? useBinaryProtocol,
bool? queueMessages,
bool? echoMessages,
this.recover,
this.environment,
this.fallbackHosts,
this.fallbackHostsUseDefault,
this.defaultTokenParams,
int? disconnectedRetryTimeout,
int? suspendedRetryTimeout,
this.idempotentRestPublishing,
this.transportParams,
int? httpOpenTimeout,
int? httpRequestTimeout,
int? httpMaxRetryCount,
this.realtimeRequestTimeout,
int? fallbackRetryTimeout,
int? channelRetryTimeout,
}) : super(
authCallback: authCallback,
authUrl: authUrl,
authMethod: authMethod,
key: key,
tokenDetails: tokenDetails,
authHeaders: authHeaders,
authParams: authParams,
queryTime: queryTime,
useTokenAuth: useTokenAuth,
) {
/// These default value assignments are only required until
/// [ClientOptions.fromKey] is removed, because then defaults can be set
/// directly in the constructor invocation
this.logLevel = logLevel ?? this.logLevel;
this.tls = tls ?? this.tls;
this.autoConnect = autoConnect ?? this.autoConnect;
this.useBinaryProtocol = useBinaryProtocol ?? this.useBinaryProtocol;
this.queueMessages = queueMessages ?? this.queueMessages;
this.echoMessages = echoMessages ?? this.echoMessages;
this.disconnectedRetryTimeout =
disconnectedRetryTimeout ?? this.disconnectedRetryTimeout;
this.suspendedRetryTimeout =
suspendedRetryTimeout ?? this.suspendedRetryTimeout;
this.httpOpenTimeout = httpOpenTimeout ?? this.httpOpenTimeout;
this.httpRequestTimeout = httpRequestTimeout ?? this.httpRequestTimeout;
this.httpMaxRetryCount = httpMaxRetryCount ?? this.httpMaxRetryCount;
this.fallbackRetryTimeout =
fallbackRetryTimeout ?? this.fallbackRetryTimeout;
this.channelRetryTimeout = channelRetryTimeout ?? this.channelRetryTimeout;
}

/// initializes [ClientOptions] with a key and log level set to info
///
/// See [AuthOptions.fromKey] for more details
@Deprecated(
"Use ClientOptions constructor with named 'key' parameter instead")
ClientOptions.fromKey(String key) : super.fromKey(key);

// TODO(tiholic) unimplemented:
//
// (TO3m) logExceptionReportingUrl
Expand Down
112 changes: 56 additions & 56 deletions lib/src/platform/src/codec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -535,102 +535,102 @@ class Codec extends StandardMessageCodec {
jsonMap,
TxClientOptions.defaultTokenParams,
));
final clientOptions = ClientOptions()
final clientOptions = ClientOptions(
// AuthOptions (super class of ClientOptions)
..authUrl = _readFromJson<String>(
authUrl: _readFromJson<String>(
jsonMap,
TxClientOptions.authUrl,
)
..authMethod = _readFromJson<String>(
),
authMethod: _readFromJson<String>(
jsonMap,
TxClientOptions.authMethod,
)
..key = _readFromJson<String>(
),
key: _readFromJson<String>(
jsonMap,
TxClientOptions.key,
)
..tokenDetails =
(tokenDetails == null) ? null : _decodeTokenDetails(tokenDetails)
..authHeaders = _readFromJson<Map<String, String>>(
),
tokenDetails:
(tokenDetails == null) ? null : _decodeTokenDetails(tokenDetails),
authHeaders: _readFromJson<Map<String, String>>(
jsonMap,
TxClientOptions.authHeaders,
)
..authParams = _readFromJson<Map<String, String>>(
),
authParams: _readFromJson<Map<String, String>>(
jsonMap,
TxClientOptions.authParams,
)
..queryTime = _readFromJson<bool>(
),
queryTime: _readFromJson<bool>(
jsonMap,
TxClientOptions.queryTime,
)
..useTokenAuth = _readFromJson<bool>(
),
useTokenAuth: _readFromJson<bool>(
jsonMap,
TxClientOptions.useTokenAuth,
)
),

// ClientOptions
..clientId = _readFromJson<String>(
clientId: _readFromJson<String>(
jsonMap,
TxClientOptions.clientId,
)
..logLevel = _decodeLogLevel(jsonMap[TxClientOptions.logLevel] as String?)
),
logLevel: _decodeLogLevel(jsonMap[TxClientOptions.logLevel] as String?),
//TODO handle logHandler
..tls = jsonMap[TxClientOptions.tls] as bool
..restHost = _readFromJson<String>(
tls: jsonMap[TxClientOptions.tls] as bool,
restHost: _readFromJson<String>(
jsonMap,
TxClientOptions.restHost,
)
..realtimeHost = _readFromJson<String>(
),
realtimeHost: _readFromJson<String>(
jsonMap,
TxClientOptions.realtimeHost,
)
..port = _readFromJson<int>(
),
port: _readFromJson<int>(
jsonMap,
TxClientOptions.port,
)
..tlsPort = _readFromJson<int>(
),
tlsPort: _readFromJson<int>(
jsonMap,
TxClientOptions.tlsPort,
)
..autoConnect = jsonMap[TxClientOptions.autoConnect] as bool
..useBinaryProtocol = jsonMap[TxClientOptions.useBinaryProtocol] as bool
..queueMessages = jsonMap[TxClientOptions.queueMessages] as bool
..echoMessages = jsonMap[TxClientOptions.echoMessages] as bool
..recover = _readFromJson<String>(
),
autoConnect: jsonMap[TxClientOptions.autoConnect] as bool,
useBinaryProtocol: jsonMap[TxClientOptions.useBinaryProtocol] as bool,
queueMessages: jsonMap[TxClientOptions.queueMessages] as bool,
echoMessages: jsonMap[TxClientOptions.echoMessages] as bool,
recover: _readFromJson<String>(
jsonMap,
TxClientOptions.recover,
)
..environment = _readFromJson<String>(
),
environment: _readFromJson<String>(
jsonMap,
TxClientOptions.environment,
)
..idempotentRestPublishing = _readFromJson<bool>(
),
idempotentRestPublishing: _readFromJson<bool>(
jsonMap,
TxClientOptions.idempotentRestPublishing,
)
..realtimeRequestTimeout =
jsonMap[TxClientOptions.realtimeRequestTimeout] as int?
..httpOpenTimeout = jsonMap[TxClientOptions.httpOpenTimeout] as int
..httpRequestTimeout = jsonMap[TxClientOptions.httpRequestTimeout] as int
..httpMaxRetryCount = jsonMap[TxClientOptions.httpMaxRetryCount] as int
..fallbackHosts = _readFromJson<List<String>>(
),
realtimeRequestTimeout:
jsonMap[TxClientOptions.realtimeRequestTimeout] as int?,
httpOpenTimeout: jsonMap[TxClientOptions.httpOpenTimeout] as int,
httpRequestTimeout: jsonMap[TxClientOptions.httpRequestTimeout] as int,
httpMaxRetryCount: jsonMap[TxClientOptions.httpMaxRetryCount] as int,
fallbackHosts: _readFromJson<List<String>>(
jsonMap,
TxClientOptions.fallbackHosts,
)
..fallbackHostsUseDefault = _readFromJson<bool>(
),
fallbackHostsUseDefault: _readFromJson<bool>(
jsonMap,
TxClientOptions.fallbackHostsUseDefault,
)
..fallbackRetryTimeout =
jsonMap[TxClientOptions.fallbackRetryTimeout] as int
..defaultTokenParams =
(tokenParams == null) ? null : _decodeTokenParams(tokenParams)
..channelRetryTimeout =
jsonMap[TxClientOptions.channelRetryTimeout] as int
..transportParams = _readFromJson<Map<String, String>>(
),
fallbackRetryTimeout:
jsonMap[TxClientOptions.fallbackRetryTimeout] as int,
defaultTokenParams:
(tokenParams == null) ? null : _decodeTokenParams(tokenParams),
channelRetryTimeout: jsonMap[TxClientOptions.channelRetryTimeout] as int,
transportParams: _readFromJson<Map<String, String>>(
jsonMap,
TxClientOptions.transportParams,
);
),
);
return clientOptions;
}

Expand Down
6 changes: 3 additions & 3 deletions lib/src/platform/src/realtime/realtime.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'dart:async';
import 'dart:io' as io show Platform;
import 'dart:collection';
import 'dart:io' as io show Platform;

import 'package:ably_flutter/ably_flutter.dart';
import 'package:ably_flutter/src/platform/platform_internal.dart';
Expand All @@ -20,7 +20,7 @@ class Realtime extends PlatformObject {
ClientOptions? options,
final String? key,
}) : assert(options != null || key != null),
options = options ?? ClientOptions.fromKey(key!),
options = options ?? ClientOptions(key: key!),
super() {
_connection = Connection(this);
_channels = RealtimeChannels(this);
Expand All @@ -29,7 +29,7 @@ class Realtime extends PlatformObject {

/// Create a realtime client from an API key without configuring other parameters
factory Realtime.fromKey(String key) =>
Realtime(options: ClientOptions.fromKey(key));
Realtime(options: ClientOptions(key: key));

@override
Future<int?> createPlatformInstance() async {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/platform/src/rest/rest.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Rest extends PlatformObject {
}

/// Create a rest client from an API key without configuring other parameters
factory Rest.fromKey(String key) => Rest(options: ClientOptions.fromKey(key));
factory Rest.fromKey(String key) => Rest(options: ClientOptions(key: key));

@override
Future<int?> createPlatformInstance() async {
Expand Down

0 comments on commit d005726

Please sign in to comment.