wcc-contentful 0.4.0.pre.alpha → 1.0.0.pre.rc3

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 (69) hide show
  1. checksums.yaml +5 -5
  2. data/Guardfile +43 -0
  3. data/README.md +246 -11
  4. data/Rakefile +5 -0
  5. data/app/controllers/wcc/contentful/webhook_controller.rb +25 -24
  6. data/app/jobs/wcc/contentful/webhook_enable_job.rb +36 -2
  7. data/config/routes.rb +1 -1
  8. data/doc +1 -0
  9. data/lib/tasks/download_schema.rake +12 -0
  10. data/lib/wcc/contentful.rb +70 -16
  11. data/lib/wcc/contentful/active_record_shim.rb +72 -0
  12. data/lib/wcc/contentful/configuration.rb +177 -46
  13. data/lib/wcc/contentful/content_type_indexer.rb +14 -0
  14. data/lib/wcc/contentful/downloads_schema.rb +112 -0
  15. data/lib/wcc/contentful/engine.rb +33 -14
  16. data/lib/wcc/contentful/event.rb +171 -0
  17. data/lib/wcc/contentful/events.rb +41 -0
  18. data/lib/wcc/contentful/exceptions.rb +3 -0
  19. data/lib/wcc/contentful/indexed_representation.rb +2 -2
  20. data/lib/wcc/contentful/instrumentation.rb +31 -0
  21. data/lib/wcc/contentful/link.rb +28 -0
  22. data/lib/wcc/contentful/link_visitor.rb +122 -0
  23. data/lib/wcc/contentful/middleware.rb +7 -0
  24. data/lib/wcc/contentful/middleware/store.rb +158 -0
  25. data/lib/wcc/contentful/middleware/store/caching_middleware.rb +114 -0
  26. data/lib/wcc/contentful/model.rb +37 -3
  27. data/lib/wcc/contentful/model_builder.rb +1 -0
  28. data/lib/wcc/contentful/model_methods.rb +40 -15
  29. data/lib/wcc/contentful/model_singleton_methods.rb +47 -30
  30. data/lib/wcc/contentful/rake.rb +4 -0
  31. data/lib/wcc/contentful/rspec.rb +46 -0
  32. data/lib/wcc/contentful/services.rb +61 -27
  33. data/lib/wcc/contentful/simple_client.rb +81 -25
  34. data/lib/wcc/contentful/simple_client/management.rb +43 -10
  35. data/lib/wcc/contentful/simple_client/response.rb +61 -22
  36. data/lib/wcc/contentful/simple_client/typhoeus_adapter.rb +17 -17
  37. data/lib/wcc/contentful/store.rb +7 -66
  38. data/lib/wcc/contentful/store/README.md +85 -0
  39. data/lib/wcc/contentful/store/base.rb +34 -119
  40. data/lib/wcc/contentful/store/cdn_adapter.rb +71 -12
  41. data/lib/wcc/contentful/store/factory.rb +186 -0
  42. data/lib/wcc/contentful/store/instrumentation.rb +55 -0
  43. data/lib/wcc/contentful/store/interface.rb +82 -0
  44. data/lib/wcc/contentful/store/memory_store.rb +27 -24
  45. data/lib/wcc/contentful/store/postgres_store.rb +268 -101
  46. data/lib/wcc/contentful/store/postgres_store/schema_1.sql +73 -0
  47. data/lib/wcc/contentful/store/postgres_store/schema_2.sql +21 -0
  48. data/lib/wcc/contentful/store/query.rb +246 -0
  49. data/lib/wcc/contentful/store/query/interface.rb +63 -0
  50. data/lib/wcc/contentful/store/rspec_examples.rb +48 -0
  51. data/lib/wcc/contentful/store/rspec_examples/basic_store.rb +629 -0
  52. data/lib/wcc/contentful/store/rspec_examples/include_param.rb +283 -0
  53. data/lib/wcc/contentful/store/rspec_examples/nested_queries.rb +342 -0
  54. data/lib/wcc/contentful/sync_engine.rb +181 -0
  55. data/lib/wcc/contentful/test.rb +7 -0
  56. data/lib/wcc/contentful/test/attributes.rb +56 -0
  57. data/lib/wcc/contentful/test/double.rb +76 -0
  58. data/lib/wcc/contentful/test/factory.rb +101 -0
  59. data/lib/wcc/contentful/version.rb +1 -1
  60. data/wcc-contentful.gemspec +23 -11
  61. metadata +299 -116
  62. data/Gemfile +0 -6
  63. data/app/jobs/wcc/contentful/delayed_sync_job.rb +0 -63
  64. data/lib/wcc/contentful/client_ext.rb +0 -28
  65. data/lib/wcc/contentful/graphql.rb +0 -14
  66. data/lib/wcc/contentful/graphql/builder.rb +0 -177
  67. data/lib/wcc/contentful/graphql/types.rb +0 -54
  68. data/lib/wcc/contentful/simple_client/http_adapter.rb +0 -24
  69. data/lib/wcc/contentful/store/lazy_cache_store.rb +0 -161
