yext-api 0.1.1

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 (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +25 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +100 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +5 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Gemfile +10 -0
  9. data/Gemfile.lock +187 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +206 -0
  12. data/Rakefile +30 -0
  13. data/app/assets/config/yext_api_manifest.js +2 -0
  14. data/app/assets/images/yext/api/.keep +0 -0
  15. data/app/assets/javascripts/yext/api/application.js +13 -0
  16. data/app/assets/stylesheets/yext/api/application.css +15 -0
  17. data/app/controllers/yext/api/application_controller.rb +12 -0
  18. data/app/docs/notes.txt +45 -0
  19. data/app/helpers/yext/api/application_helper.rb +11 -0
  20. data/app/jobs/yext/api/application_job.rb +8 -0
  21. data/app/mailers/yext/api/application_mailer.rb +11 -0
  22. data/app/models/yext/api/application_record.rb +10 -0
  23. data/app/views/layouts/yext/api/application.html.erb +14 -0
  24. data/bin/console +16 -0
  25. data/bin/rails +16 -0
  26. data/bin/setup +8 -0
  27. data/config/initializers/spyke.rb +3 -0
  28. data/config/routes.rb +4 -0
  29. data/lib/config/api.yml +1100 -0
  30. data/lib/tasks/yext/api_tasks.rake +6 -0
  31. data/lib/yext/api.rb +33 -0
  32. data/lib/yext/api/administrative_api.rb +12 -0
  33. data/lib/yext/api/administrative_api/account.rb +62 -0
  34. data/lib/yext/api/administrative_api/add_request.rb +34 -0
  35. data/lib/yext/api/administrative_api/service.rb +38 -0
  36. data/lib/yext/api/concerns/account_child.rb +92 -0
  37. data/lib/yext/api/concerns/account_relations.rb +25 -0
  38. data/lib/yext/api/concerns/api_finder.rb +61 -0
  39. data/lib/yext/api/concerns/default_scopes.rb +37 -0
  40. data/lib/yext/api/concerns/enum_all.rb +18 -0
  41. data/lib/yext/api/concerns/faraday_connection.rb +45 -0
  42. data/lib/yext/api/concerns/rate_limits.rb +31 -0
  43. data/lib/yext/api/engine.rb +13 -0
  44. data/lib/yext/api/enumerations/validation.rb +16 -0
  45. data/lib/yext/api/knowledge_api.rb +12 -0
  46. data/lib/yext/api/knowledge_api/account_settings/account.rb +33 -0
  47. data/lib/yext/api/knowledge_api/health_check/health.rb +25 -0
  48. data/lib/yext/api/knowledge_api/knowledge_manager/category.rb +25 -0
  49. data/lib/yext/api/knowledge_api/knowledge_manager/location.rb +59 -0
  50. data/lib/yext/api/live_api.rb +12 -0
  51. data/lib/yext/api/live_api/location.rb +37 -0
  52. data/lib/yext/api/utils/api_base.rb +13 -0
  53. data/lib/yext/api/utils/api_rate_limits.rb +36 -0
  54. data/lib/yext/api/utils/configuration.rb +97 -0
  55. data/lib/yext/api/utils/default_parameters.rb +57 -0
  56. data/lib/yext/api/utils/response_parser.rb +84 -0
  57. data/lib/yext/api/version.rb +7 -0
  58. data/lib/yext/include_rails.rb +31 -0
  59. data/yext-api.gemspec +51 -0
  60. metadata +271 -0
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # desc "Explaining what the task does"
4
+ # task :yext_api do
5
+ # # Task goes here
6
+ # end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yext/api/engine"
4
+
5
+ module Yext
6
+ # API interface for Yext
7
+ module Api
8
+ # Allows you to configure global settings for the Yext::Api.
9
+ #
10
+ # See Yext::Api::Utils::Configuration for details on the configuration options.
11
+ #
12
+ # Usage:
13
+ #
14
+ # Yext::Api.configure do |config|
15
+ # config.account_id = "my account_id"
16
+ # config.api_key = "my api key"
17
+ # end
18
+ def self.configure
19
+ yield configuration if block_given?
20
+ end
21
+
22
+ # Gets the configuration object for configuring a single item.
23
+ #
24
+ # See Yext::Api::Utils::Configuration for details on the configuration options.
25
+ #
26
+ # Usage:
27
+ #
28
+ # Yext::Api.configuration.api_key = "my api key"
29
+ def self.configuration
30
+ Yext::Api::Utils::Configuration.instance
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yext
4
+ module Api
5
+ # http://developer.yext.com/docs/administrative-api
6
+ #
7
+ # Yext Administrative API
8
+ module AdministrativeApi
9
+ extend Yext::Api::Concerns::RateLimits
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yext
4
+ module Api
5
+ module AdministrativeApi
6
+ # :administrative_api:
7
+ # :account:
8
+ # :actions:
9
+ # - :action: :create
10
+ # :method: :post
11
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}/newlocationaddrequests
12
+ # :path_regex: v2/accounts/\w+/newlocationaddrequests
13
+ # :default_version: 20161012
14
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/createNewLocationAddRequest
15
+ # :comment: Request that a new location be added and services added to it. The location is created only if the request succeeds.
16
+ # :sandbox_only: false
17
+ # - :action: :add_services
18
+ # :method: :post
19
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}/existinglocationaddrequests
20
+ # :path_regex: v2/accounts/\w+/existinglocationaddrequests
21
+ # :default_version: 20161012
22
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/createExistingLocationAddRequest
23
+ # :comment: Request that one or more available services be added to an existing location.
24
+ # :sandbox_only: false
25
+ # - :action: :change_status
26
+ # :method: :post
27
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}/processaddrequest
28
+ # :path_regex: v2/accounts/\w+/processaddrequest
29
+ # :default_version: 20161012
30
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/createProcessReviewAddRequest
31
+ # :comment: Request that an add request in REVIEW be processed to COMPLETE, CANCELED, or FAILED.
32
+ # :sandbox_only: true
33
+ # - :action: :index
34
+ # :method: :get
35
+ # :endpoint: https://api.yext.com/v2/accounts
36
+ # :path_regex: v2/accounts
37
+ # :default_version: 20161012
38
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/listAccounts
39
+ # :comment: List all accounts that you have access to. Unless you are in Partner Portal mode, this will only be your own account.
40
+ # :sandbox_only: false
41
+ # - :action: :show
42
+ # :method: :get
43
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}
44
+ # :path_regex: v2/accounts/\w+
45
+ # :default_version: 20161012
46
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/getAccount
47
+ # :comment: Get details for an account.
48
+ # :sandbox_only: false
49
+ # - :action: :update
50
+ # :method: :put
51
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}
52
+ # :path_regex: v2/accounts/\w+
53
+ # :default_version: 20161012
54
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/updateAccount
55
+ # :comment: Update an account's name or ID.
56
+ # :sandbox_only: false
57
+ class Account < Yext::Api::Utils::ApiBase
58
+ include Yext::Api::Concerns::AccountRelations
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: Complete and test. Untested initial framework class.
4
+ module Yext
5
+ module Api
6
+ module AdministrativeApi
7
+ # :administrative_api:
8
+ # :add_request:
9
+ # :actions:
10
+ # - :action: :index
11
+ # :method: :get
12
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}/addrequests
13
+ # :path_regex: v2/accounts/[^/]+?/addrequests
14
+ # :default_version: 20161012
15
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/listAddRequests
16
+ # :comment: Get all of the add requests in the account. The response includes both New Location
17
+ # Add Requests and Existing Location Add Requests.
18
+ # :sandbox_only: false
19
+ # - :action: :show
20
+ # :method: :get
21
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}/addrequests/{addRequestId}
22
+ # :path_regex: v2/accounts/[^/]+?/addrequests/[^/]+??
23
+ # :default_version: 20161012
24
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/getAddRequest
25
+ # :comment: Get status information about an add request previously created.
26
+ # :sandbox_only: false
27
+ class AddRequest < Yext::Api::Utils::ApiBase
28
+ uri("addrequests/(:id)")
29
+
30
+ include Yext::Api::Concerns::AccountChild
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yext
4
+ module Api
5
+ module AdministrativeApi
6
+ # :administrative_api:
7
+ # :service:
8
+ # :actions:
9
+ # - :action: :available
10
+ # :method: :get
11
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}/availableservices
12
+ # :default_version: 20161012
13
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/listAvailableServices
14
+ # :comment: Return list of services available to you under your agreements.
15
+ # :sandbox_only: false
16
+ # - :action: :index
17
+ # :method: :get
18
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}/services
19
+ # :default_version: 20161012
20
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/listServices
21
+ # :comment: Retrieve a list of all services provisioned through this account.
22
+ # :sandbox_only: false
23
+ # - :action: :destroy
24
+ # :method: :post
25
+ # :endpoint: https://api.yext.com/v2/accounts/{accountId}/cancelservices
26
+ # :default_version: 20161012
27
+ # :documentation: http://developer.yext.com/docs/administrative-api/#operation/cancelServices
28
+ # :comment: Cancel one or more active services.
29
+ # :sandbox_only: false
30
+ class Service < Yext::Api::Utils::ApiBase
31
+ include Yext::Api::Concerns::AccountChild
32
+
33
+ scope :available, -> { with(Yext::Api::Concerns::AccountChild.with_account_path("availableservices")) }
34
+ scope :cancel_services, -> { with(Yext::Api::Concerns::AccountChild.with_account_path("cancelservices")) }
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yext
4
+ module Api
5
+ module Concerns
6
+ # This concern prepends the `accounts/:account_id/` path to the URI for classes which require it.
7
+ #
8
+ # The account_id can be set in the following ways:
9
+ # * Global configuration:
10
+ # * Yext::Api.configuration.account_id = new_account_id
11
+ # * For an individual call:
12
+ # * SpykeClass.with_account(new_account_id)
13
+ # * SpykeClass.where(account_id: new_account_id)
14
+ #
15
+ # NOTE: This will not work if the DefaultParameters middleware is not being used.
16
+ #
17
+ # If the class that this is included in uses a custom URI, the `uri` call must be made before this
18
+ # module is included.
19
+ module AccountChild
20
+ extend ActiveSupport::Concern
21
+
22
+ class << self
23
+ def with_account_path(path)
24
+ File.join("accounts/:account_id", path)
25
+ end
26
+
27
+ def ensure_relation(klass)
28
+ [Yext::Api::KnowledgeApi::AccountSettings::Account, Yext::Api::AdministrativeApi::Account].each do |account_class|
29
+ next if account_class.instance_methods.include?("#{klass.model_name.element}_ids".to_sym)
30
+
31
+ klass_uri = klass.instance_variable_get(:@uri)
32
+ helper_warnings(account_class, klass, klass_uri)
33
+ klass_uri ||= klass.send(:default_uri)
34
+
35
+ add_has_many_relation(account_class, klass, klass_uri)
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def add_has_many_relation(account_class, klass, klass_uri)
42
+ account_class.class_eval do
43
+ has_many klass.model_name.element.pluralize.to_sym,
44
+ class_name: klass.name,
45
+ uri: Yext::Api::Concerns::AccountChild.with_account_path(klass_uri)
46
+ end
47
+ end
48
+
49
+ def helper_warnings(account_class, klass, klass_uri)
50
+ klass_name = klass.name
51
+ relation_name = klass.model_name.element.pluralize
52
+
53
+ puts "WARNING! #{account_class.name} does not include the relationship for #{klass_name}"
54
+ puts " Add the following line to Yext::Api::Concerns::AccountRelations:"
55
+
56
+ if klass_uri && klass_uri != klass.send(:default_uri)
57
+ puts " has_many :#{relation_name}, class_name: \"#{klass_name}\", " \
58
+ "uri: Yext::Api::Concerns::AccountChild.with_account_path(\"#{klass_uri}\")"
59
+ else
60
+ puts " has_many :#{relation_name}, class_name: \"#{klass_name}\""
61
+ end
62
+ end
63
+ end
64
+
65
+ included do
66
+ scope(:with_account, lambda do |account_or_id|
67
+ if account_or_id.is_a?(Yext::Api::KnowledgeApi::AccountSettings::Account) ||
68
+ account_or_id.is_a?(Yext::Api::AdministrativeApi::Account)
69
+ account_or_id
70
+ else
71
+ Yext::Api::KnowledgeApi::AccountSettings::Account.new(id: account_or_id)
72
+ end.public_send(model_name.element.pluralize)
73
+ end)
74
+
75
+ Yext::Api::Concerns::AccountChild.ensure_relation(self)
76
+ end
77
+
78
+ class_methods do
79
+ def all
80
+ if current_scope.nil?
81
+ Yext::Api::KnowledgeApi::AccountSettings::Account.
82
+ new(id: Yext::Api.configuration.account_id || "me").
83
+ public_send(model_name.element.pluralize)
84
+ else
85
+ current_scope
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yext
4
+ module Api
5
+ module Concerns
6
+ # Because the Account is listed in the API documentation in two locations, there are two
7
+ # different but somewhat identical Account objects.
8
+ #
9
+ # This module includes the shared code between the two.
10
+ module AccountRelations
11
+ extend ActiveSupport::Concern
12
+
13
+ # The module AccountChild will add these relations if they are missing, but if they are
14
+ # listed explicitly it is more efficient.
15
+ included do
16
+ has_many :add_requests,
17
+ class_name: "Yext::Api::AdministrativeApi::AddRequest",
18
+ uri: Yext::Api::Concerns::AccountChild.with_account_path("addrequests/(:id)")
19
+ has_many :locations, class_name: "Yext::Api::KnowledgeApi::KnowledgeManager::Location"
20
+ has_many :services, class_name: "Yext::Api::AdministrativeApi::Service"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yext
4
+ module Api
5
+ module Concerns
6
+ # This module add the `find_api` method to a class to allow the searching of the base
7
+ # api category module for a particular route.
8
+ module ApiFinder
9
+ def find_api(url, method)
10
+ return if url.nil? || method.nil?
11
+ return Yext::Api::LiveApi if url.host.include?("liveapi")
12
+
13
+ hash = YAML.load_file(Yext::Api::Engine.root.join("lib/config/api.yml"))
14
+
15
+ hash.each_key do |hash_key|
16
+ guess_api = api_from_key(hash_key)
17
+
18
+ next if guess_api.blank?
19
+
20
+ return guess_api if found_route?(hash[hash_key], url.path, method.to_s)
21
+ end
22
+
23
+ nil
24
+ end
25
+
26
+ private
27
+
28
+ def found_route?(hash, path, method)
29
+ hash.each do |key_name, sub_hash|
30
+ if sub_hash.is_a?(Hash)
31
+ return true if found_route?(sub_hash, path, method)
32
+ elsif key_name == :actions
33
+ return true if found_action?(sub_hash, path, method)
34
+ end
35
+ end
36
+
37
+ false
38
+ end
39
+
40
+ def found_action?(actions, path, method)
41
+ actions.each do |action|
42
+ next if action[:path_regex].blank?
43
+ next if action[:method].to_s != method
44
+
45
+ return true if Regexp.new("#{action[:path_regex]}$").match(path)
46
+ end
47
+
48
+ false
49
+ end
50
+
51
+ def api_from_key(hash_key)
52
+ "Yext::Api::#{hash_key.to_s.classify}".constantize
53
+ rescue NameError
54
+ # :nocov:
55
+ nil
56
+ # :nocov:
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yext
4
+ module Api
5
+ module Concerns
6
+ # This module adds default scopes that will specify configurations to be overridden for a
7
+ # particular call.
8
+ #
9
+ # If these scopes are used, the values passed in will be used in the API call, if the scope
10
+ # is not used, then the DefaultParameters middleware will insert the default values.
11
+ module DefaultScopes
12
+ extend ActiveSupport::Concern
13
+
14
+ included do
15
+ scope(:with_version, ->(version) { where(v: version) })
16
+ scope(:with_application, ->(app_id) { where(api_key: app_id) })
17
+ scope(:yext_username, ->(username) { where(yext_username: username) })
18
+ scope(:yext_user_id, ->(user_id) { where(yext_user_id: user_id) })
19
+
20
+ scope(:validate, lambda do |validation = Yext::Api::Enumerations::Validation::STRICT|
21
+ if validation.is_a?(String)
22
+ validation = Yext::Api::Enumerations::Validation::STRICT unless Yext::Api::Enumerations::Validation.all.include?(validation)
23
+ else
24
+ validation = if validation
25
+ Yext::Api::Enumerations::Validation::STRICT
26
+ else
27
+ Yext::Api::Enumerations::Validation::LENIENT
28
+ end
29
+ end
30
+
31
+ where(validation: validation)
32
+ end)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yext
4
+ module Api
5
+ module Concerns
6
+ # This concern adds an `all` method to an enumeration class to list all constants in that class.
7
+ module EnumAll
8
+ extend ActiveSupport::Concern
9
+
10
+ class_methods do
11
+ def all
12
+ (constants - %i[ClassMethods]).map { |c| const_get(c) }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yext
4
+ module Api
5
+ module Concerns
6
+ # This module defines methods that set the connection for a Spyke class.
7
+ #
8
+ # The default connection is to the sandbox or the API based on the value of the configuration
9
+ # sandbox setting.
10
+ #
11
+ # A class function live_api is provided to allow LiveApi module classes to use the live endpoint.
12
+ module FaradayConnection
13
+ extend ActiveSupport::Concern
14
+
15
+ included do
16
+ url = if Yext::Api.configuration.sandbox
17
+ "https://sandbox.yext.com/v2"
18
+ else
19
+ "https://api.yext.com/v2"
20
+ end
21
+
22
+ self.connection = Yext::Api::Concerns::FaradayConnection.faraday_connection(url)
23
+ end
24
+
25
+ class_methods do
26
+ def live_api
27
+ self.connection = Yext::Api::Concerns::FaradayConnection.faraday_connection("https://live.yext.com/v2")
28
+ end
29
+ end
30
+
31
+ def self.faraday_connection(url)
32
+ Faraday.new(url: url) do |c|
33
+ c.request :json
34
+
35
+ c.use Yext::Api::Utils::ResponseParser
36
+ c.use Yext::Api::Utils::DefaultParameters
37
+ c.use Yext::Api::Utils::ApiRateLimits
38
+
39
+ c.adapter Faraday.default_adapter
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end