activeproject 0.0.0 → 0.1.1
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/README.md +28 -82
- data/Rakefile +4 -2
- data/lib/active_project/adapters/base.rb +3 -14
- data/lib/active_project/adapters/basecamp/comments.rb +27 -0
- data/lib/active_project/adapters/basecamp/connection.rb +49 -0
- data/lib/active_project/adapters/basecamp/issues.rb +139 -0
- data/lib/active_project/adapters/basecamp/lists.rb +54 -0
- data/lib/active_project/adapters/basecamp/projects.rb +110 -0
- data/lib/active_project/adapters/basecamp/webhooks.rb +73 -0
- data/lib/active_project/adapters/basecamp_adapter.rb +46 -449
- data/lib/active_project/adapters/jira/comments.rb +28 -0
- data/lib/active_project/adapters/jira/connection.rb +47 -0
- data/lib/active_project/adapters/jira/issues.rb +132 -0
- data/lib/active_project/adapters/jira/projects.rb +100 -0
- data/lib/active_project/adapters/jira/transitions.rb +68 -0
- data/lib/active_project/adapters/jira/webhooks.rb +89 -0
- data/lib/active_project/adapters/jira_adapter.rb +59 -486
- data/lib/active_project/adapters/trello/comments.rb +21 -0
- data/lib/active_project/adapters/trello/connection.rb +37 -0
- data/lib/active_project/adapters/trello/issues.rb +117 -0
- data/lib/active_project/adapters/trello/lists.rb +27 -0
- data/lib/active_project/adapters/trello/projects.rb +82 -0
- data/lib/active_project/adapters/trello/webhooks.rb +91 -0
- data/lib/active_project/adapters/trello_adapter.rb +54 -377
- data/lib/active_project/association_proxy.rb +10 -3
- data/lib/active_project/configuration.rb +23 -17
- data/lib/active_project/configurations/trello_configuration.rb +1 -3
- data/lib/active_project/resource_factory.rb +20 -10
- data/lib/active_project/resources/comment.rb +0 -5
- data/lib/active_project/resources/issue.rb +0 -5
- data/lib/active_project/resources/project.rb +0 -3
- data/lib/active_project/resources/user.rb +0 -1
- data/lib/active_project/version.rb +3 -1
- data/lib/activeproject.rb +67 -15
- metadata +26 -8
@@ -23,13 +23,11 @@ module ActiveProject
|
|
23
23
|
# Call adapter method with appropriate arguments
|
24
24
|
if primary_arg
|
25
25
|
@adapter.send(list_method, primary_arg, options)
|
26
|
-
|
26
|
+
elsif @adapter.method(list_method).arity.zero?
|
27
27
|
# Handle case where list method might not take options (like list_projects)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
@adapter.send(list_method, options)
|
32
|
-
end
|
28
|
+
@adapter.send(list_method)
|
29
|
+
else
|
30
|
+
@adapter.send(list_method, options)
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
@@ -89,7 +87,7 @@ module ActiveProject
|
|
89
87
|
def create(attributes = {})
|
90
88
|
# Determine the correct adapter create method based on resource type
|
91
89
|
create_method = determine_create_method
|
92
|
-
#
|
90
|
+
# NOTE: Assumes create methods on adapters take attributes hash directly
|
93
91
|
# Context like project_id needs to be part of the attributes hash if required by adapter
|
94
92
|
@adapter.send(create_method, attributes)
|
95
93
|
# A full implementation would likely involve build then save:
|
@@ -106,7 +104,11 @@ module ActiveProject
|
|
106
104
|
when "ActiveProject::Resources::Issue" then :list_issues
|
107
105
|
else raise "Cannot determine list method for #{@resource_class.name}"
|
108
106
|
end
|
109
|
-
|
107
|
+
unless @adapter.respond_to?(method_name)
|
108
|
+
raise NotImplementedError,
|
109
|
+
"#{@adapter.class.name} does not implement ##{method_name}"
|
110
|
+
end
|
111
|
+
|
110
112
|
method_name
|
111
113
|
end
|
112
114
|
|
@@ -116,14 +118,22 @@ module ActiveProject
|
|
116
118
|
when "ActiveProject::Resources::Issue" then :find_issue
|
117
119
|
else raise "Cannot determine find method for #{@resource_class.name}"
|
118
120
|
end
|
119
|
-
|
121
|
+
unless @adapter.respond_to?(method_name)
|
122
|
+
raise NotImplementedError,
|
123
|
+
"#{@adapter.class.name} does not implement ##{method_name}"
|
124
|
+
end
|
125
|
+
|
120
126
|
method_name
|
121
127
|
end
|
122
128
|
|
123
129
|
def determine_create_method
|
124
130
|
singular_name = @resource_class.name.split("::").last.downcase.to_sym
|
125
131
|
method_name = :"create_#{singular_name}"
|
126
|
-
|
132
|
+
unless @adapter.respond_to?(method_name)
|
133
|
+
raise NotImplementedError,
|
134
|
+
"#{@adapter.class.name} does not implement ##{method_name}"
|
135
|
+
end
|
136
|
+
|
127
137
|
method_name
|
128
138
|
end
|
129
139
|
end
|
@@ -1,16 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "base_resource"
|
4
|
-
|
5
3
|
module ActiveProject
|
6
4
|
module Resources
|
7
5
|
# Represents a Comment on an Issue
|
8
6
|
class Comment < BaseResource
|
9
7
|
def_members :id, :body, :author, :created_at, :updated_at, :issue_id,
|
10
8
|
:adapter_source
|
11
|
-
# raw_data and adapter are inherited from BaseResource
|
12
|
-
|
13
|
-
# Add comment-specific methods here later (e.g., save, update, delete)
|
14
9
|
end
|
15
10
|
end
|
16
11
|
end
|
@@ -7,8 +7,6 @@ module ActiveProject
|
|
7
7
|
def_members :id, :key, :title, :description, :status, :assignees,
|
8
8
|
:reporter, :project_id, :created_at, :updated_at, :due_on,
|
9
9
|
:priority, :adapter_source
|
10
|
-
# raw_data and adapter are inherited from BaseResource
|
11
|
-
|
12
10
|
|
13
11
|
# Saves the issue (creates if new, updates if existing).
|
14
12
|
# Placeholder - Full implementation requires attribute tracking and adapter delegation.
|
@@ -28,14 +26,11 @@ module ActiveProject
|
|
28
26
|
raise NotImplementedError, "#update not yet implemented for #{self.class.name}"
|
29
27
|
end
|
30
28
|
|
31
|
-
|
32
29
|
# Returns an association proxy for accessing comments on this issue.
|
33
30
|
# @return [AssociationProxy<Resources::Comment>]
|
34
31
|
def comments
|
35
32
|
AssociationProxy.new(owner: self, adapter: @adapter, association_name: :comments)
|
36
33
|
end
|
37
|
-
|
38
|
-
# Add issue-specific methods here later (e.g., comments association, save, update)
|
39
34
|
end
|
40
35
|
end
|
41
36
|
end
|
@@ -7,14 +7,11 @@ module ActiveProject
|
|
7
7
|
def_members :id, :key, :name, :adapter_source
|
8
8
|
# raw_data and adapter are inherited from BaseResource
|
9
9
|
|
10
|
-
|
11
10
|
# Returns an association proxy for accessing issues within this project.
|
12
11
|
# @return [AssociationProxy<Resources::Issue>]
|
13
12
|
def issues
|
14
13
|
AssociationProxy.new(owner: self, adapter: @adapter, association_name: :issues)
|
15
14
|
end
|
16
|
-
|
17
|
-
# Add project-specific methods here later (e.g., issues association)
|
18
15
|
end
|
19
16
|
end
|
20
17
|
end
|
data/lib/activeproject.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "zeitwerk"
|
2
|
+
require "concurrent"
|
2
3
|
require_relative "active_project/errors"
|
3
4
|
require_relative "active_project/version"
|
4
5
|
|
@@ -14,6 +15,11 @@ module ActiveProject
|
|
14
15
|
yield(configuration)
|
15
16
|
end
|
16
17
|
|
18
|
+
# Resets all cached adapters, forcing them to be re-initialized with current configuration
|
19
|
+
# @return [void]
|
20
|
+
def reset_adapters
|
21
|
+
adapter_registry.clear if defined?(@adapter_registry) && @adapter_registry
|
22
|
+
end
|
17
23
|
|
18
24
|
# Returns the configured User-Agent string, including the gem version.
|
19
25
|
# @return [String] The User-Agent string.
|
@@ -23,33 +29,79 @@ module ActiveProject
|
|
23
29
|
end
|
24
30
|
|
25
31
|
# Returns a memoized instance of the requested adapter.
|
26
|
-
#
|
27
|
-
# @
|
32
|
+
# Thread-safe implementation using Concurrent::Map for the adapter registry.
|
33
|
+
# @param adapter_type [Symbol] The name of the adapter (e.g., :jira, :trello).
|
34
|
+
# @param instance_name [Symbol] The name of the adapter instance (default: :primary).
|
35
|
+
# @return [ActiveProject::Adapters::Base] An instance of a specific adapter class that inherits from Base.
|
28
36
|
# @raise [ArgumentError] if the adapter configuration is missing or invalid.
|
29
37
|
# @raise [LoadError] if the adapter class cannot be found.
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
38
|
+
# @raise [NameError] if the adapter class cannot be found after loading the file.
|
39
|
+
def adapter(adapter_type, instance_name = :primary)
|
40
|
+
key = "#{adapter_type}_#{instance_name}".to_sym
|
41
|
+
|
42
|
+
adapter_registry.fetch_or_store(key) do
|
43
|
+
config = configuration.adapter_config(adapter_type, instance_name)
|
34
44
|
|
35
45
|
unless config.is_a?(ActiveProject::Configurations::BaseAdapterConfiguration)
|
36
|
-
|
46
|
+
available_configs = list_available_configurations
|
47
|
+
|
48
|
+
error_message = "Configuration for adapter ':#{adapter_type}' (instance ':#{instance_name}') not found or invalid.\n\n"
|
49
|
+
|
50
|
+
if available_configs.empty?
|
51
|
+
error_message += "No adapters are currently configured. "
|
52
|
+
else
|
53
|
+
error_message += "Available configurations:\n"
|
54
|
+
available_configs.each do |adapter_key, config_type|
|
55
|
+
error_message += " * #{adapter_key} (#{config_type})\n"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
error_message += "\nTo configure, use:\n"
|
60
|
+
error_message += " ActiveProject.configure do |config|\n"
|
61
|
+
error_message += " config.add_adapter :#{adapter_type}, :#{instance_name}, { your_options_here }\n"
|
62
|
+
error_message += " end"
|
63
|
+
|
64
|
+
raise ArgumentError, error_message
|
37
65
|
end
|
38
66
|
|
39
|
-
|
40
|
-
adapter_class_name = "ActiveProject::Adapters::#{adapter_name.to_s.capitalize}Adapter"
|
67
|
+
adapter_class_name = "ActiveProject::Adapters::#{adapter_type.to_s.capitalize}Adapter"
|
41
68
|
|
42
|
-
|
43
|
-
|
69
|
+
begin
|
70
|
+
require "active_project/adapters/#{adapter_type}_adapter"
|
71
|
+
rescue LoadError => e
|
72
|
+
error_message = "Could not load adapter '#{adapter_type}'.\n"
|
73
|
+
error_message += "Make sure you have defined the class #{adapter_class_name} in active_project/adapters/#{adapter_type}_adapter.rb"
|
74
|
+
raise LoadError, error_message
|
75
|
+
end
|
44
76
|
|
45
|
-
|
46
|
-
|
77
|
+
begin
|
78
|
+
adapter_class = Object.const_get(adapter_class_name)
|
79
|
+
rescue NameError => e
|
80
|
+
error_message = "Could not find adapter class #{adapter_class_name}.\n"
|
81
|
+
error_message += "Make sure you have defined the class correctly in active_project/adapters/#{adapter_type}_adapter.rb"
|
82
|
+
raise NameError, error_message
|
83
|
+
end
|
47
84
|
|
48
85
|
adapter_class.new(config: config)
|
49
|
-
rescue LoadError, NameError => e
|
50
|
-
raise LoadError, "Could not find adapter class #{adapter_class_name}: #{e.message}"
|
51
86
|
end
|
52
87
|
end
|
88
|
+
|
89
|
+
# Lists all available configurations in the format adapter_name:instance_name
|
90
|
+
# @return [Hash] A hash mapping configuration keys to their configuration types
|
91
|
+
def list_available_configurations
|
92
|
+
result = {}
|
93
|
+
configuration.adapter_configs.each do |key, config|
|
94
|
+
config_type = config.class.name.split("::").last
|
95
|
+
result[key] = config_type
|
96
|
+
end
|
97
|
+
result
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns a thread-safe map that stores adapter instances
|
101
|
+
# @return [Concurrent::Map] Thread-safe hash implementation
|
102
|
+
def adapter_registry
|
103
|
+
@adapter_registry ||= Concurrent::Map.new
|
104
|
+
end
|
53
105
|
end
|
54
106
|
end
|
55
107
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activeproject
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abdelkader Boudih
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-04-
|
10
|
+
date: 2025-04-10 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: activesupport
|
@@ -35,14 +35,14 @@ dependencies:
|
|
35
35
|
requirements:
|
36
36
|
- - ">="
|
37
37
|
- !ruby/object:Gem::Version
|
38
|
-
version: '0'
|
38
|
+
version: '2.0'
|
39
39
|
type: :runtime
|
40
40
|
prerelease: false
|
41
41
|
version_requirements: !ruby/object:Gem::Requirement
|
42
42
|
requirements:
|
43
43
|
- - ">="
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: '0'
|
45
|
+
version: '2.0'
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: faraday-retry
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,8 +84,26 @@ files:
|
|
84
84
|
- README.md
|
85
85
|
- Rakefile
|
86
86
|
- lib/active_project/adapters/base.rb
|
87
|
+
- lib/active_project/adapters/basecamp/comments.rb
|
88
|
+
- lib/active_project/adapters/basecamp/connection.rb
|
89
|
+
- lib/active_project/adapters/basecamp/issues.rb
|
90
|
+
- lib/active_project/adapters/basecamp/lists.rb
|
91
|
+
- lib/active_project/adapters/basecamp/projects.rb
|
92
|
+
- lib/active_project/adapters/basecamp/webhooks.rb
|
87
93
|
- lib/active_project/adapters/basecamp_adapter.rb
|
94
|
+
- lib/active_project/adapters/jira/comments.rb
|
95
|
+
- lib/active_project/adapters/jira/connection.rb
|
96
|
+
- lib/active_project/adapters/jira/issues.rb
|
97
|
+
- lib/active_project/adapters/jira/projects.rb
|
98
|
+
- lib/active_project/adapters/jira/transitions.rb
|
99
|
+
- lib/active_project/adapters/jira/webhooks.rb
|
88
100
|
- lib/active_project/adapters/jira_adapter.rb
|
101
|
+
- lib/active_project/adapters/trello/comments.rb
|
102
|
+
- lib/active_project/adapters/trello/connection.rb
|
103
|
+
- lib/active_project/adapters/trello/issues.rb
|
104
|
+
- lib/active_project/adapters/trello/lists.rb
|
105
|
+
- lib/active_project/adapters/trello/projects.rb
|
106
|
+
- lib/active_project/adapters/trello/webhooks.rb
|
89
107
|
- lib/active_project/adapters/trello_adapter.rb
|
90
108
|
- lib/active_project/association_proxy.rb
|
91
109
|
- lib/active_project/configuration.rb
|
@@ -101,12 +119,12 @@ files:
|
|
101
119
|
- lib/active_project/version.rb
|
102
120
|
- lib/active_project/webhook_event.rb
|
103
121
|
- lib/activeproject.rb
|
104
|
-
homepage: https://github.com/seuros/
|
122
|
+
homepage: https://github.com/seuros/active_project
|
105
123
|
licenses:
|
106
124
|
- MIT
|
107
125
|
metadata:
|
108
|
-
homepage_uri: https://github.com/seuros/
|
109
|
-
source_code_uri: https://github.com/seuros/
|
126
|
+
homepage_uri: https://github.com/seuros/active_project
|
127
|
+
source_code_uri: https://github.com/seuros/active_project
|
110
128
|
rdoc_options: []
|
111
129
|
require_paths:
|
112
130
|
- lib
|
@@ -121,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
139
|
- !ruby/object:Gem::Version
|
122
140
|
version: '0'
|
123
141
|
requirements: []
|
124
|
-
rubygems_version: 3.6.
|
142
|
+
rubygems_version: 3.6.5
|
125
143
|
specification_version: 4
|
126
144
|
summary: A standardized Ruby interface for multiple project management APIs (Jira,
|
127
145
|
Basecamp, Trello, etc.).
|