@@ -7,7 +7,9 @@ module WCC::Contentful
7
7
  self.queue_adapter = :async
8
8
  queue_as :default
9
9
 
10
- def perform(args)
10
+ def perform(args = {})
11
+ args = default_configuration.merge!(args)
12
+
11
13
  client = WCC::Contentful::SimpleClient::Management.new(
12
14
  args
13
15
  )
@@ -26,7 +28,8 @@ module WCC::Contentful
26
28
  'topics' => [
27
29
  '*.publish',
28
30
  '*.unpublish'
29
- ]
31
+ ],
32
+ 'filters' => webhook_filters
30
33
  }
31
34
  body['httpBasicUsername'] = webhook_username if webhook_username.present?
32
35
  body['httpBasicPassword'] = webhook_password if webhook_password.present?
@@ -39,5 +42,36 @@ module WCC::Contentful
39
42
  raise
40
43
  end
41
44
  end
45
+
46
+ private
47
+
48
+ def default_configuration
49
+ return {} unless config = WCC::Contentful&.configuration
50
+
51
+ {
52
+ management_token: config.management_token,
53
+ app_url: config.app_url,
54
+ space: config.space,
55
+ environment: config.environment,
56
+ default_locale: config.default_locale,
57
+ connection: config.connection,
58
+ webhook_username: config.webhook_username,
59
+ webhook_password: config.webhook_password
60
+ }
61
+ end
62
+
63
+ def webhook_filters
64
+ filters = []
65
+
66
+ if (environment_id = WCC::Contentful.configuration&.environment).present?
67
+ filters << {
68
+ 'equals' => [
69
+ { 'doc' => 'sys.environment.sys.id' },
70
+ environment_id
71
+ ]
72
+ }
73
+ end
74
+ filters
75
+ end
42
76
  end
43
77
  end
data/config/routes.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  WCC::Contentful::Engine.routes.draw do
4
- post 'webhook/receive', to: 'webhook#receive'
4
+ post 'webhook/receive', to: 'wcc/contentful/webhook#receive'
5
5
  end
data/doc ADDED
@@ -0,0 +1 @@
1
+ ./../doc/wcc-contentful
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wcc/contentful'
4
+ require 'wcc/contentful/downloads_schema'
5
+
6
+ namespace :wcc_contentful do
7
+ desc 'Downloads the schema from the currently configured space and stores it in ' \
8
+ 'db/contentful-schema.json'
9
+ task download_schema: :environment do
10
+ WCC::Contentful::DownloadsSchema.call
11
+ end
12
+ end
@@ -5,9 +5,12 @@ require 'wcc/contentful/version'
5
5
  require 'active_support'
6
6
  require 'active_support/core_ext/object'
7
7
 
8
+ require 'wcc/contentful/active_record_shim'
8
9
  require 'wcc/contentful/configuration'
10
+ require 'wcc/contentful/downloads_schema'
9
11
  require 'wcc/contentful/exceptions'
10
12
  require 'wcc/contentful/helpers'
13
+ require 'wcc/contentful/link_visitor'
11
14
  require 'wcc/contentful/services'
