wcc-contentful 0.4.0.pre.rc → 1.0.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +5 -5
  2. data/Guardfile +43 -0
  3. data/README.md +101 -12
  4. data/app/controllers/wcc/contentful/webhook_controller.rb +25 -24
  5. data/app/jobs/wcc/contentful/webhook_enable_job.rb +36 -2
  6. data/config/routes.rb +1 -1
  7. data/doc/wcc-contentful.png +0 -0
  8. data/lib/tasks/download_schema.rake +12 -0
  9. data/lib/wcc/contentful.rb +70 -16
  10. data/lib/wcc/contentful/active_record_shim.rb +72 -0
  11. data/lib/wcc/contentful/configuration.rb +177 -46
  12. data/lib/wcc/contentful/content_type_indexer.rb +14 -0
  13. data/lib/wcc/contentful/downloads_schema.rb +112 -0
  14. data/lib/wcc/contentful/engine.rb +33 -14
  15. data/lib/wcc/contentful/event.rb +171 -0
  16. data/lib/wcc/contentful/events.rb +41 -0
  17. data/lib/wcc/contentful/exceptions.rb +3 -0
  18. data/lib/wcc/contentful/indexed_representation.rb +2 -2
  19. data/lib/wcc/contentful/instrumentation.rb +31 -0
  20. data/lib/wcc/contentful/link.rb +28 -0
  21. data/lib/wcc/contentful/link_visitor.rb +122 -0
  22. data/lib/wcc/contentful/middleware.rb +7 -0
  23. data/lib/wcc/contentful/middleware/store.rb +158 -0
  24. data/lib/wcc/contentful/middleware/store/caching_middleware.rb +114 -0
  25. data/lib/wcc/contentful/model.rb +37 -3
  26. data/lib/wcc/contentful/model_builder.rb +1 -0
  27. data/lib/wcc/contentful/model_methods.rb +40 -15
  28. data/lib/wcc/contentful/model_singleton_methods.rb +47 -30
  29. data/lib/wcc/contentful/rake.rb +3 -0
  30. data/lib/wcc/contentful/rspec.rb +13 -8
  31. data/lib/wcc/contentful/services.rb +61 -27
  32. data/lib/wcc/contentful/simple_client.rb +81 -25
  33. data/lib/wcc/contentful/simple_client/management.rb +43 -10
  34. data/lib/wcc/contentful/simple_client/response.rb +61 -22
  35. data/lib/wcc/contentful/simple_client/typhoeus_adapter.rb +17 -17
  36. data/lib/wcc/contentful/store.rb +7 -66
  37. data/lib/wcc/contentful/store/README.md +85 -0
  38. data/lib/wcc/contentful/store/base.rb +34 -119
  39. data/lib/wcc/contentful/store/cdn_adapter.rb +71 -12
  40. data/lib/wcc/contentful/store/factory.rb +186 -0
  41. data/lib/wcc/contentful/store/instrumentation.rb +55 -0
  42. data/lib/wcc/contentful/store/interface.rb +82 -0
  43. data/lib/wcc/contentful/store/memory_store.rb +27 -24
  44. data/lib/wcc/contentful/store/postgres_store.rb +253 -107
  45. data/lib/wcc/contentful/store/postgres_store/schema_1.sql +73 -0
  46. data/lib/wcc/contentful/store/postgres_store/schema_2.sql +21 -0
  47. data/lib/wcc/contentful/store/query.rb +246 -0
  48. data/lib/wcc/contentful/store/query/interface.rb +63 -0
  49. data/lib/wcc/contentful/store/rspec_examples.rb +48 -0
  50. data/lib/wcc/contentful/store/rspec_examples/basic_store.rb +629 -0
  51. data/lib/wcc/contentful/store/rspec_examples/include_param.rb +283 -0
  52. data/lib/wcc/contentful/store/rspec_examples/nested_queries.rb +342 -0
  53. data/lib/wcc/contentful/sync_engine.rb +181 -0
  54. data/lib/wcc/contentful/test/attributes.rb +17 -5
  55. data/lib/wcc/contentful/test/factory.rb +22 -46
  56. data/lib/wcc/contentful/version.rb +1 -1
  57. data/wcc-contentful.gemspec +14 -11
  58. metadata +201 -146
  59. data/Gemfile +0 -6
  60. data/app/jobs/wcc/contentful/delayed_sync_job.rb +0 -63
  61. data/lib/wcc/contentful/client_ext.rb +0 -28
  62. data/lib/wcc/contentful/graphql.rb +0 -14
  63. data/lib/wcc/contentful/graphql/builder.rb +0 -177
  64. data/lib/wcc/contentful/graphql/types.rb +0 -54
  65. data/lib/wcc/contentful/simple_client/http_adapter.rb +0 -24
  66. data/lib/wcc/contentful/store/lazy_cache_store.rb +0 -161
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: dbe6cdec1d0756eb9c1f8930efb8023ebbf6a758
4
- data.tar.gz: 61fadc6215d698b8865dd7ad0a1c2e3c8dd8f26f
2
+ SHA256:
3
+ metadata.gz: e8c289b7bbddc39150c9ab86fb781e4dcdd740153a6e39906f438caa11740077
4
+ data.tar.gz: 36d446fb8abe8b7dbed82f68d36280d85528f4ba60a9af2707bbccbdb4a04794
5
5
  SHA512:
