jetstream_bridge 2.2.1 β†’ 2.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.
data/Gemfile.lock DELETED
@@ -1,268 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- jetstream_bridge (2.2.1)
5
- activerecord (>= 6.0)
6
- activesupport (>= 6.0)
7
- nats-pure (~> 2.4)
8
- rails (>= 6.0)
9
-
10
- GEM
11
- remote: https://rubygems.org/
12
- specs:
13
- actioncable (8.0.2)
14
- actionpack (= 8.0.2)
15
- activesupport (= 8.0.2)
16
- nio4r (~> 2.0)
17
- websocket-driver (>= 0.6.1)
18
- zeitwerk (~> 2.6)
19
- actionmailbox (8.0.2)
20
- actionpack (= 8.0.2)
21
- activejob (= 8.0.2)
22
- activerecord (= 8.0.2)
23
- activestorage (= 8.0.2)
24
- activesupport (= 8.0.2)
25
- mail (>= 2.8.0)
26
- actionmailer (8.0.2)
27
- actionpack (= 8.0.2)
28
- actionview (= 8.0.2)
29
- activejob (= 8.0.2)
30
- activesupport (= 8.0.2)
31
- mail (>= 2.8.0)
32
- rails-dom-testing (~> 2.2)
33
- actionpack (8.0.2)
34
- actionview (= 8.0.2)
35
- activesupport (= 8.0.2)
36
- nokogiri (>= 1.8.5)
37
- rack (>= 2.2.4)
38
- rack-session (>= 1.0.1)
39
- rack-test (>= 0.6.3)
40
- rails-dom-testing (~> 2.2)
41
- rails-html-sanitizer (~> 1.6)
42
- useragent (~> 0.16)
43
- actiontext (8.0.2)
44
- actionpack (= 8.0.2)
45
- activerecord (= 8.0.2)
46
- activestorage (= 8.0.2)
47
- activesupport (= 8.0.2)
48
- globalid (>= 0.6.0)
49
- nokogiri (>= 1.8.5)
50
- actionview (8.0.2)
51
- activesupport (= 8.0.2)
52
- builder (~> 3.1)
53
- erubi (~> 1.11)
54
- rails-dom-testing (~> 2.2)
55
- rails-html-sanitizer (~> 1.6)
56
- activejob (8.0.2)
57
- activesupport (= 8.0.2)
58
- globalid (>= 0.3.6)
59
- activemodel (8.0.2)
60
- activesupport (= 8.0.2)
61
- activerecord (8.0.2)
62
- activemodel (= 8.0.2)
63
- activesupport (= 8.0.2)
64
- timeout (>= 0.4.0)
65
- activestorage (8.0.2)
66
- actionpack (= 8.0.2)
67
- activejob (= 8.0.2)
68
- activerecord (= 8.0.2)
69
- activesupport (= 8.0.2)
70
- marcel (~> 1.0)
71
- activesupport (8.0.2)
72
- base64
73
- benchmark (>= 0.3)
74
- bigdecimal
75
- concurrent-ruby (~> 1.0, >= 1.3.1)
76
- connection_pool (>= 2.2.5)
77
- drb
78
- i18n (>= 1.6, < 2)
79
- logger (>= 1.4.2)
80
- minitest (>= 5.1)
81
- securerandom (>= 0.3)
82
- tzinfo (~> 2.0, >= 2.0.5)
83
- uri (>= 0.13.1)
84
- ast (2.4.3)
85
- base64 (0.3.0)
86
- benchmark (0.4.1)
87
- bigdecimal (3.2.2)
88
- builder (3.3.0)
89
- bundler-audit (0.9.2)
90
- bundler (>= 1.2.0, < 3)
91
- thor (~> 1.0)
92
- concurrent-ruby (1.3.5)
93
- connection_pool (2.5.3)
94
- crass (1.0.6)
95
- date (3.4.1)
96
- diff-lcs (1.6.2)
97
- drb (2.2.3)
98
- erubi (1.13.1)
99
- globalid (1.2.1)
100
- activesupport (>= 6.1)
101
- i18n (1.14.7)
102
- concurrent-ruby (~> 1.0)
103
- io-console (0.8.0)
104
- irb (1.15.2)
105
- pp (>= 0.6.0)
106
- rdoc (>= 4.0.0)
107
- reline (>= 0.4.2)
108
- json (2.13.2)
109
- language_server-protocol (3.17.0.5)
110
- lint_roller (1.1.0)
111
- logger (1.7.0)
112
- loofah (2.24.0)
113
- crass (~> 1.0.2)
114
- nokogiri (>= 1.12.0)
115
- mail (2.8.1)
116
- mini_mime (>= 0.1.1)
117
- net-imap
118
- net-pop
119
- net-smtp
120
- marcel (1.0.4)
121
- mini_mime (1.1.5)
122
- mini_portile2 (2.8.9)
123
- minitest (5.25.5)
124
- nats-pure (2.5.0)
125
- base64
126
- concurrent-ruby (~> 1.0)
127
- json
128
- securerandom
129
- uri
130
- net-imap (0.5.6)
131
- date
132
- net-protocol
133
- net-pop (0.1.2)
134
- net-protocol
135
- net-protocol (0.2.2)
136
- timeout
137
- net-smtp (0.5.1)
138
- net-protocol
139
- nio4r (2.7.4)
140
- nokogiri (1.18.7)
141
- mini_portile2 (~> 2.8.2)
142
- racc (~> 1.4)
143
- nokogiri (1.18.7-arm64-darwin)
144
- racc (~> 1.4)
145
- parallel (1.27.0)
146
- parser (3.3.9.0)
147
- ast (~> 2.4.1)
148
- racc
149
- pp (0.6.2)
150
- prettyprint
151
- prettyprint (0.2.0)
152
- prism (1.4.0)
153
- psych (5.2.3)
154
- date
155
- stringio
156
- racc (1.8.1)
157
- rack (3.1.13)
158
- rack-session (2.1.0)
159
- base64 (>= 0.1.0)
160
- rack (>= 3.0.0)
161
- rack-test (2.2.0)
162
- rack (>= 1.3)
163
- rackup (2.2.1)
164
- rack (>= 3)
165
- rails (8.0.2)
166
- actioncable (= 8.0.2)
167
- actionmailbox (= 8.0.2)
168
- actionmailer (= 8.0.2)
169
- actionpack (= 8.0.2)
170
- actiontext (= 8.0.2)
171
- actionview (= 8.0.2)
172
- activejob (= 8.0.2)
173
- activemodel (= 8.0.2)
174
- activerecord (= 8.0.2)
175
- activestorage (= 8.0.2)
176
- activesupport (= 8.0.2)
177
- bundler (>= 1.15.0)
178
- railties (= 8.0.2)
179
- rails-dom-testing (2.2.0)
180
- activesupport (>= 5.0.0)
181
- minitest
182
- nokogiri (>= 1.6)
183
- rails-html-sanitizer (1.6.2)
184
- loofah (~> 2.21)
185
- nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
186
- railties (8.0.2)
187
- actionpack (= 8.0.2)
188
- activesupport (= 8.0.2)
189
- irb (~> 1.13)
190
- rackup (>= 1.0.0)
191
- rake (>= 12.2)
192
- thor (~> 1.0, >= 1.2.2)
193
- zeitwerk (~> 2.6)
194
- rainbow (3.1.1)
195
- rake (13.2.1)
196
- rdoc (6.13.1)
197
- psych (>= 4.0.0)
198
- regexp_parser (2.11.2)
199
- reline (0.6.1)
200
- io-console (~> 0.5)
201
- rspec (3.13.1)
202
- rspec-core (~> 3.13.0)
203
- rspec-expectations (~> 3.13.0)
204
- rspec-mocks (~> 3.13.0)
205
- rspec-core (3.13.5)
206
- rspec-support (~> 3.13.0)
207
- rspec-expectations (3.13.5)
208
- diff-lcs (>= 1.2.0, < 2.0)
209
- rspec-support (~> 3.13.0)
210
- rspec-mocks (3.13.5)
211
- diff-lcs (>= 1.2.0, < 2.0)
212
- rspec-support (~> 3.13.0)
213
- rspec-support (3.13.5)
214
- rubocop (1.79.2)
215
- json (~> 2.3)
216
- language_server-protocol (~> 3.17.0.2)
217
- lint_roller (~> 1.1.0)
218
- parallel (~> 1.10)
219
- parser (>= 3.3.0.2)
220
- rainbow (>= 2.2.2, < 4.0)
221
- regexp_parser (>= 2.9.3, < 3.0)
222
- rubocop-ast (>= 1.46.0, < 2.0)
223
- ruby-progressbar (~> 1.7)
224
- unicode-display_width (>= 2.4.0, < 4.0)
225
- rubocop-ast (1.46.0)
226
- parser (>= 3.3.7.2)
227
- prism (~> 1.4)
228
- rubocop-packaging (0.6.0)
229
- lint_roller (~> 1.1.0)
230
- rubocop (>= 1.72.1, < 2.0)
231
- rubocop-performance (1.25.0)
232
- lint_roller (~> 1.1)
233
- rubocop (>= 1.75.0, < 2.0)
234
- rubocop-ast (>= 1.38.0, < 2.0)
235
- ruby-progressbar (1.13.0)
236
- securerandom (0.4.1)
237
- stringio (3.1.6)
238
- thor (1.3.2)
239
- timeout (0.4.3)
240
- tzinfo (2.0.6)
241
- concurrent-ruby (~> 1.0)
242
- unicode-display_width (3.1.4)
243
- unicode-emoji (~> 4.0, >= 4.0.4)
244
- unicode-emoji (4.0.4)
245
- uri (1.0.3)
246
- useragent (0.16.11)
247
- websocket-driver (0.7.7)
248
- base64
249
- websocket-extensions (>= 0.1.0)
250
- websocket-extensions (0.1.5)
251
- zeitwerk (2.7.2)
252
-
253
- PLATFORMS
254
- arm64-darwin-24
255
- ruby
256
- x86_64-linux
257
-
258
- DEPENDENCIES
259
- bundler-audit (>= 0.9.1)
260
- jetstream_bridge!
261
- rake (>= 13.0)
262
- rspec (>= 3.12)
263
- rubocop (~> 1.66)
264
- rubocop-packaging (~> 0.5)
265
- rubocop-performance (~> 1.21)
266
-
267
- BUNDLED WITH
268
- 2.6.3
data/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Mike Attara
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 DELETED
@@ -1,302 +0,0 @@
1
- # Jetstream Bridge
2
-
3
- **Production-safe realtime data bridge** between systems using **NATS JetStream**.
4
- Includes durable consumers, backpressure, retries, **DLQ**, optional **Inbox/Outbox**, and **overlap-safe stream provisioning**.
5
-
6
- ---
7
-
8
- ## ✨ Features
9
-
10
- * πŸ”Œ Simple **Publisher** and **Consumer** interfaces
11
- * πŸ›‘ **Outbox** (reliable send) & **Inbox** (idempotent receive), opt-in
12
- * 🧨 **DLQ** for poison messages
13
- * βš™οΈ Durable `pull_subscribe` with backoff & `max_deliver`
14
- * 🎯 Clear **source/destination** subject conventions
15
- * 🧱 **Overlap-safe stream ensure** (prevents β€œsubjects overlap” BadRequest)
16
- * πŸš‚ **Rails generators** for initializer & migrations, plus an install **rake task**
17
- * ⚑️ **Eager-loaded models** via Railtie (production)
18
- * πŸ“Š Built-in logging for visibility
19
-
20
- ---
21
-
22
- ## πŸ“¦ Install
23
-
24
- ```ruby
25
- # Gemfile
26
- gem "jetstream_bridge", "~> 2.0"
27
- ```
28
-
29
- ```bash
30
- bundle install
31
- ```
32
-
33
- ---
34
-
35
- ## 🧰 Rails Generators & Rake Task
36
-
37
- From your Rails app:
38
-
39
- ```bash
40
- # Create initializer + migrations
41
- bin/rails g jetstream_bridge:install
42
-
43
- # Or run them separately:
44
- bin/rails g jetstream_bridge:initializer
45
- bin/rails g jetstream_bridge:migrations
46
-
47
- # Rake task (does both initializer + migrations)
48
- bin/rake jetstream_bridge:install
49
- ```
50
-
51
- Then:
52
-
53
- ```bash
54
- bin/rails db:migrate
55
- ```
56
-
57
- > The generators create:
58
- >
59
- > * `config/initializers/jetstream_bridge.rb`
60
- > * `db/migrate/*_create_jetstream_outbox_events.rb`
61
- > * `db/migrate/*_create_jetstream_inbox_events.rb`
62
-
63
- ---
64
-
65
- ## πŸ”§ Configure (Rails)
66
-
67
- ```ruby
68
- # config/initializers/jetstream_bridge.rb
69
- JetstreamBridge.configure do |config|
70
- # NATS connection
71
- config.nats_urls = ENV.fetch("NATS_URLS", "nats://localhost:4222")
72
- config.env = ENV.fetch("NATS_ENV", "development")
73
- config.app_name = ENV.fetch("APP_NAME", "app")
74
- config.destination_app = ENV["DESTINATION_APP"] # required
75
-
76
- # Consumer tuning
77
- config.max_deliver = 5
78
- config.ack_wait = "30s"
79
- config.backoff = %w[1s 5s 15s 30s 60s]
80
-
81
- # Reliability features (opt-in)
82
- config.use_outbox = true
83
- config.use_inbox = true
84
- config.use_dlq = true
85
-
86
- # Models (override if you use custom AR classes/table names)
87
- config.outbox_model = "JetstreamBridge::OutboxEvent"
88
- config.inbox_model = "JetstreamBridge::InboxEvent"
89
- end
90
- ```
91
-
92
- > **Defaults:**
93
- >
94
- > * `stream_name` β†’ `#{env}-jetstream-bridge-stream`
95
- > * `dlq_subject` β†’ `#{env}.data.sync.dlq`
96
-
97
- ---
98
-
99
- ## πŸ“‘ Subject Conventions
100
-
101
- | Direction | Subject Pattern |
102
- |---------------|---------------------------|
103
- | **Publish** | `{env}.{app}.sync.{dest}` |
104
- | **Subscribe** | `{env}.{dest}.sync.{app}` |
105
- | **DLQ** | `{env}.sync.dlq` |
106
-
107
- * `{app}`: `app_name`
108
- * `{dest}`: `destination_app`
109
- * `{env}`: `env`
110
-
111
- ---
112
-
113
- ## 🧱 Stream Topology (auto-ensure and overlap-safe)
114
-
115
- On first connection, Jetstream Bridge **ensures** a single stream exists for your `env` and that it covers:
116
-
117
- * `source_subject` (`{env}.{app}.sync.{dest}`)
118
- * `destination_subject` (`{env}.{dest}.sync.{app}`)
119
- * `dlq_subject` (if enabled)
120
-
121
- It’s **overlap-safe**:
122
-
123
- * Skips adding subjects already covered by existing wildcards
124
- * Pre-filters subjects owned by other streams to avoid `BadRequest: subjects overlap with an existing stream`
125
- * Retries once on concurrent races, then logs and continues safely
126
-
127
- ---
128
-
129
- ## πŸ—ƒ Database Setup (Inbox / Outbox)
130
-
131
- Inbox/Outbox are **optional**. The library detects columns at runtime and only sets what exists, so you can start minimal and evolve later.
132
-
133
- ### Generator-created tables (recommended)
134
-
135
- ```ruby
136
- # jetstream_outbox_events
137
- create_table :jetstream_outbox_events do |t|
138
- t.string :event_id, null: false
139
- t.string :subject, null: false
140
- t.jsonb :payload, null: false, default: {}
141
- t.jsonb :headers, null: false, default: {}
142
- t.string :status, null: false, default: "pending" # pending|publishing|sent|failed
143
- t.integer :attempts, null: false, default: 0
144
- t.text :last_error
145
- t.datetime :enqueued_at
146
- t.datetime :sent_at
147
- t.timestamps
148
- end
149
- add_index :jetstream_outbox_events, :event_id, unique: true
150
- add_index :jetstream_outbox_events, :status
151
-
152
- # jetstream_inbox_events
153
- create_table :jetstream_inbox_events do |t|
154
- t.string :event_id # preferred dedupe key
155
- t.string :subject, null: false
156
- t.jsonb :payload, null: false, default: {}
157
- t.jsonb :headers, null: false, default: {}
158
- t.string :stream
159
- t.bigint :stream_seq
160
- t.integer :deliveries
161
- t.string :status, null: false, default: "received" # received|processing|processed|failed
162
- t.text :last_error
163
- t.datetime :received_at
164
- t.datetime :processed_at
165
- t.timestamps
166
- end
167
- add_index :jetstream_inbox_events, :event_id, unique: true, where: 'event_id IS NOT NULL'
168
- add_index :jetstream_inbox_events, [:stream, :stream_seq], unique: true, where: 'stream IS NOT NULL AND stream_seq IS NOT NULL'
169
- add_index :jetstream_inbox_events, :status
170
- ```
171
-
172
- > Already have different table names? Point the config to your AR classes via `config.outbox_model` / `config.inbox_model`.
173
-
174
- ---
175
-
176
- ## πŸ“€ Publish Events
177
-
178
- ```ruby
179
- publisher = JetstreamBridge::Publisher.new
180
- publisher.publish(
181
- resource_type: "user",
182
- event_type: "created",
183
- payload: { id: "01H...", name: "Ada" }, # resource_id inferred from payload[:id] / payload["id"]
184
- # optional:
185
- # event_id: "uuid-or-ulid",
186
- # trace_id: "hex",
187
- # occurred_at: Time.now.utc
188
- )
189
- ```
190
-
191
- If **Outbox** is enabled, the publish call:
192
-
193
- * Upserts an outbox row by `event_id`
194
- * Publishes with `Nats-Msg-Id` (idempotent)
195
- * Marks status `sent` or records `failed` with `last_error`
196
-
197
- ---
198
-
199
- ## πŸ“₯ Consume Events
200
-
201
- ```ruby
202
- JetstreamBridge::Consumer.new(
203
- durable_name: "#{Rails.env}-#{app_name}-workers",
204
- batch_size: 25
205
- ) do |event, subject, deliveries|
206
- # Your idempotent domain logic here
207
- # `event` is the parsed envelope hash
208
- UserCreatedHandler.call(event["payload"])
209
- end.run!
210
- ```
211
-
212
- If **Inbox** is enabled, the consumer:
213
-
214
- * Dedupes by `event_id` (falls back to stream sequence if needed)
215
- * Records processing state, errors, and timestamps
216
- * Skips already-processed messages (acks immediately)
217
-
218
- ---
219
-
220
- ## πŸ“¬ Envelope Format
221
-
222
- ```json
223
- {
224
- "event_id": "01H1234567890ABCDEF",
225
- "schema_version": 1,
226
- "event_type": "created",
227
- "producer": "myapp",
228
- "resource_type": "user",
229
- "resource_id": "01H1234567890ABCDEF",
230
- "occurred_at": "2025-08-13T21:00:00Z",
231
- "trace_id": "abc123",
232
- "payload": { "id": "01H...", "name": "Ada" }
233
- }
234
- ```
235
-
236
- * `resource_id` is inferred from `payload.id` when publishing.
237
-
238
- ---
239
-
240
- ## 🧨 Dead-Letter Queue (DLQ)
241
-
242
- When enabled, the topology ensures the DLQ subject exists:
243
- **`{env}.data.sync.dlq`**
244
-
245
- You may run a separate process to subscribe and triage messages that exceed `max_deliver` or are NAK’ed to the DLQ.
246
-
247
- ---
248
-
249
- ## πŸ›  Operations Guide
250
-
251
- ### Monitoring
252
-
253
- * **Consumer lag**: `nats consumer info <stream> <durable>`
254
- * **DLQ volume**: subscribe/metrics on `{env}.data.sync.dlq`
255
- * **Outbox backlog**: alert on `jetstream_outbox_events` with `status != 'sent'` and growing count
256
-
257
- ### Scaling
258
-
259
- * Run consumers in **separate processes/containers**
260
- * Scale consumers independently of web
261
- * Tune `batch_size`, `ack_wait`, `max_deliver`, and `backoff`
262
-
263
- ### Health check
264
-
265
- * Force-connect & ensure topology at boot or in a check:
266
-
267
- ```ruby
268
- JetstreamBridge.ensure_topology!
269
- ```
270
-
271
- ### When to Use
272
-
273
- * **Inbox**: you need idempotent processing and replay safety
274
- * **Outbox**: you want β€œDB commit β‡’ event published (or recorded for retry)” guarantees
275
-
276
- ---
277
-
278
- ## 🧩 Troubleshooting
279
-
280
- * **`subjects overlap with an existing stream`**
281
- The library pre-filters overlapping subjects and retries once. If another team owns a broad wildcard (e.g., `env.data.sync.>`), coordinate subject boundaries.
282
-
283
- * **Consumer exists with mismatched filter**
284
- The library detects and recreates the durable with the desired filter subject.
285
-
286
- * **Repeated redeliveries**
287
- Increase `ack_wait`, review handler acks/NACKs, or move poison messages to DLQ.
288
-
289
- ---
290
-
291
- ## πŸš€ Getting Started
292
-
293
- 1. Add the gem & run `bundle install`
294
- 2. `bin/rails g jetstream_bridge:install`
295
- 3. `bin/rails db:migrate`
296
- 4. Start publishing/consuming!
297
-
298
- ---
299
-
300
- ## πŸ“„ License
301
-
302
- [MIT License](LICENSE)
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'lib/jetstream_bridge/version'
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = 'jetstream_bridge'
7
- spec.version = JetstreamBridge::VERSION
8
- spec.authors = ['Mike Attara']
9
- spec.email = ['mpyebattara@gmail.com']
10
-
11
- # Clear, value-focused copy
12
- spec.summary = 'Reliable realtime bridge over NATS JetStream for Rails/Ruby apps'
13
- spec.description = <<~DESC.strip
14
- Publisher/Consumer utilities for NATS JetStream with environment-scoped subjects,
15
- overlap guards, DLQ routing, retries/backoff, and optional Inbox/Outbox patterns.
16
- Includes topology setup helpers for production-safe operation.
17
- DESC
18
-
19
- spec.license = 'MIT'
20
- spec.homepage = 'https://github.com/attaradev/jetstream_bridge'
21
-
22
- # Ruby & RubyGems requirements
23
- spec.required_ruby_version = '>= 2.7.0'
24
- spec.required_rubygems_version = '>= 3.3.0'
25
-
26
- # Rich metadata for RubyGems.org
27
- spec.metadata = {
28
- 'homepage_uri' => 'https://github.com/attaradev/jetstream_bridge',
29
- 'source_code_uri' => 'https://github.com/attaradev/jetstream_bridge',
30
- 'changelog_uri' => 'https://github.com/attaradev/jetstream_bridge/blob/main/CHANGELOG.md',
31
- 'documentation_uri' => 'https://github.com/attaradev/jetstream_bridge#readme',
32
- 'bug_tracker_uri' => 'https://github.com/attaradev/jetstream_bridge/issues',
33
- 'github_repo' => 'ssh://github.com/attaradev/jetstream_bridge',
34
- 'rubygems_mfa_required' => 'true'
35
- }
36
-
37
- # Safer file list for published gem
38
- # (falls back to Dir[] if not in a git repo β€” e.g., CI tarballs)
39
- spec.files = if system('git rev-parse --is-inside-work-tree > /dev/null 2>&1')
40
- `git ls-files -z`.split("\x0").reject { |f| f.start_with?('spec/fixtures/') }
41
- else
42
- Dir['lib/**/*', 'README*', 'CHANGELOG*', 'LICENSE*']
43
- end
44
-
45
- spec.require_paths = ['lib']
46
-
47
- # Runtime dependencies
48
- spec.add_dependency 'activerecord', '>= 6.0'
49
- spec.add_dependency 'activesupport', '>= 6.0'
50
- spec.add_dependency 'nats-pure', '~> 2.4'
51
- spec.add_dependency 'rails', '>= 6.0'
52
-
53
- # Development / quality dependencies
54
- spec.add_development_dependency 'bundler-audit', '>= 0.9.1'
55
- spec.add_development_dependency 'rake', '>= 13.0'
56
- spec.add_development_dependency 'rspec', '>= 3.12'
57
- spec.add_development_dependency 'rubocop', '~> 1.66'
58
- spec.add_development_dependency 'rubocop-packaging', '~> 0.5'
59
- spec.add_development_dependency 'rubocop-performance', '~> 1.21'
60
- end