contentful_bootstrap 1.6.0 → 2.0.2
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/.rubocop.yml +26 -0
- data/.rubocop_todo.yml +123 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +25 -0
- data/Gemfile +1 -0
- data/Guardfile +5 -0
- data/README.md +40 -14
- data/Rakefile +7 -0
- data/bin/contentful_bootstrap +33 -22
- data/contentful_bootstrap.gemspec +7 -0
- data/lib/contentful/bootstrap.rb +7 -5
- data/lib/contentful/bootstrap/command_runner.rb +45 -0
- data/lib/contentful/bootstrap/commands.rb +3 -168
- data/lib/contentful/bootstrap/commands/base.rb +66 -0
- data/lib/contentful/bootstrap/commands/create_space.rb +111 -0
- data/lib/contentful/bootstrap/commands/generate_json.rb +41 -0
- data/lib/contentful/bootstrap/commands/generate_token.rb +52 -0
- data/lib/contentful/bootstrap/constants.rb +2 -2
- data/lib/contentful/bootstrap/generator.rb +94 -0
- data/lib/contentful/bootstrap/server.rb +25 -17
- data/lib/contentful/bootstrap/support.rb +3 -2
- data/lib/contentful/bootstrap/templates.rb +4 -4
- data/lib/contentful/bootstrap/templates/base.rb +51 -30
- data/lib/contentful/bootstrap/templates/blog.rb +33 -33
- data/lib/contentful/bootstrap/templates/catalogue.rb +103 -103
- data/lib/contentful/bootstrap/templates/gallery.rb +55 -56
- data/lib/contentful/bootstrap/templates/json_template.rb +22 -16
- data/lib/contentful/bootstrap/templates/links.rb +2 -2
- data/lib/contentful/bootstrap/templates/links/asset.rb +2 -2
- data/lib/contentful/bootstrap/templates/links/base.rb +3 -3
- data/lib/contentful/bootstrap/templates/links/entry.rb +2 -2
- data/lib/contentful/bootstrap/token.rb +32 -31
- data/lib/contentful/bootstrap/version.rb +1 -1
- data/spec/contentful/bootstrap/command_runner_spec.rb +111 -0
- data/spec/contentful/bootstrap/commands/base_spec.rb +102 -0
- data/spec/contentful/bootstrap/commands/create_space_spec.rb +72 -0
- data/spec/contentful/bootstrap/commands/generate_json_spec.rb +64 -0
- data/spec/contentful/bootstrap/commands/generate_token_spec.rb +82 -0
- data/spec/contentful/bootstrap/generator_spec.rb +15 -0
- data/spec/contentful/bootstrap/server_spec.rb +154 -0
- data/spec/contentful/bootstrap/support_spec.rb +27 -0
- data/spec/contentful/bootstrap/templates/base_spec.rb +34 -0
- data/spec/contentful/bootstrap/templates/blog_spec.rb +32 -0
- data/spec/contentful/bootstrap/templates/catalogue_spec.rb +40 -0
- data/spec/contentful/bootstrap/templates/gallery_spec.rb +40 -0
- data/spec/contentful/bootstrap/templates/json_template_spec.rb +52 -0
- data/spec/contentful/bootstrap/templates/links/asset_spec.rb +23 -0
- data/spec/contentful/bootstrap/templates/links/base_spec.rb +31 -0
- data/spec/contentful/bootstrap/templates/links/entry_spec.rb +23 -0
- data/spec/contentful/bootstrap/token_spec.rb +143 -0
- data/spec/fixtures/ini_fixtures/contentfulrc.ini +2 -0
- data/spec/fixtures/ini_fixtures/no_global.ini +2 -0
- data/spec/fixtures/ini_fixtures/no_token.ini +1 -0
- data/spec/fixtures/ini_fixtures/sections.ini +5 -0
- data/spec/fixtures/json_fixtures/issue_22.json +77 -0
- data/spec/fixtures/json_fixtures/simple.json +34 -0
- data/spec/fixtures/json_fixtures/wl1z0pal05vy.json +437 -0
- data/spec/fixtures/vcr_fixtures/generate_json.yml +384 -0
- data/spec/fixtures/vcr_fixtures/issue_22.yml +2488 -0
- data/spec/spec_helper.rb +51 -0
- metadata +167 -4
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'contentful/management'
|
2
|
+
require 'contentful/management/error'
|
3
|
+
require 'contentful/management/request'
|
4
|
+
require 'contentful/bootstrap/version'
|
5
|
+
require 'contentful/bootstrap/commands/base'
|
6
|
+
|
7
|
+
module Contentful
|
8
|
+
module Bootstrap
|
9
|
+
module Commands
|
10
|
+
class GenerateToken < Base
|
11
|
+
attr_reader :token_name
|
12
|
+
def initialize(token, space, token_name = 'Bootstrap Token', trigger_oauth = true)
|
13
|
+
super(token, space, trigger_oauth)
|
14
|
+
@token_name = token_name
|
15
|
+
@actual_space = space unless space.is_a?(String)
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
puts 'Creating Delivery API Token'
|
20
|
+
|
21
|
+
fetch_space
|
22
|
+
|
23
|
+
access_token = fetch_access_token
|
24
|
+
|
25
|
+
puts "Token '#{token_name}' created! - '#{access_token}'"
|
26
|
+
print 'Do you want to write the Delivery Token to your configuration file? (Y/n): '
|
27
|
+
unless gets.chomp.downcase == 'n'
|
28
|
+
@token.write_access_token(@actual_space.name, access_token)
|
29
|
+
@token.write_space_id(@actual_space.name, @actual_space.id)
|
30
|
+
end
|
31
|
+
|
32
|
+
access_token
|
33
|
+
end
|
34
|
+
|
35
|
+
def fetch_space
|
36
|
+
@actual_space ||= Contentful::Management::Space.find(@space)
|
37
|
+
end
|
38
|
+
|
39
|
+
def fetch_access_token
|
40
|
+
response = Contentful::Management::Request.new(
|
41
|
+
"/#{@actual_space.id}/api_keys",
|
42
|
+
'name' => token_name,
|
43
|
+
'description' => "Created with 'contentful_bootstrap.rb v#{Contentful::Bootstrap::VERSION}'"
|
44
|
+
).post
|
45
|
+
fail response if response.object.is_a?(Contentful::Management::Error)
|
46
|
+
|
47
|
+
response.object['accessToken']
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Contentful
|
2
2
|
module Bootstrap
|
3
3
|
module Constants
|
4
|
-
OAUTH_APP_ID =
|
5
|
-
OAUTH_CALLBACK_URL =
|
4
|
+
OAUTH_APP_ID = 'a19770bea126e6d596d8599ff42e14173409e3e252895b78d0cb289c10586276'.freeze
|
5
|
+
OAUTH_CALLBACK_URL = 'http://localhost:5123/oauth_callback'.freeze
|
6
6
|
end
|
7
7
|
end
|
8
8
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'contentful'
|
2
|
+
require 'inifile'
|
3
|
+
require 'json'
|
4
|
+
require 'zlib'
|
5
|
+
|
6
|
+
module Contentful
|
7
|
+
module Bootstrap
|
8
|
+
class Generator
|
9
|
+
def initialize(space_id, access_token)
|
10
|
+
@client = Contentful::Client.new(access_token: access_token, space: space_id)
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate_json
|
14
|
+
template = {}
|
15
|
+
template['content_types'] = content_types
|
16
|
+
template['assets'] = assets
|
17
|
+
template['entries'] = entries
|
18
|
+
JSON.pretty_generate(template)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def assets
|
24
|
+
proccessed_assets = @client.assets.map do |asset|
|
25
|
+
result = { 'id' => asset.sys[:id], 'title' => asset.title }
|
26
|
+
result['file'] = {
|
27
|
+
'filename' => ::File.basename(asset.file.file_name, '.*'),
|
28
|
+
'url' => "https:#{asset.file.url}"
|
29
|
+
}
|
30
|
+
result
|
31
|
+
end
|
32
|
+
proccessed_assets.sort_by { |item| item['id'] }
|
33
|
+
end
|
34
|
+
|
35
|
+
def content_types
|
36
|
+
proccessed_content_types = @client.content_types.map do |type|
|
37
|
+
result = { 'id' => type.sys[:id], 'name' => type.name }
|
38
|
+
result['display_field'] = type.display_field unless type.display_field.nil?
|
39
|
+
|
40
|
+
result['fields'] = type.fields.map do |field|
|
41
|
+
map_field_properties(field.properties)
|
42
|
+
end
|
43
|
+
|
44
|
+
result
|
45
|
+
end
|
46
|
+
proccessed_content_types.sort_by { |item| item['id'] }
|
47
|
+
end
|
48
|
+
|
49
|
+
def entries
|
50
|
+
entries = {}
|
51
|
+
|
52
|
+
@client.entries.each do |entry|
|
53
|
+
result = { 'id' => entry.sys[:id] }
|
54
|
+
|
55
|
+
entry.fields.each do |key, value|
|
56
|
+
value = map_field(value)
|
57
|
+
result[key] = value unless value.nil?
|
58
|
+
end
|
59
|
+
|
60
|
+
ct_id = entry.content_type.sys[:id]
|
61
|
+
entries[ct_id] = [] if entries[ct_id].nil?
|
62
|
+
entries[ct_id] << result
|
63
|
+
end
|
64
|
+
|
65
|
+
entries
|
66
|
+
end
|
67
|
+
|
68
|
+
def map_field(value)
|
69
|
+
return value.map { |v| map_field(v) } if value.is_a? ::Array
|
70
|
+
|
71
|
+
if value.is_a?(Contentful::Asset) || value.is_a?(Contentful::Entry)
|
72
|
+
return {
|
73
|
+
'link_type' => value.class.name.split('::').last,
|
74
|
+
'id' => value.sys[:id]
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
return nil if value.is_a?(Contentful::Link)
|
79
|
+
|
80
|
+
value
|
81
|
+
end
|
82
|
+
|
83
|
+
def map_field_properties(properties)
|
84
|
+
properties['link_type'] = properties.delete(:linkType) unless properties[:linkType].nil?
|
85
|
+
|
86
|
+
items = properties[:items]
|
87
|
+
properties[:items] = map_field_properties(items.properties) unless items.nil?
|
88
|
+
|
89
|
+
properties.delete_if { |k, v| v.nil? || [:required, :localized].include?(k) }
|
90
|
+
properties
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
require 'thread'
|
2
|
+
require 'webrick'
|
3
|
+
require 'launchy'
|
4
|
+
require 'contentful/bootstrap/constants'
|
5
|
+
require 'contentful/bootstrap/token'
|
6
6
|
|
7
7
|
module Contentful
|
8
8
|
module Bootstrap
|
@@ -45,40 +45,48 @@ module Contentful
|
|
45
45
|
end
|
46
46
|
|
47
47
|
class IndexController < WEBrick::HTTPServlet::AbstractServlet
|
48
|
-
def do_GET(
|
48
|
+
def do_GET(_request, response)
|
49
49
|
client_id = Contentful::Bootstrap::Constants::OAUTH_APP_ID
|
50
50
|
redirect_uri = Contentful::Bootstrap::Constants::OAUTH_CALLBACK_URL
|
51
|
-
scope =
|
51
|
+
scope = 'content_management_manage'
|
52
52
|
Launchy.open("https://be.contentful.com/oauth/authorize?response_type=token&client_id=#{client_id}&redirect_uri=#{redirect_uri}&scope=#{scope}")
|
53
53
|
response.status = 200
|
54
|
-
response.body =
|
54
|
+
response.body = ''
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
class OAuthCallbackController < WEBrick::HTTPServlet::AbstractServlet
|
59
|
-
def do_GET(
|
59
|
+
def do_GET(_request, response)
|
60
60
|
response.status = 200
|
61
|
-
response.content_type =
|
61
|
+
response.content_type = 'text/html'
|
62
62
|
response.body = OAuthEchoView.new.render
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
66
|
class SaveTokenController < WEBrick::HTTPServlet::AbstractServlet
|
67
|
+
attr_reader :token
|
68
|
+
|
69
|
+
def initialize(server, token, *options)
|
70
|
+
super(server, options)
|
71
|
+
@token = token
|
72
|
+
end
|
73
|
+
|
67
74
|
def do_GET(request, response)
|
68
|
-
|
75
|
+
@token.write(request.query['token'])
|
69
76
|
response.status = 200
|
70
|
-
response.content_type =
|
77
|
+
response.content_type = 'text/html'
|
71
78
|
response.body = ThanksView.new.render
|
72
79
|
end
|
73
80
|
end
|
74
81
|
|
75
82
|
class Server
|
76
83
|
attr_reader :server
|
77
|
-
|
78
|
-
|
79
|
-
@server.
|
80
|
-
@server.mount
|
81
|
-
@server.mount
|
84
|
+
|
85
|
+
def initialize(token)
|
86
|
+
@server = WEBrick::HTTPServer.new(Port: 5123)
|
87
|
+
@server.mount '/', IndexController
|
88
|
+
@server.mount '/oauth_callback', OAuthCallbackController
|
89
|
+
@server.mount '/save_token', SaveTokenController, token
|
82
90
|
end
|
83
91
|
|
84
92
|
def start
|
@@ -1,10 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require 'stringio'
|
2
2
|
|
3
3
|
module Contentful
|
4
4
|
module Bootstrap
|
5
5
|
module Support
|
6
6
|
def silence_stderr
|
7
|
-
old_stderr
|
7
|
+
old_stderr = $stderr
|
8
|
+
$stderr = StringIO.new
|
8
9
|
yield
|
9
10
|
ensure
|
10
11
|
$stderr = old_stderr
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require 'contentful/bootstrap/templates/blog'
|
2
|
+
require 'contentful/bootstrap/templates/catalogue'
|
3
|
+
require 'contentful/bootstrap/templates/gallery'
|
4
|
+
require 'contentful/bootstrap/templates/json_template'
|
@@ -1,5 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'json'
|
2
|
+
require 'contentful/management'
|
3
|
+
require 'contentful/bootstrap/templates/links/base'
|
3
4
|
|
4
5
|
module Contentful
|
5
6
|
module Bootstrap
|
@@ -12,9 +13,18 @@ module Contentful
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def run
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
begin
|
17
|
+
create_content_types
|
18
|
+
create_assets
|
19
|
+
create_entries
|
20
|
+
rescue Contentful::Management::Error => e
|
21
|
+
error = e.error
|
22
|
+
puts "Error at: #{error[:url]}"
|
23
|
+
puts "Message: #{error[:message]}"
|
24
|
+
puts "Details: #{error[:details]}"
|
25
|
+
|
26
|
+
raise e
|
27
|
+
end
|
18
28
|
end
|
19
29
|
|
20
30
|
def content_types
|
@@ -30,6 +40,7 @@ module Contentful
|
|
30
40
|
end
|
31
41
|
|
32
42
|
protected
|
43
|
+
|
33
44
|
def create_image(name, url)
|
34
45
|
image = Contentful::Management::File.new
|
35
46
|
image.properties[:contentType] = 'image/jpeg'
|
@@ -39,27 +50,28 @@ module Contentful
|
|
39
50
|
end
|
40
51
|
|
41
52
|
private
|
53
|
+
|
42
54
|
def create_content_types
|
43
55
|
content_types.each do |ct|
|
44
|
-
puts "Creating Content Type '#{ct[
|
56
|
+
puts "Creating Content Type '#{ct['name']}'"
|
45
57
|
|
46
58
|
fields = []
|
47
59
|
content_type = space.content_types.new
|
48
|
-
content_type.id = ct[
|
49
|
-
content_type.name = ct[
|
50
|
-
content_type.display_field = ct[
|
60
|
+
content_type.id = ct['id']
|
61
|
+
content_type.name = ct['name']
|
62
|
+
content_type.display_field = ct['display_field']
|
51
63
|
|
52
|
-
ct[
|
64
|
+
ct['fields'].each do |f|
|
53
65
|
field = Contentful::Management::Field.new
|
54
|
-
field.id = f[
|
55
|
-
field.name = f[
|
56
|
-
field.type = f[
|
57
|
-
field.link_type = f[
|
66
|
+
field.id = f['id']
|
67
|
+
field.name = f['name']
|
68
|
+
field.type = f['type']
|
69
|
+
field.link_type = f['link_type'] if link?(f)
|
58
70
|
|
59
|
-
if
|
71
|
+
if array?(f)
|
60
72
|
array_field = Contentful::Management::Field.new
|
61
|
-
array_field.type = f[
|
62
|
-
array_field.link_type = f[
|
73
|
+
array_field.type = f['items']['type']
|
74
|
+
array_field.link_type = f['items']['link_type']
|
63
75
|
field.items = array_field
|
64
76
|
end
|
65
77
|
|
@@ -72,25 +84,34 @@ module Contentful
|
|
72
84
|
end
|
73
85
|
end
|
74
86
|
|
75
|
-
def
|
76
|
-
field.
|
87
|
+
def link?(field)
|
88
|
+
field.key?('link_type')
|
77
89
|
end
|
78
90
|
|
79
|
-
def
|
80
|
-
field.
|
91
|
+
def array?(field)
|
92
|
+
field.key?('items')
|
81
93
|
end
|
82
94
|
|
83
95
|
def create_assets
|
84
96
|
assets.each do |asset|
|
85
|
-
puts "Creating Asset '#{asset[
|
97
|
+
puts "Creating Asset '#{asset['title']}'"
|
86
98
|
asset = space.assets.create(
|
87
|
-
id: asset[
|
88
|
-
title: asset[
|
89
|
-
file: asset[
|
99
|
+
id: asset['id'],
|
100
|
+
title: asset['title'],
|
101
|
+
file: asset['file']
|
90
102
|
)
|
91
103
|
asset.process_file
|
92
|
-
|
93
|
-
|
104
|
+
|
105
|
+
attempts = 0
|
106
|
+
while attempts < 10
|
107
|
+
unless space.assets.find(asset.id).file.url.nil?
|
108
|
+
asset.publish
|
109
|
+
break
|
110
|
+
end
|
111
|
+
|
112
|
+
sleep(1) # Wait for Process
|
113
|
+
attempts += 1
|
114
|
+
end
|
94
115
|
end
|
95
116
|
end
|
96
117
|
|
@@ -106,8 +127,8 @@ module Contentful
|
|
106
127
|
array_fields = []
|
107
128
|
regular_fields = []
|
108
129
|
e.each do |field_name, value|
|
109
|
-
if value.is_a? Array
|
110
|
-
array_fields << field_name
|
130
|
+
if value.is_a? ::Array
|
131
|
+
array_fields << field_name
|
111
132
|
next
|
112
133
|
end
|
113
134
|
|
@@ -116,7 +137,7 @@ module Contentful
|
|
116
137
|
|
117
138
|
array_fields.each do |af|
|
118
139
|
e[af].map! do |item|
|
119
|
-
if item.is_a? Links::Base
|
140
|
+
if item.is_a? ::Contentful::Bootstrap::Templates::Links::Base
|
120
141
|
item.to_management_object
|
121
142
|
else
|
122
143
|
item
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'contentful/bootstrap/templates/base'
|
2
|
+
require 'contentful/bootstrap/templates/links'
|
3
3
|
|
4
4
|
module Contentful
|
5
5
|
module Bootstrap
|
@@ -8,37 +8,37 @@ module Contentful
|
|
8
8
|
def content_types
|
9
9
|
[
|
10
10
|
{
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
'id' => 'author',
|
12
|
+
'name' => 'Author',
|
13
|
+
'display_field' => 'name',
|
14
|
+
'fields' => [
|
15
15
|
{
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
'id' => 'name',
|
17
|
+
'name' => 'Author Name',
|
18
|
+
'type' => 'Symbol'
|
19
19
|
}
|
20
20
|
]
|
21
21
|
},
|
22
22
|
{
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
'id' => 'post',
|
24
|
+
'name' => 'Post',
|
25
|
+
'display_field' => 'title',
|
26
|
+
'fields' => [
|
27
27
|
{
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
'id' => 'title',
|
29
|
+
'name' => 'Post Title',
|
30
|
+
'type' => 'Symbol'
|
31
31
|
},
|
32
32
|
{
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
'id' => 'content',
|
34
|
+
'name' => 'Content',
|
35
|
+
'type' => 'Text'
|
36
36
|
},
|
37
37
|
{
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
'id' => 'author',
|
39
|
+
'name' => 'Author',
|
40
|
+
'type' => 'Link',
|
41
|
+
'link_type' => 'Entry'
|
42
42
|
}
|
43
43
|
]
|
44
44
|
}
|
@@ -49,24 +49,24 @@ module Contentful
|
|
49
49
|
{
|
50
50
|
'author' => [
|
51
51
|
{
|
52
|
-
|
53
|
-
|
52
|
+
'id' => 'dan_brown',
|
53
|
+
'name' => 'Dan Brown'
|
54
54
|
},
|
55
55
|
{
|
56
|
-
|
57
|
-
|
56
|
+
'id' => 'pablo_neruda',
|
57
|
+
'name' => 'Pablo Neruda'
|
58
58
|
}
|
59
59
|
],
|
60
60
|
'post' => [
|
61
61
|
{
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
'title' => 'Inferno',
|
63
|
+
'content' => 'Inferno is the last book in Dan Brown\'s collection...',
|
64
|
+
'author' => Links::Entry.new('dan_brown')
|
65
65
|
},
|
66
66
|
{
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
'title' => 'Alturas de Macchu Picchu',
|
68
|
+
'content' => 'Alturas de Macchu Picchu is one of Pablo Neruda\'s most famous poetry books...',
|
69
|
+
'author' => Links::Entry.new('pablo_neruda')
|
70
70
|
}
|
71
71
|
]
|
72
72
|
}
|