wcc-contentful 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +1 -1
- data/.gitignore +5 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +8 -1
- data/Guardfile +23 -1
- data/app/controllers/wcc/contentful/application_controller.rb +7 -0
- data/app/controllers/wcc/contentful/webhook_controller.rb +30 -0
- data/app/jobs/wcc/contentful/delayed_sync_job.rb +14 -0
- data/bin/rails +14 -0
- data/config/initializers/mime_types.rb +3 -0
- data/config/routes.rb +5 -0
- data/lib/generators/wcc/menu_generator.rb +4 -4
- data/lib/generators/wcc/templates/contentful_shell_wrapper +109 -68
- data/lib/generators/wcc/templates/menu/menu.rb +4 -6
- data/lib/generators/wcc/templates/menu/menu_button.rb +4 -6
- data/lib/generators/wcc/templates/release +2 -2
- data/lib/generators/wcc/templates/wcc_contentful.rb +0 -1
- data/lib/wcc/contentful/client_ext.rb +1 -1
- data/lib/wcc/contentful/configuration.rb +76 -35
- data/lib/wcc/contentful/engine.rb +13 -0
- data/lib/wcc/contentful/exceptions.rb +6 -0
- data/lib/wcc/contentful/graphql/builder.rb +8 -3
- data/lib/wcc/contentful/helpers.rb +6 -0
- data/lib/wcc/contentful/indexed_representation.rb +31 -0
- data/lib/wcc/contentful/model.rb +82 -1
- data/lib/wcc/contentful/model_builder.rb +18 -8
- data/lib/wcc/contentful/model_validators.rb +69 -18
- data/lib/wcc/contentful/simple_client/http_adapter.rb +15 -0
- data/lib/wcc/contentful/simple_client/typhoeus_adapter.rb +30 -0
- data/lib/wcc/contentful/simple_client.rb +67 -18
- data/lib/wcc/contentful/store/base.rb +89 -0
- data/lib/wcc/contentful/store/cdn_adapter.rb +13 -19
- data/lib/wcc/contentful/store/lazy_cache_store.rb +76 -0
- data/lib/wcc/contentful/store/memory_store.rb +17 -23
- data/lib/wcc/contentful/store/postgres_store.rb +32 -19
- data/lib/wcc/contentful/store.rb +62 -0
- data/lib/wcc/contentful/version.rb +1 -1
- data/lib/wcc/contentful.rb +113 -24
- data/wcc-contentful.gemspec +4 -0
- metadata +75 -2
data/lib/wcc/contentful.rb
CHANGED
@@ -15,29 +15,80 @@ require 'wcc/contentful/model_validators'
|
|
15
15
|
require 'wcc/contentful/model'
|
16
16
|
require 'wcc/contentful/model_builder'
|
17
17
|
|
18
|
+
##
|
19
|
+
# The root namespace of the wcc-contentful gem
|
20
|
+
#
|
21
|
+
# Initialize the gem with the `configure` and `init` methods inside your
|
22
|
+
# initializer.
|
18
23
|
module WCC::Contentful
|
19
24
|
class << self
|
25
|
+
##
|
26
|
+
# Gets the current configuration, after calling WCC::Contentful.configure
|
20
27
|
attr_reader :configuration
|
28
|
+
|
29
|
+
##
|
30
|
+
# Gets the sync token that was returned by the Contentful CDN after the most
|
31
|
+
# recent invocation of WCC::Contentful.sync!
|
32
|
+
attr_reader :next_sync_token
|
21
33
|
end
|
22
34
|
|
35
|
+
##
|
36
|
+
# Gets a {CDN Client}[rdoc-ref:WCC::Contentful::SimpleClient::Cdn] which provides
|
37
|
+
# methods for getting and paging raw JSON data from the Contentful CDN.
|
23
38
|
def self.client
|
24
39
|
configuration&.client
|
25
40
|
end
|
26
41
|
|
42
|
+
##
|
43
|
+
# Gets the data-store which executes the queries run against the dynamic
|
44
|
+
# models in the WCC::Contentful::Model namespace.
|
45
|
+
# This is one of the following based on the configured content_delivery method:
|
46
|
+
#
|
47
|
+
# [:direct] an instance of WCC::Contentful::Store::CDNAdapter with a
|
48
|
+
# {CDN Client}[rdoc-ref:WCC::Contentful::SimpleClient::Cdn] to access the CDN.
|
49
|
+
#
|
50
|
+
# [:lazy_sync] an instance of WCC::Contentful::Store::LazyCacheStore
|
51
|
+
# with the configured ActiveSupport::Cache implementation and a
|
52
|
+
# {CDN Client}[rdoc-ref:WCC::Contentful::SimpleClient::Cdn] for when data
|
53
|
+
# cannot be found in the cache.
|
54
|
+
#
|
55
|
+
# [:eager_sync] an instance of the configured Store type, defined by
|
56
|
+
# WCC::Contentful::Configuration.sync_store
|
57
|
+
#
|
58
|
+
def self.store
|
59
|
+
WCC::Contentful::Model.store
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Configures the WCC::Contentful gem to talk to a Contentful space.
|
64
|
+
# This must be called first in your initializer, before #init! or accessing the
|
65
|
+
# client.
|
27
66
|
def self.configure
|
28
67
|
@configuration ||= Configuration.new
|
68
|
+
@next_sync_token = nil
|
29
69
|
yield(configuration)
|
30
70
|
|
31
|
-
configuration.
|
32
|
-
|
33
|
-
raise ArgumentError, 'Please provide "space" ID' unless configuration.space.present?
|
71
|
+
raise ArgumentError, 'Please provide "space"' unless configuration.space.present?
|
34
72
|
raise ArgumentError, 'Please provide "access_token"' unless configuration.access_token.present?
|
35
73
|
|
74
|
+
configuration.configure_contentful
|
75
|
+
|
36
76
|
configuration
|
37
77
|
end
|
38
78
|
|
79
|
+
##
|
80
|
+
# Initializes the WCC::Contentful model-space and backing store.
|
81
|
+
# This populates the WCC::Contentful::Model namespace with Ruby classes
|
82
|
+
# that represent content types in the configured Contentful space.
|
83
|
+
#
|
84
|
+
# These content types can be queried directly:
|
85
|
+
# WCC::Contentful::Model::Page.find('1xab...')
|
86
|
+
# Or you can inherit from them in your own app:
|
87
|
+
# class Page < WCC::Contentful::Model.page; end
|
88
|
+
# Page.find_by(slug: 'about-us')
|
39
89
|
def self.init!
|
40
90
|
raise ArgumentError, 'Please first call WCC:Contentful.configure' if configuration.nil?
|
91
|
+
@mutex ||= Mutex.new
|
41
92
|
|
42
93
|
# we want as much as possible the raw JSON from the API
|
43
94
|
content_types_resp =
|
@@ -54,18 +105,12 @@ module WCC::Contentful
|
|
54
105
|
end
|
55
106
|
@types = indexer.types
|
56
107
|
|
57
|
-
|
58
|
-
|
59
|
-
store = configuration.sync_store
|
108
|
+
store = configuration.store
|
109
|
+
WCC::Contentful::Model.store = store
|
60
110
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
65
|
-
WCC::Contentful::Model.store = store
|
66
|
-
when :direct
|
67
|
-
store = Store::CDNAdapter.new(client)
|
68
|
-
WCC::Contentful::Model.store = store
|
111
|
+
if store.respond_to?(:index)
|
112
|
+
@next_sync_token = store.find("sync:#{configuration.space}:token")
|
113
|
+
sync!
|
69
114
|
end
|
70
115
|
|
71
116
|
WCC::Contentful::ModelBuilder.new(@types).build_models
|
@@ -77,26 +122,70 @@ module WCC::Contentful
|
|
77
122
|
end
|
78
123
|
|
79
124
|
return unless defined?(Rails)
|
80
|
-
|
125
|
+
|
126
|
+
# load up the engine so it gets automatically mounted
|
127
|
+
require 'wcc/contentful/engine'
|
81
128
|
end
|
82
129
|
|
130
|
+
##
|
131
|
+
# Runs validations over the content types returned from the Contentful API.
|
132
|
+
# Validations are configured on predefined model classes using the
|
133
|
+
# `validate_field` directive. Example:
|
134
|
+
# validate_field :top_button, :Link, :optional, link_to: 'menuButton'
|
135
|
+
# This results in a WCC::Contentful::ValidationError
|
136
|
+
# if the 'topButton' field in the 'menu' content type is not a link.
|
83
137
|
def self.validate_models!
|
84
|
-
|
85
|
-
|
86
|
-
WCC::Contentful::Model.all_models.each do |klass|
|
87
|
-
next unless klass.schema
|
88
|
-
ct = klass.try(:content_type) || klass.name.demodulize
|
89
|
-
required(ct).schema(klass.schema)
|
90
|
-
end
|
91
|
-
end
|
138
|
+
# Ensure application models are loaded before we validate
|
139
|
+
Dir[Rails.root.join('app/models/**/*.rb')].each { |file| require file } if defined?(Rails)
|
92
140
|
|
93
141
|
content_types = WCC::Contentful::ModelValidators.transform_content_types_for_validation(
|
94
142
|
@content_types
|
95
143
|
)
|
96
|
-
errors = schema.call(content_types)
|
144
|
+
errors = WCC::Contentful::Model.schema.call(content_types)
|
97
145
|
raise WCC::Contentful::ValidationError, errors.errors unless errors.success?
|
98
146
|
end
|
99
147
|
|
148
|
+
##
|
149
|
+
# Calls the Contentful Sync API and updates the configured store with the returned
|
150
|
+
# data.
|
151
|
+
#
|
152
|
+
# up_to_id: An ID that we know has changed and should come back from the sync.
|
153
|
+
# If we don't find this ID in the sync data, then drop a job to try
|
154
|
+
# the sync again after a few minutes.
|
155
|
+
#
|
156
|
+
def self.sync!(up_to_id: nil)
|
157
|
+
return unless store.respond_to?(:index)
|
158
|
+
|
159
|
+
@mutex.synchronize do
|
160
|
+
sync_resp = client.sync(sync_token: next_sync_token)
|
161
|
+
|
162
|
+
id_found = up_to_id.nil?
|
163
|
+
|
164
|
+
sync_resp.items.each do |item|
|
165
|
+
id = item.dig('sys', 'id')
|
166
|
+
id_found ||= id == up_to_id
|
167
|
+
store.index(item)
|
168
|
+
end
|
169
|
+
store.set("sync:#{configuration.space}:token", sync_resp.next_sync_token)
|
170
|
+
@next_sync_token = sync_resp.next_sync_token
|
171
|
+
|
172
|
+
unless id_found
|
173
|
+
raise SyncError, "ID '#{up_to_id}' did not come back via sync." unless defined?(Rails)
|
174
|
+
sync_later!(up_to_id: up_to_id)
|
175
|
+
end
|
176
|
+
next_sync_token
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Drops an ActiveJob job to invoke WCC::Contentful.sync! after a given amount
|
182
|
+
# of time.
|
183
|
+
def self.sync_later!(up_to_id: nil, wait: 10.minutes)
|
184
|
+
raise NotImplementedError, 'Cannot sync_later! outside of a Rails app' unless defined?(Rails)
|
185
|
+
|
186
|
+
WCC::Contentful::DelayedSyncJob.set(wait: wait).perform_later(up_to_id)
|
187
|
+
end
|
188
|
+
|
100
189
|
# TODO: https://zube.io/watermarkchurch/development/c/2234 init graphql
|
101
190
|
# def self.init_graphql!
|
102
191
|
# require 'wcc/contentful/graphql'
|
data/wcc-contentful.gemspec
CHANGED
@@ -42,14 +42,18 @@ Gem::Specification.new do |spec|
|
|
42
42
|
spec.add_development_dependency 'generator_spec', '~> 0.9.4'
|
43
43
|
spec.add_development_dependency 'rails', '~> 5.1'
|
44
44
|
spec.add_development_dependency 'rspec-rails', '~> 3.7'
|
45
|
+
spec.add_development_dependency 'sqlite3'
|
45
46
|
spec.add_development_dependency 'timecop', '~> 0.9.1'
|
46
47
|
|
47
48
|
# optional dependencies
|
48
49
|
spec.add_development_dependency 'contentful', '>= 0.12.0'
|
49
50
|
spec.add_development_dependency 'contentful-management', '>= 1.10.0'
|
50
51
|
spec.add_development_dependency 'graphql', '~> 1.7'
|
52
|
+
spec.add_development_dependency 'http', '> 1.0', '< 3.0'
|
51
53
|
spec.add_development_dependency 'pg', '~> 1.0'
|
54
|
+
spec.add_development_dependency 'typhoeus', '~> 1.3'
|
52
55
|
|
53
56
|
spec.add_dependency 'activesupport', '>= 5'
|
54
57
|
spec.add_dependency 'dry-validation', '~> 0.11.1'
|
58
|
+
spec.add_dependency 'wcc-base', '~> 0.3.1'
|
55
59
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wcc-contentful
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Watermark Dev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-03-
|
11
|
+
date: 2018-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dotenv
|
@@ -206,6 +206,20 @@ dependencies:
|
|
206
206
|
- - "~>"
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: '3.7'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: sqlite3
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ">="
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
209
223
|
- !ruby/object:Gem::Dependency
|
210
224
|
name: timecop
|
211
225
|
requirement: !ruby/object:Gem::Requirement
|
@@ -262,6 +276,26 @@ dependencies:
|
|
262
276
|
- - "~>"
|
263
277
|
- !ruby/object:Gem::Version
|
264
278
|
version: '1.7'
|
279
|
+
- !ruby/object:Gem::Dependency
|
280
|
+
name: http
|
281
|
+
requirement: !ruby/object:Gem::Requirement
|
282
|
+
requirements:
|
283
|
+
- - ">"
|
284
|
+
- !ruby/object:Gem::Version
|
285
|
+
version: '1.0'
|
286
|
+
- - "<"
|
287
|
+
- !ruby/object:Gem::Version
|
288
|
+
version: '3.0'
|
289
|
+
type: :development
|
290
|
+
prerelease: false
|
291
|
+
version_requirements: !ruby/object:Gem::Requirement
|
292
|
+
requirements:
|
293
|
+
- - ">"
|
294
|
+
- !ruby/object:Gem::Version
|
295
|
+
version: '1.0'
|
296
|
+
- - "<"
|
297
|
+
- !ruby/object:Gem::Version
|
298
|
+
version: '3.0'
|
265
299
|
- !ruby/object:Gem::Dependency
|
266
300
|
name: pg
|
267
301
|
requirement: !ruby/object:Gem::Requirement
|
@@ -276,6 +310,20 @@ dependencies:
|
|
276
310
|
- - "~>"
|
277
311
|
- !ruby/object:Gem::Version
|
278
312
|
version: '1.0'
|
313
|
+
- !ruby/object:Gem::Dependency
|
314
|
+
name: typhoeus
|
315
|
+
requirement: !ruby/object:Gem::Requirement
|
316
|
+
requirements:
|
317
|
+
- - "~>"
|
318
|
+
- !ruby/object:Gem::Version
|
319
|
+
version: '1.3'
|
320
|
+
type: :development
|
321
|
+
prerelease: false
|
322
|
+
version_requirements: !ruby/object:Gem::Requirement
|
323
|
+
requirements:
|
324
|
+
- - "~>"
|
325
|
+
- !ruby/object:Gem::Version
|
326
|
+
version: '1.3'
|
279
327
|
- !ruby/object:Gem::Dependency
|
280
328
|
name: activesupport
|
281
329
|
requirement: !ruby/object:Gem::Requirement
|
@@ -304,6 +352,20 @@ dependencies:
|
|
304
352
|
- - "~>"
|
305
353
|
- !ruby/object:Gem::Version
|
306
354
|
version: 0.11.1
|
355
|
+
- !ruby/object:Gem::Dependency
|
356
|
+
name: wcc-base
|
357
|
+
requirement: !ruby/object:Gem::Requirement
|
358
|
+
requirements:
|
359
|
+
- - "~>"
|
360
|
+
- !ruby/object:Gem::Version
|
361
|
+
version: 0.3.1
|
362
|
+
type: :runtime
|
363
|
+
prerelease: false
|
364
|
+
version_requirements: !ruby/object:Gem::Requirement
|
365
|
+
requirements:
|
366
|
+
- - "~>"
|
367
|
+
- !ruby/object:Gem::Version
|
368
|
+
version: 0.3.1
|
307
369
|
description: Contentful API wrapper library for Watermark apps
|
308
370
|
email:
|
309
371
|
- dev@watermark.org
|
@@ -324,9 +386,15 @@ files:
|
|
324
386
|
- LICENSE.txt
|
325
387
|
- README.md
|
326
388
|
- Rakefile
|
389
|
+
- app/controllers/wcc/contentful/application_controller.rb
|
390
|
+
- app/controllers/wcc/contentful/webhook_controller.rb
|
391
|
+
- app/jobs/wcc/contentful/delayed_sync_job.rb
|
327
392
|
- bin/console
|
393
|
+
- bin/rails
|
328
394
|
- bin/rspec
|
329
395
|
- bin/setup
|
396
|
+
- config/initializers/mime_types.rb
|
397
|
+
- config/routes.rb
|
330
398
|
- lib/generators/wcc/USAGE
|
331
399
|
- lib/generators/wcc/menu_generator.rb
|
332
400
|
- lib/generators/wcc/templates/.keep
|
@@ -341,6 +409,7 @@ files:
|
|
341
409
|
- lib/wcc/contentful/client_ext.rb
|
342
410
|
- lib/wcc/contentful/configuration.rb
|
343
411
|
- lib/wcc/contentful/content_type_indexer.rb
|
412
|
+
- lib/wcc/contentful/engine.rb
|
344
413
|
- lib/wcc/contentful/exceptions.rb
|
345
414
|
- lib/wcc/contentful/graphql.rb
|
346
415
|
- lib/wcc/contentful/graphql/builder.rb
|
@@ -354,9 +423,13 @@ files:
|
|
354
423
|
- lib/wcc/contentful/model_validators.rb
|
355
424
|
- lib/wcc/contentful/model_validators/dsl.rb
|
356
425
|
- lib/wcc/contentful/simple_client.rb
|
426
|
+
- lib/wcc/contentful/simple_client/http_adapter.rb
|
357
427
|
- lib/wcc/contentful/simple_client/response.rb
|
428
|
+
- lib/wcc/contentful/simple_client/typhoeus_adapter.rb
|
358
429
|
- lib/wcc/contentful/store.rb
|
430
|
+
- lib/wcc/contentful/store/base.rb
|
359
431
|
- lib/wcc/contentful/store/cdn_adapter.rb
|
432
|
+
- lib/wcc/contentful/store/lazy_cache_store.rb
|
360
433
|
- lib/wcc/contentful/store/memory_store.rb
|
361
434
|
- lib/wcc/contentful/store/postgres_store.rb
|
362
435
|
- lib/wcc/contentful/version.rb
|