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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +26 -0
  3. data/.rubocop_todo.yml +123 -0
  4. data/.travis.yml +6 -0
  5. data/CHANGELOG.md +25 -0
  6. data/Gemfile +1 -0
  7. data/Guardfile +5 -0
  8. data/README.md +40 -14
  9. data/Rakefile +7 -0
  10. data/bin/contentful_bootstrap +33 -22
  11. data/contentful_bootstrap.gemspec +7 -0
  12. data/lib/contentful/bootstrap.rb +7 -5
  13. data/lib/contentful/bootstrap/command_runner.rb +45 -0
  14. data/lib/contentful/bootstrap/commands.rb +3 -168
  15. data/lib/contentful/bootstrap/commands/base.rb +66 -0
  16. data/lib/contentful/bootstrap/commands/create_space.rb +111 -0
  17. data/lib/contentful/bootstrap/commands/generate_json.rb +41 -0
  18. data/lib/contentful/bootstrap/commands/generate_token.rb +52 -0
  19. data/lib/contentful/bootstrap/constants.rb +2 -2
  20. data/lib/contentful/bootstrap/generator.rb +94 -0
  21. data/lib/contentful/bootstrap/server.rb +25 -17
  22. data/lib/contentful/bootstrap/support.rb +3 -2
  23. data/lib/contentful/bootstrap/templates.rb +4 -4
  24. data/lib/contentful/bootstrap/templates/base.rb +51 -30
  25. data/lib/contentful/bootstrap/templates/blog.rb +33 -33
  26. data/lib/contentful/bootstrap/templates/catalogue.rb +103 -103
  27. data/lib/contentful/bootstrap/templates/gallery.rb +55 -56
  28. data/lib/contentful/bootstrap/templates/json_template.rb +22 -16
  29. data/lib/contentful/bootstrap/templates/links.rb +2 -2
  30. data/lib/contentful/bootstrap/templates/links/asset.rb +2 -2
  31. data/lib/contentful/bootstrap/templates/links/base.rb +3 -3
  32. data/lib/contentful/bootstrap/templates/links/entry.rb +2 -2
  33. data/lib/contentful/bootstrap/token.rb +32 -31
  34. data/lib/contentful/bootstrap/version.rb +1 -1
  35. data/spec/contentful/bootstrap/command_runner_spec.rb +111 -0
  36. data/spec/contentful/bootstrap/commands/base_spec.rb +102 -0
  37. data/spec/contentful/bootstrap/commands/create_space_spec.rb +72 -0
  38. data/spec/contentful/bootstrap/commands/generate_json_spec.rb +64 -0
  39. data/spec/contentful/bootstrap/commands/generate_token_spec.rb +82 -0
  40. data/spec/contentful/bootstrap/generator_spec.rb +15 -0
  41. data/spec/contentful/bootstrap/server_spec.rb +154 -0
  42. data/spec/contentful/bootstrap/support_spec.rb +27 -0
  43. data/spec/contentful/bootstrap/templates/base_spec.rb +34 -0
  44. data/spec/contentful/bootstrap/templates/blog_spec.rb +32 -0
  45. data/spec/contentful/bootstrap/templates/catalogue_spec.rb +40 -0
  46. data/spec/contentful/bootstrap/templates/gallery_spec.rb +40 -0
  47. data/spec/contentful/bootstrap/templates/json_template_spec.rb +52 -0
  48. data/spec/contentful/bootstrap/templates/links/asset_spec.rb +23 -0
  49. data/spec/contentful/bootstrap/templates/links/base_spec.rb +31 -0
  50. data/spec/contentful/bootstrap/templates/links/entry_spec.rb +23 -0
  51. data/spec/contentful/bootstrap/token_spec.rb +143 -0
  52. data/spec/fixtures/ini_fixtures/contentfulrc.ini +2 -0
  53. data/spec/fixtures/ini_fixtures/no_global.ini +2 -0
  54. data/spec/fixtures/ini_fixtures/no_token.ini +1 -0
  55. data/spec/fixtures/ini_fixtures/sections.ini +5 -0
  56. data/spec/fixtures/json_fixtures/issue_22.json +77 -0
  57. data/spec/fixtures/json_fixtures/simple.json +34 -0
  58. data/spec/fixtures/json_fixtures/wl1z0pal05vy.json +437 -0
  59. data/spec/fixtures/vcr_fixtures/generate_json.yml +384 -0
  60. data/spec/fixtures/vcr_fixtures/issue_22.yml +2488 -0
  61. data/spec/spec_helper.rb +51 -0
  62. 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 = "a19770bea126e6d596d8599ff42e14173409e3e252895b78d0cb289c10586276".freeze