12
15
  require 'wcc/contentful/simple_client'
13
16
  require 'wcc/contentful/store'
@@ -16,6 +19,9 @@ require 'wcc/contentful/model'
16
19
  require 'wcc/contentful/model_methods'
17
20
  require 'wcc/contentful/model_singleton_methods'
18
21
  require 'wcc/contentful/model_builder'
22
+ require 'wcc/contentful/sync_engine'
23
+ require 'wcc/contentful/events'
24
+ require 'wcc/contentful/middleware'
19
25
 
20
26
  # The root namespace of the wcc-contentful gem
21
27
  #
@@ -23,16 +29,33 @@ require 'wcc/contentful/model_builder'
23
29
  # initializer.
24
30
  module WCC::Contentful
25
31
  class << self
32
+ attr_reader :initialized
33
+
26
34
  # Gets the current configuration, after calling WCC::Contentful.configure
27
35
  attr_reader :configuration
28
36
 
29
37
  attr_reader :types
38
+
39
+ # Gets all queryable locales.
40
+ # Reserved for future use.
41
+ def locales
42
+ @locales ||= { 'en-US' => {} }.freeze
43
+ end
44
+
45
+ def logger
46
+ return Rails.logger if defined?(Rails)
47
+
48
+ @logger ||= Logger.new(STDERR)
49
+ end
30
50
  end
31
51
 
32
52
  # Configures the WCC::Contentful gem to talk to a Contentful space.
33
53
  # This must be called first in your initializer, before #init! or accessing the
34
54
  # client.
55
+ # See WCC::Contentful::Configuration for all configuration options.
35
56
  def self.configure
57
+ raise InitializationError, 'Cannot configure after initialization' if @initialized
58
+
36
59
  @configuration ||= Configuration.new
37
60
  yield(configuration)
38
61
 
@@ -51,29 +74,60 @@ module WCC::Contentful
51
74
  # class Page < WCC::Contentful::Model::Page; end
52
75
  # Page.find_by(slug: 'about-us')
53
76
  def self.init!
54
- raise ArgumentError, 'Please first call WCC:Contentful.configure' if configuration.nil?
77
+ raise InitializationError, 'Please first call WCC:Contentful.configure' if configuration.nil?
78
+ raise InitializationError, 'Already Initialized' if @initialized
55
79
 
56
- # we want as much as possible the raw JSON from the API so use the management
57
- # client if possible
58
- client = Services.instance.management_client ||
59
- Services.instance.client
80
+ if configuration.update_schema_file == :always ||
81
+ (configuration.update_schema_file == :if_possible && Services.instance.management_client) ||
82
+ configuration.update_schema_file == :if_missing && !File.exist?(configuration.schema_file)
60
83
 
61
- @content_types = client.content_types(limit: 1000).items
84
+ begin
85
+ downloader = WCC::Contentful::DownloadsSchema.new
86
+ downloader.update! if configuration.update_schema_file == :always || downloader.needs_update?
87
+ rescue WCC::Contentful::SimpleClient::ApiError => e
88
+ raise InitializationError, e if configuration.update_schema_file == :always
62
89
 
63
- indexer =
64
- ContentTypeIndexer.new.tap do |ixr|
65
- @content_types.each { |type| ixr.index(type) }
90
+ WCC::Contentful.logger.warn("Unable to download schema from management API - #{e.message}")
66
91
  end
67
- @types = indexer.types
92
+ end
68
93
 
