ekylibre-plugin_system 0.4.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 31fa595ea20dee0bbf28b84fb549a4728e9c5420585d1414ab88378eceee9d0d
4
+ data.tar.gz: c53e1a49c95655a86ea85b44cee8f276ff1d229fc9ed6055c96662043d22168c
5
+ SHA512:
6
+ metadata.gz: '0078f0864c44175b792d194f89db19ccf28473f6881a0447cd762c3b43ce1934898f8f1fa8f3da091b1f76f7c3d32064cbfe37d39218314f9fb50ab96653be16'
7
+ data.tar.gz: ef004b7fa8ee0ca120acd0f263a7851f551a63a8ec06630d7b22bd82d6a97a6b96e1c07c9513794f774e1206da4168fd4d9e76ef2d687388e550dc980e65f546
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/ekylibre/plugin_system/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'ekylibre-plugin_system'
7
+ spec.version = Ekylibre::PluginSystem::VERSION
8
+ spec.authors = ['Ekylibre developers']
9
+ spec.email = ['dev@ekylibre.com']
10
+
11
+ spec.summary = 'Plugin system for Rails built around a Dependency Injection Container'
12
+ spec.required_ruby_version = '>= 2.6.0'
13
+ spec.homepage = 'https://www.ekylibre.com'
14
+ spec.license = 'AGPL-3.0-only'
15
+
16
+ # Specify which files should be added to the gem when it is released.
17
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
+ spec.files = Dir.glob(%w[lib/**/*.rb *.gemspec])
19
+
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'corindon', '~> 0.7.0'
23
+ spec.add_dependency 'railties', '> 4'
24
+ spec.add_dependency 'request_store', '~> 1.5.0'
25
+ spec.add_dependency 'request_store-sidekiq', '~> 0.1.0'
26
+ spec.add_dependency 'zeitwerk', '~> 2.4'
27
+
28
+ spec.add_development_dependency 'bundler', '>= 1.17'
29
+ spec.add_development_dependency 'minitest', '~> 5.14'
30
+ spec.add_development_dependency 'rake', '~> 13.0'
31
+ spec.add_development_dependency 'rubocop', '~> 1.3.0'
32
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'corindon'
4
+ require 'request_store'
5
+ require 'request_store/sidekiq'
6
+ require 'zeitwerk'
7
+
8
+ module Ekylibre # :nodoc:
9
+
10
+ end
11
+
12
+ loader = Zeitwerk::Loader.for_gem
13
+ loader.ignore(__FILE__)
14
+ loader.ignore("#{__dir__}/plugin_system/rails/**/*.rb")
15
+ loader.ignore("#{__dir__}/plugin_system/multi_tenancy/railtie.rb")
16
+ loader.setup
17
+
18
+ require_relative 'ekylibre/plugin_system/rails/railtie' if defined?(::Rails)
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ # Helper methods to access the container from the Rails console
6
+ module ConsoleHelper
7
+ extend ActiveSupport::Concern
8
+
9
+ # @return [Corindon::DependencyInjection::Container]
10
+ def container
11
+ ::Rails.application.system.container
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ # Helper module to access the container from a Rails controller
6
+ module ControllerMixin
7
+ # @return [Corindon::DependencyInjection::Container]
8
+ def container
9
+ request.env['container']
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ module Middleware
6
+ # Rack middleware adding the provided container to the request context
7
+ class RackMiddleware
8
+ # @param [#call] app
9
+ # @param [Corindon::DependencyInjection::Container] container
10
+ def initialize(app, container)
11
+ @app = app
12
+ @container = container
13
+ end
14
+
15
+ def call(env)
16
+ # request_container = enter_tenant(container, ::Ekylibre::Tenant.current)
17
+ RequestStore['container'] = container
18
+
19
+ # We HAVE to mutate the environment because Devise (and maybe other) needs to pass information up the middleware stack
20
+ # from the Rails application to the Auth middleware through the environment
21
+ env['container'] = container
22
+
23
+ @app.call(env)
24
+ end
25
+
26
+ private
27
+
28
+ # @return [Corindon::DependencyInjection::Container]
29
+ attr_reader :container
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ module Middleware
6
+ # Sidekiq server middleware adding the provided container to the job context
7
+ class SidekiqMiddleware
8
+ def initialize(container)
9
+ @container = container
10
+ end
11
+
12
+ def call(_worker_class, item, _queue)
13
+ RequestStore['container'] = container
14
+ item['container'] = container
15
+
16
+ yield
17
+ end
18
+
19
+ private
20
+ # @return [Corindon::DependencyInjection::Container]
21
+ attr_reader :container
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ using Corindon::DependencyInjection::Injectable
4
+
5
+ module Ekylibre
6
+ module PluginSystem
7
+ # Utility class defining some InjectionTokens for the plugin system
8
+ class Parameters
9
+ CURRENT_TENANT = make_parameter('current_tenant')
10
+ RAILS_APPLICATION = make_parameter('rails_application')
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ # Base class for a Plugin
6
+ class Plugin
7
+ # @return [Rails::Engine]
8
+ attr_reader :engine
9
+
10
+ # @param [Rails::Engine] engine
11
+ def initialize(engine: nil)
12
+ @engine = engine
13
+ end
14
+
15
+ # @return [String]
16
+ def name
17
+ self.class.name
18
+ end
19
+
20
+ def version
21
+ 'unknown'
22
+ end
23
+
24
+ # @param [Container] container
25
+ def boot(container) end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ # Utility module to facilitate Plugin and Engine registration into the plugin system
6
+ module PluginRegistration
7
+ class << self
8
+ def extended(base)
9
+ base.initializer(:register_railtie) do |app|
10
+ container = app.system.container
11
+
12
+ container.set_parameter(self.class, self)
13
+ end
14
+ end
15
+ end
16
+
17
+ def register_plugin(plugin_class)
18
+ initializer(:register_plugin, after: :register_railtie) do |app|
19
+ container = app.system.container
20
+
21
+ container.add_definition(plugin_class)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ module Rails
6
+ # Railtie to integrate the PluginSystem into a Rails application
7
+ class Railtie < ::Rails::Railtie
8
+ extend PluginRegistration
9
+
10
+ initializer(:register_application) do |app|
11
+ container = app.system.container
12
+
13
+ container.set_parameter(Ekylibre::PluginSystem::Parameters::RAILS_APPLICATION.key, app)
14
+ end
15
+
16
+ initializer(:register_middleware, after: :engines_blank_point) do |app|
17
+ # app.config.middleware.insert_after(apartment_middleware, Ekylibre::PluginSystem::Middleware::RackMiddleware, app.system.container)
18
+ app.config.middleware.use(Middleware::RackMiddleware, app.system.container)
19
+ end
20
+
21
+ initializer(:register_sidekiq_middleware, after: :engines_blank_point) do |app|
22
+ ::Sidekiq.configure_server do |config|
23
+ config.server_middleware do |chain|
24
+ if defined?(::Sidekiq::Batch::Server)
25
+ chain.insert_before ::Sidekiq::Batch::Server, Middleware::SidekiqMiddleware, app.system.container
26
+ else
27
+ chain.add Middleware::SidekiqMiddleware, app.system.container
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ # rubocop:disable Lint/Debugger
34
+ console do
35
+ ::Rails::ConsoleMethods.send :include, ConsoleHelper
36
+ end
37
+ # rubocop:enable Lint/Debugger
38
+
39
+ # Reboot system between requests if reloading is enabled.
40
+ # Application configuration cannot be changed but this allow us to use rails reloading system in development.
41
+ config.to_prepare do
42
+ app = Ekylibre::Application.instance
43
+
44
+ app.system.reset
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ module Sugar
6
+ # Syntactic sugar to ease the registration of Procedo procedures into the container
7
+ module Procedo
8
+ refine Plugin do
9
+ using Corindon::DependencyInjection::Injectable
10
+
11
+ # @param [Corindon::DependencyInjection::Container] container
12
+ def register_procedures(container:)
13
+ container.add_definition(
14
+ self.class.make_definition('procedure_loader', ::Procedo::ProcedureLoader) { tag 'procedo.loader' },
15
+ context: { root: engine.root }
16
+ ) do |ctx|
17
+ args root: value(ctx.root)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ module Sugar
6
+ # Syntactic sugar to ease the registration of Ekylibre Rights into the container
7
+ module Rights
8
+ refine Plugin do
9
+ using Corindon::DependencyInjection::Injectable
10
+
11
+ # @param [Corindon::DependencyInjection::Container] container
12
+ def register_rights(container:)
13
+ container.add_definition(
14
+ self.class.make_definition('rights_loader', Ekylibre::Access::RightsLoader, context: engine.root.join('config', 'rights.yml')) do |path|
15
+ args path, origin: value(:hajimari)
16
+ tag 'ekylibre.access.rights_loader'
17
+ end
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ module Sugar
6
+ # Syntactic sugar to ease the registration of ScriptAddon into the container
7
+ module Scripts
8
+ refine Plugin do
9
+ using Corindon::DependencyInjection::Injectable
10
+
11
+ # @param [Array<String>] addons
12
+ # @param [Corindon::DependencyInjection::Container] container
13
+ def register_script_addons(addons, container:)
14
+ addons.each do |relative_path|
15
+ container.add_definition(
16
+ self.class.make_definition(relative_path, Ekylibre::View::Scripts::ScriptAddon) { tag 'ekylibre.view.script_addon' },
17
+ context: { path: relative_path, origin: self.name }
18
+ ) do |ctx|
19
+ args relative_path: value(ctx.path), origin: value(ctx.name)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ module Sugar
6
+ # Syntactic sugar to ease the registration of Themes and ThemeAddon into the container
7
+ module Themes
8
+ refine Plugin do
9
+ using Corindon::DependencyInjection::Injectable
10
+
11
+ # @param [Array<String>] addons
12
+ # @param [Corindon::DependencyInjection::Container] container
13
+ def register_theme_addons(addons, container:)
14
+ addons.each do |relative_path|
15
+ container.add_definition(
16
+ self.class.make_definition(relative_path, Ekylibre::View::Themes::ThemeAddon) { tag 'ekylibre.view.theme_addon' },
17
+ context: { path: relative_path, origin: self.name }
18
+ ) do |ctx|
19
+ args for_theme: value('tekyla'), relative_path: value(ctx.path), origin: value(ctx.name)
20
+ end
21
+ end
22
+ end
23
+
24
+ def register_themes(themes, container:)
25
+ themes.each { |theme| register_theme(theme, container: container) }
26
+ end
27
+
28
+ def register_theme(theme, container:)
29
+ container.add_definition(
30
+ self.class.make_definition("themes.#{theme}", Ekylibre::View::Themes::Theme) { tag 'ekylibre.view.theme' },
31
+ context: { theme: theme }
32
+ ) do |ctx|
33
+ args value(ctx.theme)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ # This class in the interface between the Rails application and the core plugin system that is basically just the container
6
+ class System
7
+ # @return [Corindon::DependencyInjection::Container]
8
+ attr_reader :container
9
+
10
+ def initialize
11
+ @started = false
12
+ @container = Corindon::DependencyInjection::Container.new
13
+ end
14
+
15
+ def start
16
+ if !started?
17
+ @started = true
18
+ boot_plugins
19
+ end
20
+ end
21
+
22
+ # @return [Boolean]
23
+ def started?
24
+ @started
25
+ end
26
+
27
+ def reset
28
+ if !started?
29
+ start
30
+ else
31
+ container.clear
32
+ end
33
+ end
34
+
35
+ def plugins
36
+ @container.tagged('ekylibre.system.plugin').map { |key| @container.get(key) }
37
+ end
38
+
39
+ private
40
+
41
+ def boot_plugins
42
+ plugins.each { |p| p.boot(container) }
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ekylibre
4
+ module PluginSystem
5
+ VERSION = '0.4.0'
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ekylibre-plugin_system
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Ekylibre developers
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-01-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: corindon
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.7.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.7.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: railties
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: '4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: '4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: request_store
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.5.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.5.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: request_store-sidekiq
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.1.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: zeitwerk
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.4'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.4'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '1.17'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '1.17'
97
+ - !ruby/object:Gem::Dependency
98
+ name: minitest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '5.14'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '5.14'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '13.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '13.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 1.3.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 1.3.0
139
+ description:
140
+ email:
141
+ - dev@ekylibre.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ekylibre-plugin_system.gemspec
147
+ - lib/ekylibre-plugin_system.rb
148
+ - lib/ekylibre/plugin_system/console_helper.rb
149
+ - lib/ekylibre/plugin_system/controller_mixin.rb
150
+ - lib/ekylibre/plugin_system/middleware/rack_middleware.rb
151
+ - lib/ekylibre/plugin_system/middleware/sidekiq_middleware.rb
152
+ - lib/ekylibre/plugin_system/parameters.rb
153
+ - lib/ekylibre/plugin_system/plugin.rb
154
+ - lib/ekylibre/plugin_system/plugin_registration.rb
155
+ - lib/ekylibre/plugin_system/rails/railtie.rb
156
+ - lib/ekylibre/plugin_system/sugar/procedo.rb
157
+ - lib/ekylibre/plugin_system/sugar/rights.rb
158
+ - lib/ekylibre/plugin_system/sugar/scripts.rb
159
+ - lib/ekylibre/plugin_system/sugar/themes.rb
160
+ - lib/ekylibre/plugin_system/system.rb
161
+ - lib/ekylibre/plugin_system/version.rb
162
+ homepage: https://www.ekylibre.com
163
+ licenses:
164
+ - AGPL-3.0-only
165
+ metadata: {}
166
+ post_install_message:
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: 2.6.0
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ requirements: []
181
+ rubygems_version: 3.0.3
182
+ signing_key:
183
+ specification_version: 4
184
+ summary: Plugin system for Rails built around a Dependency Injection Container
185
+ test_files: []