nylas 3.2.0 → 4.0.0.rc2
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.
- checksums.yaml +4 -4
- data/lib/nylas.rb +33 -380
- data/lib/nylas/api.rb +43 -0
- data/lib/nylas/collection.rb +110 -0
- data/lib/nylas/constraints.rb +46 -0
- data/lib/nylas/contact.rb +30 -0
- data/lib/nylas/current_account.rb +23 -0
- data/lib/nylas/email_address.rb +14 -0
- data/lib/nylas/errors.rb +36 -0
- data/lib/nylas/http_client.rb +135 -0
- data/lib/nylas/im_address.rb +14 -0
- data/lib/nylas/logging.rb +41 -0
- data/lib/nylas/model.rb +92 -0
- data/lib/nylas/model/attributable.rb +57 -0
- data/lib/nylas/model/attribute_definition.rb +19 -0
- data/lib/nylas/model/attributes.rb +47 -0
- data/lib/nylas/model/list_attribute_definition.rb +28 -0
- data/lib/nylas/nylas_date.rb +20 -0
- data/lib/nylas/phone_number.rb +14 -0
- data/lib/nylas/physical_address.rb +19 -0
- data/lib/nylas/registry.rb +37 -0
- data/lib/nylas/types.rb +83 -0
- data/lib/nylas/version.rb +3 -0
- data/lib/nylas/web_page.rb +14 -0
- metadata +144 -98
- data/lib/account.rb +0 -32
- data/lib/api_account.rb +0 -22
- data/lib/api_thread.rb +0 -85
- data/lib/calendar.rb +0 -16
- data/lib/contact.rb +0 -10
- data/lib/draft.rb +0 -50
- data/lib/event.rb +0 -47
- data/lib/expanded_message.rb +0 -20
- data/lib/file.rb +0 -40
- data/lib/folder.rb +0 -12
- data/lib/label.rb +0 -4
- data/lib/message.rb +0 -102
- data/lib/mixins.rb +0 -26
- data/lib/parameters.rb +0 -26
- data/lib/restful_model.rb +0 -82
- data/lib/restful_model_collection.rb +0 -160
- data/lib/time_attr_accessor.rb +0 -12
- data/lib/version.rb +0 -3
data/lib/nylas/model.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require_relative "model/attribute_definition"
|
2
|
+
require_relative "model/list_attribute_definition"
|
3
|
+
require_relative "model/attributable"
|
4
|
+
require_relative "model/attributes"
|
5
|
+
module Nylas
|
6
|
+
# Include this to define a class to represent an object returned from the API
|
7
|
+
module Model
|
8
|
+
attr_accessor :api
|
9
|
+
|
10
|
+
def self.included(model)
|
11
|
+
model.include(Attributable)
|
12
|
+
model.extend(ClassMethods)
|
13
|
+
model.collectionable = true
|
14
|
+
model.searchable = true
|
15
|
+
model.read_only = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def save
|
19
|
+
raise_if_read_only
|
20
|
+
result = if id
|
21
|
+
api.execute(method: :put, payload: attributes.serialize, path: resource_path)
|
22
|
+
else
|
23
|
+
api.execute(method: :post, payload: attributes.serialize, path: resources_path)
|
24
|
+
end
|
25
|
+
attributes.merge(result)
|
26
|
+
end
|
27
|
+
|
28
|
+
def update(**data)
|
29
|
+
raise_if_read_only
|
30
|
+
attributes.merge(**data)
|
31
|
+
api.execute(method: :put, payload: attributes.serialize(keys: data.keys), path: resource_path)
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
def reload
|
36
|
+
attributes.merge(api.execute(method: :get, path: resource_path))
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def resource_path
|
41
|
+
"#{resources_path}/#{id}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def resources_path
|
45
|
+
self.class.resources_path
|
46
|
+
end
|
47
|
+
|
48
|
+
def destroy
|
49
|
+
api.execute(method: :delete, path: resource_path)
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [String] JSON String of the model.
|
53
|
+
def to_json
|
54
|
+
JSON.dump(to_h)
|
55
|
+
end
|
56
|
+
|
57
|
+
def raise_if_read_only
|
58
|
+
self.class.raise_if_read_only
|
59
|
+
end
|
60
|
+
|
61
|
+
# Allows you to narrow in exactly what kind of model you're working with
|
62
|
+
module ClassMethods
|
63
|
+
attr_accessor :resources_path, :searchable, :read_only, :collectionable
|
64
|
+
|
65
|
+
def read_only?
|
66
|
+
read_only == true
|
67
|
+
end
|
68
|
+
|
69
|
+
def raise_if_read_only
|
70
|
+
raise NotImplementedError, "#{self} is read only" if read_only?
|
71
|
+
end
|
72
|
+
|
73
|
+
def searchable?
|
74
|
+
searchable == true
|
75
|
+
end
|
76
|
+
|
77
|
+
def collectionable?
|
78
|
+
collectionable == true
|
79
|
+
end
|
80
|
+
|
81
|
+
def from_json(json, api:)
|
82
|
+
from_hash(JSON.parse(json, symbolize_names: true), api: api)
|
83
|
+
end
|
84
|
+
|
85
|
+
def from_hash(data, api:)
|
86
|
+
instance = new(**data)
|
87
|
+
instance.api = api
|
88
|
+
instance
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Nylas
|
2
|
+
module Model
|
3
|
+
# Allows defining of tyypecastable attributes on a model
|
4
|
+
module Attributable
|
5
|
+
def self.included(model)
|
6
|
+
model.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(**initial_data)
|
10
|
+
initial_data.each do |attribute_name, value|
|
11
|
+
send(:"#{attribute_name}=", value)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def attributes
|
16
|
+
@attributes ||= Attributes.new(self.class.attribute_definitions)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Hash] Representation of the model with values serialized into primitives based on their Type
|
20
|
+
def to_h
|
21
|
+
attributes.to_h
|
22
|
+
end
|
23
|
+
|
24
|
+
# Methods to call when tweaking Attributable classes
|
25
|
+
module ClassMethods
|
26
|
+
# rubocop:disable Style/PredicateName
|
27
|
+
def has_n_of_attribute(name, type_name, exclude_when: [], default: [])
|
28
|
+
attribute_definitions[name] = ListAttributeDefinition.new(type_name: type_name,
|
29
|
+
exclude_when: exclude_when,
|
30
|
+
default: default)
|
31
|
+
define_accessors(name)
|
32
|
+
end
|
33
|
+
# rubocop:enable Style/PredicateName
|
34
|
+
|
35
|
+
def attribute(name, type_name, exclude_when: [], default: nil)
|
36
|
+
attribute_definitions[name] = AttributeDefinition.new(type_name: type_name,
|
37
|
+
exclude_when: exclude_when, default: default)
|
38
|
+
define_accessors(name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def define_accessors(name)
|
42
|
+
define_method :"#{name}" do
|
43
|
+
attributes[name]
|
44
|
+
end
|
45
|
+
|
46
|
+
define_method :"#{name}=" do |value|
|
47
|
+
attributes[name] = value
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def attribute_definitions
|
52
|
+
@attribute_definitions ||= Registry.new
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Nylas
|
2
|
+
module Model
|
3
|
+
# Define a particular attribute for a given model
|
4
|
+
class AttributeDefinition
|
5
|
+
extend Forwardable
|
6
|
+
def_delegators :type, :cast, :serialize
|
7
|
+
attr_accessor :type_name, :exclude_when, :default
|
8
|
+
def initialize(type_name:, exclude_when:, default:)
|
9
|
+
self.type_name = type_name
|
10
|
+
self.exclude_when = exclude_when
|
11
|
+
self.default = default
|
12
|
+
end
|
13
|
+
|
14
|
+
private def type
|
15
|
+
Types.registry[type_name]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Nylas
|
2
|
+
module Model
|
3
|
+
# Stores the actual model data to allow for type casting and clean/dirty checking
|
4
|
+
class Attributes
|
5
|
+
attr_accessor :data, :attribute_definitions
|
6
|
+
|
7
|
+
def initialize(attribute_definitions)
|
8
|
+
@attribute_definitions = attribute_definitions
|
9
|
+
@data = Registry.new(default_attributes)
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](key)
|
13
|
+
data[key]
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(key, value)
|
17
|
+
data[key] = cast(key, value)
|
18
|
+
end
|
19
|
+
|
20
|
+
private def cast(key, value)
|
21
|
+
attribute_definitions[key].cast(value)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Merges data into the registry while casting input types correctly
|
25
|
+
def merge(new_data)
|
26
|
+
new_data.each do |attribute_name, value|
|
27
|
+
self[attribute_name] = value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_h(keys: attribute_definitions.keys)
|
32
|
+
keys.each_with_object({}) do |key, casted_data|
|
33
|
+
value = attribute_definitions[key].serialize(self[key])
|
34
|
+
casted_data[key] = value unless value.nil? || value.empty?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def serialize(keys: attribute_definitions.keys)
|
39
|
+
JSON.dump(to_h(keys: keys))
|
40
|
+
end
|
41
|
+
|
42
|
+
private def default_attributes
|
43
|
+
attribute_definitions.keys.zip([]).to_h
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Nylas
|
2
|
+
module Model
|
3
|
+
# Allows models to have an attribute which is a lists of another type of thing
|
4
|
+
class ListAttributeDefinition
|
5
|
+
attr_accessor :type_name, :exclude_when, :default
|
6
|
+
|
7
|
+
def initialize(type_name:, exclude_when:, default:)
|
8
|
+
self.type_name = type_name
|
9
|
+
self.exclude_when = exclude_when
|
10
|
+
self.default = default
|
11
|
+
end
|
12
|
+
|
13
|
+
def cast(list)
|
14
|
+
return default if list.nil? || list.empty?
|
15
|
+
list.map { |item| type.cast(item) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialize(list)
|
19
|
+
list = default if list.nil? || list.empty?
|
20
|
+
list.map { |item| type.serialize(item) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def type
|
24
|
+
Types.registry[type_name]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Nylas
|
2
|
+
# Structure to represent Nylas's more complex Date Schema
|
3
|
+
# @see https://docs.nylas.com/reference#contactsid
|
4
|
+
class NylasDate
|
5
|
+
extend Forwardable
|
6
|
+
def_delegators :date, :===, :==, :<=>, :eql?, :equal?
|
7
|
+
|
8
|
+
include Model::Attributable
|
9
|
+
attribute :object, :string
|
10
|
+
attribute :date, :date
|
11
|
+
end
|
12
|
+
|
13
|
+
# Serializes, Deserializes between {NylasDate} objects and a {Hash}
|
14
|
+
class NylasDateType < Types::HashType
|
15
|
+
casts_to NylasDate
|
16
|
+
def cast(value)
|
17
|
+
value.is_a?(String) ? super({ object: "date", date: value }) : super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Nylas
|
2
|
+
# Structure to represent the Phone Number Schema
|
3
|
+
# @see https://docs.nylas.com/reference#contactsid
|
4
|
+
class PhoneNumber
|
5
|
+
include Model::Attributable
|
6
|
+
attribute :type, :string
|
7
|
+
attribute :number, :string
|
8
|
+
end
|
9
|
+
|
10
|
+
# Serializes, Deserializes between {PhoneNumber} objects and a {Hash}
|
11
|
+
class PhoneNumberType < Types::HashType
|
12
|
+
casts_to PhoneNumber
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Nylas
|
2
|
+
# Structure to represent the Physical Address schema
|
3
|
+
# @see https://docs.nylas.com/reference#contactsid
|
4
|
+
class PhysicalAddress
|
5
|
+
include Model::Attributable
|
6
|
+
attribute :format, :string
|
7
|
+
attribute :type, :string
|
8
|
+
attribute :street_address, :string
|
9
|
+
attribute :postal_code, :string
|
10
|
+
attribute :state, :string
|
11
|
+
attribute :city, :string
|
12
|
+
attribute :country, :string
|
13
|
+
end
|
14
|
+
|
15
|
+
# Serializes, Deserializes between {PhysicalAddress} objects and a {Hash}
|
16
|
+
class PhysicalAddressType < Types::HashType
|
17
|
+
casts_to PhysicalAddress
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Nylas
|
2
|
+
# Used to create a hash-like structure which defaults to raising an exception in the event the key to
|
3
|
+
# retrieve does not exist.
|
4
|
+
class Registry
|
5
|
+
# Used to indicate an attempt to retrieve something not yet registered in a registry
|
6
|
+
# Includes the list of keys in the registry for debug purposes.
|
7
|
+
class MissingKeyError < Error
|
8
|
+
def initialize(key, keys)
|
9
|
+
super("key #{key} not in #{keys}")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
attr_accessor :registry_data
|
13
|
+
|
14
|
+
extend Forwardable
|
15
|
+
def_delegators :registry_data, :keys, :each, :reduce
|
16
|
+
|
17
|
+
def initialize(initial_data = {})
|
18
|
+
self.registry_data = initial_data.each.each_with_object({}) do |(key, value), registry|
|
19
|
+
registry[key] = value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def [](key)
|
24
|
+
registry_data.fetch(key)
|
25
|
+
rescue KeyError
|
26
|
+
raise MissingKeyError.new(key, keys)
|
27
|
+
end
|
28
|
+
|
29
|
+
def []=(key, value)
|
30
|
+
registry_data[key] = value
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_h
|
34
|
+
registry_data
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/nylas/types.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
module Nylas
|
2
|
+
# Collection of attribute types
|
3
|
+
module Types
|
4
|
+
def self.registry
|
5
|
+
@registry ||= Registry.new
|
6
|
+
end
|
7
|
+
|
8
|
+
# Type for attributes that are persisted in the API as a hash but exposed in ruby as a particular
|
9
|
+
# structure
|
10
|
+
class HashType
|
11
|
+
def serialize(object)
|
12
|
+
object.to_h
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.casts_to(model)
|
16
|
+
@casts_to_model = model
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
attr_reader :casts_to_model
|
21
|
+
end
|
22
|
+
|
23
|
+
def model
|
24
|
+
self.class.casts_to_model
|
25
|
+
end
|
26
|
+
|
27
|
+
def cast(value)
|
28
|
+
return model.new if value.nil?
|
29
|
+
return value if already_cast?(value)
|
30
|
+
return model.new(**actual_attributes(value)) if value.respond_to?(:key?)
|
31
|
+
raise TypeError, "Unable to cast #{value} to a #{model}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def already_cast?(value)
|
35
|
+
model.attribute_definitions.keys.all? { |attribute_name| value.respond_to?(attribute_name) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def actual_attributes(hash)
|
39
|
+
model.attribute_definitions.keys.each_with_object({}) do |attribute_name, attributes|
|
40
|
+
attributes[attribute_name] = hash[attribute_name]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Type for attributes that do not require casting/serializing/deserializing.
|
46
|
+
class ValueType
|
47
|
+
def cast(object)
|
48
|
+
object
|
49
|
+
end
|
50
|
+
|
51
|
+
def serialize(object)
|
52
|
+
object
|
53
|
+
end
|
54
|
+
|
55
|
+
def deseralize(object)
|
56
|
+
object
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Type for attributes represented as an iso8601 dates in the API and Date in Ruby
|
61
|
+
class DateType < ValueType
|
62
|
+
def cast(value)
|
63
|
+
return nil if value.nil?
|
64
|
+
Date.parse(value)
|
65
|
+
end
|
66
|
+
|
67
|
+
def serialize(value)
|
68
|
+
return value.iso8601 if value.respond_to?(:iso8601)
|
69
|
+
value
|
70
|
+
end
|
71
|
+
end
|
72
|
+
Types.registry[:date] = DateType.new
|
73
|
+
|
74
|
+
# Type for attributes represented as pure strings both within the API and in Ruby
|
75
|
+
class StringType < ValueType
|
76
|
+
# @param value [Object] Casts the passed in object to a string using #to_s
|
77
|
+
def cast(value)
|
78
|
+
value.to_s
|
79
|
+
end
|
80
|
+
end
|
81
|
+
Types.registry[:string] = StringType.new
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Nylas
|
2
|
+
# Structure to represent the Web Page Schema
|
3
|
+
# @see https://docs.nylas.com/reference#contactsid
|
4
|
+
class WebPage
|
5
|
+
include Model::Attributable
|
6
|
+
attribute :type, :string
|
7
|
+
attribute :url, :string
|
8
|
+
end
|
9
|
+
|
10
|
+
# Serializes, Deserializes between {WebPage} objects and a {Hash}
|
11
|
+
class WebPageType < Types::HashType
|
12
|
+
casts_to WebPage
|
13
|
+
end
|
14
|
+
end
|