6
- metadata.gz: 3d9ec54fe32c9380048236927fbcfd77a44e3c499327520054b61ae3976a561cdf7a1d7bad916b6f33b839963877f7d1c7e53067cebd8e646c74bb2d335c9606
7
- data.tar.gz: aed63f65c37498f9ebee35f768c49c5be763e32032714321aaa8f35eba07d8f10d033082b85401e51cb4e8c964698a11d216eb6af885707ff6ec5bd43cefccb9
6
+ metadata.gz: a3a992e38c9688f7bc0834bf0629c5df5e6d54fdca044295a534d741ce3fc6c6e4017a9a48ba65c765af91c6ff9733ec5469ecb0aaa5a1302e371c6fd3325de1
7
+ data.tar.gz: 90aa3d052268446d7d1bb15cea05048b643904026d8406ea274045db6a68b3c395b09e60178a13f028e3238a8a3606c3f63abc58a47ba5c8b822834b6a8c3064
data/Guardfile CHANGED
@@ -3,6 +3,39 @@
3
3
 
4
4
  # To run, use `bundle exec guard`.
5
5
 
6
+ def watch_async(regexp)
7
+ raise ArgumentError, "No block given" unless block_given?
8
+ match_queue = Queue.new
9
+
10
+ watch(regexp) do |match|
11
+ # Producer - add matches to the match queue
12
+ match_queue << match
13
+ nil
14
+ end
15
+
16
+ # Consumer - process matches as a batch
17
+ Thread.new do
18
+ loop do
19
+ matches = []
20
+ matches << match_queue.pop
21
+
22
+ loop do
23
+ begin
24
+ matches << match_queue.pop(true)
25
+ rescue ThreadError
26
+ break
27
+ end
28
+ end
29
+
30
+ begin
31
+ yield matches if matches.length > 0
32
+ rescue StandardError => ex
33
+ STDERR.puts "Error! #{ex}"
34
+ end
35
+ end
36
+ end
37
+ end
38
+
6
39
  group :red_green_refactor, halt_on_fail: true do
7
40
  guard :rspec, cmd: 'bundle exec rspec' do
8
41
  require 'guard/rspec/dsl'
@@ -46,6 +79,16 @@ group :red_green_refactor, halt_on_fail: true do
46
79
  watch(%r{.+\.rb$})
47
80
  watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
48
81
  end
82
+
83
+ guard :shell, all_on_start: false do
84
+ watch_async(%r{app/views/(.+\.html.*\.erb)}) { |matches|
85
+
86
+ matches = matches.map { |m| File.absolute_path(m[0]) }
87
+ Dir.chdir('..') {
88
+ system("bundle exec erblint #{matches.join(' ')}")
89
+ }
90
+ }
91
+ end
49
92
  end
50
93
 
