groovestack-base 0.1.5
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 +7 -0
- data/.rspec +1 -0
- data/.rubocop.yml +44 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +11 -0
- data/config/initializers/graphql.rb +26 -0
- data/config.ru +12 -0
- data/groovestack-base.gemspec +41 -0
- data/lib/groovestack/base/active_record.rb +19 -0
- data/lib/groovestack/base/graphql/base_input_object.rb +11 -0
- data/lib/groovestack/base/graphql/base_mutation.rb +23 -0
- data/lib/groovestack/base/graphql/base_subscription.rb +13 -0
- data/lib/groovestack/base/graphql/documentation.rb +29 -0
- data/lib/groovestack/base/graphql/helpers.rb +152 -0
- data/lib/groovestack/base/graphql/providers/react_admin/resource.rb +146 -0
- data/lib/groovestack/base/graphql/providers/react_admin/types.rb +17 -0
- data/lib/groovestack/base/graphql/subscriptions/event_handler.rb +26 -0
- data/lib/groovestack/base/graphql/tracers/atomic_multiplex_transaction.rb +63 -0
- data/lib/groovestack/base/graphql/types.rb +103 -0
- data/lib/groovestack/base/listeners.rb +85 -0
- data/lib/groovestack/base/pub_sub.rb +25 -0
- data/lib/groovestack/base/puma/plugin/core_cron.rb +62 -0
- data/lib/groovestack/base/railtie.rb +114 -0
- data/lib/groovestack/base/utilities/string.rb +29 -0
- data/lib/groovestack/base/version.rb +7 -0
- data/lib/groovestack/base.rb +142 -0
- metadata +156 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Groovestack
|
4
|
+
module Base
|
5
|
+
module GraphQL
|
6
|
+
module Types
|
7
|
+
class BaseArgument < ::GraphQL::Schema::Argument
|
8
|
+
def initialize(*args, camelize: ::Groovestack::Base.config.graphql.camelize, **kwargs, &block)
|
9
|
+
# Then, call super _without_ any args, where Ruby will take
|
10
|
+
# _all_ the args originally passed to this method and pass it to the super method.
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class BaseField < ::GraphQL::Schema::Field
|
16
|
+
argument_class ::Groovestack::Base::GraphQL::Types::BaseArgument
|
17
|
+
|
18
|
+
attr_accessor :authenticate, :visibility_permission
|
19
|
+
|
20
|
+
# rubocop:disable Metrics/ParameterLists
|
21
|
+
def initialize(
|
22
|
+
*args,
|
23
|
+
authenticate: nil,
|
24
|
+
visibility_permission: nil,
|
25
|
+
null: false,
|
26
|
+
camelize: ::Groovestack::Base.config.graphql.camelize,
|
27
|
+
**kwargs, &block
|
28
|
+
)
|
29
|
+
# Then, call super _without_ any args, where Ruby will take
|
30
|
+
# _all_ the args originally passed to this method and pass it to the super method.
|
31
|
+
@authenticate = authenticate
|
32
|
+
@visibility_permission = visibility_permission
|
33
|
+
super(*args, null: null, camelize: camelize, **kwargs, &block)
|
34
|
+
end
|
35
|
+
# rubocop:enable Metrics/ParameterLists
|
36
|
+
end
|
37
|
+
|
38
|
+
class BaseObject < ::GraphQL::Schema::Object
|
39
|
+
field_class ::Groovestack::Base::GraphQL::Types::BaseField
|
40
|
+
end
|
41
|
+
|
42
|
+
class SubscriptionPayload < ::Groovestack::Base::GraphQL::Types::BaseObject
|
43
|
+
field :event, ::GraphQL::Types::JSON, null: false
|
44
|
+
field :subscription, String, null: false
|
45
|
+
field :subscription_args, ::GraphQL::Types::JSON, null: false
|
46
|
+
end
|
47
|
+
|
48
|
+
class Currency < ::Groovestack::Base::GraphQL::Types::BaseObject
|
49
|
+
description 'A currency object'
|
50
|
+
|
51
|
+
field :code, String, null: false, description: 'currency code', method: :iso_code
|
52
|
+
field :symbol, String, null: false, description: 'currency symbol'
|
53
|
+
end
|
54
|
+
|
55
|
+
class Money < ::Groovestack::Base::GraphQL::Types::BaseObject
|
56
|
+
description 'A money object'
|
57
|
+
|
58
|
+
field :amount, String, null: false, description: 'amount in decimal'
|
59
|
+
field :currency, ::Groovestack::Base::GraphQL::Types::Currency, null: false, description: 'currency metadata'
|
60
|
+
field :formatted_amount, String, null: false,
|
61
|
+
description: 'amount in decimal formatted with currency symbol',
|
62
|
+
method: :format
|
63
|
+
|
64
|
+
def amount
|
65
|
+
object.amount.to_s
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# AUTHORIZATION
|
70
|
+
|
71
|
+
class AuthorizedBaseField < BaseField
|
72
|
+
def authorized?(obj, args, ctx)
|
73
|
+
authorized_fields = begin
|
74
|
+
obj.authorized_fields_for_serialization(ctx[:current_user])
|
75
|
+
rescue StandardError
|
76
|
+
[]
|
77
|
+
end
|
78
|
+
|
79
|
+
super && authorized_fields.include?(name.to_sym)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class AuthorizedBaseObject < BaseObject
|
84
|
+
field_class ::Groovestack::Base::GraphQL::Types::AuthorizedBaseField
|
85
|
+
end
|
86
|
+
|
87
|
+
class VisibleBaseField < BaseField
|
88
|
+
def visible?(context)
|
89
|
+
return super unless @visibility_permission
|
90
|
+
|
91
|
+
# visibility profile are the visibility levels the
|
92
|
+
# current user is authorized for
|
93
|
+
visibility_profile = context.schema.visibility_profile_for_context(context).map(&:to_sym)
|
94
|
+
|
95
|
+
return super unless visibility_profile
|
96
|
+
|
97
|
+
super && visibility_profile.include?(@visibility_permission.to_sym)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Groovestack
|
4
|
+
module Base
|
5
|
+
module Listener
|
6
|
+
extend ::ActiveSupport::Concern
|
7
|
+
|
8
|
+
CORE_LISTENER = true
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def init(_throttle_seconds: 0)
|
12
|
+
raise 'listener must define class method init'
|
13
|
+
end
|
14
|
+
|
15
|
+
def throttle(seconds)
|
16
|
+
wait = false
|
17
|
+
|
18
|
+
proc do |&block|
|
19
|
+
unless wait
|
20
|
+
wait = true
|
21
|
+
|
22
|
+
Thread.new do
|
23
|
+
block.call
|
24
|
+
|
25
|
+
sleep(seconds)
|
26
|
+
|
27
|
+
wait = false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module Listeners
|
36
|
+
class InitAll
|
37
|
+
def self.run(throttle_seconds: 0)
|
38
|
+
core_listeners = ObjectSpace.each_object(Class).select do |klass|
|
39
|
+
klass.const_defined?(:CORE_LISTENER) && klass.const_get(:CORE_LISTENER)
|
40
|
+
end
|
41
|
+
core_listeners.map { |listener| listener.init(throttle_seconds: throttle_seconds) }.flatten
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Database
|
46
|
+
attr_accessor :db_channel, :connection, :connection_instance
|
47
|
+
|
48
|
+
def initialize(db_channel)
|
49
|
+
@db_channel = db_channel
|
50
|
+
@connection = nil
|
51
|
+
@connection_instance = nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def listen
|
55
|
+
Rails.logger.info "Listening to #{db_channel}"
|
56
|
+
::ActiveRecord::Base.connection_pool.with_connection do |connection|
|
57
|
+
@connection = connection
|
58
|
+
|
59
|
+
@connection_instance = connection.instance_variable_get(:@connection)
|
60
|
+
|
61
|
+
begin
|
62
|
+
connection_instance.async_exec "LISTEN #{db_channel}"
|
63
|
+
|
64
|
+
loop do
|
65
|
+
connection_instance.wait_for_notify do |_channel, _pid, payload|
|
66
|
+
yield payload if block_given?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
ensure
|
70
|
+
unlisten
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def unlisten
|
76
|
+
connection_instance.async_exec "UNLISTEN #{db_channel}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def disconnect
|
80
|
+
::ActiveRecord::Base.connection_pool.checkin(connection)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Groovestack
|
4
|
+
module Base
|
5
|
+
module PubSub
|
6
|
+
class GraphQLPublisher
|
7
|
+
include Wisper::Publisher
|
8
|
+
|
9
|
+
def trigger_event(subscription, args, event, **kwargs)
|
10
|
+
publish(:graphql_trigger_event, subscription, args, event, kwargs)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class GraphQLSubscriber
|
15
|
+
def graphql_trigger_event(subscription, args, event, kwargs)
|
16
|
+
::Groovestack::Base::GraphQL::Subscriptions::EventHandler.trigger(subscription, args, event, kwargs)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
ActiveSupport.on_load(:after_initialize) do
|
24
|
+
::Groovestack::Base::PubSub::GraphQLPublisher.subscribe(::Groovestack::Base::PubSub::GraphQLSubscriber.new)
|
25
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'puma/plugin'
|
4
|
+
|
5
|
+
# Need to pre-declare Puma::Plugin here - not sure why, but it's innocusous so leave it
|
6
|
+
module Puma
|
7
|
+
class Plugin # rubocop:disable Lint/EmptyClass
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Puma::Plugin.create do # rubocop:disable Metrics/BlockLength
|
12
|
+
def production?
|
13
|
+
ENV.fetch('RACK_ENV', 'development') == 'production'
|
14
|
+
end
|
15
|
+
|
16
|
+
def log(msg)
|
17
|
+
if production? && defined?(Rails)
|
18
|
+
Rails.logger.info msg
|
19
|
+
else
|
20
|
+
puts msg
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def flush
|
25
|
+
Rails.logger.flush if production? && defined?(Rails)
|
26
|
+
end
|
27
|
+
|
28
|
+
def start(_launcher) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
29
|
+
trap('TERM') do
|
30
|
+
log '[core-cron] Graceful shutdown'
|
31
|
+
exit # rubocop:disable Rails/Exit
|
32
|
+
end
|
33
|
+
|
34
|
+
in_background do
|
35
|
+
log '[core-cron] Starting core-cron worker'
|
36
|
+
log '[core-cron] Waiting for CORE-CRON PGLock'
|
37
|
+
|
38
|
+
loop do
|
39
|
+
begin
|
40
|
+
core_listeners = []
|
41
|
+
|
42
|
+
# hold the command for 30 minutes
|
43
|
+
PgLock.new(name: 'core-cron-commander', ttl: 30.minutes.to_i, attempts: 1).lock do
|
44
|
+
log '[core-cron] Obtained CORE-CRON PGLock'
|
45
|
+
|
46
|
+
core_listeners = ::Groovestack::Base::Listeners::InitAll.run(throttle_seconds: 1)
|
47
|
+
end
|
48
|
+
rescue Timeout::Error
|
49
|
+
# normal behavior - don't do anything when this happens
|
50
|
+
|
51
|
+
# ensure channels closed and connections checked in for listeners
|
52
|
+
core_listeners.each(&:unlisten)
|
53
|
+
core_listeners.each(&:disconnect)
|
54
|
+
end
|
55
|
+
|
56
|
+
puts 'PGLock expired. Taking a breath before attempting to re-aquire.'
|
57
|
+
# Loop and keep checking for CORE-CRON command
|
58
|
+
sleep 14
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Groovestack
|
4
|
+
module Base
|
5
|
+
module CoreRailtie
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
CORE_ENGINE = true
|
9
|
+
|
10
|
+
included do # rubocop:disable Metrics/BlockLength
|
11
|
+
def dx_validations
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
def module_name
|
16
|
+
self.class.name.deconstantize.demodulize
|
17
|
+
end
|
18
|
+
|
19
|
+
def module_version
|
20
|
+
self.class.name.deconstantize.constantize::VERSION
|
21
|
+
end
|
22
|
+
|
23
|
+
def after_init
|
24
|
+
unless Rails.const_defined?('Console') && (ENV['RAILS_ENV'] || ENV.fetch('RACK_ENV', nil)) == 'development'
|
25
|
+
return
|
26
|
+
end
|
27
|
+
|
28
|
+
puts 'CORE Platform DX Mode'.bold if module_name == 'Base'
|
29
|
+
core_base_dx_validate
|
30
|
+
end
|
31
|
+
|
32
|
+
def append_migrations(app) # rubocop:disable Metrics/AbcSize
|
33
|
+
return if app.root.present? && root.present? && app.root.to_s.match?(root.to_s)
|
34
|
+
|
35
|
+
config.paths['db/migrate'].expanded.each do |expanded_path|
|
36
|
+
app.config.paths['db/migrate'] << expanded_path
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def append_initializers(app) # rubocop:disable Metrics/AbcSize
|
41
|
+
return if app.root.present? && root.present? && app.root.to_s.match?(root.to_s)
|
42
|
+
|
43
|
+
config.paths['config/initializers'].expanded.each do |expanded_path|
|
44
|
+
app.config.paths['config/initializers'] << expanded_path
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def core_base_dx_validate # rubocop:disable Metrics/AbcSize
|
49
|
+
errors = []
|
50
|
+
dx_validations.each do |v|
|
51
|
+
v[:eval].call
|
52
|
+
rescue StandardError
|
53
|
+
errors << v[:message]
|
54
|
+
break
|
55
|
+
end
|
56
|
+
|
57
|
+
if errors.length.positive?
|
58
|
+
print '⚠️'.brown
|
59
|
+
msg = " Groovestack::#{module_name}\t#{module_version}"
|
60
|
+
msg += module_description if respond_to?(:module_description)
|
61
|
+
msg += "\t#{errors[0]}"
|
62
|
+
else
|
63
|
+
print '✔'.green
|
64
|
+
msg = " Groovestack::#{module_name}\t#{module_version}"
|
65
|
+
msg += module_description if respond_to?(:module_description)
|
66
|
+
end
|
67
|
+
|
68
|
+
puts msg
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Railtie < Rails::Engine
|
74
|
+
include CoreRailtie
|
75
|
+
|
76
|
+
def dx_validations
|
77
|
+
[
|
78
|
+
{
|
79
|
+
eval: proc { require 'pg' },
|
80
|
+
message: "Error: 'pg' gem is required, add it your your gemfile"
|
81
|
+
},
|
82
|
+
{
|
83
|
+
eval: proc { require 'graphql' },
|
84
|
+
message: "Error: 'graphql' gem is required, add it your your gemfile"
|
85
|
+
}
|
86
|
+
]
|
87
|
+
end
|
88
|
+
|
89
|
+
initializer :append_migrations do |app|
|
90
|
+
append_migrations app
|
91
|
+
end
|
92
|
+
|
93
|
+
initializer :append_initializers do |app|
|
94
|
+
append_initializers app
|
95
|
+
end
|
96
|
+
|
97
|
+
initializer :init_puma do |app|
|
98
|
+
return unless defined?(Puma)
|
99
|
+
|
100
|
+
unless app.root.present? && root.present? && app.root.to_s.match?(root.to_s)
|
101
|
+
config.paths.add('lib/groovestack/base/puma/plugin')
|
102
|
+
app.config.paths.add('app/lib/puma/plugin')
|
103
|
+
config.paths['lib/groovestack/base/puma/plugin'].expanded.each do |expanded_path|
|
104
|
+
app.config.paths['app/lib/puma/plugin'] << expanded_path
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
config.after_initialize do
|
110
|
+
after_init
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Style/SingleLineMethods
|
4
|
+
class String
|
5
|
+
def black; "\e[30m#{self}\e[0m" end
|
6
|
+
def red; "\e[31m#{self}\e[0m" end
|
7
|
+
def green; "\e[32m#{self}\e[0m" end
|
8
|
+
def brown; "\e[33m#{self}\e[0m" end
|
9
|
+
def blue; "\e[34m#{self}\e[0m" end
|
10
|
+
def magenta; "\e[35m#{self}\e[0m" end
|
11
|
+
def cyan; "\e[36m#{self}\e[0m" end
|
12
|
+
def gray; "\e[37m#{self}\e[0m" end
|
13
|
+
|
14
|
+
def bg_black; "\e[40m#{self}\e[0m" end
|
15
|
+
def bg_red; "\e[41m#{self}\e[0m" end
|
16
|
+
def bg_green; "\e[42m#{self}\e[0m" end
|
17
|
+
def bg_brown; "\e[43m#{self}\e[0m" end
|
18
|
+
def bg_blue; "\e[44m#{self}\e[0m" end
|
19
|
+
def bg_magenta; "\e[45m#{self}\e[0m" end
|
20
|
+
def bg_cyan; "\e[46m#{self}\e[0m" end
|
21
|
+
def bg_gray; "\e[47m#{self}\e[0m" end
|
22
|
+
|
23
|
+
def bold; "\e[1m#{self}\e[22m" end
|
24
|
+
def italic; "\e[3m#{self}\e[23m" end
|
25
|
+
def underline; "\e[4m#{self}\e[24m" end
|
26
|
+
def blink; "\e[5m#{self}\e[25m" end
|
27
|
+
def reverse_color; "\e[7m#{self}\e[27m" end
|
28
|
+
end
|
29
|
+
# rubocop:enable Style/SingleLineMethods
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_record'
|
4
|
+
require 'dry-configurable'
|
5
|
+
require 'graphql'
|
6
|
+
require 'pg'
|
7
|
+
require 'pg_lock'
|
8
|
+
|
9
|
+
require 'groovestack/base/version'
|
10
|
+
require 'groovestack/base/utilities/string'
|
11
|
+
|
12
|
+
module Groovestack
|
13
|
+
module Base
|
14
|
+
module GraphQL
|
15
|
+
module Subscriptions
|
16
|
+
autoload :EventHandler, 'groovestack/base/graphql/subscriptions/event_handler'
|
17
|
+
end
|
18
|
+
|
19
|
+
autoload :Types, 'groovestack/base/graphql/types'
|
20
|
+
autoload :BaseInputObject, 'groovestack/base/graphql/base_input_object'
|
21
|
+
autoload :BaseMutation, 'groovestack/base/graphql/base_mutation'
|
22
|
+
autoload :Documentation, 'groovestack/base/graphql/documentation'
|
23
|
+
autoload :BaseSubscription, 'groovestack/base/graphql/base_subscription'
|
24
|
+
autoload :Helpers, 'groovestack/base/graphql/helpers'
|
25
|
+
|
26
|
+
module Tracers
|
27
|
+
autoload :AtomicMultiplexTransaction, 'groovestack/base/graphql/tracers/atomic_multiplex_transaction'
|
28
|
+
end
|
29
|
+
|
30
|
+
module Providers
|
31
|
+
module ReactAdmin
|
32
|
+
autoload :Resource, 'groovestack/base/graphql/providers/react_admin/resource'
|
33
|
+
autoload :Types, 'groovestack/base/graphql/providers/react_admin/types'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
autoload :ActiveRecord, 'groovestack/base/active_record'
|
39
|
+
autoload :Listener, 'groovestack/base/listeners'
|
40
|
+
autoload :Listeners, 'groovestack/base/listeners'
|
41
|
+
|
42
|
+
autoload :PubSub, 'groovestack/base/pub_sub' if defined?(Wisper)
|
43
|
+
autoload :CoreRailtie, 'groovestack/base/railtie' if defined?(Rails::Railtie)
|
44
|
+
|
45
|
+
extend Dry::Configurable
|
46
|
+
|
47
|
+
DEFAULT_ERROR_MONITOR = ::Logger.new($stdout)
|
48
|
+
|
49
|
+
# ex:
|
50
|
+
# /config/initializers/core_base.rb
|
51
|
+
|
52
|
+
# Groovestack::Base.configure do |config|
|
53
|
+
# config.error_notifier.handler = Bugsnag
|
54
|
+
# end
|
55
|
+
setting :error_notifier, reader: true do
|
56
|
+
setting :handler, reader: true
|
57
|
+
setting :notify_method, reader: true, default: :notify
|
58
|
+
end
|
59
|
+
|
60
|
+
setting :graphql do
|
61
|
+
setting :camelize, default: false
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.notify_error(prefix, err)
|
65
|
+
msg = "#{[prefix, 'error'].compact.join(' ')}: #{err}"
|
66
|
+
|
67
|
+
if error_notifier&.handler.present?
|
68
|
+
error_notifier.handler.send(error_notifier.notify_method, msg)
|
69
|
+
else
|
70
|
+
DEFAULT_ERROR_MONITOR.error(msg)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class Error < StandardError; end
|
75
|
+
class WrongSchemaFormat < Groovestack::Base::Error; end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
require 'groovestack/base/puma/plugin/core_cron' if defined?(Puma)
|
80
|
+
|
81
|
+
# TODO: remove aliases after all core modules have been updated
|
82
|
+
# to reference Groovestack::Base
|
83
|
+
module Core
|
84
|
+
module Base
|
85
|
+
module GraphQL
|
86
|
+
module Subscriptions
|
87
|
+
EventHandler = ::Groovestack::Base::GraphQL::Subscriptions::EventHandler
|
88
|
+
end
|
89
|
+
|
90
|
+
Types = ::Groovestack::Base::GraphQL::Types
|
91
|
+
BaseInputObject = ::Groovestack::Base::GraphQL::BaseInputObject
|
92
|
+
BaseMutation = ::Groovestack::Base::GraphQL::BaseMutation
|
93
|
+
Documentation = ::Groovestack::Base::GraphQL::Documentation
|
94
|
+
BaseSubscription = ::Groovestack::Base::GraphQL::BaseSubscription
|
95
|
+
Helpers = ::Groovestack::Base::GraphQL::Helpers
|
96
|
+
|
97
|
+
module Tracers
|
98
|
+
AtomicMultiplexTransaction = ::Groovestack::Base::GraphQL::Tracers::AtomicMultiplexTransaction
|
99
|
+
end
|
100
|
+
|
101
|
+
module Providers
|
102
|
+
module ReactAdmin
|
103
|
+
Resource = ::Groovestack::Base::GraphQL::Providers::ReactAdmin::Resource
|
104
|
+
Types = ::Groovestack::Base::GraphQL::Providers::ReactAdmin::Types
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
ActiveRecord = ::Groovestack::Base::ActiveRecord
|
110
|
+
Listener = ::Groovestack::Base::Listener
|
111
|
+
Listeners = ::Groovestack::Base::Listeners
|
112
|
+
|
113
|
+
PubSub = ::Groovestack::Base::PubSub if defined?(Wisper)
|
114
|
+
CoreRailtie = ::Groovestack::Base::CoreRailtie if defined?(Rails::Railtie)
|
115
|
+
|
116
|
+
extend Dry::Configurable
|
117
|
+
|
118
|
+
DEFAULT_ERROR_MONITOR = ::Logger.new($stdout)
|
119
|
+
|
120
|
+
setting :error_notifier, reader: true do
|
121
|
+
setting :handler, reader: true
|
122
|
+
setting :notify_method, reader: true, default: :notify
|
123
|
+
end
|
124
|
+
|
125
|
+
setting :graphql do
|
126
|
+
setting :camelize, default: false
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.notify_error(prefix, err)
|
130
|
+
msg = "#{[prefix, 'error'].compact.join(' ')}: #{err}"
|
131
|
+
|
132
|
+
if error_notifier&.handler.present?
|
133
|
+
error_notifier.handler.send(error_notifier.notify_method, msg)
|
134
|
+
else
|
135
|
+
DEFAULT_ERROR_MONITOR.error(msg)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
Error = ::Groovestack::Base::Error
|
140
|
+
WrongSchemaFormat = ::Groovestack::Base::WrongSchemaFormat
|
141
|
+
end
|
142
|
+
end
|