researchable-freedcamp-api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.bundle/config +2 -0
  3. data/.gitignore +1 -0
  4. data/Gemfile +7 -0
  5. data/Gemfile.lock +69 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +39 -0
  8. data/Rakefile +12 -0
  9. data/bin/console +15 -0
  10. data/bin/setup +8 -0
  11. data/lib/researchable/freedcamp_api/create_task.rb +22 -0
  12. data/lib/researchable/freedcamp_api/endpoint.rb +34 -0
  13. data/lib/researchable/freedcamp_api/list_milestones.rb +1 -0
  14. data/lib/researchable/freedcamp_api/list_projects.rb +1 -0
  15. data/lib/researchable/freedcamp_api/list_tasks.rb +36 -0
  16. data/lib/researchable/freedcamp_api/sessions/session.rb +28 -0
  17. data/lib/researchable/freedcamp_api/sessions/signed_session.rb +128 -0
  18. data/lib/researchable/freedcamp_api/sessions.rb +17 -0
  19. data/lib/researchable/freedcamp_api/structs/signature.rb +11 -0
  20. data/lib/researchable/freedcamp_api/structs/task.rb +48 -0
  21. data/lib/researchable/freedcamp_api/structs.rb +8 -0
  22. data/lib/researchable/freedcamp_api/update_task.rb +27 -0
  23. data/lib/researchable/freedcamp_api/version.rb +8 -0
  24. data/lib/researchable/freedcamp_api.rb +21 -0
  25. data/lib/researchable-freedcamp-api.rb +6 -0
  26. data/output/62d1c67bf1eebc3456f9cc8879519700b2a0fc45 +1 -0
  27. data/researchable_freedcamp_api.gemspec +44 -0
  28. data/sorbet/config +3 -0
  29. data/sorbet/rbi/gems/active_interaction.rbi +304 -0
  30. data/sorbet/rbi/gems/activemodel.rbi +342 -0
  31. data/sorbet/rbi/gems/activesupport.rbi +1023 -0
  32. data/sorbet/rbi/gems/concurrent-ruby.rbi +1662 -0
  33. data/sorbet/rbi/gems/httparty.rbi +446 -0
  34. data/sorbet/rbi/gems/i18n.rbi +133 -0
  35. data/sorbet/rbi/gems/mime-types-data.rbi +17 -0
  36. data/sorbet/rbi/gems/mime-types.rbi +225 -0
  37. data/sorbet/rbi/gems/multi_xml.rbi +35 -0
  38. data/sorbet/rbi/gems/researchable-freedcamp-api.rbi +25 -0
  39. data/sorbet/rbi/gems/rspec-core.rbi +1915 -0
  40. data/sorbet/rbi/gems/rspec-expectations.rbi +1151 -0
  41. data/sorbet/rbi/gems/rspec-mocks.rbi +1110 -0
  42. data/sorbet/rbi/gems/rspec-support.rbi +280 -0
  43. data/sorbet/rbi/gems/rspec.rbi +15 -0
  44. data/sorbet/rbi/gems/tzinfo.rbi +586 -0
  45. data/sorbet/rbi/hidden-definitions/errors.txt +4251 -0
  46. data/sorbet/rbi/hidden-definitions/hidden.rbi +8306 -0
  47. data/sorbet/rbi/sorbet-typed/lib/activemodel/all/activemodel.rbi +715 -0
  48. data/sorbet/rbi/sorbet-typed/lib/activesupport/>=6/activesupport.rbi +37 -0
  49. data/sorbet/rbi/sorbet-typed/lib/activesupport/all/activesupport.rbi +1850 -0
  50. data/sorbet/rbi/sorbet-typed/lib/httparty/all/httparty.rbi +566 -0
  51. data/sorbet/rbi/sorbet-typed/lib/minitest/all/minitest.rbi +108 -0
  52. data/sorbet/rbi/sorbet-typed/lib/rspec-core/all/rspec-core.rbi +24 -0
  53. data/sorbet/rbi/todo.rbi +7 -0
  54. data/test.rb +41 -0
  55. metadata +198 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 75d48e7be6f5c575ec993b2dc2051d27083b91b643ed6ff89ce75056e3303089
