groovestack-base 0.1.11 → 0.1.12

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72f511d14b324b1513d61cb1975c54c31db2cb58eed2b771bdc25207a822ffe1
4
- data.tar.gz: d3bc0ef6415c0f45c31d84ee605b9c03cd8c0ac0126069c2eab15012a5e61a76
3
+ metadata.gz: 682c6b2dbb33593bd71df11b9228987c66bcbcabc4525b2a4f59c2240f4980b5
4
+ data.tar.gz: e791bf96b84082d0b2c9f5bdbc378203d74db1a0cc13d5b963dca120d46cfd5c
5
5
  SHA512:
6
- metadata.gz: 6a82e1038408222eb47775c2cd8a2b0b1053fb96e7eed4cba30c07ea78ac73b95574cddacc3c2b740d641a93e6e77b6dec6c926ce9b034cd804834bfd2761ea6
7
- data.tar.gz: e423738794d1f80cf1c328d24e1392480fab3b822f40fdbc0619039b9b266da0aea602029cce504e8ddb9ffd4fe2f7cf8e3d5fe99217d2a99dcf87b78d260f5d
6
+ metadata.gz: '0852f44c5f4b5c1cb725175917d0f8dac6ddd088574c233a4f207ba821f6ce675b10348b6fb17b4aabcefe3b6eba717bc20ce2d04b593cb22b909d5298a40e56'
7
+ data.tar.gz: 7d0a44e103a9ae986f7fb91f273c8366f0b62a9a84edfc6b95f4d6b26e4c14d65d824dbb52835a115c0970c37cd0de12099af279646793062b52ccda41a9d52e
data/Gemfile CHANGED
@@ -12,4 +12,6 @@ group :test do
12
12
  end
13
13
  gem 'puma', '~> 6'
14
14
  gem 'rake', '~> 12.0'
15
- gem 'rubocop', require: false
15
+ gem 'rubocop'
16
+ gem 'rubocop-graphql', '~> 1.0'
17
+ gem 'rubocop-rails', '~> 2.18'
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Be sure to restart your server when you modify this file.
4
+
5
+ # Add new inflection rules using the following format. Inflections
6
+ # are locale specific, and you may define rules for as many different
7
+ # locales as you wish. All of these examples are active by default:
8
+ # ActiveSupport::Inflector.inflections(:en) do |inflect|
9
+ # inflect.plural /^(ox)$/i, "\\1en"
10
+ # inflect.singular /^(ox)en/i, "\\1"
11
+ # inflect.irregular "person", "people"
12
+ # inflect.uncountable %w( fish sheep )
13
+ # end
14
+
15
+ # These inflection rules are supported but not enabled by default:
16
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
17
+ inflect.acronym 'GraphQL'
18
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Groovestack
4
+ module Base
5
+ module GraphQL
6
+ module Controllers
7
+ module Execute
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ skip_before_action :verify_authenticity_token
12
+
13
+ # If accessing from outside this domain, nullify the session
14
+ # This allows for outside API access while preventing CSRF attacks,
15
+ # but you'll have to authenticate your user separately
16
+ # protect_from_forgery with: :null_session
17
+
18
+ def groovestack_graphql_schema
19
+ raise 'groovestack_graphql_schema is not set' if groovestack_graphql_schema.blank?
20
+ end
21
+
22
+ def execute
23
+ result = groovestack_graphql_schema.execute(
24
+ query,
25
+ variables: variables,
26
+ context: execute_context,
27
+ operation_name: operation_name
28
+ )
29
+
30
+ process_result_errors(result['errors'])
31
+
32
+ render json: result
33
+ rescue StandardError => e
34
+ ::Groovestack::Base.notify_error(e.class.name, e.message)
35
+
36
+ raise e unless Rails.env.development?
37
+
38
+ handle_error_in_development(e)
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def execute_context
45
+ return {} unless defined?(context)
46
+
47
+ context
48
+ end
49
+
50
+ def process_result_errors(errors)
51
+ # NOTE: This is a custom Bugsnag notify call for requests that
52
+ # have handled errors (validation, invariant, top-level, handled)
53
+ return if errors.blank?
54
+
55
+ errors.each do |error|
56
+ msg = error['message'] || error
57
+
58
+ ::Groovestack::Base.notify_error(error.class.name, msg)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -4,7 +4,7 @@ module Groovestack
4
4
  module Base
