wcc-contentful 0.3.0 → 1.0.0.pre.rc2
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 +5 -5
- data/.rspec +1 -1
- data/Guardfile +43 -0
- data/README.md +161 -11
- data/Rakefile +3 -6
- data/app/controllers/wcc/contentful/webhook_controller.rb +25 -24
- data/app/jobs/wcc/contentful/webhook_enable_job.rb +36 -2
- data/bin/console +4 -3
- data/bin/rails +2 -0
- data/config/routes.rb +1 -1
- data/doc +1 -0
- data/lib/tasks/download_schema.rake +12 -0
- data/lib/wcc/contentful.rb +69 -45
- data/lib/wcc/contentful/active_record_shim.rb +72 -0
- data/lib/wcc/contentful/configuration.rb +177 -46
- data/lib/wcc/contentful/content_type_indexer.rb +14 -0
- data/lib/wcc/contentful/downloads_schema.rb +112 -0
- data/lib/wcc/contentful/engine.rb +33 -14
- data/lib/wcc/contentful/event.rb +171 -0
- data/lib/wcc/contentful/events.rb +41 -0
- data/lib/wcc/contentful/exceptions.rb +3 -33
- data/lib/wcc/contentful/indexed_representation.rb +2 -2
- data/lib/wcc/contentful/instrumentation.rb +31 -0
- data/lib/wcc/contentful/link.rb +28 -0
- data/lib/wcc/contentful/link_visitor.rb +122 -0
- data/lib/wcc/contentful/middleware.rb +7 -0
- data/lib/wcc/contentful/middleware/store.rb +158 -0
- data/lib/wcc/contentful/middleware/store/caching_middleware.rb +114 -0
- data/lib/wcc/contentful/model.rb +37 -4
- data/lib/wcc/contentful/model_builder.rb +1 -0
- data/lib/wcc/contentful/model_methods.rb +40 -15
- data/lib/wcc/contentful/model_singleton_methods.rb +47 -30
- data/lib/wcc/contentful/rake.rb +4 -0
- data/lib/wcc/contentful/rspec.rb +46 -0
- data/lib/wcc/contentful/services.rb +61 -27
- data/lib/wcc/contentful/simple_client.rb +81 -25
- data/lib/wcc/contentful/simple_client/management.rb +43 -10
- data/lib/wcc/contentful/simple_client/response.rb +61 -22
- data/lib/wcc/contentful/simple_client/typhoeus_adapter.rb +17 -17
- data/lib/wcc/contentful/store.rb +7 -66
- data/lib/wcc/contentful/store/README.md +85 -0
- data/lib/wcc/contentful/store/base.rb +34 -119
- data/lib/wcc/contentful/store/cdn_adapter.rb +71 -12
- data/lib/wcc/contentful/store/factory.rb +186 -0
- data/lib/wcc/contentful/store/instrumentation.rb +55 -0
- data/lib/wcc/contentful/store/interface.rb +82 -0
- data/lib/wcc/contentful/store/memory_store.rb +27 -24
- data/lib/wcc/contentful/store/postgres_store.rb +268 -101
- data/lib/wcc/contentful/store/postgres_store/schema_1.sql +73 -0
- data/lib/wcc/contentful/store/postgres_store/schema_2.sql +21 -0
- data/lib/wcc/contentful/store/query.rb +246 -0
- data/lib/wcc/contentful/store/query/interface.rb +63 -0
- data/lib/wcc/contentful/store/rspec_examples.rb +48 -0
- data/lib/wcc/contentful/store/rspec_examples/basic_store.rb +629 -0
- data/lib/wcc/contentful/store/rspec_examples/include_param.rb +283 -0
- data/lib/wcc/contentful/store/rspec_examples/nested_queries.rb +342 -0
- data/lib/wcc/contentful/sync_engine.rb +181 -0
- data/lib/wcc/contentful/test.rb +7 -0
- data/lib/wcc/contentful/test/attributes.rb +56 -0
- data/lib/wcc/contentful/test/double.rb +76 -0
- data/lib/wcc/contentful/test/factory.rb +101 -0
- data/lib/wcc/contentful/version.rb +1 -1
- data/wcc-contentful.gemspec +28 -14
- metadata +248 -152
- data/.circleci/config.yml +0 -51
- data/.gitignore +0 -26
- data/.rubocop.yml +0 -242
- data/.rubocop_todo.yml +0 -19
- data/.travis.yml +0 -5
- data/CHANGELOG.md +0 -180
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -8
- data/LICENSE.txt +0 -21
- data/app/jobs/wcc/contentful/delayed_sync_job.rb +0 -63
- data/lib/generators/wcc/USAGE +0 -24
- data/lib/generators/wcc/model_generator.rb +0 -90
- data/lib/generators/wcc/templates/.keep +0 -0
- data/lib/generators/wcc/templates/Procfile +0 -3
- data/lib/generators/wcc/templates/contentful_shell_wrapper +0 -385
- data/lib/generators/wcc/templates/menu/generated_add_menus.ts +0 -192
- data/lib/generators/wcc/templates/menu/models/menu.rb +0 -23
- data/lib/generators/wcc/templates/menu/models/menu_button.rb +0 -23
- data/lib/generators/wcc/templates/page/generated_add_pages.ts +0 -50
- data/lib/generators/wcc/templates/page/models/page.rb +0 -23
- data/lib/generators/wcc/templates/release +0 -9
- data/lib/generators/wcc/templates/wcc_contentful.rb +0 -17
- data/lib/wcc/contentful/client_ext.rb +0 -28
- data/lib/wcc/contentful/graphql.rb +0 -14
- data/lib/wcc/contentful/graphql/builder.rb +0 -177
- data/lib/wcc/contentful/graphql/types.rb +0 -54
- data/lib/wcc/contentful/model/dropdown_menu.rb +0 -7
- data/lib/wcc/contentful/model/menu.rb +0 -6
- data/lib/wcc/contentful/model/menu_button.rb +0 -16
- data/lib/wcc/contentful/model/page.rb +0 -8
- data/lib/wcc/contentful/model/redirect.rb +0 -19
- data/lib/wcc/contentful/model_validators.rb +0 -121
- data/lib/wcc/contentful/model_validators/dsl.rb +0 -166
- data/lib/wcc/contentful/simple_client/http_adapter.rb +0 -24
- data/lib/wcc/contentful/store/lazy_cache_store.rb +0 -161
@@ -1,192 +0,0 @@
|
|
1
|
-
|
2
|
-
import Migration from 'contentful-migration-cli'
|
3
|
-
|
4
|
-
export = function (migration: Migration) {
|
5
|
-
const menu = migration.createContentType('menu', {
|
6
|
-
displayField: 'name',
|
7
|
-
name: 'Menu',
|
8
|
-
description: 'A Menu contains a number of Menu Buttons or other Menus, ' +
|
9
|
-
'which will be rendered as drop-downs.'
|
10
|
-
})
|
11
|
-
|
12
|
-
menu.createField('name', {
|
13
|
-
name: 'Menu Name',
|
14
|
-
type: 'Symbol',
|
15
|
-
localized: false,
|
16
|
-
required: true,
|
17
|
-
validations: [],
|
18
|
-
disabled: false,
|
19
|
-
omitted: false
|
20
|
-
})
|
21
|
-
|
22
|
-
menu.createField('items', {
|
23
|
-
name: 'Items',
|
24
|
-
type: 'Array',
|
25
|
-
localized: false,
|
26
|
-
required: false,
|
27
|
-
validations: [],
|
28
|
-
disabled: false,
|
29
|
-
omitted: false,
|
30
|
-
items:
|
31
|
-
{
|
32
|
-
type: 'Link',
|
33
|
-
validations:
|
34
|
-
[{
|
35
|
-
linkContentType:
|
36
|
-
['dropdownMenu',
|
37
|
-
'menuButton'],
|
38
|
-
message: 'The items must be either buttons or drop-down menus.'
|
39
|
-
}],
|
40
|
-
linkType: 'Entry'
|
41
|
-
}
|
42
|
-
})
|
43
|
-
|
44
|
-
menu.changeEditorInterface('name', 'singleLine')
|
45
|
-
menu.changeEditorInterface('items', 'entryLinksEditor')
|
46
|
-
|
47
|
-
const menubutton = migration.createContentType('menuButton', {
|
48
|
-
displayField: 'text',
|
49
|
-
name: 'Menu Button',
|
50
|
-
description: 'A Menu Button is a clickable button that goes on a Menu. It has a link to a Page or a URL.'
|
51
|
-
})
|
52
|
-
|
53
|
-
menubutton.createField('text', {
|
54
|
-
name: 'Text',
|
55
|
-
type: 'Symbol',
|
56
|
-
localized: false,
|
57
|
-
required: true,
|
58
|
-
validations:
|
59
|
-
[{
|
60
|
-
size:
|
61
|
-
{
|
62
|
-
min: 1,
|
63
|
-
max: 60
|
64
|
-
},
|
65
|
-
message: 'A Menu Button should have a very short text field - ideally a single word. Please limit the text to 60 characters.'
|
66
|
-
}],
|
67
|
-
disabled: false,
|
68
|
-
omitted: false
|
69
|
-
})
|
70
|
-
|
71
|
-
menubutton.createField('icon', {
|
72
|
-
name: 'Icon',
|
73
|
-
type: 'Link',
|
74
|
-
localized: false,
|
75
|
-
required: false,
|
76
|
-
validations: [{ linkMimetypeGroup: ['image'] }],
|
77
|
-
disabled: false,
|
78
|
-
omitted: false,
|
79
|
-
linkType: 'Asset'
|
80
|
-
})
|
81
|
-
|
82
|
-
menubutton.createField('externalLink', {
|
83
|
-
name: 'External Link',
|
84
|
-
type: 'Symbol',
|
85
|
-
localized: false,
|
86
|
-
required: false,
|
87
|
-
validations:
|
88
|
-
[{
|
89
|
-
regexp: { pattern: '^(\\w+):(\\/\\/)?(\\w+:{0,1}\\w*@)?((\\w+\\.)+[^\\s\\/#]+)(:[0-9]+)?(\\/|(\\/|\\#)([\\w#!:.?+=&%@!\\-\\/]+))?$|^(\\/|(\\/|\\#)([\\w#!:.?+=&%@!\\-\\/]+))$' },
|
90
|
-
message: 'The external link must be a URL like \'https://www.watermark.org/\', a mailto url like \'mailto:info@watermark.org\', or a relative URL like \'#location-on-page\''
|
91
|
-
}],
|
92
|
-
disabled: false,
|
93
|
-
omitted: false
|
94
|
-
})
|
95
|
-
|
96
|
-
menubutton.createField('link', {
|
97
|
-
name: 'Page Link',
|
98
|
-
type: 'Link',
|
99
|
-
localized: false,
|
100
|
-
required: false,
|
101
|
-
validations:
|
102
|
-
[{
|
103
|
-
linkContentType: ['page'],
|
104
|
-
message: 'The Page Link must be a link to a Page which has a slug.'
|
105
|
-
}],
|
106
|
-
disabled: false,
|
107
|
-
omitted: false,
|
108
|
-
linkType: 'Entry'
|
109
|
-
})
|
110
|
-
|
111
|
-
menubutton.createField('ionIcon', {
|
112
|
-
name: 'Ion Icon',
|
113
|
-
type: 'Symbol',
|
114
|
-
localized: false,
|
115
|
-
required: false,
|
116
|
-
validations:
|
117
|
-
[{
|
118
|
-
regexp: { pattern: '^ion-[a-z\\-]+$' },
|
119
|
-
message: 'The icon should start with \'ion-\', like \'ion-arrow-down-c\'. See http://ionicons.com/'
|
120
|
-
}],
|
121
|
-
disabled: false,
|
122
|
-
omitted: false
|
123
|
-
})
|
124
|
-
|
125
|
-
menubutton.createField('style', {
|
126
|
-
name: 'Style',
|
127
|
-
type: 'Symbol',
|
128
|
-
localized: false,
|
129
|
-
required: false,
|
130
|
-
validations: [{ in: ['oval-border'] }],
|
131
|
-
disabled: false,
|
132
|
-
omitted: false
|
133
|
-
})
|
134
|
-
|
135
|
-
menubutton.changeEditorInterface('text', 'singleLine')
|
136
|
-
menubutton.changeEditorInterface('icon', 'assetLinkEditor')
|
137
|
-
menubutton.changeEditorInterface('externalLink', 'singleLine')
|
138
|
-
menubutton.changeEditorInterface('link', 'entryLinkEditor')
|
139
|
-
menubutton.changeEditorInterface('ionIcon', 'singleLine')
|
140
|
-
menubutton.changeEditorInterface('style', 'dropdown')
|
141
|
-
|
142
|
-
const dropdownmenu = migration.createContentType('dropdownMenu', {
|
143
|
-
displayField: 'name',
|
144
|
-
name: 'Dropdown Menu',
|
145
|
-
description: 'A Dropdown Menu can be attached to a main menu to show additional menu items on click.'
|
146
|
-
})
|
147
|
-
|
148
|
-
dropdownmenu.createField('name', {
|
149
|
-
name: 'Menu Name',
|
150
|
-
type: 'Symbol',
|
151
|
-
localized: false,
|
152
|
-
required: false,
|
153
|
-
validations: [],
|
154
|
-
disabled: false,
|
155
|
-
omitted: false
|
156
|
-
})
|
157
|
-
|
158
|
-
dropdownmenu.createField('label', {
|
159
|
-
name: 'Menu Label',
|
160
|
-
type: 'Link',
|
161
|
-
localized: false,
|
162
|
-
required: false,
|
163
|
-
validations: [{ linkContentType: ['menuButton'] }],
|
164
|
-
disabled: false,
|
165
|
-
omitted: false,
|
166
|
-
linkType: 'Entry'
|
167
|
-
})
|
168
|
-
|
169
|
-
dropdownmenu.createField('items', {
|
170
|
-
name: 'Items',
|
171
|
-
type: 'Array',
|
172
|
-
localized: false,
|
173
|
-
required: false,
|
174
|
-
validations: [],
|
175
|
-
disabled: false,
|
176
|
-
omitted: false,
|
177
|
-
items:
|
178
|
-
{
|
179
|
-
type: 'Link',
|
180
|
-
validations:
|
181
|
-
[{
|
182
|
-
linkContentType:
|
183
|
-
['menuButton']
|
184
|
-
}],
|
185
|
-
linkType: 'Entry'
|
186
|
-
}
|
187
|
-
})
|
188
|
-
|
189
|
-
dropdownmenu.changeEditorInterface('name', 'singleLine')
|
190
|
-
dropdownmenu.changeEditorInterface('label', 'entryLinkEditor')
|
191
|
-
dropdownmenu.changeEditorInterface('items', 'entryLinksEditor')
|
192
|
-
}
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# This model represents the 'menu' content type in Contentful. Any linked
|
4
|
-
# entries of the 'menu' content type will be resolved as instances of this class.
|
5
|
-
# It exposes #find, #find_by, and #find_all methods to query Contentful.
|
6
|
-
class Menu < WCC::Contentful::Model::Menu
|
7
|
-
# Add custom validations to ensure that app-specific properties exist:
|
8
|
-
# validate_field :foo, :String, :required
|
9
|
-
# validate_field :bar_links, :Array, link_to: %w[bar baz]
|
10
|
-
|
11
|
-
# Override functionality or add utilities
|
12
|
-
#
|
13
|
-
# # Example: override equality
|
14
|
-
# def ===(other)
|
15
|
-
# ...
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# # Example: override "name" attribute to always be camelized.
|
19
|
-
# # `@name` is populated by the gem in the initializer.
|
20
|
-
# def name
|
21
|
-
# @name_camelized ||= @name.camelize(true)
|
22
|
-
# end
|
23
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# This model represents the 'menuButton' content type in Contentful. Any linked
|
4
|
-
# entries of the 'menuButton' content type will be resolved as instances of this class.
|
5
|
-
# It exposes #find, #find_by, and #find_all methods to query Contentful.
|
6
|
-
class MenuButton < WCC::Contentful::Model::MenuButton
|
7
|
-
# Add custom validations to ensure that app-specific properties exist:
|
8
|
-
# validate_field :foo, :String, :required
|
9
|
-
# validate_field :bar_links, :Array, link_to: %w[bar baz]
|
10
|
-
|
11
|
-
# Override functionality or add utilities
|
12
|
-
#
|
13
|
-
# # Example: override equality
|
14
|
-
# def ===(other)
|
15
|
-
# ...
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# # Example: override "text" attribute to always be camelized.
|
19
|
-
# # `@text` is populated by the gem in the initializer.
|
20
|
-
# def text
|
21
|
-
# @text_camelized ||= @text.camelize(true)
|
22
|
-
# end
|
23
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
import Migration from 'contentful-migration-cli'
|
2
|
-
|
3
|
-
export = function (migration: Migration) {
|
4
|
-
const page = migration.createContentType('page')
|
5
|
-
.name('Page')
|
6
|
-
.description('A page describes a collection of sections that correspond' +
|
7
|
-
'to a URL slug')
|
8
|
-
.displayField('title')
|
9
|
-
|
10
|
-
page.createField('title')
|
11
|
-
.name('Title')
|
12
|
-
.type('Symbol')
|
13
|
-
.required(true)
|
14
|
-
|
15
|
-
page.createField('slug')
|
16
|
-
.name('Slug')
|
17
|
-
.type('Symbol')
|
18
|
-
.required(true)
|
19
|
-
.validations([
|
20
|
-
{
|
21
|
-
unique: true
|
22
|
-
},
|
23
|
-
{
|
24
|
-
regexp: { pattern: "(\\/|\\/([\w#!:.?+=&%@!\\-\\/]))?$" },
|
25
|
-
message: "The slug must look like the path part of a URL and begin with a forward slash, example: '/my-page-slug'"
|
26
|
-
}
|
27
|
-
])
|
28
|
-
|
29
|
-
page.createField('sections')
|
30
|
-
.name('Sections')
|
31
|
-
.type('Array')
|
32
|
-
.items({
|
33
|
-
type: 'Link',
|
34
|
-
linkType: 'Entry'
|
35
|
-
})
|
36
|
-
|
37
|
-
page.createField('subpages')
|
38
|
-
.name('Subpages')
|
39
|
-
.type('Array')
|
40
|
-
.items({
|
41
|
-
type: 'Link',
|
42
|
-
linkType: 'Entry',
|
43
|
-
validations: [
|
44
|
-
{
|
45
|
-
linkContentType: [ 'page' ]
|
46
|
-
}
|
47
|
-
]
|
48
|
-
})
|
49
|
-
|
50
|
-
}
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# This model represents the 'page' content type in Contentful. Any linked
|
4
|
-
# entries of the 'page' content type will be resolved as instances of this class.
|
5
|
-
# It exposes #find, #find_by, and #find_all methods to query Contentful.
|
6
|
-
class Page < WCC::Contentful::Model::Page
|
7
|
-
# Add custom validations to ensure that app-specific properties exist:
|
8
|
-
# validate_field :foo, :String, :required
|
9
|
-
# validate_field :bar_links, :Array, link_to: %w[bar baz]
|
10
|
-
|
11
|
-
# Override functionality or add utilities
|
12
|
-
#
|
13
|
-
# # Example: override equality
|
14
|
-
# def ===(other)
|
15
|
-
# ...
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# # Example: override "title" attribute to always be titlecase.
|
19
|
-
# # `@title` is populated by the gem in the initializer.
|
20
|
-
# def title
|
21
|
-
# @title_titlecased ||= @title.titlecase
|
22
|
-
# end
|
23
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
|
2
|
-
WCC::Contentful.configure do |config|
|
3
|
-
# Required
|
4
|
-
config.access_token = # Contentful CDN access token
|
5
|
-
config.space = # Contentful Space ID
|
6
|
-
|
7
|
-
# Optional
|
8
|
-
config.management_token = # Contentful API management token
|
9
|
-
config.default_locale = # Set default locale, if left blank this is 'en-US'
|
10
|
-
config.content_delivery = # :direct, :eager_sync, or :lazy_sync
|
11
|
-
end
|
12
|
-
|
13
|
-
# Download content types, build models, and sync content
|
14
|
-
WCC::Contentful.init!
|
15
|
-
|
16
|
-
# Validate that models conform to a defined specification
|
17
|
-
WCC::Contentful.validate_models! unless defined?(Rails) && Rails.env.development?
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Contentful::Client
|
4
|
-
class << self
|
5
|
-
alias_method :old_get_http, :get_http
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.adapter
|
9
|
-
@adapter ||=
|
10
|
-
WCC::Contentful::SimpleClient.load_adapter(WCC::Contentful.configuration.http_adapter) ||
|
11
|
-
->(url, query, headers, proxy) { old_get_http(url, query, headers, proxy) }
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.get_http(url, query, headers = {}, proxy = {})
|
15
|
-
if environment = WCC::Contentful.configuration.environment
|
16
|
-
url = rewrite_to_environment(url, environment)
|
17
|
-
end
|
18
|
-
|
19
|
-
adapter.call(url, query, headers, proxy)
|
20
|
-
end
|
21
|
-
|
22
|
-
REWRITE_REGEXP = /^(https?\:\/\/(?:\w+)\.contentful\.com\/spaces\/[^\/]+\/)(?!environments)(.+)$/
|
23
|
-
def self.rewrite_to_environment(url, environment)
|
24
|
-
return url unless m = REWRITE_REGEXP.match(url)
|
25
|
-
|
26
|
-
File.join(m[1], 'environments', environment, m[2])
|
27
|
-
end
|
28
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
gem 'graphql', '~> 1.7'
|
4
|
-
require 'graphql'
|
5
|
-
|
6
|
-
module WCC::Contentful
|
7
|
-
# This module builds a GraphQL schema out of our IndexedRepresentation.
|
8
|
-
# It is currently unused and not hooked up in the WCC::Contentful.init! method.
|
9
|
-
# TODO: https://zube.io/watermarkchurch/development/c/2234 hook it up
|
10
|
-
module Graphql
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
require_relative 'graphql/builder'
|
@@ -1,177 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'graphql'
|
4
|
-
|
5
|
-
require_relative 'types'
|
6
|
-
|
7
|
-
module WCC::Contentful::Graphql
|
8
|
-
class Builder
|
9
|
-
attr_reader :schema_types
|
10
|
-
|
11
|
-
def initialize(types, store)
|
12
|
-
@types = types
|
13
|
-
@store = store
|
14
|
-
end
|
15
|
-
|
16
|
-
def build_schema
|
17
|
-
@schema_types = build_schema_types
|
18
|
-
|
19
|
-
root_query_type = build_root_query(@schema_types)
|
20
|
-
|
21
|
-
builder = self
|
22
|
-
GraphQL::Schema.define do
|
23
|
-
query root_query_type
|
24
|
-
|
25
|
-
resolve_type ->(_type, obj, _ctx) {
|
26
|
-
content_type = WCC::Contentful::Helpers.content_type_from_raw(obj)
|
27
|
-
builder.schema_types[content_type]
|
28
|
-
}
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def build_root_query(schema_types)
|
35
|
-
store = @store
|
36
|
-
|
37
|
-
GraphQL::ObjectType.define do
|
38
|
-
name 'Query'
|
39
|
-
description 'The query root of this schema'
|
40
|
-
|
41
|
-
schema_types.each do |content_type, schema_type|
|
42
|
-
field schema_type.name.to_sym do
|
43
|
-
type schema_type
|
44
|
-
argument :id, types.ID
|
45
|
-
description "Find a #{schema_type.name} by ID"
|
46
|
-
|
47
|
-
resolve ->(_obj, args, _ctx) {
|
48
|
-
if args['id'].nil?
|
49
|
-
store.find_by(content_type: content_type)
|
50
|
-
else
|
51
|
-
store.find(args['id'])
|
52
|
-
end
|
53
|
-
}
|
54
|
-
end
|
55
|
-
|
56
|
-
field "all#{schema_type.name}".to_sym do
|
57
|
-
type schema_type.to_list_type
|
58
|
-
argument :filter, Types::FilterType
|
59
|
-
|
60
|
-
resolve ->(_obj, args, ctx) {
|
61
|
-
relation = store.find_all(content_type: content_type)
|
62
|
-
# TODO: improve this POC
|
63
|
-
if args[:filter]
|
64
|
-
filter = {}
|
65
|
-
filter[args[:filter]['field']] = { eq: args[:filter][:eq] }
|
66
|
-
relation = relation.apply(filter, ctx)
|
67
|
-
end
|
68
|
-
relation.result
|
69
|
-
}
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def build_schema_types
|
76
|
-
@types.each_with_object({}) do |(k, v), h|
|
77
|
-
h[k] = build_schema_type(v)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def build_schema_type(typedef)
|
82
|
-
store = @store
|
83
|
-
builder = self
|
84
|
-
content_type = typedef.content_type
|
85
|
-
|
86
|
-
GraphQL::ObjectType.define do
|
87
|
-
name(typedef.name)
|
88
|
-
|
89
|
-
description("Generated from content type #{content_type}")
|
90
|
-
|
91
|
-
field :id, !types.ID do
|
92
|
-
resolve ->(obj, _args, _ctx) {
|
93
|
-
obj.dig('sys', 'id')
|
94
|
-
}
|
95
|
-
end
|
96
|
-
|
97
|
-
field :_content_type, !types.String do
|
98
|
-
resolve ->(_, _, _) {
|
99
|
-
content_type
|
100
|
-
}
|
101
|
-
end
|
102
|
-
|
103
|
-
# Make a field for each column:
|
104
|
-
typedef.fields.each_value do |f|
|
105
|
-
case f.type
|
106
|
-
when :Asset
|
107
|
-
field(f.name.to_sym, -> {
|
108
|
-
type = builder.schema_types['Asset']
|
109
|
-
type = type.to_list_type if f.array
|
110
|
-
type
|
111
|
-
}) do
|
112
|
-
resolve ->(obj, _args, ctx) {
|
113
|
-
links = obj.dig('fields', f.name, ctx[:locale] || 'en-US')
|
114
|
-
return if links.nil?
|
115
|
-
|
116
|
-
if links.is_a? Array
|
117
|
-
links.reject(&:nil?).map { |l| store.find(l.dig('sys', 'id')) }
|
118
|
-
else
|
119
|
-
store.find(links.dig('sys', 'id'))
|
120
|
-
end
|
121
|
-
}
|
122
|
-
end
|
123
|
-
when :Link
|
124
|
-
field(f.name.to_sym, -> {
|
125
|
-
type =
|
126
|
-
if f.link_types.nil? || f.link_types.empty?
|
127
|
-
builder.schema_types['AnyContentful'] ||=
|
128
|
-
Types::BuildUnionType.call(builder.schema_types, 'AnyContentful')
|
129
|
-
elsif f.link_types.length == 1
|
130
|
-
builder.schema_types[f.link_types.first]
|
131
|
-
else
|
132
|
-
from_types = builder.schema_types.select { |key| f.link_types.include?(key) }
|
133
|
-
name = "#{typedef.name}_#{f.name}"
|
134
|
-
builder.schema_types[name] ||= Types::BuildUnionType.call(from_types, name)
|
135
|
-
end
|
136
|
-
type = type.to_list_type if f.array
|
137
|
-
type
|
138
|
-
}) do
|
139
|
-
resolve ->(obj, _args, ctx) {
|
140
|
-
links = obj.dig('fields', f.name, ctx[:locale] || 'en-US')
|
141
|
-
return if links.nil?
|
142
|
-
|
143
|
-
if links.is_a? Array
|
144
|
-
links.reject(&:nil?).map { |l| store.find(l.dig('sys', 'id')) }
|
145
|
-
else
|
146
|
-
store.find(links.dig('sys', 'id'))
|
147
|
-
end
|
148
|
-
}
|
149
|
-
end
|
150
|
-
else
|
151
|
-
type =
|
152
|
-
case f.type
|
153
|
-
when :DateTime
|
154
|
-
Types::DateTimeType
|
155
|
-
when :Coordinates
|
156
|
-
Types::CoordinatesType
|
157
|
-
when :Json
|
158
|
-
Types::HashType
|
159
|
-
else
|
160
|
-
types.public_send(f.type)
|
161
|
-
end
|
162
|
-
type = type.to_list_type if f.array
|
163
|
-
field(f.name.to_sym, type) do
|
164
|
-
resolve ->(obj, _args, ctx) {
|
165
|
-
if obj.is_a? Array
|
166
|
-
obj.map { |o| o.dig('fields', f.name, ctx[:locale] || 'en-US') }
|
167
|
-
else
|
168
|
-
obj.dig('fields', f.name, ctx[:locale] || 'en-US')
|
169
|
-
end
|
170
|
-
}
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|