69
- store = Services.instance.store
70
- if store.respond_to?(:index)
71
- # Drop an initial sync
72
- WCC::Contentful::DelayedSyncJob.perform_later
94
+ @content_types =
95
+ begin
96
+ if File.exist?(configuration.schema_file)
97
+ JSON.parse(File.read(configuration.schema_file))['contentTypes']
98
+ end
99
+ rescue JSON::ParserError
100
+ WCC::Contentful.logger.warn("Schema file invalid, ignoring it: #{configuration.schema_file}")
101
+ nil
102
+ end
103
+
104
+ if !@content_types && %i[if_possible never].include?(configuration.update_schema_file)
105
+ # Final fallback - try to grab content types from CDN. We can't update the file
106
+ # because the CDN doesn't have all the field validation info, but we can at least
107
+ # build the WCC::Contentful::Model instances.
108
+ client = Services.instance.management_client ||
109
+ Services.instance.client
110
+ begin
111
+ @content_types = client.content_types(limit: 1000).items if client
112
+ rescue WCC::Contentful::SimpleClient::ApiError => e
113
+ # indicates bad credentials
114
+ WCC::Contentful.logger.warn("Unable to load content types from API - #{e.message}")
115
+ end
73
116
  end
74
117
 
75
- WCC::Contentful::ModelBuilder.new(@types).build_models
118
+ unless @content_types
119
+ raise InitializationError, 'Unable to load content types from schema file or API!' \
120
+ ' Check your access token and space ID.'
121
+ end
76
122
 
77
- require_relative 'contentful/client_ext' if defined?(::Contentful)
123
+ indexer = ContentTypeIndexer.from_json_schema(@content_types)
124
+ @types = indexer.types
125
+
126
+ # Drop an initial sync
127
+ WCC::Contentful::SyncEngine::Job.perform_later if defined?(WCC::Contentful::SyncEngine::Job)
128
+
129
+ WCC::Contentful::ModelBuilder.new(@types).build_models
130
+ @configuration = @configuration.freeze
131
+ @initialized = true
78
132
  end
79
133
  end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WCC::Contentful::ActiveRecordShim
4
+ extend ActiveSupport::Concern
5
+
6
+ def attributes
7
+ @attributes ||= to_h['fields'].tap { |fields| fields['id'] = id }
8
+ end
9
+
10
+ def cache_key
11
+ return cache_key_with_version unless ActiveRecord::Base.try(:cache_versioning) == true
12
+
13
+ "#{self.class.model_name}/#{id}"
14
+ end
15
+
16
+ def cache_key_with_version
17
+ "#{self.class.model_name}/#{id}-#{cache_version}"
18
+ end
19
+
20
+ def cache_version
21
+ sys.revision.to_s
22
+ end
23
+
24
+ included do
25
+ unless defined?(ActiveRecord)
26
+ raise NotImplementedError, 'WCC::Contentful::ActiveRecordShim requires ActiveRecord to be loaded'
27
+ end
28
+ end
29
+
30
+ class_methods do
31
+ def model_name
32
+ WCC::Contentful::Helpers.constant_from_content_type(content_type)
33
+ end
34
+
35
+ def const_get(name)
36
+ # Because our pattern is `class MyModel < WCC::Contentful::Model::MyModel`
37
+ # if you do MyModel.const_get('MyModel') Algolia expects you to return
38
+ # ::MyModel not WCC::Contentful::Model::MyModel
39
+ return self if name == model_name
40
+
41
+ super
42
+ end
43
+
44
+ def table_name
45
+ model_name.tableize
46
+ end
47
+
48
+ def unscoped
49
+ yield
50
+ end
51
+
52
+ def find_in_batches(options, &block)
53
+ options ||= {}
54
+ batch_size = options.delete(:batch_size) || 1000
55
+ filter = {
56
+ options: {
57
+ limit: batch_size,
58
+ skip: options.delete(:start) || 0,
59
+ include: options.delete(:include) || 1
60
+ }
61
+ }
62
+
63
+ find_all(filter).each_slice(batch_size, &block)
64
+ end
65
+
66
+ def where(**conditions)
67
+ # TODO: return a Query object that implements more of the ActiveRecord query interface
68
+ # https://guides.rubyonrails.org/active_record_querying.html#conditions
69
+ find_all(conditions)
70
+ end
71
+ end
72
+ end
@@ -1,22 +1,61 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # This object contains all the configuration options for the `wcc-contentful` gem.
3
4
  class WCC::Contentful::Configuration