51
94
  group :autofix do
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- [![Gem Version](https://badge.fury.io/rb/wcc-contentful.svg)](https://badge.fury.io/rb/wcc-contentful)
2
- [![CircleCI](https://circleci.com/gh/watermarkchurch/wcc-contentful.svg?style=svg)](https://circleci.com/gh/watermarkchurch/wcc-contentful)
1
+ [![Gem Version](https://badge.fury.io/rb/wcc-contentful.svg)](https://rubygems.org/gems/wcc-contentful)
2
+ [![Build Status](https://travis-ci.org/watermarkchurch/wcc-contentful.svg?branch=master)](https://travis-ci.org/watermarkchurch/wcc-contentful)
3
3
  [![Coverage Status](https://coveralls.io/repos/github/watermarkchurch/wcc-contentful/badge.svg?branch=master)](https://coveralls.io/github/watermarkchurch/wcc-contentful?branch=master)
4
4
 
5
- Full documentation: https://www.rubydoc.info/github/watermarkchurch/wcc-contentful
5
+ Full documentation: https://www.rubydoc.info/gems/wcc-contentful
6
6
 
7
7
  # WCC::Contentful
8
8
 
@@ -14,17 +14,26 @@ Add this line to your application's Gemfile:
14
14
  gem 'wcc-contentful', require: 'wcc/contentful/rails'
15
15
  ```
16
16
 
17
- And then execute:
17
+ If you're not using rails, exclude the `require:` parameter.
18
18
 
19
- $ bundle
19
+ ```ruby
20
+ gem 'wcc-contentful'
21
+ ```
20
22
 
23
+ And then execute:
24
+ ```
25
+ $ bundle
26
+ ```
21
27
  Or install it yourself as:
22
-
28
+ ```
23
29
  $ gem install wcc-contentful
30
+ ```
24
31
 
25
32
  ## Configure
26
33
 
34
+ Put this in an initializer:
27
35
  ```ruby
36
+ # config/initializers/wcc_contentful.rb
28
37
  WCC::Contentful.configure do |config|
29
38
  config.access_token = <CONTENTFUL_ACCESS_TOKEN>
30
39
  config.space = <CONTENTFUL_SPACE_ID>
@@ -33,13 +42,16 @@ end
33
42
  WCC::Contentful.init!
34
43
  ```
35
44
 
45
+ All configuration options can be found [in the rubydoc](https://www.rubydoc.info/gems/wcc-contentful/WCC/Contentful/Configuration) under
46
+ {WCC::Contentful::Configuration}
47
+
36
48
  ## Usage
37
49
 
38
50
  ### WCC::Contentful::Model API
39
51
 
40
52
  The WCC::Contentful::Model API exposes Contentful data as a set of dynamically
41
53
  generated Ruby objects. These objects are based on the content types in your
42
- Contentful space. All these objects are generated by WCC::Contentful.init!
54
+ Contentful space. All these objects are generated by `WCC::Contentful.init!`
43
55
 
44
56
  The following examples show how to use this API to find entries of the `page`
45
57
  content type:
@@ -164,7 +176,8 @@ response.includes
164
176
 
165
177
  The client handles Paging automatically within the lazy iterator returned by #items.
166
178
  This lazy iterator does not respect the `limit` param - that param is only passed
167
- through to the API to set the page size.
179
+ through to the API to set the page size. If you truly want a limited subset of
180
+ response items, use [`response.items.take(n)`](https://ruby-doc.org/core-2.5.3/Enumerable.html#method-i-take)
168
181
 
169
182
  Entries included via the `include` parameter are made available on the #includes
170
183
  field. This is a hash of `<entry ID> => <raw entry>` and makes it easy to grab
@@ -211,6 +224,10 @@ class MyJob < ApplicationJob
211
224
  end
212
225
  ```
213
226
 
227
+ ## Architecture
228
+
229
+ ![wcc-contentful diagram](./doc/wcc-contentful.png)
230
+
214
231
  ## Test Helpers
215
232
 
216
233
  To use the test helpers, include the following in your rails_helper.rb:
@@ -239,7 +256,7 @@ instance.other_optional_field
239
256
  # => nil
240
257
 
241
258
  instance.not_a_field
242
- # NoMethodError: undefined method `not_a_field' for #<Menu:0x00007fbac81ee490>
259
+ # NoMethodError: undefined method `not_a_field' for #<MyContentType:0x00007fbac81ee490>
243
260
 
244
261
  ##
245
262
  # Builds a rspec double of the Contentful model for the given content_type.
@@ -251,6 +268,9 @@ dbl = contentful_double('my-content-type', my_field: 'other-value')
251
268
  dbl.my_field
252
269
  # => "other-value"
253
270
 
271
+ dbl.other_optional_field
272
+ # => nil
273
+
254
274
  dbl.not_a_field
255
275
  # => #<Double (anonymous)> received unexpected message :not_a_field with (no args)
256
276
 
@@ -270,12 +290,81 @@ MyContentType.find_by(my_field: 'test') == stubbed
270
290
  # => true
271
291
  ```
272
292
 
293
+ ## Advanced Configuration Example
273
294
 
274
- ## Development
295
+ Here's an example containing all the configuration options, and a sample setup for
296
+ automatic deployment to Heroku. This is intended to make you aware of what is possible,
297
+ and not as a general recommendation of what your setup should look like.
298
+
299
+ ```ruby
300
+ # config/initializers/wcc_contentful.rb
301
+ WCC::Contentful.configure do |config|
302
+ config.access_token = ENV['CONTENTFUL_ACCESS_TOKEN']
303
+ config.space = ENV['CONTENTFUL_SPACE_ID']
304
+ config.environment = ENV['CONTENTFUL_ENVIRONMENT']
305
+ config.preview_token = ENV['CONTENTFUL_PREVIEW_ACCESS_TOKEN']
306
+
307
+ # You may or may not want to provide this to your production server...
308
+ config.management_token = ENV['CONTENTFUL_MANAGEMENT_TOKEN'] unless Rails.env.production?
309
+
310
+ config.app_url = "https://#{ENV['HOSTNAME']}"
311
+ config.webhook_username = 'my-app-webhook'
312
+ config.webhook_password = Rails.application.secrets.webhook_password
313
+ config.webhook_jobs << MyOnWebhookJob
314
+
315
+ config.store = :lazy_sync, Rails.cache if Rails.env.production?
316
+ # config.store = MyCustomStore.new
317
+
318
+ # Use a custom Faraday connection
319
+ config.connection = Faraday.new do |builder|
320
+ f.request :retry
321
+ f.request MyFaradayRequestAdapter.new
322
+ ...
323
+ end
324
+ # OR implement some adapter like this to use another HTTP client
325
+ config.connection = MyNetHttpAdapter.new
326
+
327
+ config.update_schema_file = :never
328
+ end
329
+
330
+ WCC::Contentful.init!
331
+ ```
332
+
333
+ For Heroku:
334
+
335
+ ```yaml
336
+ # Procfile
337
+ web: bundle exec rails s
338
+ worker: bundle exec sidekiq
339
+ release: bin/release
340
+ ```
275
341
 
276
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
342
+ ```sh
343
+ # bin/release
344
+ #!/bin/sh
345
+
346
+ set -e
347
+
348
+ echo "Migrating database..."
349
+ bin/rake db:migrate
350
+
351
+ echo "Migrating contentful..."
352
+ migrations_to_be_run=$( ... ) # somehow figure this out
353
+ node_modules/.bin/contentful-migration \
354
+ -s $CONTENTFUL_SPACE_ID -a $CONTENTFUL_MANAGEMENT_TOKEN \
355
+ -y -p "$migrations_to_be_run"
356
+
357
+ echo "Updating schema file..."
358
+ rake wcc_contentful:download_schema
359
+ ```
360
+
361
+ All configuration options can be found [in the rubydoc](https://www.rubydoc.info/gems/wcc-contentful/WCC/Contentful/Configuration) under
362
+ {WCC::Contentful::Configuration}
363
+
364
+
365
+ ## Development
277
366
 
278
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
367
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
279
368
 
280
369
  ## Contributing
281
370
 
@@ -8,6 +8,7 @@ module WCC::Contentful
8
8
  # the jobs configured in {WCC::Contentful::Configuration WCC::Contentful::Configuration#webhook_jobs}
9
9
  class WebhookController < ApplicationController
10
10
  include WCC::Contentful::ServiceAccessors
11
+ include Wisper::Publisher
11
12
 
12
13
  before_action :authorize_contentful
13
14
  protect_from_forgery unless: -> { request.format.json? }
@@ -17,27 +18,17 @@ module WCC::Contentful
17
18
  end
18
19
 
19
20
  def receive
20
- event = params.require('webhook').permit!
21
- event.require('sys').require(%w[id type])
22
- event = event.to_h
23
-
24
- # Immediately update the store, we may update again later using DelayedSyncJob.
25
- store.index(event) if store.respond_to?(:index)
26
-
27
- jobs.each do |job|
28
- begin
29
- if job.respond_to?(:perform_later)
30
- job.perform_later(event)
31
- elsif job.respond_to?(:call)
32
- job.call(event)
33
- else
34
- Rails.logger.error "Misconfigured webhook job: #{job} does not respond to " \
35
- ':perform_later or :call'
36
- end
37
- rescue StandardError => e
38
- Rails.logger.error "Error in job #{job}: #{e}"
39
- end
40
- end
21
+ params.require('sys').require(%w[id type])
22
+ params.permit('sys', 'fields')
23
+ event = params.slice('sys', 'fields').permit!.to_h
24
+
25
+ return unless check_environment(event)
26
+
27
+ # Immediately update the store, we may update again later using SyncEngine::Job.
28
+ store.index(event) if store.index?
29
+
30
+ event = WCC::Contentful::Event.from_raw(event, source: self)
31
+ emit_event(event)
41
32
  end
42
33
 
43
34
  private
@@ -62,9 +53,19 @@ module WCC::Contentful
62
53
  render json: { msg: 'This endpoint only responds to webhooks from Contentful' }, status: 406
63
54
  end
64
55
 
65
- def jobs
66
- jobs = [WCC::Contentful::DelayedSyncJob]
67
- jobs.push(*WCC::Contentful.configuration.webhook_jobs)
56
+ def check_environment(event)
57
+ environment_id = event.dig('sys', 'environment', 'sys', 'id')
58
+ return true unless environment_id.present?
59
+
60
+ configured_environment = WCC::Contentful.configuration.environment.presence || 'master'
61
+ configured_environment.casecmp(environment_id) == 0
62
+ end
63
+
64
+ def emit_event(event)
65
+ type = event.dig('sys', 'type')
66
+ raise ArgumentError, "Unknown event type #{event}" unless type.present?
67
+
68
+ broadcast(type, event)
68
69
  end
69
70
  end
70
71
  end
@@ -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
@@ -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
Binary file
@@ -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