5
5
  module GraphQL
6
6
  module Controllers
7
- module GraphQLController
7
+ module Helpers
8
8
  extend ActiveSupport::Concern
9
9
 
10
10
  included do # rubocop:disable Metrics/BlockLength
@@ -86,7 +86,7 @@ module Groovestack
86
86
  end
87
87
 
88
88
  def define_meta_resolver(entity, authorize, policy, base_scope)
89
- define_method :"#{entity}_meta" do |_page: nil, _per_page: nil, **attrs|
89
+ define_method :"#{entity}_meta" do |page: nil, per_page: nil, **attrs| # rubocop:disable Lint/UnusedBlockArgument
90
90
  scope = resolve_scope(authorize, policy, :IndexScope, base_scope)
91
91
  { count: send("#{entity}_scope", **attrs, base_scope: scope).size }
92
92
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Groovestack
4
+ module Base
5
+ module GraphQL
6
+ class SchemaAbstract < ::GraphQL::Schema
7
+ # NOTE: This is intended to be a base class for all GraphQL schemas in the Groovestack ecosystem.
8
+ # It is not intended to be used directly.
9
+ #
10
+ # To create a new GraphQL schema, subclass this class and specify:
11
+ # - query(::Types::QueryType) (required)
12
+ # - mutation(::Types::MutationType) (optional)
13
+ # - subscription(::Types::SubscriptionType) (optional)
14
+ #
15
+ # Example:
16
+ #
17
+ # class MySchema < Groovestack::Base::GraphQL::SchemaAbstract
18
+ # query(::Types::QueryType)
19
+ # mutation(::Types::MutationType)
20
+ # subscription(::Types::SubscriptionType)
21
+
22
+ use ::GraphQL::Subscriptions::ActionCableSubscriptions
23
+
24
+ # For batch-loading (see https://graphql-ruby.org/dataloader/overview.html)
25
+ use ::GraphQL::Dataloader
26
+
27
+ # Stop validating when it encounters this many errors:
28
+ validate_max_errors(100)
29
+
30
+ # Error Handling https://graphql-ruby.org/errors/error_handling.html
31
+ rescue_from(
32
+ ::ActiveRecord::RecordInvalid,
33
+ ::ActiveRecord::RecordNotDestroyed
34
+ # AASM::InvalidTransition
35
+ ) do |err, _obj, args, _ctx, _field|
36
+ # Raise a graphql-friendly error with a custom message
37
+ raise ::GraphQL::ExecutionError.new(err.message, extensions: { args: })
38
+ end
39
+
40
+ rescue_from(::ActiveRecord::RecordNotFound) do |_err, _obj, args, _ctx, field|
41
+ # Raise a graphql-friendly error with a custom message
42
+ raise ::GraphQL::ExecutionError.new("#{field.type.unwrap.graphql_name} not found", extensions: { args: })
43
+ end
44
+
45
+ rescue_from(::ActiveRecord::RecordNotUnique) do |_err, _obj, args, _ctx, field|
46
+ # Raise a graphql-friendly error with a custom message
47
+ raise ::GraphQL::ExecutionError.new("#{field.type.unwrap.graphql_name} not unique", extensions: { args: })
48
+ end
49
+
50
+ # GraphQL-Ruby calls this when something goes wrong while running a query:
51
+
52
+ # Union and Interface Resolution
53
+ def self.resolve_type(_abstract_type, _obj, _ctx)
54
+ # to return the correct GraphQL object type for `obj`
55
+ raise(::GraphQL::RequiredImplementationMissingError)
56
+ end
57
+
58
+ # Relay-style Object Identification:
59
+
60
+ # Return a string UUID for `object`
61
+ def self.id_from_object(object, _type_definition, _query_ctx)
62
+ # For example, use Rails' GlobalID library (https://github.com/rails/globalid):
63
+ object.to_gid_param
64
+ end
65
+
66
+ # Given a string UUID, find the object
67
+ def self.object_from_id(global_id, _query_ctx)
68
+ # For example, use Rails' GlobalID library (https://github.com/rails/globalid):
69
+ ::GlobalID.find(global_id)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -45,6 +45,14 @@ module Groovestack
45
45
  end