4
5
  ATTRIBUTES = %i[
6
+ space
5
7
  access_token
6
8
  app_url
7
9
  management_token
8
- space
9
10
  environment
10
11
  default_locale
11
- content_delivery
12
12
  preview_token
13
- http_adapter
14
- sync_cache_store
15
13
  webhook_username
16
14
  webhook_password
17
15
  webhook_jobs
16
+ connection
17
+ connection_options
18
+ update_schema_file
19
+ schema_file
20
+ store
21
+ instrumentation_adapter
18
22
  ].freeze
19
- attr_accessor(*ATTRIBUTES)
23
+
24
+ # (required) Sets the Contentful Space ID.
25
+ attr_accessor :space
26
+ # (required) Sets the Content Delivery API access token.
27
+ attr_accessor :access_token
28
+
29
+ # Sets the app's root URL for a Rails app. Used by the WCC::Contentful::Engine
30
+ # to automatically set up webhooks to point at the WCC::Contentful::WebhookController
31
+ attr_accessor :app_url
32
+ # Sets the Content Management Token used to communicate with the Management API.
33
+ # This is required for automatically setting up webhooks, and to create the
34
+ # WCC::Contentful::Services#management_client.
35
+ attr_accessor :management_token
36
+ # Sets the Environment ID. Leave blank to use master.
37
+ attr_accessor :environment
38
+ # Sets the default locale. Defaults to 'en-US'.
39
+ attr_accessor :default_locale
40
+ # Sets the Content Preview API access token. Only required if you use the
41
+ # preview flag.
42
+ attr_accessor :preview_token
43
+ # Sets an optional basic auth username that will be validated by the webhook controller.
44
+ # You must ensure the configured webhook sets the "HTTP Basic Auth username"
45
+ attr_accessor :webhook_username
46
+ # Sets an optional basic auth password that will be validated by the webhook controller.
47
+ # You must ensure the configured webhook sets the "HTTP Basic Auth password"
48
+ attr_accessor :webhook_password
49
+ # An array of jobs that are run whenever a webhook is received by the webhook controller.
50
+ # The job can be an ActiveJob class which responds to `:perform_later`, or a lambda or
51
+ # other object that responds to `:call`.
52
+ # Example:
53
+ # config.webhook_jobs << MyJobClass
54
+ # config.webhook_jobs << ->(event) { ... }
55
+ #
56
+ # See the source code for WCC::Contentful::SyncEngine::Job for an example of how
57
+ # to implement a webhook job.
58
+ attr_accessor :webhook_jobs
20
59
 
21
60
  # Returns true if the currently configured environment is pointing at `master`.
22
61
  def master?
@@ -25,22 +64,23 @@ class WCC::Contentful::Configuration
25
64
 
26
65
  # Defines the method by which content is downloaded from the Contentful CDN.
27
66
  #
28
- # [:direct] `config.content_delivery = :direct`
67
+ # [:direct] `config.store :direct`
29
68
  # with the `:direct` method, all queries result in web requests to
30
69
  # 'https://cdn.contentful.com' via the
31
70
  # {WCC::Contentful::SimpleClient::Cdn SimpleClient}
32
71
  #
33
- # [:eager_sync] `config.content_delivery = :eager_sync, [sync_store], [options]`
72
+ # [:eager_sync] `config.store :eager_sync, [sync_store], [options]`
34
73
  # with the `:eager_sync` method, the entire content of the Contentful
35
74
  # space is downloaded locally and stored in the
36
75
  # {WCC::Contentful::Services#store configured store}. The application is
37
- # responsible to periodically call `WCC::Contentful.sync!` to keep the store
38
- # updated. Alternatively, the provided {WCC::Contentful::Engine Engine}
39
- # can be mounted to receive a webhook from the Contentful space
40
- # on publish events:
41
- # mount WCC::Contentful::Engine, at: '/wcc/contentful'
76
+ # responsible to periodically call the WCC::Contentful::SyncEngine#next to
77
+ # keep the store updated. Alternatively, the provided {WCC::Contentful::Engine Engine}
78
+ # can be mounted to automatically call WCC::Contentful::SyncEngine#next on
79
+ # webhook events.
80
+ # In `routes.rb` add the following:
81
+ # mount WCC::Contentful::Engine, at: '/'
42
82
  #
