bunny_app 2.3.0 → 2.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f14177f1f9c2cff9cfe3ee28ac8bba3e22bbcf2dab081c9520a3355e284bf45
4
- data.tar.gz: 658782618952e5b80d66fec671c8cdbd79cc9375c6f58cb3ab2ea43c468985df
3
+ metadata.gz: 00eca4966ed34106d628843766d2f00f2e8a53b7611154ade889825d0add544c
4
+ data.tar.gz: 6994edecbd4d80b5b0e6dc53e79603629ca7ff85b1cf799f9bb9bab310ba52b1
5
5
  SHA512:
6
- metadata.gz: ce7d03e473bda729c45611e529afafd01e0db24afde29e132e51e2d2db78f8241158f463522d115a90746479f3af20458b65506e5edb4c4411bf90285a6498c5
7
- data.tar.gz: 3963e0e0603b0a4091ecee8504f4967d70b1662cd68213c6709f415cafa3bd6c465aebfb6508a7a3f206aa07193e5f789f03bdce3b0d60582bc9ec55c0e362db
6
+ metadata.gz: e2f422c3846e990cd2a35bc0b0b7ace22e099228cf54cca3641a3dc8915f3aec1a0681e31a1ff0c2db579e27b422fbffad0305d48eb25373488e024e27284c5d
7
+ data.tar.gz: 43a366d65b9f131444e08b7cc1caa9ec6c83a0feb8803e16560d2450d64fbbe406db89030d5781b69c3e602d5ea9b947267b2f4d62d24c59ab3255cc77be452b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.4.0 (14-Apr-2026)
4
+
5
+ - Add `Subscription.quantity_update` for updating subscription charge quantities
6
+ - Add `Subscription.trial_convert` for converting a trial to a paid subscription
7
+
8
+ ## 2.3.0 (22-Nov-2025)
9
+
10
+ - Remove deprecated `latestProvisioningChange` fields from `Tenant.find_by` query
11
+
3
12
  ## 2.2.2 (13-Sep-2025)
4
13
 
5
14
  - Make returnUrl optional in PortalSession.create mutation
data/README.md CHANGED
@@ -1,182 +1,398 @@
1
1
  # bunny-ruby
2
2
 
