ably-pubsub-core 0.0.1.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/lib/ably/agent.rb +8 -0
  3. data/lib/ably/auth.rb +791 -0
  4. data/lib/ably/exceptions.rb +169 -0
  5. data/lib/ably/logger.rb +119 -0
  6. data/lib/ably/models/auth_details.rb +45 -0
  7. data/lib/ably/models/channel_details.rb +69 -0
  8. data/lib/ably/models/channel_metrics.rb +107 -0
  9. data/lib/ably/models/channel_occupancy.rb +50 -0
  10. data/lib/ably/models/channel_options.rb +120 -0
  11. data/lib/ably/models/channel_state_change.rb +84 -0
  12. data/lib/ably/models/channel_status.rb +63 -0
  13. data/lib/ably/models/cipher_params.rb +137 -0
  14. data/lib/ably/models/connection_details.rb +149 -0
  15. data/lib/ably/models/connection_state_change.rb +83 -0
  16. data/lib/ably/models/delta_extras.rb +28 -0
  17. data/lib/ably/models/device_details.rb +126 -0
  18. data/lib/ably/models/device_push_details.rb +94 -0
  19. data/lib/ably/models/error_info.rb +104 -0
  20. data/lib/ably/models/http_paginated_response.rb +112 -0
  21. data/lib/ably/models/idiomatic_ruby_wrapper.rb +235 -0
  22. data/lib/ably/models/message.rb +223 -0
  23. data/lib/ably/models/message_encoders/base.rb +135 -0
  24. data/lib/ably/models/message_encoders/base64.rb +40 -0
  25. data/lib/ably/models/message_encoders/cipher.rb +84 -0
  26. data/lib/ably/models/message_encoders/json.rb +34 -0
  27. data/lib/ably/models/message_encoders/utf8.rb +26 -0
  28. data/lib/ably/models/nil_logger.rb +20 -0
  29. data/lib/ably/models/paginated_result.rb +201 -0
  30. data/lib/ably/models/presence_message.rb +244 -0
  31. data/lib/ably/models/protocol_message.rb +288 -0
  32. data/lib/ably/models/push_channel_subscription.rb +114 -0
  33. data/lib/ably/models/stats.rb +242 -0
  34. data/lib/ably/models/stats_types.rb +107 -0
  35. data/lib/ably/models/token_details.rb +148 -0
  36. data/lib/ably/models/token_request.rb +180 -0
  37. data/lib/ably/modules/ably.rb +26 -0
  38. data/lib/ably/modules/async_wrapper.rb +69 -0
  39. data/lib/ably/modules/channels_collection.rb +105 -0
  40. data/lib/ably/modules/conversions.rb +153 -0
  41. data/lib/ably/modules/encodeable.rb +111 -0
  42. data/lib/ably/modules/enum.rb +230 -0
  43. data/lib/ably/modules/event_emitter.rb +200 -0
  44. data/lib/ably/modules/event_machine_helpers.rb +26 -0
  45. data/lib/ably/modules/exception_codes.rb +128 -0
  46. data/lib/ably/modules/http_helpers.rb +41 -0
  47. data/lib/ably/modules/message_emitter.rb +78 -0
  48. data/lib/ably/modules/message_pack.rb +14 -0
  49. data/lib/ably/modules/model_common.rb +84 -0
  50. data/lib/ably/modules/safe_deferrable.rb +83 -0
  51. data/lib/ably/modules/safe_yield.rb +41 -0
  52. data/lib/ably/modules/state_emitter.rb +181 -0
  53. data/lib/ably/modules/state_machine.rb +59 -0
  54. data/lib/ably/modules/statesman_monkey_patch.rb +33 -0
  55. data/lib/ably/modules/uses_state_machine.rb +111 -0
  56. data/lib/ably/realtime/auth.rb +283 -0
  57. data/lib/ably/realtime/channel/channel_manager.rb +272 -0
  58. data/lib/ably/realtime/channel/channel_properties.rb +40 -0
  59. data/lib/ably/realtime/channel/channel_state_machine.rb +104 -0
  60. data/lib/ably/realtime/channel/publisher.rb +82 -0
  61. data/lib/ably/realtime/channel/push_channel.rb +69 -0
  62. data/lib/ably/realtime/channel.rb +440 -0
  63. data/lib/ably/realtime/channels.rb +71 -0
  64. data/lib/ably/realtime/client/incoming_message_dispatcher.rb +225 -0
  65. data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +87 -0
  66. data/lib/ably/realtime/client.rb +363 -0
  67. data/lib/ably/realtime/connection/connection_manager.rb +594 -0
  68. data/lib/ably/realtime/connection/connection_state_machine.rb +144 -0
  69. data/lib/ably/realtime/connection/websocket_transport.rb +287 -0
  70. data/lib/ably/realtime/connection.rb +738 -0
  71. data/lib/ably/realtime/models/nil_channel.rb +30 -0
  72. data/lib/ably/realtime/presence/members_map.rb +395 -0
  73. data/lib/ably/realtime/presence/presence_manager.rb +78 -0
  74. data/lib/ably/realtime/presence/presence_state_machine.rb +57 -0
  75. data/lib/ably/realtime/presence.rb +502 -0
  76. data/lib/ably/realtime/push/admin.rb +75 -0
  77. data/lib/ably/realtime/push/channel_subscriptions.rb +108 -0
  78. data/lib/ably/realtime/push/device_registrations.rb +105 -0
  79. data/lib/ably/realtime/push.rb +25 -0
  80. data/lib/ably/realtime/recovery_key_context.rb +36 -0
  81. data/lib/ably/realtime.rb +60 -0
  82. data/lib/ably/rest/channel/push_channel.rb +59 -0
  83. data/lib/ably/rest/channel.rb +194 -0
  84. data/lib/ably/rest/channels.rb +47 -0
  85. data/lib/ably/rest/client.rb +727 -0
  86. data/lib/ably/rest/middleware/encoder.rb +49 -0
  87. data/lib/ably/rest/middleware/exceptions.rb +53 -0
  88. data/lib/ably/rest/middleware/external_exceptions.rb +24 -0
  89. data/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +22 -0
  90. data/lib/ably/rest/middleware/logger.rb +58 -0
  91. data/lib/ably/rest/middleware/parse_json.rb +27 -0
  92. data/lib/ably/rest/middleware/parse_message_pack.rb +43 -0
  93. data/lib/ably/rest/presence.rb +113 -0
  94. data/lib/ably/rest/push/admin.rb +58 -0
  95. data/lib/ably/rest/push/channel_subscriptions.rb +121 -0
  96. data/lib/ably/rest/push/device_registrations.rb +114 -0
  97. data/lib/ably/rest/push.rb +25 -0
  98. data/lib/ably/rest.rb +40 -0
  99. data/lib/ably/util/ably_extensions.rb +29 -0
  100. data/lib/ably/util/crypto.rb +134 -0
  101. data/lib/ably/util/pub_sub.rb +45 -0
  102. data/lib/ably/util/safe_deferrable.rb +44 -0
  103. data/lib/ably/version.rb +7 -0
  104. data/lib/ably.rb +16 -0
  105. metadata +497 -0
