bmx-event_hook_client_server 1.0.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.
Files changed (29) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +11 -0
  3. data/Gemfile.lock +80 -0
  4. data/event_hook_client_server.gemspec +65 -0
  5. data/lib/event_hook_client_server.rb +13 -0
  6. data/lib/event_hook_client_server/client.rb +177 -0
  7. data/lib/event_hook_client_server/client/models/error.rb +16 -0
  8. data/lib/event_hook_client_server/client/models/integration.rb +25 -0
  9. data/lib/event_hook_client_server/client/models/integrations/binding.rb +21 -0
  10. data/lib/event_hook_client_server/client/response.rb +43 -0
  11. data/lib/event_hook_client_server/errors.rb +5 -0
  12. data/lib/event_hook_client_server/protobuf/event_hook_client_server/v1/enums/integrator_pb.rb +20 -0
  13. data/lib/event_hook_client_server/protobuf/event_hook_client_server/v1/messages/error_pb.rb +23 -0
  14. data/lib/event_hook_client_server/protobuf/event_hook_client_server/v1/messages/integration_pb.rb +107 -0
  15. data/lib/event_hook_client_server/protobuf/event_hook_client_server/v1/messages/pagination_pb.rb +35 -0
  16. data/lib/event_hook_client_server/protobuf/event_hook_client_server/v1/services/webhook_configurator_pb.rb +17 -0
  17. data/lib/event_hook_client_server/protobuf/event_hook_client_server/v1/services/webhook_configurator_services_pb.rb +38 -0
  18. data/lib/event_hook_client_server/refinements/hash/bury.rb +19 -0
  19. data/lib/event_hook_client_server/refinements/hash/transmute.rb +27 -0
  20. data/lib/event_hook_client_server/refinements/object/bubbling_const_lookup.rb +60 -0
  21. data/lib/event_hook_client_server/refinements/protobuf/hashable_struct_values.rb +28 -0
  22. data/lib/event_hook_client_server/refinements/protobuf/nullable_values.rb +122 -0
  23. data/lib/event_hook_client_server/server.rb +100 -0
  24. data/lib/event_hook_client_server/server/request_processor.rb +61 -0
  25. data/lib/event_hook_client_server/service.rb +9 -0
  26. data/lib/event_hook_client_server/services/grpc/struct_encoder.rb +62 -0
  27. data/lib/event_hook_client_server/types.rb +9 -0
  28. data/lib/event_hook_client_server/version.rb +8 -0
  29. metadata +143 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6efc8bee29cfcfd9391e5331900e30fc47676c0cb25be9f09142a6acc35924d1