43
- # [:lazy_sync] `config.content_delivery = :lazy_sync, [cache]`
83
+ # [:lazy_sync] `config.store :lazy_sync, [cache]`
44
84
  # The `:lazy_sync` method is a hybrid between the other two methods.
45
85
  # Frequently accessed data is stored in an ActiveSupport::Cache implementation
46
86
  # and is kept up-to-date via the Sync API. Any data that is not present
@@ -48,62 +88,153 @@ class WCC::Contentful::Configuration
48
88
  # The application is still responsible to periodically call `sync!`
49
89
  # or to mount the provided Engine.
50
90
  #
51
- def content_delivery=(params)
52
- cd, *cd_params = params
53
- unless cd.is_a? Symbol
54
- raise ArgumentError, 'content_delivery must be a symbol, use store= to '\
55
- 'directly set contentful CDN access adapter'
91
+ # [:custom] `config.store :custom, do ... end`
92
+ # The block is executed in the context of a WCC::Contentful::Store::Factory.
93
+ # this can be used to apply middleware, etc.
94
+ def store(*params, &block)
95
+ type, *params = params
96
+ if type
97
+ @store_factory = WCC::Contentful::Store::Factory.new(
98
+ self,
99
+ type,
100
+ params
101
+ )
56
102
  end
57
103
 
58
- WCC::Contentful::Store::Factory.new(
59
- self,
60
- nil,
61
- cd,
62
- cd_params
63
- ).validate!
104
+ @store_factory.instance_exec(&block) if block_given?
105
+ @store_factory
106
+ end
64
107
 
65
- @content_delivery = cd
66
- @content_delivery_params = cd_params
108
+ # Convenience for setting store without a block
109
+ def store=(param_array)
110
+ store(*param_array)
67
111
  end
68
112
 
69
- attr_reader :content_delivery_params
113
+ # Explicitly read the store factory
114
+ attr_reader :store_factory
115
+
116
+ # Sets the connection which is used to make HTTP requests.
117
+ # If left unset, the gem attempts to load 'faraday' or 'typhoeus'.
118
+ # You can pass your own adapter which responds to 'get' and 'post', and returns
119
+ # a response that quacks like Faraday.
120
+ attr_accessor :connection
121
+
122
+ # Sets the connection options which are given to the client. This can include
123
+ # an alternative Cdn API URL, timeouts, etc.
124
+ # See WCC::Contentful::SimpleClient constructor for details.
125
+ attr_accessor :connection_options
70
126
 
71
- # Directly sets the adapter layer for communicating with Contentful
72
- def store=(value)
73
- @content_delivery = :custom
74
- store, *cd_params = value
75
- @store = store
76
- @content_delivery_params = cd_params
127
+ # Indicates whether to update the contentful-schema.json file for building models.
128
+ # The schema can also be updated with `rake wcc_contentful:download_schema`
129
+ # Valid values are:
130
+ #
131
+ # [:never] wcc-contentful will not update the schema even if a management token is available.
132
+ # If your schema file is out of date this could cause null-reference errors or
133
+ # not found errors at runtime. If your schema file does not exist or is invalid,
134
+ # WCC::Contentful.init! will raise a WCC::Contentful::InitializitionError
135
+ #
136
+ # [:if_missing] wcc-contentful will only download the schema if the schema file
137
+ # doesn't exist.
138
+ #
139
+ # [:if_possible] wcc-contentful will attempt to reach out to the management API for
140
+ # content types, and will fall back to the schema file if the API
141
+ # cannot be reached. This is the default.
142
+ #
143
+ # [:always] wcc-contentful will check either the management API or the CDN for the
144
+ # most up-to-date content types and will raise a
145
+ # WCC::Contentful::InitializationError if the API cannot be reached.
146
+ def update_schema_file=(sym)
147
+ valid_syms = %i[never if_possible if_missing always]
148
+ unless valid_syms.include?(sym)
149
+ raise ArgumentError, "update_schema_file must be one of #{valid_syms}"
150
+ end
151
+
152
+ @update_schema_file = sym
77
153
  end
