nylas 4.0.0.rc2 → 4.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +5 -5
  2. data/lib/nylas.rb +48 -5
  3. data/lib/nylas/account.rb +31 -0
  4. data/lib/nylas/api.rb +86 -2
  5. data/lib/nylas/calendar.rb +27 -0
  6. data/lib/nylas/collection.rb +46 -19
  7. data/lib/nylas/constraints.rb +12 -4
  8. data/lib/nylas/contact.rb +10 -2
  9. data/lib/nylas/current_account.rb +1 -4
  10. data/lib/nylas/delta.rb +46 -0
  11. data/lib/nylas/deltas.rb +17 -0
  12. data/lib/nylas/deltas_collection.rb +36 -0
  13. data/lib/nylas/draft.rb +51 -0
  14. data/lib/nylas/email_address.rb +1 -5
  15. data/lib/nylas/errors.rb +13 -0
  16. data/lib/nylas/event.rb +42 -0
  17. data/lib/nylas/event_collection.rb +13 -0
  18. data/lib/nylas/file.rb +58 -0
  19. data/lib/nylas/folder.rb +22 -0
  20. data/lib/nylas/http_client.rb +38 -29
  21. data/lib/nylas/im_address.rb +0 -5
  22. data/lib/nylas/label.rb +22 -0
  23. data/lib/nylas/message.rb +45 -0
  24. data/lib/nylas/message_headers.rb +25 -0
  25. data/lib/nylas/message_tracking.rb +11 -0
  26. data/lib/nylas/model.rb +75 -24
  27. data/lib/nylas/model/attributable.rb +2 -2
  28. data/lib/nylas/model/attributes.rb +3 -1
  29. data/lib/nylas/native_authentication.rb +31 -0
  30. data/lib/nylas/new_message.rb +29 -0
  31. data/lib/nylas/nylas_date.rb +5 -2
  32. data/lib/nylas/participant.rb +10 -0
  33. data/lib/nylas/phone_number.rb +0 -5
  34. data/lib/nylas/physical_address.rb +0 -5
  35. data/lib/nylas/raw_message.rb +15 -0
  36. data/lib/nylas/recurrence.rb +9 -0
  37. data/lib/nylas/rsvp.rb +18 -0
  38. data/lib/nylas/search_collection.rb +8 -0
  39. data/lib/nylas/thread.rb +52 -0
  40. data/lib/nylas/timespan.rb +18 -0
  41. data/lib/nylas/types.rb +62 -9
  42. data/lib/nylas/version.rb +1 -1
  43. data/lib/nylas/web_page.rb +0 -5
  44. data/lib/nylas/webhook.rb +19 -0
  45. metadata +31 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5fd4eb7f8982e3da95740a92b4ff5d1307d22bc7
4
- data.tar.gz: 3806c9465a159c517fc71165570a0c787751f79f
2
+ SHA256:
3
+ metadata.gz: fac446793677a8c9ae9f69d5d70e1ef43cb5a452e600f590665afa2f6d82f0de
4
+ data.tar.gz: d42bf8cf84bf85be8e4a3b6bf896492da0e3e6795f6eb5afb538d6cdc55cad78
5
5
  SHA512:
6
- metadata.gz: a1841957b48b50212c6026428401306cadf9c83fddb109e5567c0cb5bb5aa187e2a6383c804b546ffe1082d7bca395e73a2f63f035d20ab42a516fd44e831474
7
- data.tar.gz: a21d29a3a95331f855b5f4a312183fea5da5dcf73de7546df452d4723b080838bdc26fe376eec1455b98b108e3d92c0e8a2ec6742e05efaa1e80d72f5ff89d61
6
+ metadata.gz: 7fe7bdd1b56c7fb1e37ce318c28ed419bf38124e052c8a5a5de61c609d1132cdeff7a728126d549e3e0da0388303585e63701fdc37f01cab6b0c773d7587729c
7
+ data.tar.gz: 33d014b9b2cbc74fc1d52a5b203017d9272952baa207ada25e89aef029051539f4d1f9066b72a055e319783b13dee6bb4a5f0130c69f9de1a675de0b1bc0e11a
data/lib/nylas.rb CHANGED
@@ -17,15 +17,42 @@ require_relative "nylas/model"
17
17
 
18
18
  # Attribute types supported by the API
19
19
  require_relative "nylas/email_address"
20
+ require_relative "nylas/event"
21
+ require_relative "nylas/event_collection"
22
+ require_relative "nylas/file"
23
+ require_relative "nylas/folder"
20
24
  require_relative "nylas/im_address"