4
+ data.tar.gz: 714debdde3ca76fb171828d6f136225ab4772c793bb9b967741ffc47eb6d04d5
5
+ SHA512:
6
+ metadata.gz: 4a2b0548d0f5bb7e91962a0e68d1ae6340a55b45e60e3f33cc96bdd0a6c251f37947640cc85a33493e0a219f5892dc2f1aee895f116c9252f8fcef47ab30ad86
7
+ data.tar.gz: a6e77965718008f8cd1197546f8481084adf2b14fa819da0a5a0e14f9b661360ae73162a10c6789089fdc8b0bfbeffe04ad440bfb7d82e3cc7a46fa69ea8fd97
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ group :development, :test do
8
+ gem 'grpc'
9
+ gem 'grpc-tools'
10
+ gem 'pry'
11
+ end
@@ -0,0 +1,80 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ bmx-event_hook_client_server (1.0.1)
5
+ dry-struct (~> 1.0)
6
+ grpc
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ coderay (1.1.2)
12
+ concurrent-ruby (1.1.5)
13
+ diff-lcs (1.3)
14
+ dry-configurable (0.8.3)
15
+ concurrent-ruby (~> 1.0)
16
+ dry-core (~> 0.4, >= 0.4.7)
17
+ dry-container (0.7.2)
18
+ concurrent-ruby (~> 1.0)
19
+ dry-configurable (~> 0.1, >= 0.1.3)
20
+ dry-core (0.4.9)
21
+ concurrent-ruby (~> 1.0)
22
+ dry-equalizer (0.2.2)
23
+ dry-inflector (0.1.2)
24
+ dry-logic (1.0.3)
25
+ concurrent-ruby (~> 1.0)
26
+ dry-core (~> 0.2)
27
+ dry-equalizer (~> 0.2)
28
+ dry-struct (1.0.0)
29
+ dry-core (~> 0.4, >= 0.4.3)
30
+ dry-equalizer (~> 0.2)
31
+ dry-types (~> 1.0)
32
+ ice_nine (~> 0.11)
33
+ dry-types (1.1.1)
34
+ concurrent-ruby (~> 1.0)
35
+ dry-container (~> 0.3)
36
+ dry-core (~> 0.4, >= 0.4.4)
37
+ dry-equalizer (~> 0.2, >= 0.2.2)
38
+ dry-inflector (~> 0.1, >= 0.1.2)
39
+ dry-logic (~> 1.0, >= 1.0.2)
40
+ google-protobuf (3.8.0)
41
+ googleapis-common-protos-types (1.0.4)
42
+ google-protobuf (~> 3.0)
43
+ grpc (1.21.0)
44
+ google-protobuf (~> 3.7)
45
+ googleapis-common-protos-types (~> 1.0)
46
+ grpc-tools (1.21.0)
47
+ ice_nine (0.11.2)
48
+ method_source (0.9.2)
49
+ pry (0.12.2)
50
+ coderay (~> 1.1.0)
51
+ method_source (~> 0.9.0)
52
+ rake (10.5.0)
53
+ rspec (3.8.0)
54
+ rspec-core (~> 3.8.0)
55
+ rspec-expectations (~> 3.8.0)
56
+ rspec-mocks (~> 3.8.0)
57
+ rspec-core (3.8.1)
58
+ rspec-support (~> 3.8.0)
59
+ rspec-expectations (3.8.4)
60
+ diff-lcs (>= 1.2.0, < 2.0)
61
+ rspec-support (~> 3.8.0)
62
+ rspec-mocks (3.8.1)
63
+ diff-lcs (>= 1.2.0, < 2.0)
64
+ rspec-support (~> 3.8.0)
65
+ rspec-support (3.8.2)
66
+
67
+ PLATFORMS
68
+ ruby
69
+
70
+ DEPENDENCIES
71
+ bmx-event_hook_client_server!
72
+ bundler (~> 2.0)
73
+ grpc
74
+ grpc-tools
75
+ pry
76
+ rake (~> 10.0)
77
+ rspec (~> 3.0)
78
+
79
+ BUNDLED WITH
80
+ 2.0.1
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'event_hook_client_server/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'bmx-event_hook_client_server'
9
+ spec.version = EventHookClientServer::VERSION
10
+ spec.authors = ['Stanko K.R.']
11
+ spec.email = ['me@stanko.io']
12
+
13
+ spec.summary = 'Client and server implementation for the Webhook '\
14
+ 'Configurator service.'
15
+ spec.description = spec.summary
16
+ spec.homepage =
17
+ 'https://github.com/runslikebutter/event_hook_client_server'
18
+
19
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the
20
+ # 'allowed_push_host' to allow pushing to a single host or delete this
21
+ # section to allow pushing to any host.
22
+ if spec.respond_to?(:metadata)
23
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
24
+
25
+ spec.metadata['homepage_uri'] = spec.homepage
26
+ spec.metadata['source_code_uri'] = spec.homepage
27
+ spec.metadata['changelog_uri'] =
28
+ 'https://github.com/runslikebutter/event_hook_client_server/'\
29
+ 'blob/master/CHANGELOG.md'
30
+ else
31
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
32
+ 'public gem pushes.'
33
+ end
34
+
35
+ # Specify which files should be added to the gem when it is released.
36
+ # The `git ls-files -z` loads the files in the RubyGem that have been added
37
+ # into git.
38
+ IGNORED_FILES = [
39
+ '.gitignore',
40
+ '.rspec',
41
+ 'Makefile',
42
+ 'Rakefile',
43
+ 'README.md',
44
+ 'CHANGELOG.md',
45
+ /^bin\/.*$/,
46
+ /^protos\/.*$/
47
+ ]
48
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
49
+ `git ls-files -z`.split("\x0").reject do |f|
50
+ f.match(%r{^(test|spec|features)/})
51
+ end.reject do |f|
52
+ IGNORED_FILES.reduce(false) { |result, path| result || f.match?(path) }
53
+ end
54
+ end
55
+ spec.bindir = 'exe'
56
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
57
+ spec.require_paths = ['lib']
58
+
59
+ spec.add_dependency 'dry-struct', '~> 1.0'
60
+ spec.add_dependency 'grpc'
61
+
62
+ spec.add_development_dependency 'bundler', '~> 2.0'
63
+ spec.add_development_dependency 'rake', '~> 10.0'
64
+ spec.add_development_dependency 'rspec', '~> 3.0'
65
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ unless $LOAD_PATH.include?(__dir__)
4
+ $LOAD_PATH.unshift(File.expand_path(__dir__))
5
+ end
6
+
7
+ module EventHookClientServer
8
+ end
9
+
10
+ require 'event_hook_client_server/version'
11
+ require 'event_hook_client_server/errors'
12
+ require 'event_hook_client_server/server'
13
+ require 'event_hook_client_server/client'
@@ -0,0 +1,177 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'event_hook_client_server/protobuf/event_hook_client_server/v1/services/webhook_configurator_services_pb'
5
+ require 'event_hook_client_server/refinements/protobuf/nullable_values'
6
+ require 'event_hook_client_server/refinements/protobuf/hashable_struct_values'
7
+ require 'event_hook_client_server/refinements/object/bubbling_const_lookup'
8
+ require 'event_hook_client_server/refinements/hash/transmute'
9
+ require 'event_hook_client_server/refinements/hash/bury'
10
+ require 'event_hook_client_server/services/grpc/struct_encoder'
11
+
12
+ using EventHookClientServer::Refinements::Protobuf::HashableStructValues
13
+ using EventHookClientServer::Refinements::Protobuf::NullableValues
14
+ using EventHookClientServer::Refinements::Object::BubblingConstLookup
15
+ using EventHookClientServer::Refinements::Hash::Bury
16
+ using EventHookClientServer::Refinements::Hash::Transmute
17
+
18
+ module EventHookClientServer
19
+ class Client < EventHookClientServer::V1::Services::EventHook::Stub
20
+ DEFAULT_CONFIG = {
21
+ host: '0.0.0.0:3000',
22
+ channel_mode: :this_channel_is_insecure,
23
+ timeout: 6, # in seconds (negative number means disabled)
24
+ channel_args: {
25
+ 'grpc.min_reconnect_backoff_ms': 1_000,
26
+ 'grpc.max_reconnect_backoff_ms': 5_000
27
+ }
28
+ }.freeze
29
+ private_constant :DEFAULT_CONFIG
30
+
31
+ def self.default
32
+ @default ||= new(default_config)
33
+ end
34
+
35
+ def self.default_config
36
+ @default_config ||= DEFAULT_CONFIG.dup
37
+ end
38
+
39
+ def initialize(options)
40
+ options = self.class.default_config.merge(options)
41
+ super(
42
+ options[:host],
43
+ options[:channel_mode],
44
+ timeout: options[:timeout],
45
+ channel_args: options[:channel_args]
46
+ )
47
+ end
48
+
49
+ # FIND INTEGRATION FOR HEADERS
50
+ def find_integration_from_headers(headers: nil, cursor: nil)
51
+ request = V1::Messages::FindIntegrationsFromHeadersRequest.new(
52
+ headers: EventHookClientServer::GRPC::StructEncoder.call(headers),
53
+ pagination: { cursor: cursor }
54
+ )
55
+
56
+ response = handle_timeout { super(request) }
57
+
58
+ integrations = response.integrations.map do |integration|
59
+ Integration.new(integration.to_h)
60
+ end
61
+
62
+ Response.success!(data: integrations,
63
+ pagination: response.pagination.to_h)
64
+ end
65
+
66
+ # SHOW
67
+ def integration(id)
68
+ request = V1::Messages::GetIntegrationRequest.new(id: id.to_s)
69
+
70
+ response = handle_timeout { super(request) }
71
+
72
+ if response.errors.any?
73
+ Response.fail!(response.errors.map { |e| Error.new(e.to_h) })
74
+ else
75
+ Response.success!(data: Integration.new(response.integration.to_h))
76
+ end
77
+ end
78
+
79
+ # INDEX
80
+ def integrations(query_params: nil, cursor: nil, per_page: nil)
81
+ per_page =
82
+ if per_page.to_i.zero? || per_page.to_i.negative?
83
+ 10
84
+ else
85
+ per_page.to_i
86
+ end
87
+
88
+ pagination = { cursor: cursor.to_s, per_page: per_page }
89
+
90
+ query_params&.each_with_object(query_params) do |(key, value), hash|
91
+ hash[key] = { value: value.to_s } unless value.nil?
92
+ end
93
+
94
+ request =
95
+ V1::Messages::ListIntegrationsRequest.new(query_params: query_params,
96
+ pagination: pagination)
97
+
98
+ response = handle_timeout { super(request) }
99
+
100
+ integrations = response.integrations.map do |integration|
101
+ Integration.new(integration.to_h)
102
+ end
103
+
104
+ Response.success!(data: integrations,
105
+ pagination: response.pagination.to_h)
106
+ end
107
+
108
+ # CREATE
109
+ def create_integration(params: {})
110
+ params = symbolize_keys(params)
111
+ params.transmute(EventHookClientServer::GRPC::StructEncoder,
112
+ %I[config parmas])
113
+
114
+ request = V1::Messages::IntegrationCreateRequest.new(input: params)
115
+
116
+ response = handle_timeout { super(request) }
117
+
118
+ if response.errors.any?
119
+ Response.fail!(response.errors.map { |e| Error.new(e.to_h) })
120
+ else
121
+ Response.success!(data: Integration.new(response.integration.to_h))
122
+ end
123
+ end
124
+
125
+ # UPDATE
126
+ def update_integration(id:, params: {})
127
+ params = symbolize_keys(params)
128
+ params.transmute(EventHookClientServer::GRPC::StructEncoder,
129
+ %I[config parmas])
130
+
131
+ request = V1::Messages::IntegrationUpdateRequest.new(id: id.to_s,
132
+ input: params)
133
+ response = handle_timeout { super(request) }
134
+
135
+ if response.errors.any?
136
+ Response.fail!(response.errors.map { |e| Error.new(e.to_h) })
137
+ else
138
+ Response.success!(data: Integration.new(response.integration.to_h))
139
+ end
140
+ end
141
+
142
+ # DESTROY
143
+ def destroy_integration(id:)
144
+ request = V1::Messages::IntegrationDestroyRequest.new(id: id.to_s)
145
+
146
+ response = handle_timeout { super(request) }
147
+
148
+ if response.errors.any?
149
+ Response.fail!([])
150
+ else
151
+ Response.success!(data: true)
152
+ end
153
+ end
154
+
155
+ private
156
+
157
+ def handle_timeout(max_retries: 3, sleep_time: 1)
158
+ yield
159
+ rescue GRPC::DeadlineExceeded => error
160
+ try ||= 0
161
+ try += 1
162
+
163
+ sleep(sleep_time) if sleep_time.positive?
164
+ retry if try < max_retries
165
+
166
+ raise(error)
167
+ end
168
+
169
+ def symbolize_keys(hash)
170
+ JSON.parse(hash.to_json, symbolize_keys: true)
171
+ end
172
+ end
173
+ end
174
+
175
+ require 'event_hook_client_server/client/response'
176
+ require 'event_hook_client_server/client/models/integration'
177
+ require 'event_hook_client_server/client/models/error'
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-struct'
4
+
5
+ module EventHookClientServer
6
+ class Client
7
+ class Error < Dry::Struct
8
+ transform_keys(&:to_sym)
9
+
10
+ attribute :code, Types::Strict::String
11
+ attribute :key, Types::Strict::String
12
+ attribute :path, Types::Strict::String
13
+ attribute :messages, Types::Array.of(Types::Strict::String)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-struct'
4
+ require 'event_hook_client_server/types'
5
+ require 'event_hook_client_server/client/models/integrations/binding'
6
+ require 'event_hook_client_server/refinements/object/bubbling_const_lookup'
7
+
8
+ using EventHookClientServer::Refinements::Object::BubblingConstLookup
9
+
10
+ module EventHookClientServer
11
+ class Client
12
+ class Integration < Dry::Struct
13
+ Binding = EventHookClientServer::Client::Integrations::Binding
14
+ transform_keys(&:to_sym)
15
+
16
+ attribute :id, Types::Strict::String
17
+ attribute :building_id, Types::Strict::String.optional
18
+ attribute :tenant_id, Types::Strict::String.optional
19
+ attribute :company_id, Types::Strict::String.optional
20
+ attribute :integrator, Types::Strict::Symbol
21
+ attribute :config, Types::Strict::Hash
22
+ attribute :bindings, Types::Array.of(Binding)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-struct'
4
+ require 'event_hook_client_server/types'
5
+ require 'event_hook_client_server/refinements/object/bubbling_const_lookup'
6
+
7
+ using EventHookClientServer::Refinements::Object::BubblingConstLookup
8
+
9
+ module EventHookClientServer
10
+ class Client
11
+ module Integrations
12
+ class Binding < Dry::Struct
13
+ transform_keys(&:to_sym)
14
+
15
+ attribute :resource_type, Types::String
16
+ attribute :resource_id, Types::String.optional
17
+ attribute :actions, Types::Array.of(Types::Strict::String)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EventHookClientServer
4
+ class Client
5
+ class Response
6
+ def self.success!(data: nil, pagination: nil)
7
+ new(data: data, pagination: pagination)
8
+ end
9
+
10
+ def self.fail!(errors)
11
+ new(errors: Array(errors), failure: true)
12
+ end
13
+
14
+ attr_reader :data
15
+ attr_reader :pagination
16
+ attr_reader :errors
17
+
18
+ def initialize(data: nil, pagination: nil, errors: nil, failure: false)
19
+ @data = data
20
+ @pagination = pagination
21
+ @errors = errors
22
+ @failure = failure
23
+ freeze
24
+ end
25
+
26
+ def failed?
27
+ failure == true
28
+ end
29
+ alias failure? failed?
30
+ alias error? failed?
31
+
32
+ def success?
33
+ !failed?
34
+ end
35
+ alias succeeded? success?
36
+ alias ok? success?
37
+
38
+ protected
39
+
40
+ attr_reader :failure
41
+ end
42
+ end
43
+ end