46
46
  end
47
47
 
48
+ def append_locales(app) # rubocop:disable Metrics/AbcSize
49
+ return if app.root.present? && root.present? && app.root.to_s.match?(root.to_s)
50
+
51
+ config.paths['config/locales'].expanded.each do |expanded_path|
52
+ app.config.paths['config/locales'] << expanded_path
53
+ end
54
+ end
55
+
48
56
  def core_base_dx_validate # rubocop:disable Metrics/AbcSize
49
57
  errors = []
50
58
  dx_validations.each do |v|
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Groovestack
4
+ module Base
5
+ module Settings
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ extend Dry::Configurable
10
+
11
+ setting :error_notifier, reader: true do
12
+ setting :handler, reader: true, default: ::Logger.new($stdout)
13
+ setting :notify_method, reader: true, default: :notify
14
+ end
15
+
16
+ setting :graphql do
17
+ setting :camelize, default: false
18
+ end
19
+
20
+ def self.notify_error(prefix, err)
21
+ msg = "#{[prefix, 'error'].compact.join(' ')}: #{err}"
22
+
23
+ error_notifier.handler.send(error_notifier.notify_method, msg)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Groovestack
4
4
  module Base
5
- VERSION = '0.1.11'
5
+ VERSION = '0.1.12'
6
6
  end
7
7
  end
@@ -8,16 +8,13 @@ require 'pg_lock'
8
8
 
9
9
  require 'groovestack/base/version'
10
10
  require 'groovestack/base/utilities/string'
11
+ require 'groovestack/base/settings'
11
12
 
12
13
  module Groovestack
13
14
  module Base
14
- module GraphQL
15
- module Authorization
16
- autoload :AuthorizedField, 'groovestack/base/graphql/authorization/authorized_field'
17
- autoload :AuthorizedObject, 'groovestack/base/graphql/authorization/authorized_object'
18
- autoload :VisibleField, 'groovestack/base/graphql/authorization/visible_field'
19
- end
15
+ include ::Groovestack::Base::Settings
20
16
 
17
+ module GraphQL
21
18
  module Base
22
19
  autoload :Argument, 'groovestack/base/graphql/base/argument'
23
20
  autoload :Field, 'groovestack/base/graphql/base/field'
@@ -28,7 +25,8 @@ module Groovestack
28
25
  end
29
26
 
30
27
  module Controllers
31
- autoload :GraphQLController, 'groovestack/base/graphql/controllers/graphql_controller'
28
+ autoload :Helpers, 'groovestack/base/graphql/controllers/helpers'
29
+ autoload :Execute, 'groovestack/base/graphql/controllers/execute'
32
30
  end
33
31
 
34
32
  module Documentation
@@ -50,6 +48,8 @@ module Groovestack
50
48
  end
51
49
  end
52
50
 
51
+ autoload :SchemaAbstract, 'groovestack/base/graphql/schema_abstract'
52
+
53
53
  module Subscriptions
54
54
  autoload :Trigger, 'groovestack/base/graphql/subscriptions/trigger'
55
55
  end
@@ -67,42 +67,12 @@ module Groovestack
67
67
  end
68
68
  end
69
69
 
70
- autoload :ActiveRecord, 'groovestack/base/active_record'
71
70
  autoload :Listener, 'groovestack/base/listeners'
72
71
  autoload :Listeners, 'groovestack/base/listeners'
73
72
 
74
73
  autoload :PubSub, 'groovestack/base/pub_sub' if defined?(Wisper)
75
74
  autoload :CoreRailtie, 'groovestack/base/railtie' if defined?(Rails::Railtie)
76
75
 
77
- extend Dry::Configurable
78
-
79
- DEFAULT_ERROR_MONITOR = ::Logger.new($stdout)
80
-
81
- # ex:
82
- # /config/initializers/core_base.rb
83
-
84
- # Groovestack::Base.configure do |config|
85
- # config.error_notifier.handler = Bugsnag
86
- # end
87
- setting :error_notifier, reader: true do
88
- setting :handler, reader: true
89
- setting :notify_method, reader: true, default: :notify
90
- end
91
-
92
- setting :graphql do
93
- setting :camelize, default: false
94
- end
95
-
96
- def self.notify_error(prefix, err)
97
- msg = "#{[prefix, 'error'].compact.join(' ')}: #{err}"
98
-
99
- if error_notifier&.handler.present?
100
- error_notifier.handler.send(error_notifier.notify_method, msg)
101
- else
102
- DEFAULT_ERROR_MONITOR.error(msg)
103
- end
104
- end
105
-
106
76
  class Error < StandardError; end