4
+ data.tar.gz: 182f78158dabec5f59889a00a277187ba5b7d57651787630672875ef94a94bab
5
+ SHA512:
6
+ metadata.gz: 3eb40dbd7912f74b5391d6951c617e60e6552db39df5992cbe8bd140b20a3bc893e288537a95814c7e640f6df699c1621fd9d6339914d128ae712cd35468be1e
7
+ data.tar.gz: ffe562dc9a4aa8f8d682d23b513d892cfbe3854b7d6b36eb8f153041427c633b72de236dcd8507af551bf70c6ba1d7ad793d526acf2595f55377e504d65bf63a
data/.bundle/config ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_JOBS: "8"
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ output/*
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in researchable_freedcamp_api.gemspec
6
+ gemspec
7
+
data/Gemfile.lock ADDED
@@ -0,0 +1,69 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ researchable-freedcamp-api (0.1.0)
5
+ active_interaction (>= 3.2)
6
+ httparty (>= 0.14)
7
+ sorbet-runtime
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ active_interaction (4.1.0)
13
+ activemodel (>= 5, < 8)
14
+ activesupport (>= 5, < 8)
15
+ activemodel (6.1.4.4)
16
+ activesupport (= 6.1.4.4)
17
+ activesupport (6.1.4.4)
18
+ concurrent-ruby (~> 1.0, >= 1.0.2)
19
+ i18n (>= 1.6, < 2)
20
+ minitest (>= 5.1)
21
+ tzinfo (~> 2.0)
22
+ zeitwerk (~> 2.3)
23
+ byebug (11.1.3)
24
+ concurrent-ruby (1.1.9)
25
+ diff-lcs (1.5.0)
26
+ httparty (0.20.0)
27
+ mime-types (~> 3.0)
28
+ multi_xml (>= 0.5.2)
29
+ i18n (1.8.11)
30
+ concurrent-ruby (~> 1.0)
31
+ mime-types (3.4.1)
32
+ mime-types-data (~> 3.2015)
33
+ mime-types-data (3.2022.0105)
34
+ minitest (5.15.0)
35
+ multi_xml (0.6.0)
36
+ rspec (3.10.0)
37
+ rspec-core (~> 3.10.0)
38
+ rspec-expectations (~> 3.10.0)
39
+ rspec-mocks (~> 3.10.0)
40
+ rspec-core (3.10.1)
41
+ rspec-support (~> 3.10.0)
42
+ rspec-expectations (3.10.2)
43
+ diff-lcs (>= 1.2.0, < 2.0)
44
+ rspec-support (~> 3.10.0)
45
+ rspec-mocks (3.10.2)
46
+ diff-lcs (>= 1.2.0, < 2.0)
47
+ rspec-support (~> 3.10.0)
48
+ rspec-support (3.10.3)
49
+ sorbet (0.5.9542)
50
+ sorbet-static (= 0.5.9542)
51
+ sorbet-runtime (0.5.9468)
52
+ sorbet-static (0.5.9542-x86_64-linux)
53
+ tzinfo (2.0.4)
54
+ concurrent-ruby (~> 1.0)
55
+ zeitwerk (2.5.3)
56
+
57
+ PLATFORMS
58
+ ruby
59
+ x86_64-linux
60
+
61
+ DEPENDENCIES
62
+ bundler (> 0)
63
+ byebug
64
+ researchable-freedcamp-api!
65
+ rspec (~> 3.0)
66
+ sorbet
67
+
68
+ BUNDLED WITH
69
+ 2.2.15
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Frank Blaauw
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,39 @@
1
+ # FreedcampApi
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/freedcamp_api`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'freedcamp_api'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install freedcamp_api
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/freedcamp_api.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "researchable-freedcamp-api"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
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,22 @@
1
+ # typed: false
2
+ # typed: sigil
3
+ #
4
+ module Researchable
5
+ module FreedcampApi
6
+ # @api private
7
+ class CreateTask < Endpoint
8
+ object :task, class: Researchable::FreedcampApi::Structs::Task
9
+ def execute
10
+ create_task(task)
11
+ end
12
+
13
+ private
14
+
15
+ sig { params(task: Researchable::FreedcampApi::Structs::Task).returns(T::Hash[T.untyped, T.untyped]) }
16
+ def create_task(task)
17
+ # title
18
+ session.post('/tasks', task)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,34 @@
1
+ # typed: strict
2
+ #
3
+ module Researchable
4
+ module FreedcampApi
5
+ # TODO: Does this work?
6
+ class Endpoint < ActiveInteraction::Base
7
+ # class Endpoint < T::Types::Base
8
+ extend T::Sig
9
+ object :session,
10
+ default: -> { FreedcampApi.signed_session },
11
+ class: Researchable::FreedcampApi::Sessions::Session
12
+
13
+ private
14
+
15
+ # Fetch all browses paginated responses
16
+ # @param keyword [[TODO:type]] [TODO:description]
17
+ sig { params(keyword: String).returns(T::Array[T.untyped]) }
18
+ def fetch_all(keyword)
19
+ result = T.let([], T::Array[T.untyped])
20
+ has_more = T.let(true, T::Boolean)
21
+ offset = T.let(0, Integer)
22
+ limit = T.let(200, Integer)
23
+
24
+ while has_more
25
+ temp = yield limit, offset
26
+ has_more = T.let(temp.dig('data', 'meta', 'has_more') == 'true', T::Boolean)
27
+ result += temp['data'][keyword]
28
+ offset += limit
29
+ end
30
+ result
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1 @@
1
+ # typed: strict
@@ -0,0 +1 @@
1
+ # typed: strict
@@ -0,0 +1,36 @@
1
+ # typed: false
2
+ module Researchable
3
+ module FreedcampApi
4
+ class ListTasks < Endpoint
5
+ integer :task_id, default: nil
6
+ integer :f_with_archived, default: 1
7
+
8
+ # Accepts "active", "archived", "all" values. Omitting is equal to "active".
9
+ string :lists_status, default: 'active'
10
+ integer :f_cf, default: 1
11
+
12
+ # @api private
13
+ def execute
14
+ list_tasks(task_id)
15
+ end
16
+
17
+ sig do
18
+ params(
19
+ task_id: T.nilable(Integer)
20
+ ).returns(
21
+ T::Array[Researchable::FreedcampApi::Structs::Task]
22
+ )
23
+ end
24
+ def list_tasks(task_id)
25
+ task_query = task_id ? "/#{task_id}" : '/'
26
+ fetch_all('tasks') do |limit, offset|
27
+ session.get("/tasks#{task_query}?limit=#{limit}
28
+ &offset=#{offset}
29
+ &f_with_archived=#{f_with_archived}
30
+ &f_cf=#{f_cf}
31
+ &lists_status=#{lists_status}")
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,28 @@
1
+ # typed: strict
2
+ module Researchable
3
+ module FreedcampApi
4
+ module Sessions
5
+ class Session
6
+ extend T::Sig
7
+ extend T::Helpers # (1)
8
+ abstract! # (2)
9
+
10
+ sig { abstract.params(path: String).returns(T::Hash[T.untyped, T.untyped]) }
11
+ def get(path); end
12
+
13
+ # (3)
14
+ sig do
15
+ abstract.params(
16
+ path: String,
17
+ data: T.any(
18
+ Researchable::FreedcampApi::Structs::Task,
19
+ Researchable::FreedcampApi::Structs::Comment,
20
+ T::Hash[T.untyped, T.untyped]
21
+ )
22
+ ).returns(T.untyped)
23
+ end
24
+ def post(path, data); end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,128 @@
1
+ # typed: strict
2
+ require 'json'
3
+ require 'httparty'
4
+ require 'byebug'
5
+
6
+ require_relative '../structs/signature'
7
+ require_relative '../structs/task'
8
+
9
+ module Researchable
10
+ module FreedcampApi
11
+ module Sessions
12
+ class SignedSession < Session
13
+ extend T::Sig
14
+ extend T::Helpers
15
+
16
+ BASE = T.let('https://freedcamp.com/api/v1'.freeze, String)
17
+ HEADERS = T.let({ 'Content-Type' => 'application/x-www-form-urlencoded' }.freeze,
18
+ T::Hash[T.untyped, T.untyped])
19
+
20
+ # rubocop:disable Style/AccessorGrouping
21
+ sig { returns(String) }
22
+ attr_reader :public_key
23
+
24
+ sig { returns(String) }
25
+ attr_reader :secret_key
26
+
27
+ sig { returns(T::Boolean) }
28
+ attr_reader :use_cache
29
+
30
+ # rubocop:enable Style/AccessorGrouping
31
+
32
+ sig { params(public_key: String, secret_key: String, use_cache: T::Boolean).void }
33
+ def initialize(public_key: ENV['PUBLIC_KEY'], secret_key: ENV['SECRET_KEY'], use_cache: true)
34
+ @public_key = public_key
35
+ @secret_key = secret_key
36
+ @use_cache = use_cache
37
+ end
38
+
39
+ sig { override.params(path: String).returns(T::Hash[T.untyped, T.untyped]) }
40
+ def get(path)
41
+ call_url(path, :get)
42
+ end
43
+
44
+ # (3)
45
+ sig do
46
+ override.params(
47
+ path: String,
48
+ data: T.any(
49
+ Researchable::FreedcampApi::Structs::Task,
50
+ Researchable::FreedcampApi::Structs::Comment,
51
+ T::Hash[T.untyped, T.untyped]
52
+ )
53
+ ).returns(T.untyped)
54
+ end
55
+ def post(path, data)
56
+ call_url(path, :post, data)
57
+ end
58
+
59
+ private
60
+
61
+ sig do
62
+ params(
63
+ path: String, method: Symbol,
64
+ data: T.any(
65
+ Researchable::FreedcampApi::Structs::Task,
66
+ Researchable::FreedcampApi::Structs::Comment,
67
+ T::Hash[T.untyped, T.untyped]
68
+ )
69
+ ).returns(T::Hash[T.untyped, T.untyped])
70
+ end
71
+ def call_url(path, method, data = {})
72
+ cache_url = "output/#{Digest::SHA1.hexdigest(path + method.to_s)}"
73
+ content = if data == {} && File.exist?(cache_url) && @use_cache
74
+ render_cache(cache_url)
75
+ else
76
+ render_call(path, method, data, cache_url)
77
+ end
78
+
79
+ content = JSON.parse(content) if content
80
+ content
81
+ end
82
+
83
+ def render_cache(cache_url)
84
+ file = File.open(cache_url)
85
+ content = file.read
86
+ end
87
+
88
+ def render_call(path, method, data, cache_url)
89
+ signature = generate_signature
90
+ url = make_url(path, signature)
91
+ data = serialize_data(data)
92
+ content = HTTParty.send(method,
93
+ url,
94
+ body: data,
95
+ headers: HEADERS).body
96
+ File.open(cache_url, 'w') { |f| f.write content }
97
+ content
98
+ end
99
+
100
+ def serialize_data(data = {})
101
+ return {} if data == {}
102
+
103
+ data = data.serialize if data.is_a? T::Struct
104
+ data = { data: data.to_json }
105
+ end
106
+
107
+ sig { params(path: String, signature: Signature).returns(String) }
108
+ def make_url(path, signature)
109
+ result = BASE + path
110
+ sep = result.include?('?') ? '&' : '?'
111
+ result + "#{sep}api_key=#{signature.api_key}&timestamp=#{signature.timestamp}&hash=#{signature.calculated_hash}"
112
+ end
113
+
114
+ sig { returns(Signature) }
115
+ def generate_signature
116
+ time = Time.new.to_i * 1000
117
+ data = "#{@public_key}#{time}"
118
+ signature = OpenSSL::HMAC.hexdigest('sha1', @secret_key, data)
119
+ Signature.new(
120
+ timestamp: time,
121
+ api_key: @public_key,
122
+ calculated_hash: signature
123
+ )
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,17 @@
1
+ # typed: false
2
+ # typed: sigil
3
+ require 'httparty'
4
+ require_relative 'sessions/session'
5
+ require_relative 'sessions/signed_session'
6
+
7
+ module Researchable
8
+ module FreedcampApi
9
+ extend T::Sig
10
+
11
+ def self.signed_session(*arguments, &block)
12
+ Researchable::FreedcampApi::Sessions::SignedSession.new(
13
+ *arguments, &block)
14
+ #public_key: ENV['PUBLIC_KEY'], secret_key: ENV['SECRET_KEY'], use_cache: true
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ # typed: strict
2
+ #require 'sorbet-runtime'
3
+
4
+ # (1) Create a new class that subclasses `T::Struct`
5
+ class Signature < T::Struct
6
+ # (2) Declare fields on the struct with the `prop` and `const` DSL
7
+ prop :timestamp, Integer
8
+ const :api_key, String
9
+ const :calculated_hash, String
10
+ end
11
+
@@ -0,0 +1,48 @@
1
+ # typed: strict
2
+ # require 'sorbet-runtime'
3
+
4
+ # (1) Create a new class that subclasses `T::Struct`
5
+ module Researchable
6
+ module FreedcampApi
7
+ module Structs
8
+ class Task < T::Struct
9
+ const :title, T.nilable(String)
10
+ const :description, T.nilable(String)
11
+ const :project_id, T.nilable(String)
12
+ # Can be empty or absent if task_group_name is passed
13
+ const :task_group_id, T.nilable(String)
14
+
15
+ # If passed, task_group_id is ignored, and new tasks group with this name will be created
16
+ const :task_group_name, T.nilable(String)
17
+
18
+ # Will be used if task_group_name passed, can be an empty string or absent
19
+ const :task_group_description, T.nilable(String)
20
+
21
+ # Priority id. See priorities for :get.
22
+ const :priority, T.nilable(Integer)
23
+
24
+ # Should contain assigned to user id OR one of the two constants: -1 (ASSIGNED_EVERYONE) and 0 (ASSIGNED_NOONE)
25
+ const :assigned_to_id, T.nilable(String)
26
+ const :assigned_ids, T.nilable(T::Array[String])
27
+
28
+ # Can be empty or absent, the format is YYYY-MM-DD (empty value will be used if start_date is not allowed for the plan. Old start_date will be overridden in this case, if any).
29
+ const :start_date, T.nilable(String)
30
+
31
+ # The recurrence rule in iCalendar (RFC 5545) format, can be an empty string or absent
32
+ const :r_rule, T.nilable(String)
33
+
34
+ # Can be empty or absent, the format is YYYY-MM-DD
35
+ const :due_date, T.nilable(String)
36
+
37
+ # An array of files uploaded previously with temporary=1 flag
38
+ const :attached_ids, T.nilable(Integer)
39
+
40
+ # Can be absent or empty. It contains a parent task id. Note: parent task should be in the same tasks group as passed task_group_id. WARN! if a project, where subtask is added to, does not allow advanced subtasks (i.e. has f_subtasks_adv = false, see above), added subtask should contain empty string for description and due_date fields, and "0" for priority and assigned_to_id fields. Also, the parent task should not be a subtask. In case when other values are passed, they will be implicitly fixed to the right values with triggering an error sent to Freedcamp developers.
41
+ const :item_parent_id, T.nilable(Integer)
42
+
43
+ const :status, T.nilable(Integer)
44
+ const :status_title, T.nilable(String)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,8 @@
1
+ require_relative 'structs/task'
2
+ require_relative 'structs/comment'
3
+ module Researchable
4
+ module FreedcampApi
5
+ module Structs
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,27 @@
1
+ # typed: false
2
+ #
3
+ module Researchable
4
+ module FreedcampApi
5
+ class UpdateTask < Endpoint
6
+ integer :task_id, default: 44_509_132
7
+ object :task, class: Researchable::FreedcampApi::Structs::Task
8
+
9
+ def execute
10
+ update_task(task_id, task)
11
+ end
12
+
13
+ sig do
14
+ params(
15
+ task_id: Integer,
16
+ task: Researchable::FreedcampApi::Structs::Task
17
+ ).returns(
18
+ T::Array[Researchable::FreedcampApi::Structs::Task]
19
+ )
20
+ end
21
+ def update_task(task_id, task)
22
+ result = session.post("/tasks/#{task_id}", task)
23
+ result['data']['tasks']
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,8 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Researchable
5
+ module FreedcampApi
6
+ VERSION = "0.1.0"
7
+ end
8
+ end
@@ -0,0 +1,21 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'active_interaction'
5
+ require_relative 'freedcamp_api/version'
6
+ require_relative 'freedcamp_api/structs'
7
+ require_relative 'freedcamp_api/sessions'
8
+ require_relative 'freedcamp_api/endpoint'
9
+
10
+ require_relative 'freedcamp_api/list_tasks'
11
+ require_relative 'freedcamp_api/update_task'
12
+ require_relative 'freedcamp_api/create_task'
13
+
14
+ require_relative 'freedcamp_api/create_comment'
15
+
16
+ module Researchable
17
+ module FreedcampApi
18
+ class Error < StandardError; end
19
+ # Your code goes here...
20
+ end
21
+ end
@@ -0,0 +1,6 @@
1
+ # typed: strict
2
+ require 'sorbet-runtime'
3
+ require_relative 'researchable/freedcamp_api'
4
+
5
+ module Researchable
6
+ end