25
+ require_relative "nylas/label"
26
+ require_relative "nylas/message_headers"
27
+ require_relative "nylas/message_tracking"
28
+ require_relative "nylas/participant"
21
29
  require_relative "nylas/physical_address"
22
30
  require_relative "nylas/phone_number"
31
+ require_relative "nylas/recurrence"
32
+ require_relative "nylas/rsvp"
33
+ require_relative "nylas/timespan"
23
34
  require_relative "nylas/web_page"
24
35
  require_relative "nylas/nylas_date"
25
36
 
37
+ # Custom collection types
38
+ require_relative "nylas/search_collection"
39
+ require_relative "nylas/deltas_collection"
40
+
26
41
  # Models supported by the API
42
+ require_relative "nylas/account"
43
+ require_relative "nylas/calendar"
27
44
  require_relative "nylas/contact"
28
45
  require_relative "nylas/current_account"
46
+ require_relative "nylas/deltas"
47
+ require_relative "nylas/delta"
48
+ require_relative "nylas/draft"
49
+ require_relative "nylas/message"
50
+ require_relative "nylas/new_message"
51
+ require_relative "nylas/raw_message"
52
+ require_relative "nylas/thread"
53
+ require_relative "nylas/webhook"
54
+
55
+ require_relative "nylas/native_authentication"
29
56
 
30
57
  require_relative "nylas/http_client"
31
58
  require_relative "nylas/api"
@@ -33,10 +60,26 @@ require_relative "nylas/api"
33
60
  # an SDK for interacting with the Nylas API
34
61
  # @see https://docs.nylas.com/reference
35
62
  module Nylas
36
- Types.registry[:email_address] = EmailAddressType.new
37
- Types.registry[:im_address] = IMAddressType.new
38
- Types.registry[:physical_address] = PhysicalAddressType.new
39
- Types.registry[:phone_number] = PhoneNumberType.new
40
- Types.registry[:web_page] = WebPageType.new
63
+ Types.registry[:account] = Types::ModelType.new(model: Account)
64
+ Types.registry[:calendar] = Types::ModelType.new(model: Calendar)
65
+ Types.registry[:contact] = Types::ModelType.new(model: Contact)
66
+ Types.registry[:delta] = DeltaType.new
67
+ Types.registry[:draft] = Types::ModelType.new(model: Draft)
68
+ Types.registry[:email_address] = Types::ModelType.new(model: EmailAddress)
69
+ Types.registry[:event] = Types::ModelType.new(model: Event)
70
+ Types.registry[:file] = Types::ModelType.new(model: File)
71
+ Types.registry[:folder] = Types::ModelType.new(model: Folder)
72
+ Types.registry[:im_address] = Types::ModelType.new(model: IMAddress)
73
+ Types.registry[:label] = Types::ModelType.new(model: Label)
74
+ Types.registry[:message] = Types::ModelType.new(model: Message)
75
+ Types.registry[:message_headers] = MessageHeadersType.new
76
+ Types.registry[:message_tracking] = Types::ModelType.new(model: MessageTracking)
77
+ Types.registry[:participant] = Types::ModelType.new(model: Participant)
78
+ Types.registry[:physical_address] = Types::ModelType.new(model: PhysicalAddress)
79
+ Types.registry[:phone_number] = Types::ModelType.new(model: PhoneNumber)
80
+ Types.registry[:recurrence] = Types::ModelType.new(model: Recurrence)
81
+ Types.registry[:thread] = Types::ModelType.new(model: Thread)
82
+ Types.registry[:timespan] = Types::ModelType.new(model: Timespan)
83
+ Types.registry[:web_page] = Types::ModelType.new(model: WebPage)
41
84
  Types.registry[:nylas_date] = NylasDateType.new
42
85
  end
@@ -0,0 +1,31 @@
1
+ module Nylas
2
+ # Representation of the accounts for Account management purposes.
3
+ # @see https://docs.nylas.com/reference#account-management
4
+ class Account
5
+ include Model
6
+ self.listable = true
7
+ self.showable = true
8
+
9
+ attribute :id, :string
10
+ attribute :account_id, :string
11
+ attribute :billing_state, :string
12
+ attribute :sync_state, :string
13
+
14
+ attribute :email, :string
15
+ attribute :trial, :boolean
16
+
17
+ def upgrade
18
+ response = execute(method: :post, path: "#{resource_path}/upgrade")
19
+ response[:success]
20
+ end
21
+
22
+ def downgrade
23
+ response = execute(method: :post, path: "#{resource_path}/downgrade")
24
+ response[:success]
25
+ end
26
+
27
+ def self.resources_path(api:)
28
+ "/a/#{api.app_id}/accounts"
29
+ end
30
+ end
31
+ end
data/lib/nylas/api.rb CHANGED
@@ -3,7 +3,7 @@ module Nylas
3
3
  class API
