kaal-hanami 0.3.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a23772c397096d568be16ed50e2b9ddfb7f26d6935756a9e2338c18eec699055
4
+ data.tar.gz: 44a53add8dc6b3f8d67d025196025f212985acfd672645d437e9114560e90e64
5
+ SHA512:
6
+ metadata.gz: 0c4ba8e7331404d75190dae4e72034967d3997adb328e353e9f0efac91b06ecc082522bb7efcd8fffd4cdb41d88f1331f6f3b4409c145dd0e5cfb5fb3c9f3bdf
7
+ data.tar.gz: 1dea739720d9b1797732d75294adf8af1f15b253930a1d00e86cbb3b258959bd3c5a50acd24386f37c671abb04ccfdb07b367ceb8f1a571a5dd9575a393101ac
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-present Codevedas Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # Kaal::Hanami
2
+
3
+ Hanami integration gem for Kaal.
4
+
5
+ `kaal-hanami` depends on:
6
+
7
+ - `kaal`
8
+ - `kaal-sequel`
9
+ - `hanami`
10
+
11
+ It owns the Hanami integration surface:
12
+
13
+ - explicit middleware-based boot wiring for Hanami apps
14
+ - backend wiring for memory, redis, SQLite, PostgreSQL, and MySQL
15
+ - scheduler file boot loading relative to the Hanami app root
16
+ - opt-in scheduler startup and shutdown helpers
17
+ - Hanami-specific test coverage and a dummy app
18
+
19
+ ## Install
20
+
21
+ ```ruby
22
+ gem 'kaal-hanami'
23
+ gem 'redis' # for redis
24
+ gem 'sqlite3' # or pg / mysql2 for SQL
25
+ ```
26
+
27
+ If you use SQL persistence, create the Kaal tables using Sequel migrations. `kaal-sequel` exposes templates for:
28
+
29
+ - SQLite: `kaal_dispatches`, `kaal_locks`, `kaal_definitions`
30
+ - PostgreSQL: `kaal_dispatches`, `kaal_definitions`
31
+ - MySQL: `kaal_dispatches`, `kaal_definitions`
32
+
33
+ Your app should also provide `config/scheduler.yml`.
34
+
35
+ ## What It Provides
36
+
37
+ - Hanami-native middleware wiring on top of the Kaal engine
38
+ - explicit backend injection for memory and custom backends
39
+ - redis convenience wiring when the app passes a redis client
40
+ - automatic SQL backend selection from the Sequel adapter unless the app passes `adapter:`
41
+ - explicit lifecycle helpers so web processes do not implicitly start background scheduler threads
42
+
43
+ ## Minimal Hanami
44
+
45
+ ```ruby
46
+ require 'hanami'
47
+ require 'kaal/hanami'
48
+
49
+ module MyApp
50
+ class App < Hanami::App
51
+ Kaal::Hanami.configure!(
52
+ self,
53
+ backend: Kaal::Backend::MemoryAdapter.new,
54
+ scheduler_config_path: 'config/scheduler.yml',
55
+ namespace: 'my-app',
56
+ start_scheduler: false
57
+ )
58
+ end
59
+ end
60
+ ```
61
+
62
+ ## Redis
63
+
64
+ ```ruby
65
+ require 'redis'
66
+
67
+ module MyApp
68
+ class App < Hanami::App
69
+ REDIS = Redis.new(url: ENV.fetch('REDIS_URL'))
70
+
71
+ Kaal::Hanami.configure!(
72
+ self,
73
+ redis: REDIS,
74
+ scheduler_config_path: 'config/scheduler.yml',
75
+ namespace: 'my-app',
76
+ start_scheduler: false
77
+ )
78
+ end
79
+ end
80
+ ```
81
+
82
+ ## SQL Backends
83
+
84
+ For SQL-backed Hanami apps, pass a Sequel connection:
85
+
86
+ ```ruby
87
+ require 'sequel'
88
+
89
+ database = Sequel.connect(ENV.fetch('DATABASE_URL'))
90
+
91
+ module MyApp
92
+ class App < Hanami::App
93
+ Kaal::Hanami.configure!(
94
+ self,
95
+ database: database,
96
+ adapter: 'postgres', # optional when Sequel can infer it
97
+ scheduler_config_path: 'config/scheduler.yml'
98
+ )
99
+ end
100
+ end
101
+ ```
102
+
103
+ ## Lifecycle
104
+
105
+ `kaal-hanami` does not auto-start the scheduler by default.
106
+
107
+ If you want the web process to run it:
108
+
109
+ ```ruby
110
+ Kaal::Hanami.start!
111
+ ```
112
+
113
+ To stop it explicitly:
114
+
115
+ ```ruby
116
+ Kaal::Hanami.stop!
117
+ ```
118
+
119
+ If you pass `start_scheduler: true` to `Kaal::Hanami.configure!`, the addon starts the scheduler and installs an `at_exit` shutdown hook for that managed scheduler instance.
120
+
121
+ Preferred deployment model:
122
+
123
+ - run the scheduler in a dedicated process when possible
124
+ - use web-process startup only when you intentionally want co-located scheduling
125
+
126
+ ## Public API
127
+
128
+ - `Kaal::Hanami.configure!(app, **options)`
129
+ - `Kaal::Hanami.register!(app, backend: nil, database: nil, redis: nil, scheduler_config_path: 'config/scheduler.yml', namespace: nil, start_scheduler: false, adapter: nil, root: nil, environment: nil)`
130
+ - `Kaal::Hanami.configure_backend!(backend: nil, database: nil, redis: nil, adapter: nil, configuration: Kaal.configuration)`
131
+ - `Kaal::Hanami.detect_backend_name(database, adapter: nil)`
132
+ - `Kaal::Hanami.load_scheduler_file!(root:, environment: nil)`
133
+ - `Kaal::Hanami.start!`
134
+ - `Kaal::Hanami.stop!`
135
+ - `Kaal::Hanami::Middleware`
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Codevedas Inc. 2025-present
4
+ #
5
+ # This source code is licensed under the MIT license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+ require 'bundler/setup'
8
+ require 'bundler/gem_tasks'
data/bin/reek ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright Codevedas Inc. 2025-present
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ require 'pty'
9
+
10
+ root_dir = File.expand_path('..', __dir__)
11
+ Dir.chdir(root_dir)
12
+
13
+ command = ['bundle', 'exec', 'reek', *ARGV]
14
+ output = +''
15
+ status = nil
16
+
17
+ PTY.spawn(*command) do |reader, _writer, pid|
18
+ reader.each { |line| output << line }
19
+ rescue Errno::EIO
20
+ nil
21
+ ensure
22
+ _, status = Process.wait2(pid)
23
+ end
24
+
25
+ print(output.gsub("\r\n", "\n"))
26
+ exit(status.exitstatus || 1)
data/bin/rspec ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright Codevedas Inc. 2025-present
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+ # This file was generated by Bundler.
10
+ #
11
+ # The application 'rspec' is installed as part of a gem, and
12
+ # this file is here to facilitate running it.
13
+ #
14
+
15
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
16
+
17
+ bundle_binstub = File.expand_path('bundle', __dir__)
18
+
19
+ if File.file?(bundle_binstub)
20
+ if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
21
+ load(bundle_binstub)
22
+ else
23
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
24
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
25
+ end
26
+ end
27
+
28
+ require 'rubygems'
29
+ require 'bundler/setup'
30
+
31
+ load Gem.bin_path('rspec-core', 'rspec')
data/bin/rspec-e2e ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ADAPTER="${1:-memory}"
5
+ shift || true
6
+
7
+ E2E="1" NO_COVERAGE=1 bin/rspec spec/e2e --tag "integration:${ADAPTER}" "$@"
data/bin/rspec-unit ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ bin/rspec spec/kaal --tag ~feature --tag ~integration "$@"
data/bin/rubocop ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Copyright Codevedas Inc. 2025-present
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+ # This file was generated by Bundler.
10
+ #
11
+ # The application 'rubocop' is installed as part of a gem, and
12
+ # this file is here to facilitate running it.
13
+ #
14
+
15
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
16
+
17
+ bundle_binstub = File.expand_path('bundle', __dir__)
18
+
19
+ if File.file?(bundle_binstub)
20
+ if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
21
+ load(bundle_binstub)
22
+ else
23
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
24
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
25
+ end
26
+ end
27
+
28
+ require 'rubygems'
29
+ require 'bundler/setup'
30
+
31
+ load Gem.bin_path('rubocop', 'rubocop')
data/bin/update-bundle ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ bundle update
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Codevedas Inc. 2025-present
4
+ #
5
+ # This source code is licensed under the MIT license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+ module Kaal
8
+ module Hanami
9
+ # Rack middleware that bootstraps Kaal for Hanami applications.
10
+ class Middleware
11
+ def initialize(
12
+ app,
13
+ hanami_app:,
14
+ backend: nil,
15
+ database: nil,
16
+ redis: nil,
17
+ scheduler_config_path: 'config/scheduler.yml',
18
+ namespace: nil,
19
+ start_scheduler: false,
20
+ adapter: nil,
21
+ root: nil,
22
+ environment: nil
23
+ )
24
+ @app = app
25
+
26
+ Kaal::Hanami.register!(
27
+ hanami_app,
28
+ backend:,
29
+ database:,
30
+ redis:,
31
+ scheduler_config_path:,
32
+ namespace:,
33
+ start_scheduler:,
34
+ adapter:,
35
+ root:,
36
+ environment:
37
+ )
38
+ end
39
+
40
+ def call(env)
41
+ @app.call(env)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Codevedas Inc. 2025-present
4
+ #
5
+ # This source code is licensed under the MIT license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+ module Kaal
8
+ module Hanami
9
+ VERSION = '0.3.0'
10
+ end
11
+ end
@@ -0,0 +1,198 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright Codevedas Inc. 2025-present
4
+ #
5
+ # This source code is licensed under the MIT license found in the
6
+ # LICENSE file in the root directory of this source tree.
7
+ require 'pathname'
8
+ require 'kaal/sequel'
9
+ require 'hanami'
10
+ require 'kaal/hanami/version'
11
+ require 'kaal/hanami/middleware'
12
+
13
+ module Kaal
14
+ # Hanami integration surface for Kaal.
15
+ module Hanami
16
+ class << self
17
+ def configure!(app, **)
18
+ app.config.middleware.use(Kaal::Hanami::Middleware, hanami_app: app, **)
19
+ app
20
+ end
21
+
22
+ def register!(
23
+ app,
24
+ backend: nil,
25
+ database: nil,
26
+ redis: nil,
27
+ scheduler_config_path: 'config/scheduler.yml',
28
+ namespace: nil,
29
+ start_scheduler: false,
30
+ adapter: nil,
31
+ root: nil,
32
+ environment: nil
33
+ )
34
+ configuration = Kaal.configuration
35
+ normalized_scheduler_config_path = scheduler_config_path.to_s.strip
36
+ normalized_namespace = namespace.to_s.strip
37
+ configuration.scheduler_config_path = normalized_scheduler_config_path unless normalized_scheduler_config_path.empty?
38
+ configuration.namespace = normalized_namespace unless normalized_namespace.empty?
39
+
40
+ configure_backend!(backend:, database:, redis:, adapter:, configuration:)
41
+ load_scheduler_file!(
42
+ root: root_path_for(app, root:),
43
+ environment: environment_name_for(app, environment:)
44
+ )
45
+
46
+ start_managed_scheduler! if start_scheduler
47
+ app
48
+ end
49
+
50
+ def configure_backend!(backend: nil, database: nil, redis: nil, adapter: nil, configuration: Kaal.configuration)
51
+ current_backend = configuration.backend
52
+ return current_backend if current_backend
53
+
54
+ return configuration.backend = backend if backend
55
+ return configuration.backend = build_redis_backend(redis, configuration) if redis
56
+
57
+ explicit_adapter = adapter.to_s.strip
58
+ unless explicit_adapter.empty?
59
+ raise ArgumentError, 'database is required when adapter is provided' unless database
60
+
61
+ backend_name = normalize_backend_name(explicit_adapter)
62
+ raise ArgumentError, "Unsupported Hanami datastore backend: #{adapter.inspect}" unless backend_name
63
+
64
+ return configuration.backend = build_backend(backend_name, database)
65
+ end
66
+
67
+ return configuration.backend = Kaal::Backend::MemoryAdapter.new unless database
68
+
69
+ backend_name = detect_backend_name(database, adapter:)
70
+ raise ArgumentError, 'Unsupported Hanami datastore backend; use memory, redis, sqlite, postgres, or mysql' unless backend_name
71
+
72
+ configuration.backend = build_backend(backend_name, database)
73
+ end
74
+
75
+ def detect_backend_name(database, adapter: nil)
76
+ explicit_adapter = normalize_backend_name(adapter)
77
+ return explicit_adapter if explicit_adapter
78
+
79
+ inferred_adapter = database_adapter_name(database)
80
+ normalize_backend_name(inferred_adapter)
81
+ end
82
+
83
+ def load_scheduler_file!(root:, environment: nil)
84
+ runtime_context = Kaal::Runtime::RuntimeContext.new(
85
+ root_path: root,
86
+ environment_name: runtime_environment_name(environment)
87
+ )
88
+
89
+ Kaal::Runtime::SchedulerBootLoader.new(
90
+ configuration_provider: -> { Kaal.configuration },
91
+ logger: Kaal.configuration.logger,
92
+ runtime_context: runtime_context,
93
+ load_scheduler_file: -> { Kaal.load_scheduler_file!(runtime_context:) }
94
+ ).load_on_boot!
95
+ end
96
+
97
+ def start!
98
+ Kaal.start!
99
+ end
100
+
101
+ def stop!(timeout: 30)
102
+ Kaal.stop!(timeout:)
103
+ end
104
+
105
+ private
106
+
107
+ def build_redis_backend(redis, configuration)
108
+ Kaal::Backend::RedisAdapter.new(redis, namespace: configuration.namespace)
109
+ end
110
+
111
+ def build_backend(backend_name, database)
112
+ case backend_name
113
+ when 'sqlite'
114
+ Kaal::Backend::DatabaseAdapter.new(database)
115
+ when 'postgres'
116
+ Kaal::Backend::PostgresAdapter.new(database)
117
+ when 'mysql'
118
+ Kaal::Backend::MySQLAdapter.new(database)
119
+ end
120
+ end
121
+
122
+ def database_adapter_name(database)
123
+ return if database.nil?
124
+
125
+ database_type = database.database_type if database.respond_to?(:database_type)
126
+ return database_type.to_s unless database_type.to_s.strip.empty?
127
+
128
+ adapter_scheme = database.adapter_scheme if database.respond_to?(:adapter_scheme)
129
+ adapter_scheme.to_s
130
+ end
131
+
132
+ def normalize_backend_name(adapter_name)
133
+ adapter = adapter_name.to_s.strip.downcase
134
+ return if adapter.empty?
135
+ return 'sqlite' if adapter.include?('sqlite')
136
+ return 'postgres' if adapter.include?('postgres')
137
+ return 'mysql' if adapter.include?('mysql') || adapter.include?('trilogy')
138
+
139
+ nil
140
+ end
141
+
142
+ def root_path_for(app, root: nil)
143
+ explicit_root = root.to_s.strip
144
+ return Pathname.new(explicit_root) unless explicit_root.empty?
145
+
146
+ app_root = app.config.root if app.respond_to?(:config) && app.config.respond_to?(:root)
147
+ Pathname.new(app_root || Dir.pwd)
148
+ end
149
+
150
+ def environment_name_for(app, environment: nil)
151
+ explicit_environment = environment.to_s.strip
152
+ return explicit_environment unless explicit_environment.empty?
153
+
154
+ app_environment = app.config.env if app.respond_to?(:config) && app.config.respond_to?(:env)
155
+ return app_environment.to_s unless app_environment.to_s.empty?
156
+
157
+ runtime_environment_name(nil)
158
+ end
159
+
160
+ def runtime_environment_name(environment)
161
+ explicit_environment = environment.to_s.strip
162
+ return explicit_environment unless explicit_environment.empty?
163
+
164
+ hanami_env = ENV['HANAMI_ENV'].to_s.strip
165
+ return hanami_env unless hanami_env.empty?
166
+
167
+ return ::Hanami.env.to_s if defined?(::Hanami) && ::Hanami.respond_to?(:env)
168
+
169
+ Kaal::Runtime::RuntimeContext.environment_name_from(ENV)
170
+ end
171
+
172
+ def start_managed_scheduler!
173
+ return if Kaal.running?
174
+
175
+ start!
176
+ install_shutdown_hook
177
+ end
178
+
179
+ def install_shutdown_hook
180
+ @shutdown_hook_mutex ||= Mutex.new
181
+ @shutdown_hook_mutex.synchronize do
182
+ return if @shutdown_hook_installed
183
+
184
+ @shutdown_hook_installed = true
185
+ Kernel.at_exit do
186
+ if Kaal.running?
187
+ begin
188
+ stop!
189
+ rescue StandardError => e
190
+ Kaal.configuration.logger&.error("Failed to stop Kaal during Hanami shutdown: #{e.message}")
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kaal-hanami
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Nitesh Purohit
8
+ - Codevedas Inc.
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: hanami
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '3.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '2.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: kaal
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '='
38
+ - !ruby/object:Gem::Version
39
+ version: 0.3.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - '='
45
+ - !ruby/object:Gem::Version
46
+ version: 0.3.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: kaal-sequel
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - '='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.3.0
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '='
59
+ - !ruby/object:Gem::Version
60
+ version: 0.3.0
61
+ - !ruby/object:Gem::Dependency
62
+ name: rack
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '2.2'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '2.2'
75
+ description: " Kaal-Hanami provides a thin integration layer that wires Kaal and
76
+ Kaal-Sequel into Hanami applications with explicit lifecycle control.\n"
77
+ email:
78
+ - nitesh.purohit.it@gmail.com
79
+ - team@codevedas.com
80
+ executables: []
81
+ extensions: []
82
+ extra_rdoc_files: []
83
+ files:
84
+ - LICENSE
85
+ - README.md
86
+ - Rakefile
87
+ - bin/reek
88
+ - bin/rspec
89
+ - bin/rspec-e2e
90
+ - bin/rspec-unit
91
+ - bin/rubocop
92
+ - bin/update-bundle
93
+ - lib/kaal/hanami.rb
94
+ - lib/kaal/hanami/middleware.rb
95
+ - lib/kaal/hanami/version.rb
96
+ homepage: https://github.com/Code-Vedas/kaal
97
+ licenses:
98
+ - MIT
99
+ metadata:
100
+ bug_tracker_uri: https://github.com/Code-Vedas/kaal/issues
101
+ changelog_uri: https://github.com/Code-Vedas/kaal/blob/main/CHANGELOG.md
102
+ documentation_uri: https://kaal.codevedas.com
103
+ homepage_uri: https://github.com/Code-Vedas/kaal
104
+ source_code_uri: https://github.com/Code-Vedas/kaal.git
105
+ funding_uri: https://github.com/sponsors/Code-Vedas
106
+ support_uri: https://kaal.codevedas.com/support
107
+ rubygems_uri: https://rubygems.org/gems/kaal-hanami
108
+ rubygems_mfa_required: 'true'
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '3.2'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubygems_version: 3.6.7
124
+ specification_version: 4
125
+ summary: Hanami integration for Kaal, a distributed cron scheduler for Ruby.
126
+ test_files: []