3
- Ruby SDK for Bunny
3
+ Ruby SDK for [Bunny](https://www.bunny.com) — the subscription billing and management platform.
4
4
 
5
5
  ## Installation
6
6
 
7
- Run `bundle add bunny_app` or add this line to your application's Gemfile:
7
+ Add to your Gemfile:
8
8
 
9
9
  ```ruby
10
10
  gem 'bunny_app'
11
11
  ```
12
12
 
13
- And then execute:
13
+ Then run:
14
14
 
15
15
  ```sh
16
- $ bundle
16
+ bundle install
17
17
  ```
18
18
 
19
- Or install it yourself as:
19
+ Or install directly:
20
20
 
21
21
  ```sh
22
- $ gem install bunny_app
22
+ gem install bunny_app
23
23
  ```
24
24
 
25
- ## Getting Started
25
+ ## Configuration
26
26
 
27
- You can use this gem to send customized graphql queries to Bunny or use the built in convience methods.
27
+ ### With client credentials (recommended)
28
28
 
29
- First configure the Bunny client.
29
+ Using `client_id` and `client_secret` enables automatic token refresh when the access token expires.
30
30
 
31
31
  ```ruby
32
32
  require 'bunny_app'
33
33
 
34
- # We recommend using the client_id/secret of your Bunny client app
35
- # this will enable automatic retries when the access token expires
36
34
  BunnyApp.config do |c|
37
- c.client_id = 'xxx'
38
- c.client_secret = 'xxx'
39
- c.scope = 'standard:read standard:write'
40
- c.base_uri = 'https://<subdomain>.bunny.com'
35
+ c.client_id = 'your-client-id'
36
+ c.client_secret = 'your-client-secret'
37
+ c.scope = 'standard:read standard:write'
38
+ c.base_uri = 'https://<subdomain>.bunny.com'
41
39
  end
40
+ ```
41
+
42
+ ### With a pre-existing access token
42
43
 
43
- # Alternately you can generate the access token outside of this sdk
44
- # be aware that if your access_token expires an exception will be raised
44
+ If you manage token lifecycle yourself, you can pass the token directly. An `AuthorizationError` will be raised if the token expires.
45
+
46
+ ```ruby
45
47
  BunnyApp.config do |c|
46
- c.access_token = 'xxx'
47
- c.base_uri = 'https://<subdomain>.bunny.com'
48
+ c.access_token = 'your-access-token'
49
+ c.base_uri = 'https://<subdomain>.bunny.com'
48
50
  end
49
51
  ```
50
52
 
51
- > Remember! Don't commit secrets to source control!
53
+ > **Never commit secrets to source control.** Load credentials from environment variables or a secret store.
52
54
 
53
- ### Generate rails config
55
+ ### Rails initializer
54
56
 
55
- Create a config file at `config/initializers/bunny_app.rb`
57
+ Generate a config file at `config/initializers/bunny_app.rb`:
56
58
 
57
59
  ```sh
58
- > bin/rails g bunny_app:install
60
+ bin/rails g bunny_app:install
61
+ ```
62
+
63
+ This creates a template that reads credentials from environment variables:
64
+
65
+ ```ruby
66
+ BunnyApp.config do |c|
67
+ c.client_id = ENV['BUNNY_APP_CLIENT_ID']
68
+ c.client_secret = ENV['BUNNY_APP_CLIENT_SECRET']
69
+ c.scope = ENV['BUNNY_APP_SCOPE']
70
+ c.base_uri = 'https://<subdomain>.bunny.com'
71
+ end
59
72
  ```
60
73
 
74
+ ---
75
+
76
+ ## Subscriptions
77
+
61
78
  ### Create a subscription
62
79
 
80
+ Create a new subscription for an account. You can create the account inline or attach to an existing account by ID.
81
+
63
82
  ```ruby
64
- response = BunnyApp::Subscription.create(
83
+ # Create with a new account
84
+ subscription = BunnyApp::Subscription.create(
85
+ price_list_code: 'starter',
86
+ options: {
87
+ account_name: 'Acme Corp',
88
+ first_name: 'Jane',
89
+ last_name: 'Smith',
90
+ email: 'jane@acme.com',
91
+ trial: true,
92
+ tenant_code: 'acme-123',
93
+ tenant_name: 'Acme Corp'
94
+ }
95
+ )
96
+
97
+ # Create against an existing account
98
+ subscription = BunnyApp::Subscription.create(
65
99
  price_list_code: 'starter',
66
100
  options: {
67
- account_name: "Superdesk",
68
- first_name: "Meg",
69
- last_name: "La Don",
70
- email: "meg@example.com",
71
- trial: true,
72
- tenant_code: "123456",
73
- tenant_name: "Superdesk"
101
+ account_id: '456',
102
+ tenant_code: 'acme-123',
103
+ tenant_name: 'Acme Corp'
74
104
  }
75
105
  )
76
106
  ```
77
107
 
78
- ### Get a portal session token for use with Bunny.js
108
+ Returns a hash containing the created subscription, including `id`, `state`, `trialStartDate`, `trialEndDate`, `plan`, `priceList`, and `tenant`.
109
+
110
+ ### Update subscription quantities
111
+
112
+ Adjust the quantities for one or more charges on an existing subscription.
79
113
 
80
114
  ```ruby
81
- response = BunnyApp::PortalSession.create(
82
- tenant_code: "123456"
115
+ quote = BunnyApp::Subscription.quantity_update(
116
+ subscription_id: '456123',
117
+ quantities: [
118
+ { code: 'users', quantity: 25 }
119
+ ],
120
+ options: {
121
+ invoice_immediately: true,
122
+ start_date: '2024-06-01',
123
+ name: 'Add users — June',
124
+ allow_quantity_limits_override: false
125
+ }
83
126
  )
84
127
  ```
85
128
 
86
- ### Track feature usage
129
+ Returns a `quote` hash with `id` and `name`.
87
130
 
88
- If you have usage based billing or just want to track feature usage then use this method.
131
+ ### Convert a trial to paid
89
132
 
90
133
  ```ruby
91
- # Usage is tracked as if it just happened
92
- response = BunnyApp::FeatureUsage.create(
93
- quantity: 5, feature_code: 'products', tenant_code: '2')
134
+ # Convert using a price list code
135
+ result = BunnyApp::Subscription.trial_convert(
136
+ subscription_id: '456123',
137
+ price_list_code: 'starter'
138
+ )
94
139
 
95
- # Usage is tracked using the date supplied
96
- response = BunnyApp::FeatureUsage.create(
97
- quantity: 5, feature_code: 'products', tenant_code: '2', usage_at: '2022-03-10')
140
+ # Convert using a price list ID and payment method
141
+ result = BunnyApp::Subscription.trial_convert(
142
+ subscription_id: '456123',
143
+ price_list_id: '789',
144
+ payment_id: '101112'
145
+ )
98
146
  ```
99
147
 
100
- ### Custom queries & mutations
148
+ Returns a hash containing `invoice` (with `amount`, `id`, `number`, `subtotal`) and `subscription` (with `id`, `name`).
101
149
 
102
- Alternately you can build and send your own custom graphql queries or mutations
150
+ ### Cancel a subscription
103
151
 
104
152
  ```ruby
105
- query = <<-'GRAPHQL'
106
- mutation featureUsageCreate ($attributes: FeatureUsageAttributes!) {
107
- featureUsageCreate (attributes: $attributes) {
108
- errors
109
- featureUsage {
110
- id
111
- quantity
112
- usageAt
113
- tenant {
114
- id
115
- code
116
- name
117
- }
118
- feature {
119
- id
120
- code
121
- name
122
- }
123
- }
124
- }
125
- }
126
- GRAPHQL
153
+ BunnyApp::Subscription.cancel(subscription_id: '456123')
154
+ # => true
155
+ ```
156
+
157
+ ---
127
158
 
128
- variables = {
129
- attributes: {
130
- quantity: 1,
131
- usageAt: "2022-03-10",
132
- tenantCode: "123456",
133
- featureCode: "users"
159
+ ## Tenants
160
+
161
+ ### Create a tenant
162
+
163
+ ```ruby
164
+ tenant = BunnyApp::Tenant.create(
165
+ name: 'Acme Corp',
166
+ code: 'acme-123',
167
+ account_id: '456',
168
+ platform_code: 'main' # optional, defaults to 'main'
169
+ )
170
+ ```
171
+
172
+ Returns a hash with `id`, `code`, `name`, `subdomain`, `lastLogin`, and `platform`.
173
+
174
+ ### Update a tenant
175
+
176
+ Either `id` or `code` must be provided to identify the tenant. If only `code` is given, a lookup is performed first to resolve the ID.
177
+
178
+ ```ruby
179
+ # Identify by id
180
+ tenant = BunnyApp::Tenant.update(
181
+ id: '456123',
182
+ name: 'Acme Corp',
183
+ subdomain: 'acme',
184
+ last_login: '2024-06-01T12:00:00Z'
185
+ )
186
+
187
+ # Identify by code
188
+ tenant = BunnyApp::Tenant.update(
189
+ code: 'acme-123',
190
+ name: 'Acme Corp',
191
+ subdomain: 'acme'
192
+ )
193
+ ```
194
+
195
+ Only the fields you provide will be sent. Returns a hash with `id`, `code`, `name`, `subdomain`, `lastLogin`, and `platform`.
196
+
197
+ ### Find a tenant by code
198
+
199
+ ```ruby
200
+ tenant = BunnyApp::Tenant.find_by(code: 'acme-123')
201
+ # => { "id" => "1", "code" => "acme-123", "name" => "Acme Corp",
202
+ # "subdomain" => "acme", "lastLogin" => "...", "account" => { "id" => "456", ... } }
203
+ ```
204
+
205
+ Returns `nil` if no tenant is found.
206
+
207
+ ---
208
+
209
+ ## Tenant Metrics
210
+
211
+ Push usage and engagement metrics to Bunny for a tenant. Useful for health scoring and churn signals.
212
+
213
+ ```ruby
214
+ BunnyApp::TenantMetrics.update(
215
+ code: 'acme-123',
216
+ last_login: '2024-06-01T12:00:00Z',
217
+ user_count: 42,
218
+ utilization_metrics: {
219
+ projects_created: 10,
220
+ exports_run: 3
134
221
  }
135
- }
222
+ )
223
+ # => true
224
+ ```
136
225
 
137
- response = BunnyApp.query(query, variables)
226
+ `utilization_metrics` is optional and accepts any key/value pairs you want to track.
227
+
228
+ ---
229
+
230
+ ## Feature Usage
231
+
232
+ Track usage of individual features for usage-based billing or analytics.
233
+
234
+ ```ruby
235
+ # Track usage now
236
+ usage = BunnyApp::FeatureUsage.create(
237
+ quantity: 5,
238
+ feature_code: 'api_calls',
239
+ subscription_id: '456123'
240
+ )
241
+
242
+ # Track usage for a specific date
243
+ usage = BunnyApp::FeatureUsage.create(
244
+ quantity: 5,
245
+ feature_code: 'api_calls',
246
+ subscription_id: '456123',
247
+ usage_at: '2024-03-10'
248
+ )
138
249
  ```
139
250
 
140
- ### Verify webhook signature
251
+ Returns a hash with `id`, `quantity`, `usageAt`, `subscription`, and `feature`.
252
+
253
+ ---
141
254
 
142
- Bunny can send webhooks for key actions like a subscription change. When you get a webhook from Bunny you should verify the signature that is supplied in the `x-bunny-signature` header matches the payload.
255
+ ## Portal Sessions
256
+
257
+ Generate a short-lived token to embed the Bunny billing portal in your app using Bunny.js.
143
258
 
144
259
  ```ruby
145
- payload = '{"type":"SubscriptionProvisioningChange","payload":{"subscription":{"id":27,"state":"trial","trial_start_date":"2022-06-04","trial_end_date":"2022-06-18","start_date":null,"end_date":null,"auto_renew":false,"account":{"id":33,"name":"Ondricka, Flatley and Kessler"},"tenant":null,"product":{"code":"stealth","name":"Stealth","description":null,"sku":null},"features":[{"code":"users","quantity":1},{"code":"crm","quantity":null}]}}}'
260
+ # Basic session
261
+ token = BunnyApp::PortalSession.create(tenant_code: 'acme-123')
262
+
263
+ # With a return URL and custom expiry (in hours, default: 24)
264
+ token = BunnyApp::PortalSession.create(
265
+ tenant_code: 'acme-123',
266
+ return_url: 'https://yourapp.com/billing',
267
+ expiry_hours: 4
268
+ )
269
+ ```
270
+
271
+ Returns the session token string.
272
+
273
+ ---
146
274
 
147
- BunnyApp::Webhook.verify("8bd5aa9c6a96fbce9fc3065af6e9871ac19a1d0a", payload, "secret-key")
275
+ ## Platforms
276
+
277
+ Platforms allow you to group tenants. Create a platform before assigning tenants to it.
278
+
279
+ ```ruby
280
+ platform = BunnyApp::Platform.create(
281
+ name: 'My SaaS Platform',
282
+ code: 'my-saas'
283
+ )
284
+ # => { "id" => "1", "name" => "My SaaS Platform", "code" => "my-saas" }
148
285
  ```
149
286
 
150
- ## Requirements
287
+ ---
151
288
 
152
- This gem requires Ruby 2.5+
289
+ ## Webhooks
153
290
 
154
- ## Development
291
+ Bunny sends webhooks for events like subscription state changes. Verify the `x-bunny-signature` header to confirm the payload is authentic.
292
+
293
+ ```ruby
294
+ payload = request.raw_post
295
+ signature = request.headers['x-bunny-signature']
296
+ signing_key = ENV['BUNNY_WEBHOOK_SECRET']
297
+
298
+ if BunnyApp::Webhook.verify(signature, payload, signing_key)
299
+ # payload is authentic — process the event
300
+ event = JSON.parse(payload)
301
+ case event['type']
302
+ when 'SubscriptionProvisioningChange'
303
+ # handle provisioning change
304
+ end
305
+ else
306
+ head :unauthorized
307
+ end
308
+ ```
155
309
 
156
- Run `bundle install` to install dependencies.
310
+ ---
157
311
 
158
- Run `bundle exec rake spec` to run the tests.
312
+ ## Custom GraphQL Queries
159
313
 
160
- You can also run `bin/console` for an interactive prompt that will allow you to experiment.
314
+ You can send any GraphQL query or mutation directly if you need fields not covered by the convenience methods.
161
315
 
162
- Set IGNORE_SSL when running locally to ignore ssl warnings.
316
+ ### Synchronous query
163
317
 
164
- ```sh
165
- > IGNORE_SSL=true bin/console
318
+ ```ruby
319
+ query = <<~GRAPHQL
320
+ query GetTenant($code: String!) {
321
+ tenant(code: $code) {
322
+ id
323
+ name
324
+ account {
325
+ id
326
+ name
327
+ }
328
+ }
329
+ }
330
+ GRAPHQL
331
+
332
+ response = BunnyApp.query(query, { code: 'acme-123' })
333
+ tenant = response['data']['tenant']
334
+ ```
335
+
336
+ ### Asynchronous query (fire-and-forget)
337
+
338
+ Runs the request in a background thread. Useful for non-critical tracking calls where you don't want to block the request cycle.
339
+
340
+ ```ruby
341
+ BunnyApp.query_async(query, variables)
166
342
  ```
167
343
 
168
- ## Publish to Ruby gems
344
+ ---
345
+
346
+ ## Error Handling
347
+
348
+ All convenience methods raise on error. Two exception classes are provided:
349
+
350
+ | Exception | When raised |
351
+ |---|---|
352
+ | `BunnyApp::AuthorizationError` | Invalid or expired credentials |
353
+ | `BunnyApp::ResponseError` | API returned errors in the response body |
354
+
355
+ ```ruby
356
+ begin
357
+ BunnyApp::Subscription.cancel(subscription_id: '456123')
358
+ rescue BunnyApp::AuthorizationError => e
359
+ # Re-authenticate or alert
360
+ Rails.logger.error "Bunny auth failed: #{e.message}"
361
+ rescue BunnyApp::ResponseError => e
362
+ # The API rejected the request
363
+ Rails.logger.error "Bunny error: #{e.message}"
364
+ end
365
+ ```
169
366
 
170
- Update `version.rb` with a new version number then build the gem
367
+ ---
368
+
369
+ ## Requirements
370
+
371
+ Ruby 2.5+
372
+
373
+ ---
374
+
375
+ ## Development
171
376
 
172
377
  ```sh
173
- gem build
378
+ bundle install # install dependencies
379
+ bundle exec rake spec # run tests
380
+ bin/console # interactive console
174
381
  ```
175
382
 
176
- Then publish using the new build number
383
+ Set `IGNORE_SSL=true` when running locally to suppress SSL warnings:
177
384
 
178
385
  ```sh
386
+ IGNORE_SSL=true bin/console
387
+ ```
388
+
389
+ ## Publishing
390
+
391
+ Update `lib/bunny_app/version.rb`, then:
392
+
393
+ ```sh
394
+ gem build
179
395
  gem push bunny_app-x.x.x.gem
180
396
  ```
181
397
 
182
- The rubygems account for publishing is protected by MFA and currently managed by @richet
398
+ The RubyGems account is protected by MFA and managed by @richet.
@@ -39,6 +39,36 @@ module BunnyApp
39
39
  }
40
40
  GRAPHQL
41
41
 
42
+ @subscription_quantity_update_mutation = <<-GRAPHQL
43
+ mutation subscriptionQuantityUpdate ($subscriptionId: ID!, $quantities: [SubscriptionChargeQuantityAttributes!]!, $invoiceImmediately: Boolean!, $startDate: ISO8601Date!, $name: String!, $allowQuantityLimitsOverride: Boolean!) {
44
+ subscriptionQuantityUpdate (subscriptionId: $subscriptionId, quantities: $quantities, invoiceImmediately: $invoiceImmediately, startDate: $startDate, name: $name, allowQuantityLimitsOverride: $allowQuantityLimitsOverride) {
45
+ errors
46
+ quote {
47
+ id
48
+ name
49
+ }
50
+ }
51
+ }
52
+ GRAPHQL
53
+
54
+ @subscription_trial_convert_mutation = <<-GRAPHQL
55
+ mutation subscriptionTrialConvert ($subscriptionId: ID!, $paymentId: ID!, $priceListId: ID!, $priceListCode: String!) {
56
+ subscriptionTrialConvert (subscriptionId: $subscriptionId, paymentId: $paymentId, priceListId: $priceListId, priceListCode: $priceListCode) {
57
+ errors
58
+ invoice {
59
+ amount
60
+ id
61
+ number
62
+ subtotal
63
+ }
64
+ subscription {
65
+ id
66
+ name
67
+ }
68
+ }
69
+ }
70
+ GRAPHQL
71
+
42
72
  @subscription_cancel_mutation = <<-GRAPHQL
43
73
  mutation subscriptionCancel ($ids: [ID!]!) {
44
74
  subscriptionCancel (ids: $ids) {
@@ -83,6 +113,43 @@ module BunnyApp
83
113
  res['data']['subscriptionCreate']['subscription']
84
114
  end
85
115
 
116
+ def self.quantity_update(subscription_id:, quantities:, options: {})
117
+ variables = {
118
+ subscriptionId: subscription_id,
119
+ quantities:,
120
+ invoiceImmediately: options[:invoice_immediately] || false,
121
+ startDate: options[:start_date],
122
+ name: options[:name],
123
+ allowQuantityLimitsOverride: options[:allow_quantity_limits_override] || false
124
+ }
125
+
126
+ res = Client.new.query(@subscription_quantity_update_mutation, variables)
127
+ if res['data']['subscriptionQuantityUpdate']['errors']
128
+ raise ResponseError,
129
+ res['data']['subscriptionQuantityUpdate']['errors'].join(',')
130
+ end
131
+
132
+ res['data']['subscriptionQuantityUpdate']['quote']
133
+ end
134
+
135
+ def self.trial_convert(subscription_id:, price_list_id: nil, price_list_code: nil, payment_id: nil)
136
+ variables = {
137
+ subscriptionId: subscription_id
138
+ }
139
+
140
+ variables[:paymentId] = payment_id if payment_id
141
+ variables[:priceListId] = price_list_id if price_list_id
142
+ variables[:priceListCode] = price_list_code if price_list_code
143
+
144
+ res = Client.new.query(@subscription_trial_convert_mutation, variables)
145
+ if res['data']['subscriptionTrialConvert']['errors']
146
+ raise ResponseError,
147
+ res['data']['subscriptionTrialConvert']['errors'].join(',')
148
+ end
149
+
150
+ res['data']['subscriptionTrialConvert']
151
+ end
152
+
86
153
  def self.cancel(subscription_id:)
87
154
  variables = {
88
155
  ids: [subscription_id]
@@ -7,6 +7,8 @@ module BunnyApp
7
7
  code
8
8
  id
9
9
  name
10
+ subdomain
11
+ lastLogin
10
12
  platform {
11
13
  id
12
14
  name
@@ -25,6 +27,7 @@ module BunnyApp
25
27
  code
26
28
  name
27
29
  subdomain
30
+ lastLogin
28
31
  account {
29
32
  id
30
33
  name
@@ -34,6 +37,26 @@ module BunnyApp
34
37
  }
35
38
  GRAPHQL
36
39
 
40
+ @tenant_update_mutation = <<-GRAPHQL
41
+ mutation tenantUpdate ($id: ID, $code: String, $attributes: TenantAttributes!) {
42
+ tenantUpdate (id: $id, code: $code, attributes: $attributes) {
43
+ errors
44
+ tenant {
45
+ code
46
+ id
47
+ name
48
+ subdomain
49
+ lastLogin
50
+ platform {
51
+ id
52
+ name
53
+ code
54
+ }
55
+ }
56
+ }
57
+ }
58
+ GRAPHQL
59
+
37
60
  def self.create(name:, code:, account_id:, platform_code: 'main')
38
61
  variables = {
39
62
  attributes: {
@@ -50,10 +73,26 @@ module BunnyApp
50
73
  res['data']['tenantCreate']['tenant']
51
74
  end
52
75
 
76
+ def self.update(id: nil, code: nil, **attrs)
77
+ raise ArgumentError, 'id or code is required' unless id || code
78
+
79
+ attributes = {
80
+ name: attrs[:name],
81
+ code: attrs[:code],
82
+ subdomain: attrs[:subdomain],
83
+ lastLogin: attrs[:last_login]
84
+ }.compact
85
+
86
+ variables = { id:, code:, attributes: }
87
+
88
+ res = Client.new.query(@tenant_update_mutation, variables)
89
+ raise ResponseError, res['data']['tenantUpdate']['errors'].join(',') if res['data']['tenantUpdate']['errors']
90
+
91
+ res['data']['tenantUpdate']['tenant']
92
+ end
93
+
53
94
  def self.find_by(code:)
54
- variables = {
55
- code:
56
- }
95
+ variables = { code: }
57
96
 
58
97
  res = Client.new.query(@tenant_query, variables)
59
98
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BunnyApp
4
- VERSION = '2.3.0'
4
+ VERSION = '2.5.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bunny_app
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bunny
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-11-21 00:00:00.000000000 Z
12
+ date: 2026-05-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: httparty