storyblok 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8dbb219ff3c07b2f526fa5c816276ae32126dd6b
4
+ data.tar.gz: f59d2ebfa84847b4b5bb94a580a8e06e0d2e4e4b
5
+ SHA512:
6
+ metadata.gz: 7e6dd72f70bfa84ec18bf5f130a08a68f6c74d14f4dd39fd22b4bf5219ec183e0f826a48d52ca15bc862580f47b2cef07078607860d5d97b63277fe1cd3ad179
7
+ data.tar.gz: 4429276f86a4cdf585ff47cfe5a1631a87a0abf800186ef1edc2b4efd9aef91a66bf12453e6c2eb06066eab024f9b7927a2801a78e963beb6ebdab468a396135
data/.editorconfig ADDED
@@ -0,0 +1,9 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 2
6
+ end_of_line = lf
7
+ charset = utf-8
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ pkg
2
+ doc/
3
+ .yardoc/
4
+ coverage
5
+ Gemfile.lock
6
+ .idea
7
+ *.DS_Store
8
+ .ruby-version
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # About
2
+ This is the Storyblok ruby client for easy access of the content delivery api.
3
+
4
+ ## Install
5
+
6
+ ```bash
7
+ gem 'storyblok'
8
+ ```
9
+
10
+ ## Usage
11
+
12
+ ### Load a Story
13
+
14
+ ```ruby
15
+ client = new Storyblok(token: 'YOUR_TOKEN')
16
+
17
+ # Optionally set a cache client
18
+ Storyblok::Cache.client = Redis.new(:url => 'redis://localhost:6379')
19
+
20
+ # Get a story
21
+ client.story('home')
22
+ ```
23
+
24
+ ### Load a list of Stories
25
+
26
+ ```ruby
27
+ # Get all Stories that start with news
28
+ client.stories({
29
+ :starts_with => 'news'
30
+ })
31
+ ```
32
+
33
+ ### Load a list of datasource entries
34
+
35
+ ```ruby
36
+ # Get all label datasource entries
37
+ client.datasource_entries({
38
+ :datasource => 'labels'
39
+ })
40
+
41
+ ```
42
+
43
+ ### Load a list of tags
44
+
45
+ ```ruby
46
+ # Get all Tags that within the folder news
47
+ client.tags({
48
+ :starts_with => 'news'
49
+ })
50
+
51
+ ```
52
+
53
+ ## Generate a navigation tree
54
+
55
+ ```ruby
56
+ links = client.links
57
+ tree = links.as_tree
58
+
59
+ puts '<ul>'
60
+ tree.each do |key, item|
61
+ puts '<li>' + item['item']['name']
62
+
63
+ if !item['children'].empty?
64
+ puts '<ul>'
65
+ item['children'].each do |key, inner_item|
66
+ puts '<li>' + inner_item['item']['name'] + '</li>'
67
+ end
68
+ puts '</ul>'
69
+ end
70
+
71
+ puts '</li>'
72
+ end
73
+ puts '</ul>'
74
+ ```
75
+
76
+ ### License
77
+
78
+ This project is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
@@ -0,0 +1,15 @@
1
+ require 'storyblok'
2
+
3
+ logger = Logger.new(STDOUT)
4
+
5
+ client = Storyblok::Client.new(
6
+ token: 't618GfLe1YHICBioAHnMrwtt',
7
+ api_url: 'localhost:3001',
8
+ secure: false,
9
+ logger: logger
10
+ )
11
+
12
+ p client.stories(starts_with: 'en/news')
13
+ p client.story('demo1')
14
+ p client.datasource_entries(datasource: 'labels', per_page: 10)
15
+ p client.links
data/examples/tree.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'storyblok'
2
+
3
+ logger = Logger.new(STDOUT)
4
+
5
+ client = Storyblok::Client.new(
6
+ token: 't618GfLe1YHICBioAHnMrwtt',
7
+ api_url: 'localhost:3001',
8
+ secure: false,
9
+ logger: logger
10
+ )
11
+
12
+ links = client.links
13
+ tree = links.as_tree
14
+
15
+ puts '<ul>'
16
+ tree.each do |key, item|
17
+ puts '<li>' + item['item']['name']
18
+
19
+ if !item['children'].empty?
20
+ puts '<ul>'
21
+ item['children'].each do |key, inner_item|
22
+ puts '<li>' + inner_item['item']['name'] + '</li>'
23
+ end
24
+ puts '</ul>'
25
+ end
26
+
27
+ puts '</li>'
28
+ end
29
+ puts '</ul>'
data/lib/storyblok.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'storyblok/version'
2
+ require 'storyblok/cache'
3
+ require 'storyblok/client'
@@ -0,0 +1,26 @@
1
+ module Storyblok
2
+ class Cache
3
+ def self.client=(client)
4
+ @client = client
5
+ end
6
+
7
+ def self.client
8
+ @client
9
+ end
10
+
11
+ def cache(key, expire = nil)
12
+ if expire == 0
13
+ return yield(self)
14
+ end
15
+
16
+ if (value = @client.get(key)).nil?
17
+ value = yield(self)
18
+ @client.set(key, value)
19
+ @client.expire(key, expire) if expire
20
+ value
21
+ else
22
+ value
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,153 @@
1
+ require_relative 'request'
2
+ require_relative 'links'
3
+
4
+ require 'rest-client'
5
+ require 'logger'
6
+
7
+ module Storyblok
8
+ class Client
9
+ DEFAULT_CONFIGURATION = {
10
+ secure: true,
11
+ api_url: 'api.storyblok.com',
12
+ api_version: 1,
13
+ logger: false,
14
+ log_level: Logger::INFO,
15
+ version: 'draft',
16
+ cache_version: Time.now.to_i
17
+ }
18
+
19
+ attr_reader :configuration, :logger
20
+
21
+ # @param [Hash] given_configuration
22
+ # @option given_configuration [String] :token Required
23
+ # @option given_configuration [String] :api_url
24
+ # @option given_configuration [Number] :api_version
25
+ # @option given_configuration [false, ::Logger] :logger
26
+ # @option given_configuration [::Logger::DEBUG, ::Logger::INFO, ::Logger::WARN, ::Logger::ERROR] :log_level
27
+ def initialize(given_configuration = {})
28
+ @configuration = default_configuration.merge(given_configuration)
29
+ validate_configuration!
30
+ setup_logger
31
+ end
32
+
33
+ # Gets a collection of stories
34
+ #
35
+ # @param [Hash] query
36
+ #
37
+ # @return [Hash]
38
+ def stories(query = {})
39
+ Request.new(self, '/cdn/stories', query).get
40
+ end
41
+
42
+ # Gets a specific story
43
+ #
44
+ # @param [String] id
45
+ # @param [Hash] query
46
+ #
47
+ # @return [Hash]
48
+ def story(id, query = {})
49
+ Request.new(self, '/cdn/stories', query, id).get
50
+ end
51
+
52
+ # Gets a collection of datasource entries
53
+ #
54
+ # @param [Hash] query
55
+ #
56
+ # @return [Hash]
57
+ def datasource_entries(query = {})
58
+ Request.new(self, '/cdn/datasource_entries', query).get
59
+ end
60
+
61
+ # Gets a collection of tags
62
+ #
63
+ # @param [Hash] query
64
+ #
65
+ # @return [Hash]
66
+ def tags(query = {})
67
+ Request.new(self, '/cdn/tags', query).get
68
+ end
69
+
70
+ # Gets a collection of links
71
+ #
72
+ # @param [Hash] query
73
+ #
74
+ # @return [Hash]
75
+ def links(query = {})
76
+ Links.new(Request.new(self, '/cdn/links', query).get)
77
+ end
78
+
79
+ def get(request)
80
+ endpoint = base_url + request.endpoint
81
+ query = request_query(request.query)
82
+ query_string = build_nested_query(query)
83
+
84
+ if Cache.client.nil?
85
+ result = run_request(endpoint, query_string)
86
+ else
87
+ cache_key = 'storyblok:' + configuration[:token] + ':' + request.endpoint + ':' + Base64.encode64(query_string)
88
+ cache_time = 60 * 60 * 2
89
+
90
+ result = Cache.client.cache(cache_key, cache_time) do
91
+ run_request(endpoint, query)
92
+ end
93
+ end
94
+
95
+ JSON.parse(result)
96
+ end
97
+
98
+ private
99
+
100
+ def run_request(endpoint, query_string)
101
+ logger.info(request: { endpoint: endpoint, query: query_string }) if logger
102
+ res = RestClient.get "#{endpoint}?#{query_string}"
103
+
104
+ {headers: res.headers, data: JSON.parse(res.body)}.to_json
105
+ end
106
+
107
+ # Patches a query hash with the client configurations for queries
108
+ def request_query(query)
109
+ query[:token] = configuration[:token]
110
+ query[:version] = configuration[:version] if query[:version].nil?
111
+ query[:cv] = configuration[:cache_version] if query[:cache_version].nil?
112
+ query
113
+ end
114
+
115
+ # Returns the base url for all of the client's requests
116
+ def base_url
117
+ "http#{configuration[:secure] ? 's' : ''}://#{configuration[:api_url]}/v#{configuration[:api_version]}"
118
+ end
119
+
120
+ def default_configuration
121
+ DEFAULT_CONFIGURATION.dup
122
+ end
123
+
124
+ def setup_logger
125
+ @logger = configuration[:logger]
126
+ logger.level = configuration[:log_level] if logger
127
+ end
128
+
129
+ def validate_configuration!
130
+ fail ArgumentError, 'You will need to initialize a client with an :token' if configuration[:token].empty?
131
+ fail ArgumentError, 'The client configuration needs to contain an :api_url' if configuration[:api_url].empty?
132
+ fail ArgumentError, 'The :api_version must be a positive number' unless configuration[:api_version].to_i >= 0
133
+ end
134
+
135
+ def build_nested_query(value, prefix = nil)
136
+ case value
137
+ when Array
138
+ value.map { |v|
139
+ build_nested_query(v, "#{prefix}[]")
140
+ }.join("&")
141
+ when Hash
142
+ value.map { |k, v|
143
+ build_nested_query(v, prefix ? "#{prefix}[#{URI.encode_www_form_component(k)}]" : URI.encode_www_form_component(k))
144
+ }.reject(&:empty?).join('&')
145
+ when nil
146
+ prefix
147
+ else
148
+ raise ArgumentError, "value must be a Hash" if prefix.nil?
149
+ "#{prefix}=#{URI.encode_www_form_component(value)}"
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,42 @@
1
+ module Storyblok
2
+ class Links
3
+ def initialize(response_obj)
4
+ @links = response_obj['data']['links']
5
+ end
6
+
7
+ def as_tree
8
+ tree = {}
9
+
10
+ @links.each do |key, item|
11
+ if tree[item['parent_id']].nil?
12
+ tree[item['parent_id']] = []
13
+ end
14
+
15
+ tree[item['parent_id']] << item
16
+ end
17
+
18
+ generate_tree(0, tree)
19
+ end
20
+
21
+ private
22
+
23
+ def generate_tree(parent_id = 0, items)
24
+ tree = {}
25
+
26
+ if !items[parent_id].nil?
27
+ result = items[parent_id]
28
+
29
+ result.each do |item|
30
+ if tree[item['id']].nil?
31
+ tree[item['id']] = {}
32
+ end
33
+
34
+ tree[item['id']]['item'] = item
35
+ tree[item['id']]['children'] = generate_tree(item['id'], items)
36
+ end
37
+ end
38
+
39
+ tree
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,37 @@
1
+ module Storyblok
2
+ # This object represents a request that is to be made. It gets initialized by the client
3
+ # with domain specific logic. The client later uses the Request's #url and #query methods
4
+ # to execute the HTTP request.
5
+ class Request
6
+ attr_reader :client, :type, :query, :id, :endpoint
7
+
8
+ def initialize(client, endpoint, query = {}, id = nil)
9
+ @client = client
10
+ @endpoint = endpoint
11
+ @query = query
12
+
13
+ if id
14
+ @type = :single
15
+ @id = URI.escape(id)
16
+ else
17
+ @type = :multi
18
+ @id = nil
19
+ end
20
+ end
21
+
22
+ # Returns the final URL, relative to a storyblok space
23
+ def url
24
+ "#{@endpoint}#{@type == :single ? "/#{id}" : ''}"
25
+ end
26
+
27
+ # Delegates the actual HTTP work to the client
28
+ def get
29
+ client.get(self)
30
+ end
31
+
32
+ # Returns a new Request object with the same data
33
+ def copy
34
+ Marshal.load(Marshal.dump(self))
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,4 @@
1
+ module Storyblok
2
+ # Gem Version
3
+ VERSION = '1.0.0'
4
+ end
data/storyblok.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../lib/storyblok/version', __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'storyblok'
5
+ gem.version = Storyblok::VERSION
6
+ gem.summary = 'storyblok'
7
+ gem.description = 'Ruby client for the https://www.storyblok.com Content Delivery API'
8
+ gem.license = 'MIT'
9
+ gem.authors = ['Storyblok (Alexander Feiglstorfer)']
10
+ gem.email = 'it@storyblok.com'
11
+ gem.homepage = 'https://github.com/storyblok/storyblok-ruby'
12
+
13
+ gem.files = Dir['{**/}{.*,*}'].select { |path| File.file?(path) && !path.start_with?('pkg') }
14
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^spec/})
16
+ gem.require_paths = ['lib']
17
+
18
+ gem.add_dependency 'rest-client', '~> 1.8'
19
+
20
+ gem.add_development_dependency 'bundler', '~> 1.5'
21
+ gem.add_development_dependency 'rspec', '~> 3'
22
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: storyblok
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Storyblok (Alexander Feiglstorfer)
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3'
55
+ description: Ruby client for the https://www.storyblok.com Content Delivery API
56
+ email: it@storyblok.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - ".editorconfig"
62
+ - ".gitignore"
63
+ - ".ruby-version"
64
+ - Gemfile
65
+ - Gemfile.lock
66
+ - README.md
67
+ - examples/example_queries.rb
68
+ - examples/tree.rb
69
+ - lib/storyblok.rb
70
+ - lib/storyblok/cache.rb
71
+ - lib/storyblok/client.rb
72
+ - lib/storyblok/links.rb
73
+ - lib/storyblok/request.rb
74
+ - lib/storyblok/version.rb
75
+ - storyblok.gemspec
76
+ homepage: https://github.com/storyblok/storyblok-ruby
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.5.1
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: storyblok
100
+ test_files: []