yext-api 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -1
- data/Gemfile.lock +16 -8
- data/PULL_REQUEST_TEMPLATE.md +11 -0
- data/README.md +25 -7
- data/app/controllers/yext/api/agreements/add_request_controller.rb +78 -0
- data/app/controllers/yext/api/application_controller.rb +1 -3
- data/config/initializers/memoist.rb +3 -0
- data/config/routes.rb +3 -0
- data/lib/config/api.yml +95 -230
- data/lib/yext/api/administrative_api/account.rb +37 -27
- data/lib/yext/api/administrative_api/add_request.rb +87 -3
- data/lib/yext/api/administrative_api/service.rb +26 -4
- data/lib/yext/api/concerns/account_child.rb +37 -8
- data/lib/yext/api/concerns/account_relations.rb +16 -1
- data/lib/yext/api/concerns/default_scopes.rb +8 -2
- data/lib/yext/api/concerns/faraday_connection.rb +21 -7
- data/lib/yext/api/concerns/rate_limits.rb +8 -1
- data/lib/yext/api/enumerations/add_request_status.rb +19 -0
- data/lib/yext/api/enumerations/location_type.rb +18 -0
- data/lib/yext/api/knowledge_api/account_settings/account.rb +0 -2
- data/lib/yext/api/knowledge_api/account_settings/role.rb +24 -0
- data/lib/yext/api/knowledge_api/account_settings/user.rb +81 -0
- data/lib/yext/api/knowledge_api/health_check/health.rb +0 -1
- data/lib/yext/api/knowledge_api/knowledge_manager/category.rb +0 -1
- data/lib/yext/api/knowledge_api/knowledge_manager/location.rb +18 -6
- data/lib/yext/api/live_api/location.rb +0 -4
- data/lib/yext/api/utils/api_base.rb +8 -0
- data/lib/yext/api/utils/api_finder.rb +100 -0
- data/lib/yext/api/utils/configuration.rb +93 -0
- data/lib/yext/api/utils/middleware/api_rate_limits.rb +35 -0
- data/lib/yext/api/utils/middleware/default_parameters.rb +138 -0
- data/lib/yext/api/utils/middleware/response_parser.rb +111 -0
- data/lib/yext/api/utils/middleware/uri_cleanup.rb +48 -0
- data/lib/yext/api/utils/params.rb +69 -0
- data/lib/yext/api/version.rb +1 -1
- data/yext-api.gemspec +6 -7
- metadata +56 -31
- data/.travis.yml +0 -5
- data/app/assets/config/yext_api_manifest.js +0 -2
- data/app/assets/images/yext/api/.keep +0 -0
- data/app/assets/javascripts/yext/api/application.js +0 -13
- data/app/assets/stylesheets/yext/api/application.css +0 -15
- data/app/docs/notes.txt +0 -45
- data/app/helpers/yext/api/application_helper.rb +0 -11
- data/app/jobs/yext/api/application_job.rb +0 -8
- data/app/mailers/yext/api/application_mailer.rb +0 -11
- data/app/models/yext/api/application_record.rb +0 -10
- data/app/views/layouts/yext/api/application.html.erb +0 -14
- data/lib/tasks/yext/api_tasks.rake +0 -6
- data/lib/yext/api/concerns/api_finder.rb +0 -61
- data/lib/yext/api/utils/api_rate_limits.rb +0 -36
- data/lib/yext/api/utils/default_parameters.rb +0 -57
- data/lib/yext/api/utils/response_parser.rb +0 -84
data/.travis.yml
DELETED
File without changes
|
@@ -1,13 +0,0 @@
|
|
1
|
-
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
-
// listed below.
|
3
|
-
//
|
4
|
-
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
-
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
-
//
|
7
|
-
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
-
// compiled file. JavaScript code in this file should be added after the last require_* statement.
|
9
|
-
//
|
10
|
-
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
-
// about supported directives.
|
12
|
-
//
|
13
|
-
//= require_tree .
|
@@ -1,15 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
-
* listed below.
|
4
|
-
*
|
5
|
-
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
-
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
-
*
|
8
|
-
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
-
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
-
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
-
* It is generally better to create a new file per style scope.
|
12
|
-
*
|
13
|
-
*= require_tree .
|
14
|
-
*= require_self
|
15
|
-
*/
|
data/app/docs/notes.txt
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
Other
|
2
|
-
Date/time: Time.now.iso8601
|
3
|
-
Date: Time.now.to_date.iso8601
|
4
|
-
|
5
|
-
Classes examples:
|
6
|
-
AdministrativeApi::Account
|
7
|
-
AdministrativeApi::AddRequest
|
8
|
-
AdministrativeApi::Service
|
9
|
-
KnowledgeApi::HealthCheck::Health
|
10
|
-
KnowledgeApi::KnowledgeManager::Location
|
11
|
-
KnowledgeApi::KnowledgeManager::Folder
|
12
|
-
KnowledgeApi::KnowledgeManager::Menu
|
13
|
-
KnowledgeApi::KnowledgeManager::Bio
|
14
|
-
KnowledgeApi::KnowledgeManager::Product
|
15
|
-
KnowledgeApi::KnowledgeManager::Event
|
16
|
-
KnowledgeApi::KnowledgeManager::Category
|
17
|
-
KnowledgeApi::KnowledgeManager::GoogleField
|
18
|
-
KnowledgeApi::KnowledgeManager::CustomField
|
19
|
-
KnowledgeApi::KnowledgeManager::LanguageProfile
|
20
|
-
KnowledgeApi::KnowledgeManager::Asset
|
21
|
-
KnowledgeApi::PowerListings::Publisher
|
22
|
-
KnowledgeApi::PowerListings::Listing
|
23
|
-
KnowledgeApi::PowerListings::PublisherSuggestion
|
24
|
-
KnowledgeApi::Analytics::MaxDate
|
25
|
-
KnowledgeApi::Analytics::Report
|
26
|
-
KnowledgeApi::Analytics::Activity
|
27
|
-
KnowledgeApi::Reviews::Review
|
28
|
-
KnowledgeApi::Reviews::Comment
|
29
|
-
KnowledgeApi::Reviews::ReviewInvitation
|
30
|
-
KnowledgeApi::Reviews::ReviewGenerationSetting
|
31
|
-
KnowledgeApi::Social::Post
|
32
|
-
KnowledgeApi::Social::Comment
|
33
|
-
KnowledgeApi::Social::LinkedAccount
|
34
|
-
KnowledgeApi::AccountSettings::Role
|
35
|
-
KnowledgeApi::AccountSettings::User
|
36
|
-
KnowledgeApi::AccountSettings::Account
|
37
|
-
KnowledgeApi::OptimizationTasks::OptimizationTask
|
38
|
-
LiveApi::Menu
|
39
|
-
LiveApi::Bio
|
40
|
-
LiveApi::Product
|
41
|
-
LiveApi::Event
|
42
|
-
LiveApi::LanguageProfile
|
43
|
-
LiveApi::LanguageProfileSchema
|
44
|
-
LiveApi::Location
|
45
|
-
LiveApi::LocationSchema
|
@@ -1,14 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Yext Api</title>
|
5
|
-
<%= stylesheet_link_tag "yext/api/application", media: "all" %>
|
6
|
-
<%= javascript_include_tag "yext/api/application" %>
|
7
|
-
<%= csrf_meta_tags %>
|
8
|
-
</head>
|
9
|
-
<body>
|
10
|
-
|
11
|
-
<%= yield %>
|
12
|
-
|
13
|
-
</body>
|
14
|
-
</html>
|
@@ -1,61 +0,0 @@
|
|
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
|
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Yext
|
4
|
-
module Api
|
5
|
-
module Utils
|
6
|
-
# Faraday Middleware for extracting API limits from call responses.
|
7
|
-
class ApiRateLimits < Faraday::Response::Middleware
|
8
|
-
include Yext::Api::Concerns::ApiFinder
|
9
|
-
|
10
|
-
def call(env)
|
11
|
-
@app.call(env).on_complete do |environment|
|
12
|
-
save_rates(environment, find_api(env[:url], env[:method].to_s))
|
13
|
-
|
14
|
-
env.response
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def save_rates(environment, api_module)
|
21
|
-
return if api_module.blank?
|
22
|
-
|
23
|
-
api_module.last_status = environment[:status]
|
24
|
-
|
25
|
-
response_headers = environment[:response_headers]
|
26
|
-
|
27
|
-
return unless response_headers.key?("rate-limit-remaining")
|
28
|
-
|
29
|
-
api_module.update_rates(remaining: response_headers["rate-limit-remaining"].to_i,
|
30
|
-
limit: response_headers["rate-limit-limit"].to_i,
|
31
|
-
reset_at: Time.at(response_headers["rate-limit-reset"].to_i))
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Yext
|
4
|
-
module Api
|
5
|
-
module Utils
|
6
|
-
# Faraday Middleware for adding Configuration default values to API calls as needed.
|
7
|
-
#
|
8
|
-
# Most options can be set via scopes and the soped values will be kept if they are used.
|
9
|
-
#
|
10
|
-
# The following configuration options are defaulted:
|
11
|
-
# validation_level: Added to query parameters if not already there and is not nil
|
12
|
-
# api_key: Added to query parameters if not already there
|
13
|
-
# api_version: Added to qeury parameters if not already there
|
14
|
-
# account_id: Inserted into the path if the path includes the Account default URI and no
|
15
|
-
# account_id was specified.
|
16
|
-
class DefaultParameters < Faraday::Response::Middleware
|
17
|
-
attr_reader :configuration
|
18
|
-
|
19
|
-
def call(request_env)
|
20
|
-
@configuration = Yext::Api.configuration
|
21
|
-
url = request_env[:url]
|
22
|
-
params = Rack::Utils.parse_nested_query(url.query).with_indifferent_access
|
23
|
-
|
24
|
-
add_username_headers(request_env, configuration, params)
|
25
|
-
add_default_query_params(configuration, params)
|
26
|
-
save_query_params(url, params)
|
27
|
-
|
28
|
-
@app.call(request_env)
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def add_default_query_params(configuration, params)
|
34
|
-
params.reverse_merge!(api_key: configuration.api_key,
|
35
|
-
v: configuration.api_version || "20161012")
|
36
|
-
|
37
|
-
params[:validation] ||= configuration.validation_level if configuration.validation_level.present?
|
38
|
-
end
|
39
|
-
|
40
|
-
def save_query_params(url, params)
|
41
|
-
url.query = params.to_query
|
42
|
-
end
|
43
|
-
|
44
|
-
def add_username_headers(request_env, configuration, params)
|
45
|
-
username = params.delete(:yext_username) || configuration.yext_username
|
46
|
-
user_id = params.delete(:yext_user_id) || configuration.yext_user_id
|
47
|
-
|
48
|
-
return unless %w[put post patch delete].include?(request_env[:method].to_s)
|
49
|
-
|
50
|
-
request_headers = request_env[:request_headers]
|
51
|
-
request_headers["Yext-Username"] = username if username.present?
|
52
|
-
request_headers["Yext-User-Id"] = user_id if user_id.present?
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,84 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Yext
|
4
|
-
module Api
|
5
|
-
module Utils
|
6
|
-
# The default response parser for Faraday to get the results from Yext into the structure
|
7
|
-
# that is needed by Spyke.
|
8
|
-
class ResponseParser < Faraday::Response::Middleware
|
9
|
-
include Yext::Api::Concerns::ApiFinder
|
10
|
-
|
11
|
-
def call(env)
|
12
|
-
@parse_env = env
|
13
|
-
|
14
|
-
@app.call(env).on_complete do |environment|
|
15
|
-
on_complete(environment)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def parse(body)
|
20
|
-
# Yext Response:
|
21
|
-
# http://developer.yext.com/docs/api-reference/#section/Policies-and-Conventions
|
22
|
-
#
|
23
|
-
# Example response format:
|
24
|
-
# {
|
25
|
-
# "meta": {
|
26
|
-
# "uuid": "bb0c7e19-4dc3-4891-bfa5-8593b1f124ad",
|
27
|
-
# "errors": [
|
28
|
-
# {
|
29
|
-
# "code": ...error code...,
|
30
|
-
# "type": ...error, fatal error, non fatal error, or warning...,
|
31
|
-
# "message": ...explanation of the issue...
|
32
|
-
# }
|
33
|
-
# ]
|
34
|
-
# },
|
35
|
-
# "response": {
|
36
|
-
# ...results...
|
37
|
-
# }
|
38
|
-
# }
|
39
|
-
#
|
40
|
-
# Spyke Expected Response Format:
|
41
|
-
# https://github.com/balvig/spyke#configuration
|
42
|
-
#
|
43
|
-
# { data: { id: 1, name: 'Bob' }, metadata: {}, errors: {} }
|
44
|
-
#
|
45
|
-
# Errors:
|
46
|
-
# https://github.com/balvig/spyke#api-side-validations
|
47
|
-
#
|
48
|
-
# { title: [{ error: 'blank'}, { error: 'too_short', count: 10 }]}
|
49
|
-
|
50
|
-
# yext_response_json = MultiJson.load(body, symbolize_keys: true)
|
51
|
-
return {} if body.starts_with?("<html")
|
52
|
-
return { data: [{ response_string: body }], metadata: {}, errors: {} } unless body.starts_with?("{")
|
53
|
-
|
54
|
-
yext_response_json = JSON.parse(body, symbolize_names: true)
|
55
|
-
|
56
|
-
data = extract_data_value(yext_response_json)
|
57
|
-
|
58
|
-
save_meta_data(find_api(parse_env[:url], parse_env[:method].to_s), yext_response_json[:meta])
|
59
|
-
|
60
|
-
{ data: data,
|
61
|
-
metadata: yext_response_json[:meta],
|
62
|
-
errors: {} }
|
63
|
-
end
|
64
|
-
|
65
|
-
private
|
66
|
-
|
67
|
-
def extract_data_value(yext_response_json)
|
68
|
-
data = yext_response_json[:response]
|
69
|
-
data = data[(data.keys - [:count]).first] if data.is_a?(Hash) && (data.key?(:count) || data.length <= 2)
|
70
|
-
|
71
|
-
data
|
72
|
-
end
|
73
|
-
|
74
|
-
attr_reader :parse_env
|
75
|
-
|
76
|
-
def save_meta_data(api_module, metadata)
|
77
|
-
return if api_module.blank?
|
78
|
-
|
79
|
-
api_module.last_meta = metadata
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|