4
4
  attr_accessor :client
5
5
  extend Forwardable
6
- def_delegators :client, :execute, :get, :post, :put, :delete
6
+ def_delegators :client, :execute, :get, :post, :put, :delete, :app_id
7
7
 
8
8
  include Logging
9
9
 
@@ -24,6 +24,13 @@ module Nylas
24
24
  end
25
25
  # rubocop:enable Metrics/ParameterLists
26
26
 
27
+ # @return [String] A Nylas access token for that particular user.
28
+ def authenticate(name:, email_address:, provider:, settings:, reauth_account_id: nil)
29
+ NativeAuthentication.new(api: self).authenticate(name: name, email_address: email_address,
30
+ provider: provider, settings: settings,
31
+ reauth_account_id: reauth_account_id)
32
+ end
33
+
27
34
  # @return [Collection<Contact>] A queryable collection of Contacts
28
35
  def contacts
29
36
  @contacts ||= Collection.new(model: Contact, api: self)
@@ -32,7 +39,84 @@ module Nylas
32
39
  # @return [CurrentAccount] The account details for whomevers access token is set
33
40
  def current_account
34
41
  prevent_calling_if_missing_access_token(:current_account)
35
- CurrentAccount.from_hash(client.execute(method: :get, path: "/account"), api: self)
42
+ CurrentAccount.from_hash(execute(method: :get, path: "/account"), api: self)
43
+ end
44
+
45
+ # @return [Collection<Account>] A queryable collection of {Account}s
46
+ def accounts
47
+ @accounts ||= Collection.new(model: Account, api: as(client.app_secret))
48
+ end
49
+
50
+ # @return [Collection<Calendar>] A queryable collection of {Calendar}s
51
+ def calendars
52
+ @calendars ||= Collection.new(model: Calendar, api: self)
53
+ end
54
+
55
+ # @return [DeltasCollection<Delta>] A queryable collection of Deltas, which are themselves a collection.
56
+ def deltas
57
+ @deltas ||= DeltasCollection.new(api: self)
58
+ end
59
+
60
+ # @return[Collection<Draft>] A queryable collection of {Draft} objects
61
+ def drafts
62
+ @drafts ||= Collection.new(model: Draft, api: self)
63
+ end
64
+
65
+ # @return [Collection<Event>] A queryable collection of {Event}s
66
+ def events
67
+ @events ||= EventCollection.new(model: Event, api: self)
68
+ end
69
+
70
+ # @return [Collection<Folder>] A queryable collection of {Folder}s
71
+ def folders
72
+ @folders ||= Collection.new(model: Folder, api: self)
73
+ end
74
+
75
+ # @return [Collection<File>] A queryable collection of {File}s
76
+ def files
77
+ @files ||= Collection.new(model: File, api: self)
78
+ end
79
+
80
+ # @return [Collection<Label>] A queryable collection of {Label} objects
81
+ def labels
82
+ @labels ||= Collection.new(model: Label, api: self)
83
+ end
84
+
85
+ # @return[Collection<Message>] A queryable collection of {Message} objects
86
+ def messages
87
+ @messages ||= Collection.new(model: Message, api: self)
88
+ end
89
+
90
+ # Revokes access to the Nylas API for the given access token
91
+ # @return [Boolean]
92
+ def revoke(access_token)
93
+ response = client.as(access_token).post(path: "/oauth/revoke")
94
+ response.code == 200 && response.empty?
95
+ end
96
+
97
+ # @param message [Hash, String, #send!]
98
+ # @return [Message] The resulting message
99
+ def send!(message)
100
+ return message.send! if message.respond_to?(:send!)
101
+ return NewMessage.new(**message.merge(api: self)).send! if message.respond_to?(:key?)
102
+ return RawMessage.new(message, api: self).send! if message.is_a? String
103
+ end
104
+
105
+ # Allows you to get an API that acts as a different user but otherwise has the same settings
106
+ # @param [String] Oauth Access token or app secret used to authenticate with the API
107
+ # @return [API]
108
+ def as(access_token)
109
+ API.new(client: client.as(access_token))
110
+ end
111
+
112
+ # @return [Collection<Thread>] A queryable collection of Threads
113
+ def threads
114
+ @threads ||= Collection.new(model: Thread, api: self)
115
+ end
116
+
117
+ # @return [Collection<Webhook>] A queryable collection of {Webhook}s
118
+ def webhooks
119
+ @webhooks ||= Collection.new(model: Webhook, api: as(client.app_secret))
36
120
  end
