webflow-rb 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
+ SHA256:
3
+ metadata.gz: caf289ff080b55720bef55a8fe1ff021d43a3c44ae0fb94ee7c6517c6495af44
4
+ data.tar.gz: e44d6b178c268e754a7d2c7653f7bcb6eb78daddef16bcba0156d8a8dbc43092
5
+ SHA512:
6
+ metadata.gz: '00918cd8a2991b4e64478b6695a93e828ac7b89a40be5fc03617c5d7d50580743ff9d3a62f36c76c4b41aaeabcb0e9611cecce6155cce698fa52b4f714ed8230'
7
+ data.tar.gz: 0dfdce4df3b8b8fd246796313e0e0e4c7d529d6b58d81dd668b0f764f8dc298b1c35729b0fd9edc43eb472e73d37ab84ec9cde143340a8b45fdb4e7af3eb502e
@@ -0,0 +1,19 @@
1
+ name: build
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ build:
9
+ strategy:
10
+ matrix:
11
+ ruby: [2.7.2, 3.2.2]
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
19
+ - run: bundle exec rake
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ *.gem
10
+ *.swo
11
+ *.swp
12
+
13
+ .irb_history
data/.irbrc ADDED
@@ -0,0 +1,5 @@
1
+ $LOAD_PATH.unshift File.expand_path('lib')
2
+
3
+ require 'webflow'
4
+
5
+ @client = Webflow::Client.new(ENV.fetch('TEST_API_TOKEN'))
data/.rubocop.yml ADDED
@@ -0,0 +1,18 @@
1
+ require:
2
+ - rubocop-minitest
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.7.0
6
+ NewCops: enable
7
+
8
+ Layout/LineLength:
9
+ Max: 140
10
+ Metrics/ClassLength:
11
+ Enabled: false
12
+ Style/Documentation:
13
+ Enabled: false
14
+ Style/FrozenStringLiteralComment:
15
+ Enabled: false
16
+ Style/HashSyntax:
17
+ Enabled: true
18
+ EnforcedShorthandSyntax: never
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.2.2
data/CHANGELOG.md ADDED
@@ -0,0 +1,34 @@
1
+ ## 2.0.0
2
+
3
+ - [FEATURE] Upgrade to Webflow API v2 😍 @vfonic
4
+ - [BREAKING] This version brings many breaking changes! All returned hashes' keys are symbolized. Webflow item fields are now located under `:fieldData` key in the hash: `client.item(collection_id, item_id).dig(:fieldData, :name)` 😍 @vfonic
5
+ - [BREAKING] Check `lib/webflow/client.rb` for the full API.
6
+
7
+ ## 1.2.1
8
+
9
+ - [FEATURE] Handle Problems in Validation errors https://github.com/penseo/webflow-ruby/pull/14 https://github.com/penseo/webflow-ruby/pull/16 😍 @vfonic @sega
10
+
11
+ ## 1.2.0
12
+
13
+ - [FEATURE] Add patch support for updating items https://github.com/penseo/webflow-ruby/issues/10 😍 @ukd1
14
+
15
+ ## 1.1.0
16
+
17
+ - [FEATURE] Allow passing a block to `items` that yields the results by page https://github.com/penseo/webflow-ruby/issues/9 😍 @emilesilvis
18
+ - [FEATURE] Handle Webflow live feature https://github.com/penseo/webflow-ruby/pull/8 😍 @emilesilvis
19
+
20
+ ## 1.0.0
21
+
22
+ - [BREAKING] Raise errors when status > 200, see also https://github.com/penseo/webflow-ruby/pull/7 😍 @sega
23
+
24
+ ## 0.7.0
25
+
26
+ - [FEATURE] Configuration class to store api token https://github.com/penseo/webflow-ruby/pull/6 😍 @mateuscruz
27
+
28
+ ## 0.6.0
29
+
30
+ - [CHANGE] Use pure ruby dependencies
31
+
32
+ ## 0.5.0
33
+
34
+ - [FEATURE] Pagination https://github.com/penseo/webflow-ruby/pull/2 😍 @cohesiveneal
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'bundler', '> 1.13'
6
+ gem 'byebug'
7
+ gem 'minitest', '> 5.0'
8
+ gem 'pry'
9
+ gem 'rake', '> 10.0'
10
+ gem 'rubocop'
11
+ gem 'rubocop-minitest'
12
+ gem 'vcr'
13
+ gem 'webmock'
data/Gemfile.lock ADDED
@@ -0,0 +1,73 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ webflow-rb (1.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ addressable (2.8.5)
10
+ public_suffix (>= 2.0.2, < 6.0)
11
+ ast (2.4.2)
12
+ byebug (11.1.3)
13
+ coderay (1.1.3)
14
+ crack (0.4.5)
15
+ rexml
16
+ hashdiff (1.0.1)
17
+ json (2.6.3)
18
+ language_server-protocol (3.17.0.3)
19
+ method_source (1.0.0)
20
+ minitest (5.14.4)
21
+ parallel (1.23.0)
22
+ parser (3.2.2.4)
23
+ ast (~> 2.4.1)
24
+ racc
25
+ pry (0.14.2)
26
+ coderay (~> 1.1)
27
+ method_source (~> 1.0)
28
+ public_suffix (5.0.3)
29
+ racc (1.7.3)
30
+ rainbow (3.1.1)
31
+ rake (13.1.0)
32
+ regexp_parser (2.8.2)
33
+ rexml (3.2.6)
34
+ rubocop (1.57.2)
35
+ json (~> 2.3)
36
+ language_server-protocol (>= 3.17.0)
37
+ parallel (~> 1.10)
38
+ parser (>= 3.2.2.4)
39
+ rainbow (>= 2.2.2, < 4.0)
40
+ regexp_parser (>= 1.8, < 3.0)
41
+ rexml (>= 3.2.5, < 4.0)
42
+ rubocop-ast (>= 1.28.1, < 2.0)
43
+ ruby-progressbar (~> 1.7)
44
+ unicode-display_width (>= 2.4.0, < 3.0)
45
+ rubocop-ast (1.30.0)
46
+ parser (>= 3.2.1.0)
47
+ rubocop-minitest (0.33.0)
48
+ rubocop (>= 1.39, < 2.0)
49
+ ruby-progressbar (1.13.0)
50
+ unicode-display_width (2.5.0)
51
+ vcr (6.2.0)
52
+ webmock (3.19.1)
53
+ addressable (>= 2.8.0)
54
+ crack (>= 0.3.2)
55
+ hashdiff (>= 0.4.0, < 2.0.0)
56
+
57
+ PLATFORMS
58
+ ruby
59
+
60
+ DEPENDENCIES
61
+ bundler (> 1.13)
62
+ byebug
63
+ minitest (> 5.0)
64
+ pry
65
+ rake (> 10.0)
66
+ rubocop
67
+ rubocop-minitest
68
+ vcr
69
+ webflow-rb!
70
+ webmock
71
+
72
+ BUNDLED WITH
73
+ 2.4.22
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 phoet
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # Webflow [![Build Status](https://github.com/vfonic/webflow-rb/workflows/build/badge.svg)](https://github.com/vfonic/webflow-rb/actions)
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'webflow-rb'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ ```bash
14
+ bundle
15
+ ```
16
+
17
+ Or install it yourself as:
18
+
19
+ ```bash
20
+ gem install webflow-rb
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ Check out [lib/webflow/client.rb](lib/webflow/client.rb).
26
+
27
+ Check the documentation at: https://developers.webflow.com/reference/list-collection-items
28
+
29
+ Basic usage:
30
+
31
+ ```ruby
32
+ client = Webflow::Client.new(ENV.fetch('WEBFLOW_API_TOKEN'))
33
+ sites = client.sites
34
+ ```
35
+
36
+ Here are method signatures:
37
+
38
+ ```ruby
39
+ def sites
40
+ def site(site_id)
41
+ def publish(site_id)
42
+ def collections(site_id)
43
+ def collection(collection_id)
44
+ def list_items(collection_id, limit: 100, offset: 0)
45
+ def list_all_items(collection_id)
46
+ def get_item(collection_id, item_id)
47
+ def create_item(collection_id, data)
48
+ def update_item(collection_id, item_id, data)
49
+ def delete_item(collection_id, item_id)
50
+ ```
51
+
52
+ ## Contributing
53
+
54
+ Bug reports and pull requests are welcome!
55
+
56
+ ## Plugins
57
+
58
+ - [webflow_sync](https://github.com/vfonic/webflow_sync) - Keep Rails models in sync with WebFlow collections.
59
+
60
+ ## Thanks and Credits
61
+
62
+ This gem wouldn't be possible without the amazing work of [webflow-ruby](https://github.com/penseo/webflow-ruby) gem. Thank you, [@phoet](https://github.com/phoet) and [@sega](https://github.com/sega)!
63
+
64
+ ## License
65
+
66
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'rubocop/rake_task'
4
+
5
+ Rake::TestTask.new(:test) do |t|
6
+ ENV['TEST_API_TOKEN'] = 'your_api_token_here' if ENV['TEST_API_TOKEN'].nil?
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
10
+ end
11
+
12
+ RuboCop::RakeTask.new
13
+
14
+ task default: %i[rubocop test]
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'webflow'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,140 @@
1
+ require 'net/http'
2
+ require 'json'
3
+
4
+ module Webflow
5
+ class Client
6
+ HOST = 'https://api.webflow.com/v2'.freeze
7
+ PAGINATION_LIMIT = 100
8
+
9
+ def initialize(token = Webflow.config.api_token)
10
+ @token = token
11
+ end
12
+
13
+ def sites
14
+ get('/sites').fetch(:sites)
15
+ end
16
+
17
+ def site(site_id)
18
+ get("/sites/#{site_id}")
19
+ end
20
+
21
+ def publish(site_id)
22
+ custom_domains = site(site_id).fetch(:customDomains).map { |domain| domain[:id] }
23
+ post("/sites/#{site_id}/publish", { publishToWebflowSubdomain: true, customDomains: custom_domains })
24
+ end
25
+
26
+ def collections(site_id)
27
+ get("/sites/#{site_id}/collections").fetch(:collections)
28
+ end
29
+
30
+ def collection(collection_id)
31
+ get("/collections/#{collection_id}")
32
+ end
33
+
34
+ # https://developers.webflow.com/reference/list-collection-items
35
+ #
36
+ # {
37
+ # items: [] your list of items returned,
38
+ # pagination: {
39
+ # limit: the limit specified in the request (default: 100),
40
+ # offset: the offset specified for pagination (default: 0),
41
+ # total: total # of items in the collection
42
+ # }
43
+ # }
44
+ def list_items(collection_id, limit: PAGINATION_LIMIT, offset: 0)
45
+ limit = [limit, PAGINATION_LIMIT].min
46
+ get("/collections/#{collection_id}/items", { limit: limit, offset: offset }).fetch(:items)
47
+ end
48
+
49
+ def list_all_items(collection_id) # rubocop:disable Metrics/MethodLength
50
+ fetched_items = []
51
+ offset = 0
52
+
53
+ loop do
54
+ response = get("/collections/#{collection_id}/items", { limit: PAGINATION_LIMIT, offset: offset })
55
+ items = response.fetch(:items)
56
+
57
+ if block_given?
58
+ yield(items)
59
+ else
60
+ fetched_items.concat(items)
61
+ end
62
+
63
+ offset += PAGINATION_LIMIT
64
+ break if offset >= response.dig(:pagination, :total)
65
+ end
66
+
67
+ fetched_items
68
+ end
69
+
70
+ def get_item(collection_id, item_id)
71
+ get("/collections/#{collection_id}/items/#{item_id}")
72
+ end
73
+
74
+ def create_item(collection_id, data)
75
+ result = post("/collections/#{collection_id}/items", { isArchived: false, isDraft: false, fieldData: data })
76
+ publish_item(collection_id, result.fetch(:id))
77
+ result
78
+ end
79
+
80
+ def update_item(collection_id, item_id, data)
81
+ result = patch("/collections/#{collection_id}/items/#{item_id}", { isArchived: false, isDraft: false, fieldData: data }.compact)
82
+ publish_item(collection_id, item_id)
83
+ result
84
+ end
85
+
86
+ def delete_item(collection_id, item_id)
87
+ # deleting items from Webflow doesn't work as expected.
88
+ # if we delete without archiving, the item will stay visible on the site until the site is published
89
+ # if we first archive + publish item, the item will be set as archived and not visible on the site
90
+ # then we call delete to remove the item from Webflow CMS
91
+ patch("/collections/#{collection_id}/items/#{item_id}", { isArchived: true, isDraft: false })
92
+ publish_item(collection_id, item_id)
93
+ delete("/collections/#{collection_id}/items/#{item_id}")
94
+ end
95
+
96
+ private
97
+
98
+ def publish_item(collection_id, item_id)
99
+ post("/collections/#{collection_id}/items/publish", { itemIds: Array(item_id) })
100
+ end
101
+
102
+ def get(path, data = nil)
103
+ request(path, method: :get, data: data)
104
+ end
105
+
106
+ def post(path, data)
107
+ request(path, method: :post, data: data)
108
+ end
109
+
110
+ def patch(path, data)
111
+ request(path, method: :patch, data: data)
112
+ end
113
+
114
+ def delete(path)
115
+ request(path, method: :delete)
116
+ end
117
+
118
+ def request(path, method:, data: nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
119
+ url = URI.parse(HOST + path)
120
+ bearer = "Bearer #{@token}"
121
+ headers = { accept: 'application/json', 'content-type': 'application/json', authorization: bearer }
122
+ http = Net::HTTP.new(url.host, url.port)
123
+ http.use_ssl = true if url.scheme == 'https'
124
+
125
+ url.query = URI.encode_www_form(data) if data && method == :get
126
+
127
+ request_class = { get: Net::HTTP::Get, post: Net::HTTP::Post, patch: Net::HTTP::Patch, delete: Net::HTTP::Delete }.fetch(method)
128
+ request = request_class.new(url.to_s, headers)
129
+ request.body = data.to_json if %i[post patch].include?(method)
130
+
131
+ response = http.request(request)
132
+ body = response.read_body
133
+
134
+ result = JSON.parse(body, symbolize_names: true) unless body.nil?
135
+ raise Webflow::Error, result if response.code.to_i >= 400
136
+
137
+ result
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,15 @@
1
+ module Webflow
2
+ class << self
3
+ def config
4
+ @config ||= Config.new
5
+ end
6
+
7
+ def configure
8
+ yield config
9
+ end
10
+ end
11
+
12
+ class Config
13
+ attr_accessor :api_token
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ module Webflow
2
+ class Error < StandardError
3
+ attr_reader :data
4
+
5
+ def initialize(data)
6
+ @data = data
7
+
8
+ message = "#{data[:message]}#{": #{Array(details)}" if details?}"
9
+ super(message)
10
+ end
11
+
12
+ def details?
13
+ details && !details.empty?
14
+ end
15
+
16
+ def details
17
+ data[:details]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ require 'webflow/version'
2
+ require 'webflow/config'
3
+ require 'webflow/client'
4
+ require 'webflow/error'
@@ -0,0 +1,3 @@
1
+ module Webflow
2
+ VERSION = '1.0.0'.freeze
3
+ end
data/lib/webflow.rb ADDED
@@ -0,0 +1 @@
1
+ require 'webflow/ruby'
data/webflow.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'webflow/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'webflow-rb'
7
+ spec.version = Webflow::VERSION
8
+ spec.authors = %w[phoet vfonic]
9
+ spec.email = ['phoetmail@googlemail.com']
10
+
11
+ spec.summary = 'Webflow API wrapper'
12
+ spec.description = spec.summary
13
+ spec.homepage = 'https://github.com/vfonic/webflow-rb'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.metadata['rubygems_mfa_required'] = 'true'
24
+ spec.required_ruby_version = '>= 2.7.0'
25
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: webflow-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - phoet
8
+ - vfonic
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2023-12-05 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Webflow API wrapper
15
+ email:
16
+ - phoetmail@googlemail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".github/workflows/build.yaml"
22
+ - ".gitignore"
23
+ - ".irbrc"
24
+ - ".rubocop.yml"
25
+ - ".ruby-version"
26
+ - CHANGELOG.md
27
+ - Gemfile
28
+ - Gemfile.lock
29
+ - LICENSE.txt
30
+ - README.md
31
+ - Rakefile
32
+ - bin/console
33
+ - bin/setup
34
+ - lib/webflow.rb
35
+ - lib/webflow/client.rb
36
+ - lib/webflow/config.rb
37
+ - lib/webflow/error.rb
38
+ - lib/webflow/ruby.rb
39
+ - lib/webflow/version.rb
40
+ - webflow.gemspec
41
+ homepage: https://github.com/vfonic/webflow-rb
42
+ licenses:
43
+ - MIT
44
+ metadata:
45
+ rubygems_mfa_required: 'true'
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 2.7.0
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubygems_version: 3.4.22
62
+ signing_key:
63
+ specification_version: 4
64
+ summary: Webflow API wrapper
65
+ test_files: []