107
77
  class WrongSchemaFormat < Groovestack::Base::Error; end
108
78
  end
@@ -114,6 +84,8 @@ require 'groovestack/base/puma/plugin/core_cron' if defined?(Puma)
114
84
  # to reference Groovestack::Base
115
85
  module Core
116
86
  module Base
87
+ include ::Groovestack::Base::Settings
88
+
117
89
  module GraphQL
118
90
  module Subscriptions
119
91
  EventHandler = ::Groovestack::Base::GraphQL::Subscriptions::Trigger
@@ -123,9 +95,8 @@ module Core
123
95
  BaseArgument = ::Groovestack::Base::GraphQL::Base::Argument
124
96
  BaseField = ::Groovestack::Base::GraphQL::Base::Field
125
97
  BaseObject = ::Groovestack::Base::GraphQL::Base::Object
126
- AuthorizedBaseField = ::Groovestack::Base::GraphQL::Authorization::AuthorizedField
127
- AuthorizedBaseObject = ::Groovestack::Base::GraphQL::Authorization::AuthorizedObject
128
- VisibleBaseField = ::Groovestack::Base::GraphQL::Authorization::VisibleField
98
+ Money = ::Groovestack::Base::GraphQL::Types::Money
99
+ SubscriptionPayload = ::Groovestack::Base::GraphQL::Types::SubscriptionPayload
129
100
  end
130
101
  BaseInputObject = ::Groovestack::Base::GraphQL::Base::InputObject
131
102
  BaseMutation = ::Groovestack::Base::GraphQL::Base::Mutation
@@ -144,7 +115,7 @@ module Core
144
115
  StatusEvents = ::Groovestack::Base::GraphQL::Mutations::AASMEventTrigger
145
116
  InstanceMethods = ::Groovestack::Base::GraphQL::Mutations::MethodTrigger
146
117
  end
147
- Controller = ::Groovestack::Base::GraphQL::Controllers::GraphQLController
118
+ Controller = ::Groovestack::Base::GraphQL::Controllers::Helpers
148
119
  end
149
120
 
150
121
  module Providers
@@ -161,36 +132,12 @@ module Core
161
132
  end
162
133
  end
163
134
 
164
- ActiveRecord = ::Groovestack::Base::ActiveRecord
165
135
  Listener = ::Groovestack::Base::Listener
166
136
  Listeners = ::Groovestack::Base::Listeners
167
137
 
168
138
  PubSub = ::Groovestack::Base::PubSub if defined?(Wisper)
169
139
  CoreRailtie = ::Groovestack::Base::CoreRailtie if defined?(Rails::Railtie)
170
140
 
171
- extend Dry::Configurable
172
-
173
- DEFAULT_ERROR_MONITOR = ::Logger.new($stdout)
174
-
175
- setting :error_notifier, reader: true do
176
- setting :handler, reader: true
177
- setting :notify_method, reader: true, default: :notify
178
- end
179
-
180
- setting :graphql do
181
- setting :camelize, default: false
182
- end
183
-
184
- def self.notify_error(prefix, err)
185
- msg = "#{[prefix, 'error'].compact.join(' ')}: #{err}"
186
-
187
- if error_notifier&.handler.present?
188
- error_notifier.handler.send(error_notifier.notify_method, msg)
189
- else
190
- DEFAULT_ERROR_MONITOR.error(msg)
191
- end
192
- end
193
-
194
141
  Error = ::Groovestack::Base::Error
195
142
  WrongSchemaFormat = ::Groovestack::Base::WrongSchemaFormat
196
143
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: groovestack-base
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.11
4
+ version: 0.1.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darren Rush
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2025-05-14 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: activerecord
@@ -118,24 +119,23 @@ files:
118
119
  - Gemfile
119
120
  - config.ru
120
121
  - config/initializers/graphql.rb
122
+ - config/initializers/inflections.rb
121
123
  - groovestack-base.gemspec
122
124
  - lib/groovestack/base.rb