5
- OAUTH_CALLBACK_URL = "http://localhost:5123/oauth_callback".freeze
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 "thread"
2
- require "webrick"
3
- require "launchy"
4
- require "contentful/bootstrap/constants"
5
- require "contentful/bootstrap/token"
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(request, response)
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 = "content_management_manage"
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(request, response)
59
+ def do_GET(_request, response)
60
60
  response.status = 200
61
- response.content_type = "text/html"
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
- Token.write(request.query["token"])
75
+ @token.write(request.query['token'])
69
76
  response.status = 200
70
- response.content_type = "text/html"
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
- def initialize
78
- @server = WEBrick::HTTPServer.new(:Port => 5123)
79
- @server.mount "/", IndexController
80
- @server.mount "/oauth_callback", OAuthCallbackController
81
- @server.mount "/save_token", SaveTokenController
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 "stringio"
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, $stderr = $stderr, StringIO.new
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 "contentful/bootstrap/templates/blog"
2
- require "contentful/bootstrap/templates/catalogue"
3
- require "contentful/bootstrap/templates/gallery"
4
- require "contentful/bootstrap/templates/json_template"
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 "contentful/management"
2
- require "contentful/bootstrap/templates/links/base"
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
- create_content_types
16
- create_assets
17
- create_entries
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["name"]}'"
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["id"]
49
- content_type.name = ct["name"]
50
- content_type.display_field = ct["display_field"]
60
+ content_type.id = ct['id']
61
+ content_type.name = ct['name']
62
+ content_type.display_field = ct['display_field']
51
63
 
52
- ct["fields"].each do |f|
64
+ ct['fields'].each do |f|
53
65
  field = Contentful::Management::Field.new
54
- field.id = f["id"]
55
- field.name = f["name"]
56
- field.type = f["type"]
57
- field.link_type = f["link_type"] if is_link?(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 is_array?(f)
71
+ if array?(f)
60
72
  array_field = Contentful::Management::Field.new
61
- array_field.type = f["items"]["type"]
62
- array_field.link_type = f["items"]["link_type"]
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 is_link?(field)
76
- field.has_key?("link_type")
87
+ def link?(field)
88
+ field.key?('link_type')
77
89
  end
78
90
 
79
- def is_array?(field)
80
- field.has_key?("items")
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["title"]}'"
97
+ puts "Creating Asset '#{asset['title']}'"
86
98
  asset = space.assets.create(
87
- id: asset["id"],
88
- title: asset["title"],
89
- file: asset["file"]
99
+ id: asset['id'],
100
+ title: asset['title'],
101
+ file: asset['file']
90
102
  )
91
103
  asset.process_file
92
- sleep(1) # Wait for Process
93
- asset.publish
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 if value.is_a? Array
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 "contentful/bootstrap/templates/base"
2
- require "contentful/bootstrap/templates/links"
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
- "id" => 'author',
12
- "name" => 'Author',
13
- "display_field" => 'name',
14
- "fields" => [
11
+ 'id' => 'author',
12
+ 'name' => 'Author',
13
+ 'display_field' => 'name',
14
+ 'fields' => [
15
15
  {
16
- "id" => 'name',
17
- "name" => "Author Name",
18
- "type" => "Symbol"
16
+ 'id' => 'name',
17
+ 'name' => 'Author Name',
18
+ 'type' => 'Symbol'
19
19
  }
20
20
  ]
21
21
  },
22
22
  {
23
- "id" => 'post',
24
- "name" => 'Post',
25
- "display_field" => 'title',
26
- "fields" => [
23
+ 'id' => 'post',
24
+ 'name' => 'Post',
25
+ 'display_field' => 'title',
26
+ 'fields' => [
27
27
  {
28
- "id" => 'title',
29
- "name" => "Post Title",
30
- "type" => "Symbol"
28
+ 'id' => 'title',
29
+ 'name' => 'Post Title',
30
+ 'type' => 'Symbol'
31
31
  },
32
32
  {
33
- "id" => 'content',
34
- "name" => "Content",
35
- "type" => "Text"
33
+ 'id' => 'content',
34
+ 'name' => 'Content',
35
+ 'type' => 'Text'
36
36
  },
37
37
  {
38
- "id" => 'author',
39
- "name" => "Author",
40
- "type" => "Link",
41
- "link_type" => "Entry"
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
- "id" => "dan_brown",
53
- "name" => "Dan Brown"
52
+ 'id' => 'dan_brown',
53
+ 'name' => 'Dan Brown'
54
54
  },
55
55
  {
56
- "id" => "pablo_neruda",
57
- "name" => "Pablo Neruda"
56
+ 'id' => 'pablo_neruda',
57
+ 'name' => 'Pablo Neruda'
58
58
  }
59
59
  ],
60
60
  'post' => [
61
61
  {
62
- "title" => "Inferno",
63
- "content" => "Inferno is the last book in Dan Brown's collection...",
64
- "author" => Links::Entry.new("dan_brown")
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
- "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")
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
  }