154
+ attr_reader :update_schema_file
78
155
 
79
- attr_reader :store
156
+ # The file to store the Contentful schema in. You should check this into source
157
+ # control, similar to `db/schema.rb`. This filename is relative to the rails root.
158
+ # Defaults to 'db/contentful-schema.json
159
+ attr_writer :schema_file
160
+
161
+ def schema_file
162
+ if defined?(Rails)
163
+ Rails.root.join(@schema_file)
164
+ else
165
+ @schema_file
166
+ end
167
+ end
80
168
 
81
- # Sets the adapter which is used to make HTTP requests.
82
- # If left unset, the gem attempts to load either 'http' or 'typhoeus'.
83
- # You can pass your own adapter which responds to 'call', or even a lambda
84
- # that accepts the following parameters:
85
- # ->(url, query, headers = {}, proxy = {}) { ... }
86
- attr_writer :http_adapter
169
+ # Overrides the use of ActiveSupport::Notifications throughout this library to
170
+ # emit instrumentation events. The object or module provided here must respond
171
+ # to :instrument like ActiveSupport::Notifications.instrument
172
+ attr_accessor :instrumentation_adapter
87
173
 
88
174
  def initialize
89
- @access_token = ''
175
+ @access_token = ENV['CONTENTFUL_ACCESS_TOKEN']
90
176
  @app_url = ENV['APP_URL']
91
- @management_token = ''
92
- @preview_token = ''
93
- @space = ''
177
+ @connection_options = {
178
+ api_url: 'https://cdn.contentful.com/',
179
+ preview_api_url: 'https://preview.contentful.com/',
180
+ management_api_url: 'https://api.contentful.com'
181
+ }
182
+ @management_token = ENV['CONTENTFUL_MANAGEMENT_TOKEN']
183
+ @preview_token = ENV['CONTENTFUL_PREVIEW_TOKEN']
184
+ @space = ENV['CONTENTFUL_SPACE_ID']
94
185
  @default_locale = nil
95
- @content_delivery = :direct
186
+ @middleware = []
187
+ @update_schema_file = :if_possible
188
+ @schema_file = 'db/contentful-schema.json'
96
189
  @webhook_jobs = []
190
+ @store_factory = WCC::Contentful::Store::Factory.new(self, :direct)
97
191
  end
98
192
 
193
+ # Validates the configuration, raising ArgumentError if anything is wrong. This
194
+ # is called by WCC::Contentful.init!
99
195
  def validate!
100
196
  raise ArgumentError, 'Please provide "space"' unless space.present?
101
197
  raise ArgumentError, 'Please provide "access_token"' unless access_token.present?
102
198
 
103
- webhook_jobs&.each do |job|
199
+ store_factory.validate!
200
+
201
+ if update_schema_file == :always && management_token.blank?
202
+ raise ArgumentError, 'A management_token is required in order to update the schema file.'
203
+ end
204
+
205
+ webhook_jobs.each do |job|
104
206
  next if job.respond_to?(:call) || job.respond_to?(:perform_later)
105
207
 
106
208
  raise ArgumentError, "The job '#{job}' must be an instance of ActiveJob::Base or respond to :call"
107
209
  end
108
210
  end
211
+
212
+ def frozen?
213
+ false
214
+ end
215
+
216
+ def freeze
217
+ FrozenConfiguration.new(self)
218
+ end
219
+
220
+ class FrozenConfiguration
221
+ attr_reader(*ATTRIBUTES)
222
+
223
+ def initialize(configuration)
224
+ ATTRIBUTES.each do |att|
225
+ val = configuration.public_send(att)
226
+ val.freeze if val.is_a?(Hash) || val.is_a?(Array)
227
+ instance_variable_set("@#{att}", val)
228
+ end
229
+ end
230
+
231
+ # Returns true if the currently configured environment is pointing at `master`.
232
+ def master?
233
+ !environment.present?
234
+ end
235
+
236
+ def frozen?
237
+ true
238
+ end
239
+ end
109
240
  end