37
121
 
38
122
  private def prevent_calling_if_missing_access_token(method_name)
@@ -0,0 +1,27 @@
1
+ module Nylas
2
+ # Ruby bindings for the Nylas Calendar API
3
+ # @see https://docs.nylas.com/reference#calendars
4
+ class Calendar
5
+ include Model
6
+ self.resources_path = "/calendars"
7
+ allows_operations(listable: true, filterable: true, showable: true)
8
+
9
+ attribute :id, :string
10
+ attribute :account_id, :string
11
+
12
+ attribute :object, :string
13
+
14
+ attribute :name, :string
15
+ attribute :description, :string
16
+
17
+ attribute :read_only, :boolean
18
+
19
+ def read_only?
20
+ read_only == true
21
+ end
22
+
23
+ def events
24
+ api.events.where(calendar_id: id)
25
+ end
26
+ end
27
+ end
@@ -2,56 +2,70 @@ module Nylas
2
2
  # An enumerable for working with index and search endpoints
3
3
  class Collection
4
4
  attr_accessor :model, :api, :constraints
5
+ extend Forwardable
6
+ def_delegators :each, :map, :select, :reject, :to_a, :take
7
+ def_delegators :to_a, :first, :last, :[]
8
+
5
9
  def initialize(model:, api:, constraints: nil)
6
10
  self.constraints = Constraints.from_constraints(constraints)
7
11
  self.model = model
8
12
  self.api = api
9
13
  end
10
14
 
15
+ # Instantiates a new model
11
16
  def new(**attributes)
12
- model.from_hash(attributes, api: api)
17
+ model.new(attributes.merge(api: api))
13
18
  end
14
19
 
15
20
  def create(**attributes)
16
- model.raise_if_read_only
17
- instance = model.from_hash(attributes, api: api)
21
+ instance = model.new(attributes.merge(api: api))
18
22
  instance.save
19
23
  instance
20
24
  end
21
25
 
26
+ # Merges in additional filters when querying the collection
27
+ # @return [Collection<Model>]
22
28
  def where(filters)
23
- raise NotImplementedError, "#{model} does not support search" unless model.searchable?
29
+ raise ModelNotFilterableError, model unless model.filterable?
24
30
  self.class.new(model: model, api: api, constraints: constraints.merge(where: filters))
25
31
  end
26
32
 
33
+ def search(query)
34
+ raise ModelNotSearchableError, model unless model.searchable?
35
+ SearchCollection.new(model: model, api: api, constraints: constraints.merge(where: { q: query }))
36
+ end
37
+
38
+ # The collection now returns a string representation of the model in a particular mime type instead of
39
+ # Model objects
40
+ # @return [Collection<String>]
41
+ def raw
42
+ raise ModelNotAvailableAsRawError, model unless model.exposable_as_raw?
43
+ self.class.new(model: model, api: api, constraints: constraints.merge(accept: model.raw_mime_type))
44
+ end
45
+
46
+ # @return [Integer]
27
47
  def count
28
48
  self.class.new(model: model, api: api, constraints: constraints.merge(view: "count")).execute[:count]
29
49
  end
30
50
 
31
- def first
32
- model.from_hash(execute.first, api: api)
51
+ # @return [Collection<Model>]
52
+ def expanded
53
+ self.class.new(model: model, api: api, constraints: constraints.merge(view: "expanded"))
33
54
  end
34
55
 
35
- def[](index)
36
- model.from_hash(execute(index), api: api)
56
+ # @return [Array<String>]
57
+ def ids
58
+ self.class.new(model: model, api: api, constraints: constraints.merge(view: "ids")).execute
37
59
  end
38
60
 
39
61
  # Iterates over a single page of results based upon current pagination settings
40
62
  def each
41
63
  return enum_for(:each) unless block_given?
42
64
  execute.each do |result|
43
- yield(model.from_hash(result, api: api))
65
+ yield(model.new(result.merge(api: api)))
44
66
  end
45
67
  end
46
68
 
47
- def to_a
48
- each.to_a
49
- end
50
-
51
- def map(&block)
52
- each.map(&block)
53
- end
54
-
55
69
  def limit(quantity)