@@ -0,0 +1,84 @@
1
+ module Ably::Models
2
+ # Contains state change information emitted by {Ably::Rest::Channel} and {Ably::Realtime::Channel} objects.
3
+ #
4
+ class ChannelStateChange
5
+ include Ably::Modules::ModelCommon
6
+
7
+ def initialize(hash_object)
8
+ unless (hash_object.keys - [:current, :previous, :event, :reason, :resumed, :protocol_message]).empty?
9
+ raise ArgumentError, 'Invalid attributes, expecting :current, :previous, :event, :reason, :resumed'
10
+ end
11
+
12
+ @hash_object = {
13
+ current: hash_object.fetch(:current),
14
+ previous: hash_object.fetch(:previous),
15
+ event: hash_object[:event],
16
+ reason: hash_object[:reason],
17
+ protocol_message: hash_object[:protocol_message],
18
+ resumed: hash_object[:resumed]
19
+ }
20
+ rescue KeyError => e
21
+ raise ArgumentError, e
22
+ end
23
+
24
+ # The new current {Ably::Realtime::Channel::STATE}.
25
+ #
26
+ # @spec RTL2a, RTL2b
27
+ #
28
+ # @return [Ably::Realtime::Channel::STATE]
29
+ #
30
+ def current
31
+ @hash_object[:current]
32
+ end
33
+
34
+ # The previous state. For the {Ably::Realtime::Channel::EVENT}(:update) event, this is equal to the current {Ably::Realtime::Channel::STATE}.
35
+ #
36
+ # @spec RTL2a, RTL2b
37
+ #
38
+ # @return [Ably::Realtime::Channel::EVENT]
39
+ #
40
+ def previous
41
+ @hash_object[:previous]
42
+ end
43
+
44
+ # The event that triggered this {Ably::Realtime::Channel::STATE} change.
45
+ #
46
+ # @spec TH5
47
+ #
48
+ # @return [Ably::Realtime::Channel::STATE]
49
+ #
50
+ def event
51
+ @hash_object[:event]
52
+ end
53
+
54
+ # An {Ably::Models::ErrorInfo} object containing any information relating to the transition.
55
+ #
56
+ # @spec RTL2e, TH3
57
+ #
58
+ # @return [Ably::Models::ErrorInfo, nil]
59
+ #
60
+ def reason
61
+ @hash_object[:reason]
62
+ end
63
+
64
+ # Indicates whether message continuity on this channel is preserved, see Nonfatal channel errors for more info.
65
+ #
66
+ # @spec RTL2f, TH4
67
+ #
68
+ # @return [Boolean]
69
+ #
70
+ def resumed
71
+ !!@hash_object[:resumed]
72
+ end
73
+ alias_method :resumed?, :resumed
74
+
75
+ # @api private
76
+ def protocol_message
77
+ @hash_object[:protocol_message]
78
+ end
79
+
80
+ def to_s
81
+ "<ChannelStateChange: current state #{current}, previous state #{previous}>"
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,63 @@
1
+ module Ably::Models
2
+ # Convert token details argument to a {ChannelStatus} object
3
+ #
4
+ # @param attributes (see #initialize)
5
+ #
6
+ # @return [ChannelStatus]
7
+ #
8
+ def self.ChannelStatus(attributes)
9
+ case attributes
10
+ when ChannelStatus
11
+ return attributes
12
+ else
13
+ ChannelStatus.new(attributes)
14
+ end
15
+ end
16
+
17
+ # Contains the status of a {Ably::Models::Rest::Channel} or {Ably::Models::Realtime::Channel} object
18
+ # such as whether it is active and its {Ably::Models::ChannelOccupancy}.
19
+ #
20
+ # @spec CHS1
21
+ #
22
+ class ChannelStatus
23
+ extend Ably::Modules::Enum
24
+ extend Forwardable
25
+ include Ably::Modules::ModelCommon
26
+
27
+ # The attributes of ChannelStatus
28
+ #
29
+ # @spec CHS2
30
+ #
31
+ attr_reader :attributes
32
+
33
+ alias_method :to_h, :attributes
34
+
35
+ # Initialize a new ChannelStatus
36
+ #
37
+ def initialize(attrs)
38
+ @attributes = IdiomaticRubyWrapper(attrs.clone)
39
+ end
40
+
41
+ # If true, the channel is active, otherwise false.
42
+ #
43
+ # @spec CHS2a
44
+ #
45
+ # @return [Boolean]
46
+ #
47
+ def is_active
48
+ attributes[:isActive]
49
+ end
50
+ alias_method :active?, :is_active
51
+ alias_method :is_active?, :is_active
52
+
53
+ # A {Ably::Models::ChannelOccupancy} object.
54
+ #
55
+ # @spec CHS2b
56
+ #
57
+ # @return [Ably::Models::ChannelOccupancy, nil]
58
+ #
59
+ def occupancy
60
+ Ably::Models::ChannelOccupancy(attributes[:occupancy])
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,137 @@
1
+ require 'base64'
2
+ require 'ably/util/crypto'
3
+
4
+ module Ably::Models
5
+ # Convert cipher param attributes to a {CipherParams} object
6
+ #
7
+ # @param attributes (see #initialize)
8
+ #
9
+ # @return [CipherParams]
10
+ #
11
+ def self.CipherParams(attributes)
12
+ case attributes
13
+ when CipherParams
14
+ return attributes
15
+ else
16
+ CipherParams.new(attributes || {})
17
+ end
18
+ end
19
+
20
+ # Sets the properties to configure encryption for a {Ably::Models::Rest::Channel} or {Ably::Models::Realtime::Channel} object.
21
+ #
22
+ class CipherParams
23
+ include Ably::Modules::ModelCommon
24
+
25
+ # @param params [Hash]
26
+ # @option params [String,Binary] :key Required private key must be either a binary (e.g. a ASCII_8BIT encoded string), or a base64-encoded string. If the key is a base64-encoded string, the it will be automatically converted into a binary
27
+ # @option params [String] :algorithm optional (default AES), specify the encryption algorithm supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
28
+ # @option params [String] :mode optional (default CBC), specify the cipher mode supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
29
+ # @option params [Integer] :key_length optional (default 128), specify the key length of the cipher supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
30
+ # @option params [String] :combined optional (default AES-128-CBC), specify in one option the algorithm, key length and cipher of the cipher supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
31
+ #
32
+ def initialize(params = {})
33
+ @attributes = IdiomaticRubyWrapper(params.clone)
34
+
35
+ raise Ably::Exceptions::CipherError, ':key param is required' unless attributes[:key]
36
+ raise Ably::Exceptions::CipherError, ':key param must be a base64-encoded string or byte array (ASCII_8BIT enocdede string)' unless key.kind_of?(String)
37
+ attributes[:key] = decode_key(key) if key.kind_of?(String) && key.encoding != Encoding::ASCII_8BIT
38
+
39
+ if attributes[:combined]
40
+ match = /(?<algorithm>\w+)-(?<key_length>\d+)-(?<mode>\w+)/.match(attributes[:combined])
41
+ raise Ably::Exceptions::CipherError, "Invalid :combined param, expecting format such as AES-256-CBC" unless match
42
+ attributes[:algorithm] = match[:algorithm]
43
+ attributes[:key_length] = match[:key_length].to_i
44
+ attributes[:mode] = match[:mode]
45
+ end
46
+
47
+ if attributes[:key_length] && (key_length != attributes[:key_length])
48
+ raise Ably::Exceptions::CipherError, "Incompatible :key length of #{key_length} and provided :key_length of #{attributes[:key_length]}"
49
+ end
50
+
51
+ if algorithm == 'aes' && mode == 'cbc'
52
+ unless [128, 256].include?(key_length)
53
+ raise Ably::Exceptions::CipherError, "Unsupported key length #{key_length} for aes-cbc encryption. Encryption key must be 128 or 256 bits (16 or 32 ASCII characters)"
54
+ end
55
+ end
56
+
57
+ attributes.freeze
58
+ end
59
+
60
+ # The Cipher algorithm string such as AES-128-CBC
61
+ #
62
+ # @param [Hash] params Hash containing :algorithm, :key_length and :mode key values
63
+ #
64
+ # @return [String]
65
+ #
66
+ def self.cipher_type(params)
67
+ "#{params[:algorithm]}-#{params[:key_length]}-#{params[:mode]}".to_s.upcase
68
+ end
69
+
70
+ # The algorithm to use for encryption. Only AES is supported and is the default value.
71
+ #
72
+ # @spec TZ2a
73
+ #
74
+ # @return [String]
75
+ #
76
+ def algorithm
77
+ attributes.fetch(:algorithm) do
78
+ Ably::Util::Crypto::DEFAULTS.fetch(:algorithm)
79
+ end.downcase
80
+ end
81
+
82
+ # The private key used to encrypt and decrypt payloads.
83
+ #
84
+ # @spec TZ2d
85
+ #
86
+ # @return [Binary]
87
+ #
88
+ def key
89
+ attributes[:key]
90
+ end
91
+
92
+ # The length of the key in bits; for example 128 or 256.
93
+ #
94
+ # @spec TZ2b
95
+ #
96
+ # @return [Integer]
97
+ #
98
+ def key_length
99
+ key.unpack('b*').first.length
100
+ end
101
+
102
+ # The cipher mode. Only CBC is supported and is the default value.
103
+ #
104
+ # @spec TZ2c
105
+ #
106
+ # @return [String]
107
+ #
108
+ def mode
109
+ attributes.fetch(:mode) do
110
+ Ably::Util::Crypto::DEFAULTS.fetch(:mode)
111
+ end.downcase
112
+ end
113
+
114
+ # The complete Cipher algorithm string such as AES-128-CBC
115
+ #
116
+ # @return [String]
117
+ #
118
+ def cipher_type
119
+ self.class.cipher_type(algorithm: algorithm, key_length: key_length, mode: mode)
120
+ end
121
+
122
+ # Access the token details Hash object ruby'fied to use symbolized keys
123
+ #
124
+ # @return [Hash]
125
+ #
126
+ def attributes
127
+ @attributes
128
+ end
129
+
130
+ private
131
+
132
+ def decode_key(encoded_key)
133
+ normalised_key = encoded_key.gsub('_', '/').gsub('-', '+')
134
+ Base64.decode64(normalised_key)
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,149 @@
1
+ module Ably::Models
2
+ # Convert connection details attributes to a {ConnectionDetails} object
3
+ #
4
+ # @param attributes (see #initialize)
5
+ #
6
+ # @return [ConnectionDetails]
7
+ #
8
+ def self.ConnectionDetails(attributes)
9
+ case attributes
10
+ when ConnectionDetails
11
+ return attributes
12
+ else
13
+ ConnectionDetails.new(attributes || {})
14
+ end
15
+ end
16
+
17
+ # Contains any constraints a client should adhere to and provides additional metadata about a {Ably::Realtime::Connection},
18
+ # such as if a request to {Ably::Realtime::Client#publish} a message that exceeds the maximum message size should be rejected immediately without communicating with Ably.
19
+ #
20
+ class ConnectionDetails
21
+ include Ably::Modules::ModelCommon
22
+
23
+ # Max message size
24
+ MAX_MESSAGE_SIZE = 65536 # See spec TO3l8
25
+
26
+ # Max frame size
27
+ MAX_FRAME_SIZE = 524288 # See spec TO3l9
28
+
29
+ # @param attributes [Hash]
30
+ # @option attributes [String] :client_id Contains the client ID assigned to the token. If clientId is null or omitted, then the client is prohibited from assuming a clientId in any operations, however if clientId is a wildcard string *, then the client is permitted to assume any clientId. Any other string value for clientId implies that the clientId is both enforced and assumed for all operations from this client.
31
+ # @option attributes [String] :connection_key the connection secret key string that is used to resume a connection and its state
32
+ # @option attributes [Integer] :max_message_size maximum individual message size in bytes
33
+ # @option attributes [Integer] :max_frame_size maximum size for a single frame of data sent to Ably. This restriction applies to a {Ably::Models::ProtocolMessage} sent over a realtime connection, or the total body size for a REST request
34
+ # @option attributes [Integer] :max_inbound_rate maximum allowable number of requests per second from a client
35
+ # @option attributes [Integer] :max_idle_interval is the maximum length of time in seconds that the server will allow no activity to occur in the server->client direction. After such a period of inactivity, the server will send a @HEARTBEAT@ or transport-level ping to the client. If the value is 0, the server will allow arbitrarily-long levels of inactivity.
36
+ # @option attributes [Integer] :connection_state_ttl duration in seconds that Ably will persist the connection state when a Realtime client is abruptly disconnected
37
+ # @option attributes [String] :server_id unique identifier of the Ably server where the connection is established
38
+ #
39
+ def initialize(attributes = {})
40
+ @hash_object = IdiomaticRubyWrapper(attributes.clone)
41
+ [:connection_state_ttl, :max_idle_interval].each do |duration_field|
42
+ if self.attributes[duration_field]
43
+ self.attributes[duration_field] = (self.attributes[duration_field].to_f / 1000).round
44
+ end
45
+ end
46
+ self.attributes[:max_message_size] ||= MAX_MESSAGE_SIZE
47
+ self.attributes[:max_frame_size] ||= MAX_FRAME_SIZE
48
+ self.attributes.freeze
49
+ end
50
+
51
+ # Contains the client ID assigned to the token. If clientId is null or omitted, then the client is prohibited from
52
+ # assuming a clientId in any operations, however if clientId is a wildcard string *, then the client is permitted
53
+ # to assume any clientId. Any other string value for clientId implies that the clientId is both enforced and assumed
54
+ # for all operations from this client.
55
+ #
56
+ # @spec RSA12a, CD2a
57
+ #
58
+ # @return [String]
59
+ #
60
+ def client_id
61
+ attributes[:client_id]
62
+ end
63
+
64
+ # The connection secret key string that is used to resume a connection and its state.
65
+ #
66
+ # @spec RTN15e, CD2b
67
+ #
68
+ # @return [String]
69
+ #
70
+ def connection_key
71
+ attributes[:connection_key]
72
+ end
73
+
74
+ # The duration that Ably will persist the connection state for when a Realtime client is abruptly disconnected.
75
+ #
76
+ # @spec CD2f, RTN14e, DF1a
77
+ #
78
+ # @return [Integer]
79
+ #
80
+ def connection_state_ttl
81
+ attributes[:connection_state_ttl]
82
+ end
83
+
84
+ # Overrides the default maxFrameSize.
85
+ #
86
+ # @spec CD2d
87
+ #
88
+ # @return [Integer]
89
+ #
90
+ def max_frame_size
91
+ attributes[:max_frame_size]
92
+ end
93
+
94
+ # The maximum allowable number of requests per second from a client or Ably. In the case of a realtime connection,
95
+ # this restriction applies to the number of messages sent, whereas in the case of REST, it is the total number of REST requests per second.
96
+ #
97
+ # @spec CD2e
98
+ #
99
+ # @return [Integer]
100
+ #
101
+ def max_inbound_rate
102
+ attributes[:max_inbound_rate]
103
+ end
104
+
105
+ # The maximum message size is an attribute of an Ably account and enforced by Ably servers.
106
+ # maxMessageSize indicates the maximum message size allowed by the Ably account this connection is using.
107
+ # Overrides the default value of ClientOptions.maxMessageSize.
108
+ #
109
+ # @spec CD2c
110
+ #
111
+ # @return [Integer]
112
+ #
113
+ def max_message_size
114
+ attributes[:max_message_size]
115
+ end
116
+
117
+ # A unique identifier for the front-end server that the client has connected to. This server ID is only used for the purposes of debugging.
118
+ #
119
+ # @spec CD2g
120
+ #
121
+ # @return [String]
122
+ #
123
+ def server_id
124
+ attributes[:server_id]
125
+ end
126
+
127
+ # The maximum length of time in milliseconds that the server will allow no activity to occur in the server to client direction.
128
+ # After such a period of inactivity, the server will send a HEARTBEAT or transport-level ping to the client.
129
+ # If the value is 0, the server will allow arbitrarily-long levels of inactivity.
130
+ #
131
+ # @spec CD2h
132
+ #
133
+ # @return [Integer]
134
+ #
135
+ def max_idle_interval
136
+ attributes[:max_idle_interval]
137
+ end
138
+
139
+ def has_client_id?
140
+ attributes.has_key?(:client_id)
141
+ end
142
+
143
+ # @return [Hash] Access the token details Hash object ruby'fied to use symbolized keys
144
+ #
145
+ def attributes
146
+ @hash_object
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,83 @@
1
+ module Ably::Models
2
+ # Contains {Ably::Models::ConnectionState} change information emitted by the {Ably::Realtime::Connection} object.
3
+ #
4
+ class ConnectionStateChange
5
+ include Ably::Modules::ModelCommon
6
+
7
+ def initialize(hash_object)
8
+ unless (hash_object.keys - [:current, :previous, :event, :retry_in, :reason, :protocol_message]).empty?
9
+ raise ArgumentError, 'Invalid attributes, expecting :current, :previous, :event, :retry_in, :reason'
10
+ end
11
+
12
+ @hash_object = {
13
+ current: hash_object.fetch(:current),
14
+ previous: hash_object.fetch(:previous),
15
+ event: hash_object[:event],
16
+ retry_in: hash_object[:retry_in],
17
+ reason: hash_object[:reason],
18
+ protocol_message: hash_object[:protocol_message]
19
+ }
20
+ rescue KeyError => e
21
+ raise ArgumentError, e
22
+ end
23
+
24
+ # The new {Ably::Realtime::Connection::STATE}.
25
+ #
26
+ # @spec TA2
27
+ #
28
+ # @return [Ably::Realtime::Connection::STATE]
29
+ #
30
+ def current
31
+ @hash_object[:current]
32
+ end
33
+
34
+ # The event that triggered this {Ably::Realtime::Connection::EVENT} change.
35
+ #
36
+ # @spec TA5
37
+ #
38
+ # @return [Ably::Realtime::Connection::STATE]
39
+ #
40
+ def event
41
+ @hash_object[:event]
42
+ end
43
+
44
+ # The previous {Ably::Models::Connection::STATE}. For the {Ably::Models::Connection::EVENT} UPDATE event,
45
+ # this is equal to the current {Ably::Models::Connection::STATE}.
46
+ #
47
+ # @spec TA2
48
+ #
49
+ # @return [Ably::Realtime::Connection::STATE]
50
+ #
51
+ def previous
52
+ @hash_object[:previous]
53
+ end
54
+
55
+ # An {Ably::Models::ErrorInfo} object containing any information relating to the transition.
56
+ #
57
+ # @spec RTN4f, TA3
58
+ #
59
+ # @return [Ably::Models::ErrorInfo, nil]
60
+ #
61
+ def reason
62
+ @hash_object[:reason]
63
+ end
64
+
65
+ # Duration in milliseconds, after which the client retries a connection where applicable.
66
+ #
67
+ # @spec RTN14d, TA2
68
+ #
69
+ # @return [Integer]
70
+ #
71
+ def retry_in
72
+ @hash_object[:retry_in]
73
+ end
74
+
75
+ def protocol_message
76
+ @hash_object[:protocol_message]
77
+ end
78
+
79
+ def to_s
80
+ "<ConnectionStateChange: current state #{current}, previous state #{previous}>"
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,28 @@
1
+ module Ably::Models
2
+ # Contains any arbitrary key-value pairs, which may also contain other primitive JSON types, JSON-encodable objects,
3
+ # or JSON-encodable arrays from delta compression.
4
+ #
5
+ class DeltaExtras
6
+ include Ably::Modules::ModelCommon
7
+
8
+ # The ID of the message the delta was generated from.
9
+ #
10
+ # @return [String, nil]
11
+ #
12
+ attr_reader :from
13
+
14
+ # The delta compression format. Only vcdiff is supported.
15
+ #
16
+ # @return [String, nil]
17
+ #
18
+ attr_reader :format
19
+
20
+ def initialize(attributes = {})
21
+ @from, @format = IdiomaticRubyWrapper((attributes || {}), stop_at: [:from, :format]).attributes.values_at(:from, :format)
22
+ end
23
+
24
+ def to_json(*args)
25
+ as_json(args).to_json
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,126 @@
1
+ module Ably::Modules
2
+ module Conversions
3
+ private
4
+ # Convert device_details argument to a {Ably::Models::DeviceDetails} object
5
+ #
6
+ # @param device_details [Ably::Models::DeviceDetails,Hash,nil] A device details object
7
+ #
8
+ # @return [Ably::Models::DeviceDetails]
9
+ #
10
+ def DeviceDetails(device_details)
11
+ case device_details
12
+ when Ably::Models::DeviceDetails
13
+ device_details
14
+ else
15
+ Ably::Models::DeviceDetails.new(device_details)
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ module Ably::Models
22
+ # Contains the properties of a device registered for push notifications.
23
+ #
24
+ class DeviceDetails < Ably::Exceptions::BaseAblyException
25
+ include Ably::Modules::ModelCommon
26
+
27
+ # @param hash_object [Hash,nil] Device detail attributes
28
+ #
29
+ def initialize(hash_object = {})
30
+ @raw_hash_object = hash_object || {}
31
+ @hash_object = IdiomaticRubyWrapper(hash_object)
32
+ end
33
+
34
+ # A unique ID generated by the device.
35
+ #
36
+ # @spec PCD2
37
+ #
38
+ def id
39
+ attributes[:id]
40
+ end
41
+
42
+ # The DevicePlatform associated with the device.
43
+ # Describes the platform the device uses, such as android or ios.
44
+ #
45
+ # @spec PCD6
46
+ #
47
+ # @return [String]
48
+ #
49
+ def platform
50
+ attributes[:platform]
51
+ end
52
+
53
+ # The client ID the device is connected to Ably with.
54
+ #
55
+ # @spec PCD3
56
+ #
57
+ # @return [String]
58
+ #
59
+ def client_id
60
+ attributes[:client_id]
61
+ end
62
+
63
+ # The DeviceFormFactor object associated with the device.
64
+ # Describes the type of the device, such as phone or tablet.
65
+ #
66
+ # @spec PCD4
67
+ #
68
+ # @return [String]
69
+ #
70
+ def form_factor
71
+ attributes[:form_factor]
72
+ end
73
+
74
+ def device_secret
75
+ attributes[:device_secret]
76
+ end
77
+
78
+ %w(id platform form_factor client_id device_secret).each do |attribute|
79
+ define_method "#{attribute}=" do |val|
80
+ unless val.nil? || val.kind_of?(String)
81
+ raise ArgumentError, "#{attribute} must be nil or a string value"
82
+ end
83
+ attributes[attribute.to_sym] = val
84
+ end
85
+ end
86
+
87
+ # A JSON object of key-value pairs that contains metadata for the device.
88
+ #
89
+ # @spec PCD5
90
+ #
91
+ # @return [Hash, nil]
92
+ #
93
+ def metadata
94
+ attributes[:metadata] || {}
95
+ end
96
+
97
+ def metadata=(val)
98
+ unless val.nil? || val.kind_of?(Hash)
99
+ raise ArgumentError, "metadata must be nil or a Hash value"
100
+ end
101
+ attributes[:metadata] = val
102
+ end
103
+
104
+ # The {Ably::Models::DevicePushDetails} object associated with the device.
105
+ # Describes the details of the push registration of the device.
106
+ #
107
+ # @spec PCD7
108
+ #
109
+ # @return [Ably::Models::DevicePushDetails]
110
+ #
111
+ def push
112
+ DevicePushDetails(attributes[:push] || {})
113
+ end
114
+
115
+ def push=(val)
116
+ unless val.nil? || val.kind_of?(Hash) || val.kind_of?(Ably::Models::DevicePushDetails)
117
+ raise ArgumentError, "push must be nil, a Hash value or a DevicePushDetails object"
118
+ end
119
+ attributes[:push] = DevicePushDetails(val)
120
+ end
121
+
122
+ def attributes
123
+ @hash_object
124
+ end
125
+ end
126
+ end