123
- - lib/groovestack/base/active_record.rb
124
- - lib/groovestack/base/graphql/authorization/authorized_field.rb
125
- - lib/groovestack/base/graphql/authorization/authorized_object.rb
126
- - lib/groovestack/base/graphql/authorization/visible_field.rb
127
125
  - lib/groovestack/base/graphql/base/argument.rb
128
126
  - lib/groovestack/base/graphql/base/field.rb
129
127
  - lib/groovestack/base/graphql/base/input_object.rb
130
128
  - lib/groovestack/base/graphql/base/mutation.rb
131
129
  - lib/groovestack/base/graphql/base/object.rb
132
130
  - lib/groovestack/base/graphql/base/subscription.rb
133
- - lib/groovestack/base/graphql/controllers/graphql_controller.rb
131
+ - lib/groovestack/base/graphql/controllers/execute.rb
132
+ - lib/groovestack/base/graphql/controllers/helpers.rb
134
133
  - lib/groovestack/base/graphql/documentation/arguments.rb
135
134
  - lib/groovestack/base/graphql/documentation/fields.rb
136
135
  - lib/groovestack/base/graphql/mutations/aasm_event_trigger.rb
137
136
  - lib/groovestack/base/graphql/mutations/method_trigger.rb
138
137
  - lib/groovestack/base/graphql/providers/react_admin.rb
138
+ - lib/groovestack/base/graphql/schema_abstract.rb
139
139
  - lib/groovestack/base/graphql/subscriptions/trigger.rb
140
140
  - lib/groovestack/base/graphql/tracers.rb
141
141
  - lib/groovestack/base/graphql/types/aasm_event_attributes.rb
@@ -147,6 +147,7 @@ files:
147
147
  - lib/groovestack/base/pub_sub.rb
148
148
  - lib/groovestack/base/puma/plugin/core_cron.rb
149
149
  - lib/groovestack/base/railtie.rb
150
+ - lib/groovestack/base/settings.rb
150
151
  - lib/groovestack/base/utilities/string.rb
151
152
  - lib/groovestack/base/version.rb
152
153
  homepage: https://talysto.com/tech/groovestack/
@@ -172,7 +173,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
173
  - !ruby/object:Gem::Version
173
174
  version: '0'
174
175
  requirements: []
175
- rubygems_version: 3.6.7
176
+ rubygems_version: 3.3.26
177
+ signing_key:
176
178
  specification_version: 4
177
179
  summary: Shared extensions for CORE modules
178
180
  test_files: []
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Groovestack
4
- module Base
5
- module ActiveRecord
6
- module Authorization
7
- module FieldsForSerialization
8
- extend ActiveSupport::Concern
9
-
10
- # required for memoization during graphql serialization
11
- def authorized_fields_for_serialization(user)
12
- @authorized_fields_for_serialization ||= Pundit.policy!(user, self).permitted_attributes_for_show
13
- @authorized_fields_for_serialization
14
- end
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Groovestack
4
- module Base
5
- module GraphQL
6
- module Authorization
7
- class AuthorizedField < ::Groovestack::Base::GraphQL::Base::Field
8
- def authorized?(obj, args, ctx)
9
- authorized_fields = begin
10
- obj.authorized_fields_for_serialization(ctx[:current_user])
11
- rescue StandardError
12
- []
13
- end
14
-
15
- super && authorized_fields.include?(name.to_sym)
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Groovestack
4
- module Base
5
- module GraphQL
6
- module Authorization
7
- class AuthorizedObject < ::Groovestack::Base::GraphQL::Base::Object
8
- field_class ::Groovestack::Base::GraphQL::Authorization::AuthorizedField
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Groovestack
4
- module Base
5
- module GraphQL
6
- module Authorization
7
- class VisibleField < ::Groovestack::Base::GraphQL::Base::Field
8
- def visible?(context)
9
- return super unless @visibility_permission
10
-
11
- # visibility profile are the visibility levels the
12
- # current user is authorized for
13
- visibility_profile = context.schema.visibility_profile_for_context(context).map(&:to_sym)
14
-
15
- return super unless visibility_profile
16
-
17
- super && visibility_profile.include?(@visibility_permission.to_sym)
18
- end
19
- end
20
- end
21
- end
22
- end
23
- end