nylas_v2 5.14.2

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 (91) hide show
  1. checksums.yaml +7 -0
  2. data/lib/nylas_v2/account.rb +56 -0
  3. data/lib/nylas_v2/api.rb +244 -0
  4. data/lib/nylas_v2/application_details.rb +13 -0
  5. data/lib/nylas_v2/calendar.rb +46 -0
  6. data/lib/nylas_v2/calendar_collection.rb +144 -0
  7. data/lib/nylas_v2/categorize.rb +14 -0
  8. data/lib/nylas_v2/collection.rb +175 -0
  9. data/lib/nylas_v2/component.rb +35 -0
  10. data/lib/nylas_v2/component_collection.rb +10 -0
  11. data/lib/nylas_v2/constraints.rb +56 -0
  12. data/lib/nylas_v2/contact.rb +53 -0
  13. data/lib/nylas_v2/contact_group.rb +23 -0
  14. data/lib/nylas_v2/current_account.rb +23 -0
  15. data/lib/nylas_v2/delta.rb +56 -0
  16. data/lib/nylas_v2/deltas.rb +19 -0
  17. data/lib/nylas_v2/deltas_collection.rb +40 -0
  18. data/lib/nylas_v2/draft.rb +100 -0
  19. data/lib/nylas_v2/email_address.rb +12 -0
  20. data/lib/nylas_v2/errors.rb +111 -0
  21. data/lib/nylas_v2/event.rb +141 -0
  22. data/lib/nylas_v2/event_collection.rb +15 -0
  23. data/lib/nylas_v2/event_conferencing.rb +12 -0
  24. data/lib/nylas_v2/event_conferencing_autocreate.rb +10 -0
  25. data/lib/nylas_v2/event_conferencing_details.rb +14 -0
  26. data/lib/nylas_v2/event_notification.rb +17 -0
  27. data/lib/nylas_v2/file.rb +75 -0
  28. data/lib/nylas_v2/filter_attributes.rb +25 -0
  29. data/lib/nylas_v2/folder.rb +26 -0
  30. data/lib/nylas_v2/free_busy.rb +13 -0
  31. data/lib/nylas_v2/free_busy_collection.rb +48 -0
  32. data/lib/nylas_v2/http_client.rb +279 -0
  33. data/lib/nylas_v2/im_address.rb +11 -0
  34. data/lib/nylas_v2/job_status.rb +27 -0
  35. data/lib/nylas_v2/job_status_collection.rb +21 -0
  36. data/lib/nylas_v2/label.rb +27 -0
  37. data/lib/nylas_v2/logging.rb +41 -0
  38. data/lib/nylas_v2/message.rb +98 -0
  39. data/lib/nylas_v2/message_headers.rb +27 -0
  40. data/lib/nylas_v2/message_tracking.rb +13 -0
  41. data/lib/nylas_v2/model/attributable.rb +89 -0
  42. data/lib/nylas_v2/model/attribute_definition.rb +24 -0
  43. data/lib/nylas_v2/model/attributes.rb +97 -0
  44. data/lib/nylas_v2/model/list_attribute_definition.rb +39 -0
  45. data/lib/nylas_v2/model/transferable.rb +53 -0
  46. data/lib/nylas_v2/model.rb +217 -0
  47. data/lib/nylas_v2/native_authentication.rb +39 -0
  48. data/lib/nylas_v2/neural.rb +87 -0
  49. data/lib/nylas_v2/neural_categorizer.rb +29 -0
  50. data/lib/nylas_v2/neural_clean_conversation.rb +33 -0
  51. data/lib/nylas_v2/neural_contact_link.rb +11 -0
  52. data/lib/nylas_v2/neural_contact_name.rb +11 -0
  53. data/lib/nylas_v2/neural_message_options.rb +35 -0
  54. data/lib/nylas_v2/neural_ocr.rb +16 -0
  55. data/lib/nylas_v2/neural_sentiment_analysis.rb +17 -0
  56. data/lib/nylas_v2/neural_signature_contact.rb +81 -0
  57. data/lib/nylas_v2/neural_signature_extraction.rb +18 -0
  58. data/lib/nylas_v2/new_message.rb +39 -0
  59. data/lib/nylas_v2/nylas_date.rb +25 -0
  60. data/lib/nylas_v2/open_hours.rb +15 -0
  61. data/lib/nylas_v2/outbox.rb +116 -0
  62. data/lib/nylas_v2/outbox_job_status.rb +19 -0
  63. data/lib/nylas_v2/outbox_message.rb +17 -0
  64. data/lib/nylas_v2/participant.rb +13 -0
  65. data/lib/nylas_v2/phone_number.rb +11 -0
  66. data/lib/nylas_v2/physical_address.rb +17 -0
  67. data/lib/nylas_v2/raw_message.rb +25 -0
  68. data/lib/nylas_v2/recurrence.rb +11 -0
  69. data/lib/nylas_v2/registry.rb +42 -0
  70. data/lib/nylas_v2/room_resource.rb +19 -0
  71. data/lib/nylas_v2/rsvp.rb +24 -0
  72. data/lib/nylas_v2/scheduler.rb +51 -0
  73. data/lib/nylas_v2/scheduler_booking_confirmation.rb +24 -0
  74. data/lib/nylas_v2/scheduler_booking_request.rb +17 -0
  75. data/lib/nylas_v2/scheduler_collection.rb +104 -0
  76. data/lib/nylas_v2/scheduler_config.rb +20 -0
  77. data/lib/nylas_v2/scheduler_time_slot.rb +14 -0
  78. data/lib/nylas_v2/search_collection.rb +10 -0
  79. data/lib/nylas_v2/send_grid_verified_status.rb +12 -0
  80. data/lib/nylas_v2/thread.rb +66 -0
  81. data/lib/nylas_v2/time_slot.rb +16 -0
  82. data/lib/nylas_v2/time_slot_capacity.rb +13 -0
  83. data/lib/nylas_v2/timespan.rb +20 -0
  84. data/lib/nylas_v2/token_info.rb +20 -0
  85. data/lib/nylas_v2/types.rb +168 -0
  86. data/lib/nylas_v2/version.rb +5 -0
  87. data/lib/nylas_v2/web_page.rb +11 -0
  88. data/lib/nylas_v2/webhook.rb +98 -0
  89. data/lib/nylas_v2/when.rb +75 -0
  90. data/lib/nylas_v2.rb +162 -0
  91. metadata +415 -0
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # An enumerable for working with index and search endpoints
5
+ class Collection
6
+ attr_accessor :model, :api, :constraints
7
+
8
+ extend Forwardable
9
+ def_delegators :each, :map, :select, :reject, :to_a, :take
10
+ def_delegators :to_a, :first, :last, :[]
11
+
12
+ def initialize(model:, api:, constraints: nil)
13
+ self.constraints = Constraints.from_constraints(constraints)
14
+ self.model = model
15
+ self.api = api
16
+ end
17
+
18
+ # Instantiates a new model
19
+ def new(**attributes)
20
+ model.new(**attributes.merge(api: api))
21
+ end
22
+
23
+ def create(**attributes)
24
+ instance = model.new(**attributes.merge(api: api))
25
+ instance.save
26
+ instance
27
+ end
28
+
29
+ # Merges in additional filters when querying the collection
30
+ # @return [Collection<Model>]
31
+ def where(filters)
32
+ raise ModelNotFilterableError, model unless model.filterable?
33
+
34
+ self.class.new(model: model, api: api, constraints: constraints.merge(where: filters))
35
+ end
36
+
37
+ def search(query)
38
+ raise ModelNotSearchableError, model unless model.searchable?
39
+
40
+ SearchCollection.new(model: model, api: api, constraints: constraints.merge(where: { q: query }))
41
+ end
42
+
43
+ # The collection now returns a string representation of the model in a particular mime type instead of
44
+ # Model objects
45
+ # @return [Collection<String>]
46
+ def raw
47
+ raise ModelNotAvailableAsRawError, model unless model.exposable_as_raw?
48
+
49
+ self.class.new(model: model, api: api, constraints: constraints.merge(accept: model.raw_mime_type))
50
+ end
51
+
52
+ # @return [Integer]
53
+ def count
54
+ collection = self.class.new(model: model, api: api, constraints: constraints)
55
+
56
+ if model.countable
57
+ collection.constraints = collection.constraints.merge(view: "count")
58
+ collection.execute[:count]
59
+ else
60
+ collection.find_each.map.count
61
+ end
62
+ end
63
+
64
+ # @return [Collection<Model>]
65
+ def expanded
66
+ self.class.new(model: model, api: api, constraints: constraints.merge(view: "expanded"))
67
+ end
68
+
69
+ # @return [Array<String>]
70
+ def ids
71
+ collection = self.class.new(model: model, api: api, constraints: constraints)
72
+
73
+ if model.id_listable
74
+ collection.constraints = collection.constraints.merge(view: "ids")
75
+ collection.execute
76
+ else
77
+ collection.find_each.map(&:id)
78
+ end
79
+ end
80
+
81
+ # Iterates over a single page of results based upon current pagination settings
82
+ def each
83
+ return enum_for(:each) unless block_given?
84
+
85
+ execute.each do |result|
86
+ yield(model.new(**result.merge(api: api)))
87
+ end
88
+ end
89
+
90
+ def limit(quantity)
91
+ self.class.new(model: model, api: api, constraints: constraints.merge(limit: quantity))
92
+ end
93
+
94
+ def offset(start)
95
+ self.class.new(model: model, api: api, constraints: constraints.merge(offset: start))
96
+ end
97
+
98
+ # Iterates over every result that meets the filters, retrieving a page at a time
99
+ def find_each
100
+ return enum_for(:find_each) unless block_given?
101
+
102
+ query = self
103
+ accumulated = 0
104
+
105
+ while query
106
+ results = query.each do |instance|
107
+ yield(instance)
108
+ end
109
+
110
+ accumulated += results.length
111
+ query = query.next_page(accumulated: accumulated, current_page: results)
112
+ end
113
+ end
114
+
115
+ def next_page(accumulated:, current_page:)
116
+ return nil unless more_pages?(accumulated, current_page)
117
+
118
+ self.class.new(model: model, api: api, constraints: constraints.next_page)
119
+ end
120
+
121
+ def more_pages?(accumulated, current_page)
122
+ return false if current_page.empty?
123
+ return false if constraints.limit && accumulated >= constraints.limit
124
+ return false if constraints.per_page && current_page.length < constraints.per_page
125
+
126
+ true
127
+ end
128
+
129
+ # Retrieves a record. Nylas doesn't support where filters on GET so this will not take into
130
+ # consideration other query constraints, such as where clauses.
131
+ def find(id)
132
+ constraints.accept == "application/json" ? find_model(id) : find_raw(id)
133
+ end
134
+
135
+ def find_raw(id)
136
+ api.execute(**to_be_executed.merge(path: "#{resources_path}/#{id}")).to_s
137
+ end
138
+
139
+ def resources_path
140
+ model.resources_path(api: api)
141
+ end
142
+
143
+ def find_model(id)
144
+ response = api.execute(
145
+ **to_be_executed.merge(
146
+ path: "#{resources_path}/#{id}",
147
+ query: view_query
148
+ )
149
+ )
150
+ model.from_hash(response, api: api)
151
+ end
152
+
153
+ # @return [Hash] Specification for request to be passed to {API#execute}
154
+ def to_be_executed
155
+ { method: :get, path: resources_path, query: constraints.to_query,
156
+ headers: constraints.to_headers, auth_method: model.auth_method }
157
+ end
158
+
159
+ # Retrieves the data from the API for the particular constraints
160
+ # @return [Hash,Array]
161
+ def execute
162
+ api.execute(**to_be_executed)
163
+ end
164
+
165
+ private
166
+
167
+ def view_query
168
+ if constraints.view
169
+ { view: constraints.view }
170
+ else
171
+ {}
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Structure to represent a the Component Schema.
5
+ class Component
6
+ include Model
7
+ self.creatable = true
8
+ self.listable = true
9
+ self.showable = true
10
+ self.filterable = true
11
+ self.updatable = true
12
+ self.destroyable = true
13
+ self.auth_method = HttpClient::AuthMethod::BASIC
14
+
15
+ attribute :id, :string, read_only: true
16
+ attribute :account_id, :string
17
+ attribute :name, :string
18
+ attribute :type, :string
19
+ attribute :action, :integer
20
+ attribute :active, :boolean
21
+ attribute :settings, :hash
22
+ attribute :public_account_id, :string
23
+ attribute :public_token_id, :string
24
+ attribute :public_application_id, :string, read_only: true
25
+ attribute :access_token, :string
26
+ attribute :created_at, :date, read_only: true
27
+ attribute :updated_at, :date, read_only: true
28
+
29
+ has_n_of_attribute :allowed_domains, :string
30
+
31
+ def resources_path(*)
32
+ "/component/#{api.client.app_id}"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Additional configuration for the Component CRUD API
5
+ class ComponentCollection < Collection
6
+ def resources_path
7
+ "/component/#{api.client.app_id}"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # The constraints a particular GET request will include in their query params
5
+ class Constraints
6
+ attr_accessor :where, :limit, :offset, :view, :per_page, :accept
7
+
8
+ def initialize(where: {}, limit: nil, offset: 0, view: nil, per_page: 100, accept: "application/json")
9
+ self.where = where
10
+ self.limit = limit
11
+ self.offset = offset
12
+ self.view = view
13
+ self.per_page = per_page
14
+ self.accept = accept
15
+ end
16
+
17
+ def merge(where: {}, limit: nil, offset: nil, view: nil, per_page: nil, accept: nil)
18
+ Constraints.new(where: self.where.merge(where),
19
+ limit: limit || self.limit,
20
+ per_page: per_page || self.per_page,
21
+ offset: offset || self.offset,
22
+ view: view || self.view,
23
+ accept: accept || self.accept)
24
+ end
25
+
26
+ def next_page
27
+ merge(offset: offset + per_page)
28
+ end
29
+
30
+ def to_query
31
+ query = where.each_with_object({}) do |(name, value), result|
32
+ result[name] = value
33
+ end
34
+ query[:limit] = limit_for_query
35
+ query[:offset] = offset unless offset.nil?
36
+ query[:view] = view unless view.nil?
37
+ query
38
+ end
39
+
40
+ def to_headers
41
+ accept == "application/json" ? {} : { "Accept" => accept, "Content-types" => accept }
42
+ end
43
+
44
+ def limit_for_query
45
+ !limit.nil? && limit < per_page ? limit : per_page
46
+ end
47
+
48
+ def self.from_constraints(constraints = Constraints.new)
49
+ return constraints if constraints.is_a?(Constraints)
50
+ return new(**constraints) if constraints.respond_to?(:key?)
51
+ return new if constraints.nil?
52
+
53
+ raise TypeError, "passed in constraints #{constraints} cannot be cast to a set of constraints"
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # ActiveModel compliant interface for interacting with the Contacts API
5
+ # @see https://docs.nylas.com/reference#contacts
6
+ class Contact
7
+ include Model
8
+ self.resources_path = "/contacts"
9
+ self.creatable = true
10
+ self.listable = true
11
+ self.showable = true
12
+ self.filterable = true
13
+ self.updatable = true
14
+ self.destroyable = true
15
+
16
+ attribute :id, :string, read_only: true
17
+ attribute :object, :string, default: "contact"
18
+ attribute :account_id, :string, read_only: true
19
+
20
+ attribute :given_name, :string
21
+ attribute :middle_name, :string
22
+ attribute :picture_url, :string
23
+ attribute :surname, :string
24
+ attribute :birthday, :string
25
+ attribute :suffix, :string
26
+ attribute :nickname, :string
27
+ attribute :company_name, :string
28
+ attribute :job_title, :string
29
+ attribute :manager_name, :string
30
+ attribute :office_location, :string
31
+ attribute :notes, :string
32
+ attribute :source, :string
33
+ attribute :job_status_id, :string, read_only: true
34
+
35
+ has_n_of_attribute :groups, :contact_group
36
+ has_n_of_attribute :emails, :email_address
37
+ has_n_of_attribute :im_addresses, :im_address
38
+ has_n_of_attribute :physical_addresses, :physical_address
39
+ has_n_of_attribute :phone_numbers, :phone_number
40
+ has_n_of_attribute :web_pages, :web_page
41
+
42
+ # @returns [Tempfile] path to the retrieved picture. It is preferrable to cache this in your system than
43
+ # to retrieve it from nylas every time.
44
+ def picture
45
+ return @picture_tempfile if @picture_tempfile
46
+
47
+ @picture_tempfile = Tempfile.new
48
+ @picture_tempfile.write(api.get(path: "#{resource_path}/picture"))
49
+ @picture_tempfile.close
50
+ @picture_tempfile
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Structure to represent the Contact Group schema
5
+ # @see https://docs.nylas.com/reference#contactsid
6
+ class ContactGroup
7
+ include Model
8
+ self.resources_path = "/contacts/groups"
9
+
10
+ self.creatable = false
11
+ self.destroyable = false
12
+ self.filterable = false
13
+ self.listable = true
14
+ self.showable = false
15
+ self.updatable = false
16
+
17
+ attribute :id, :string
18
+ attribute :object, :string
19
+ attribute :account_id, :string
20
+ attribute :name, :string
21
+ attribute :path, :string
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Ruby representation of the Nylas /account API
5
+ # @see https://docs.nylas.com/reference#account
6
+ class CurrentAccount
7
+ include Model
8
+ self.showable = true
9
+
10
+ self.resources_path = "/account"
11
+
12
+ attribute :id, :string
13
+ attribute :object, :string, default: "account"
14
+
15
+ attribute :account_id, :string
16
+ attribute :email_address, :string
17
+ attribute :name, :string
18
+ attribute :organization_unit, :string
19
+ attribute :provider, :string
20
+ attribute :sync_state, :string
21
+ attribute :linked_at, :unix_timestamp
22
+ end
23
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Ruby object to represent a single change. Used both when receiving a webhook, as well as the deltas API.
5
+ # @see https://docs.nylas.com/reference#receiving-notifications
6
+ # @see https://docs.nylas.com/reference#deltas
7
+ class Delta
8
+ include Model::Attributable
9
+
10
+ attribute :id, :string
11
+ attribute :type, :string
12
+ attribute :object, :string
13
+ attribute :event, :string
14
+ attribute :cursor, :string
15
+ attribute :namespace_id, :string
16
+ attribute :account_id, :string
17
+
18
+ attribute :headers, :message_headers
19
+
20
+ attribute :date, :unix_timestamp
21
+ attribute :metadata, :hash
22
+ attribute :object_attributes, :hash
23
+
24
+ def model
25
+ return nil if object.nil?
26
+
27
+ @model ||= Types.registry[object.to_sym].cast(object_attributes_with_ids)
28
+ end
29
+
30
+ private
31
+
32
+ def object_attributes_with_ids
33
+ (object_attributes || {}).merge(id: id, account_id: account_id)
34
+ end
35
+ end
36
+
37
+ # Casts Delta data from either a webhook or a delta stream to a Delta
38
+ class DeltaType < Types::ModelType
39
+ def initialize
40
+ super(model: Delta)
41
+ end
42
+
43
+ def cast(data)
44
+ data = if data.key?(:object_data)
45
+ object_data = data.delete(:object_data)
46
+ data.merge(object_data)
47
+ else
48
+ data
49
+ end
50
+
51
+ data = data.merge(data[:attributes]) if data[:attributes]
52
+ data[:object_attributes] = data.delete(:attributes)
53
+ super(**data)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Ruby object to represent a collection of changes. Used both when receiving a webhook, as well as the
5
+ # deltas API.
6
+ # @see https://docs.nylas.com/reference#receiving-notifications
7
+ # @see https://docs.nylas.com/reference#deltas
8
+ class Deltas
9
+ include Model
10
+ self.resources_path = "/delta"
11
+ self.filterable = true
12
+ has_n_of_attribute :deltas, :delta
13
+ attribute :cursor_start, :string
14
+ attribute :cursor_end, :string
15
+
16
+ extend Forwardable
17
+ def_delegators :deltas, :count, :length, :each, :map, :first, :last, :to_a, :empty?
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Special collection for delta objects
5
+ class DeltasCollection < Collection
6
+ attr_accessor :deltas
7
+
8
+ extend Forwardable
9
+ def_delegators :execute, :cursor_start, :cursor_end,
10
+ :count, :each, :to_h, :to_a, :empty?
11
+
12
+ def initialize(api:, constraints: nil, model: Deltas)
13
+ super(api: api, model: model, constraints: constraints)
14
+ end
15
+
16
+ def latest_cursor
17
+ api.execute(method: :post, path: "#{resources_path}/latest_cursor")[:cursor]
18
+ end
19
+
20
+ def latest
21
+ since(latest_cursor)
22
+ end
23
+
24
+ def since(cursor)
25
+ where(cursor: cursor)
26
+ end
27
+
28
+ def next_page(*)
29
+ return nil if empty?
30
+
31
+ where(cursor: cursor_end)
32
+ end
33
+
34
+ # Retrieves the data from the API for the particular constraints
35
+ # @return [Detlas]
36
+ def execute
37
+ self.deltas ||= Deltas.new(**api.execute(**to_be_executed))
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Ruby representatin of a Nylas Draft object
5
+ # @see https://docs.nylas.com/reference#drafts
6
+ class Draft
7
+ include Model
8
+ self.resources_path = "/drafts"
9
+ self.creatable = true
10
+ self.listable = true
11
+ self.showable = true
12
+ self.updatable = true
13
+ self.destroyable = true
14
+ self.id_listable = true
15
+ self.countable = true
16
+
17
+ attribute :id, :string
18
+ attribute :object, :string
19
+ attribute :version, :integer
20
+ attribute :account_id, :string
21
+ attribute :thread_id, :string
22
+ attribute :reply_to_message_id, :string
23
+
24
+ has_n_of_attribute :to, :email_address
25
+ has_n_of_attribute :from, :email_address
26
+ has_n_of_attribute :cc, :email_address
27
+ has_n_of_attribute :bcc, :email_address
28
+ has_n_of_attribute :reply_to, :email_address
29
+
30
+ attribute :date, :unix_timestamp
31
+ attribute :subject, :string
32
+ attribute :snippet, :string
33
+ attribute :body, :string
34
+ attribute :starred, :boolean
35
+ attribute :unread, :boolean
36
+ attribute :metadata, :hash
37
+
38
+ has_n_of_attribute :events, :event
39
+ has_n_of_attribute :files, :file, read_only: true
40
+ has_n_of_attribute :file_ids, :string
41
+ attribute :folder, :folder
42
+ has_n_of_attribute :labels, :label
43
+
44
+ attribute :tracking, :message_tracking
45
+ attribute :job_status_id, :string, read_only: true
46
+
47
+ transfer :api, to: %i[events files folder labels]
48
+
49
+ def update(**data)
50
+ # If files are provided, replace files with file IDs
51
+ self.files = data[:files] if data[:files]
52
+ extract_file_ids!
53
+ data[:file_ids] = file_ids
54
+ # If version is not provided, add version or request will fail
55
+ data[:version] = version unless data[:version]
56
+
57
+ super
58
+ end
59
+
60
+ def create
61
+ extract_file_ids!
62
+
63
+ super
64
+ end
65
+
66
+ def send!
67
+ return execute(method: :post, path: "/send", payload: to_json) unless id
68
+
69
+ data = { draft_id: id, version: version }
70
+ data[:tracking] = tracking.to_h if tracking
71
+ execute(method: :post, path: "/send", payload: JSON.dump(data))
72
+ end
73
+
74
+ def starred?
75
+ starred
76
+ end
77
+
78
+ def unread?
79
+ unread
80
+ end
81
+
82
+ def destroy
83
+ execute(method: :delete, path: resource_path, payload: attributes.serialize_for_api(keys: [:version]))
84
+ end
85
+
86
+ def save
87
+ extract_file_ids!
88
+
89
+ super
90
+ end
91
+
92
+ private
93
+
94
+ def extract_file_ids!
95
+ files = self.files || []
96
+
97
+ self.file_ids ||= files.map(&:id)
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NylasV2
4
+ # Structure to represent the Email Address Schema
5
+ # @see https://docs.nylas.com/reference#contactsid
6
+ class EmailAddress
7
+ include Model::Attributable
8
+ attribute :type, :string
9
+ attribute :email, :string
10
+ attribute :name, :string
11
+ end
12
+ end