56
70
  self.class.new(model: model, api: api, constraints: constraints.merge(limit: quantity))
57
71
  end
@@ -76,7 +90,7 @@ module Nylas
76
90
  end
77
91
  end
78
92
 
79
- def next_page(accumulated: nil, current_page: nil)
93
+ def next_page(accumulated:, current_page:)
80
94
  return nil unless more_pages?(accumulated, current_page)
81
95
  self.class.new(model: model, api: api, constraints: constraints.next_page)
82
96
  end
@@ -91,6 +105,18 @@ module Nylas
91
105
  # Retrieves a record. Nylas doesn't support where filters on GET so this will not take into
92
106
  # consideration other query constraints, such as where clauses.
93
107
  def find(id)
108
+ constraints.accept == "application/json" ? find_model(id) : find_raw(id)
109
+ end
110
+
111
+ def find_raw(id)
112
+ api.execute(to_be_executed.merge(path: "#{resources_path}/#{id}")).to_s
113
+ end
114
+
115
+ def resources_path
116
+ model.resources_path(api: api)
117
+ end
118
+
119
+ def find_model(id)
94
120
  instance = model.from_hash({ id: id }, api: api)
95
121
  instance.reload
96
122
  instance
@@ -98,7 +124,8 @@ module Nylas
98
124
 
99
125
  # @return [Hash] Specification for request to be passed to {API#execute}
100
126
  def to_be_executed
101
- { method: :get, path: model.resources_path, query: constraints.to_query }
127
+ { method: :get, path: resources_path, query: constraints.to_query,
128
+ headers: constraints.to_headers }
102
129
  end
103
130
 
104
131
  # Retrieves the data from the API for the particular constraints
@@ -1,22 +1,26 @@
1
1
  module Nylas
2
2
  # The constraints a particular GET request will include in their query params
3
3
  class Constraints
4
- attr_accessor :where, :limit, :offset, :view, :per_page
5
- def initialize(where: {}, limit: nil, offset: 0, view: nil, per_page: 100)
4
+ attr_accessor :where, :limit, :offset, :view, :per_page, :accept
5
+ # rubocop:disable Metrics/ParameterLists
6
+ def initialize(where: {}, limit: nil, offset: 0, view: nil, per_page: 100, accept: "application/json")
6
7
  self.where = where
7
8
  self.limit = limit
8
9
  self.offset = offset
9
10
  self.view = view
10
11
  self.per_page = per_page
12
+ self.accept = accept
11
13
  end
12
14
 
13
- def merge(where: {}, limit: nil, offset: nil, view: nil, per_page: nil)
15
+ def merge(where: {}, limit: nil, offset: nil, view: nil, per_page: nil, accept: nil)
14
16
  Constraints.new(where: where.merge(where),
15
17
  limit: limit || self.limit,
16
18
  per_page: per_page || self.per_page,
17
19
  offset: offset || self.offset,
18
- view: view || self.view)
20
+ view: view || self.view,
21
+ accept: accept || self.accept)
19
22
  end
23
+ # rubocop:enable Metrics/ParameterLists
20
24
 
21
25
  def next_page
22
26
  merge(offset: offset + per_page)
@@ -32,6 +36,10 @@ module Nylas
32
36
  query
33
37
  end
34
38
 
39
+ def to_headers
40
+ accept == "application/json" ? {} : { "Accept" => accept, "Content-types" => accept }
41
+ end
42
+
35
43
  def limit_for_query
36
44
  !limit.nil? && limit < per_page ? limit : per_page
37
45
  end
data/lib/nylas/contact.rb CHANGED
@@ -4,12 +4,20 @@ module Nylas
4
4
  class Contact
5
5
  include Model
6
6
  self.resources_path = "/contacts"
7
+ self.creatable = true
8
+ self.listable = true
9
+ self.showable = true
10
+ self.filterable = true
11
+ self.updatable = true
12
+ self.destroyable = true
7
13
 
8
- attribute :id, :string, exclude_when: %i(creating updating)
14
+ attribute :id, :string, exclude_when: %i[creating updating]
9
15
  attribute :object, :string, default: "contact"
10
- attribute :account_id, :string, exclude_when: %i(creating updating)
16
+ attribute :account_id, :string, exclude_when: %i[creating updating]
17
+
11
18
  attribute :given_name, :string
12
19
  attribute :middle_name, :string
20
+ attribute :picture_url, :string
13
21
  attribute :surname, :string
14
22
  attribute :birthday, :nylas_date
15
23
  attribute :suffix, :string