schematichq 1.4.1 → 1.4.3

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.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.fern/metadata.json +3 -3
  3. data/.fern/replay.lock +10 -0
  4. data/.fernignore +3 -0
  5. data/README.md +34 -4
  6. data/WASM_VERSION +1 -1
  7. data/lib/schematic/billing/client.rb +38 -2
  8. data/lib/schematic/billing/types/count_billing_products_params.rb +1 -0
  9. data/lib/schematic/billing/types/count_billing_products_request.rb +1 -0
  10. data/lib/schematic/billing/types/create_billing_price_request_body.rb +1 -0
  11. data/lib/schematic/billing/types/delete_payment_method_by_external_id_response.rb +12 -0
  12. data/lib/schematic/billing/types/list_billing_products_params.rb +1 -0
  13. data/lib/schematic/billing/types/list_billing_products_request.rb +1 -0
  14. data/lib/schematic/client.rb +6 -6
  15. data/lib/schematic/companies/client.rb +6 -2
  16. data/lib/schematic/companies/types/count_companies_params.rb +1 -0
  17. data/lib/schematic/companies/types/count_companies_request.rb +1 -0
  18. data/lib/schematic/companies/types/list_companies_params.rb +1 -0
  19. data/lib/schematic/companies/types/list_companies_request.rb +1 -0
  20. data/lib/schematic/credits/client.rb +108 -2
  21. data/lib/schematic/credits/types/acquire_credit_lease_request_body.rb +14 -0
  22. data/lib/schematic/credits/types/acquire_credit_lease_response.rb +12 -0
  23. data/lib/schematic/credits/types/count_billing_plan_credit_grants_params.rb +1 -0
  24. data/lib/schematic/credits/types/count_billing_plan_credit_grants_request.rb +1 -0
  25. data/lib/schematic/credits/types/extend_credit_lease_request_body.rb +13 -0
  26. data/lib/schematic/credits/types/extend_credit_lease_response.rb +12 -0
  27. data/lib/schematic/credits/types/list_billing_plan_credit_grants_params.rb +1 -0
  28. data/lib/schematic/credits/types/list_billing_plan_credit_grants_request.rb +1 -0
  29. data/lib/schematic/credits/types/release_credit_lease_response.rb +12 -0
  30. data/lib/schematic/datastream/merge.rb +71 -0
  31. data/lib/schematic/datastream/websocket_client.rb +32 -1
  32. data/lib/schematic/entitlements/client.rb +6 -2
  33. data/lib/schematic/entitlements/types/count_feature_usage_params.rb +1 -0
  34. data/lib/schematic/entitlements/types/count_feature_usage_request.rb +1 -0
  35. data/lib/schematic/entitlements/types/create_billing_linked_plan_entitlement_request_body.rb +5 -0
  36. data/lib/schematic/entitlements/types/create_plan_entitlement_request_body.rb +5 -0
  37. data/lib/schematic/entitlements/types/list_feature_usage_params.rb +1 -0
  38. data/lib/schematic/entitlements/types/list_feature_usage_request.rb +1 -0
  39. data/lib/schematic/entitlements/types/update_plan_entitlement_request_body.rb +5 -0
  40. data/lib/schematic/event_buffer.rb +17 -3
  41. data/lib/schematic/events/client.rb +3 -1
  42. data/lib/schematic/events/types/list_events_params.rb +1 -0
  43. data/lib/schematic/events/types/list_events_request.rb +1 -0
  44. data/lib/schematic/features/client.rb +6 -2
  45. data/lib/schematic/features/types/count_features_params.rb +1 -0
  46. data/lib/schematic/features/types/count_features_request.rb +1 -0
  47. data/lib/schematic/features/types/list_features_params.rb +1 -0
  48. data/lib/schematic/features/types/list_features_request.rb +1 -0
  49. data/lib/schematic/integrationsapi/client.rb +177 -0
  50. data/lib/schematic/integrationsapi/types/list_integrations_params.rb +18 -0
  51. data/lib/schematic/integrationsapi/types/list_integrations_request.rb +17 -0
  52. data/lib/schematic/integrationsapi/types/list_integrations_response.rb +12 -0
  53. data/lib/schematic/integrationsapi/types/load_sample_data_set_v_2_response.rb +12 -0
  54. data/lib/schematic/integrationsapi/types/run_integration_response.rb +12 -0
  55. data/lib/schematic/integrationsapi/types/start_data_import_request_body.rb +13 -0
  56. data/lib/schematic/integrationsapi/types/start_data_import_response.rb +12 -0
  57. data/lib/schematic/integrationsapi/types/uninstall_integration_response.rb +12 -0
  58. data/lib/schematic/logger.rb +1 -1
  59. data/lib/schematic/planbundle/client.rb +32 -0
  60. data/lib/schematic/planbundle/types/create_custom_plan_bundle_request_body.rb +13 -0
  61. data/lib/schematic/planbundle/types/create_custom_plan_bundle_response.rb +12 -0
  62. data/lib/schematic/planmigrations/client.rb +101 -0
  63. data/lib/schematic/planmigrations/types/create_migration_input.rb +17 -0
  64. data/lib/schematic/planmigrations/types/create_migration_response.rb +12 -0
  65. data/lib/schematic/planmigrations/types/retry_company_migration_response.rb +12 -0
  66. data/lib/schematic/planmigrations/types/retry_migration_request_body.rb +12 -0
  67. data/lib/schematic/planmigrations/types/retry_migration_response.rb +12 -0
  68. data/lib/schematic/plans/client.rb +43 -2
  69. data/lib/schematic/plans/types/count_plans_params.rb +2 -0
  70. data/lib/schematic/plans/types/count_plans_request.rb +2 -0
  71. data/lib/schematic/plans/types/create_billing_linked_plan_request_body.rb +1 -0
  72. data/lib/schematic/plans/types/list_plans_params.rb +2 -0
  73. data/lib/schematic/plans/types/list_plans_request.rb +2 -0
  74. data/lib/schematic/plans/types/mark_custom_plan_billing_paid_response.rb +12 -0
  75. data/lib/schematic/schematic_client.rb +46 -13
  76. data/lib/schematic/types/api_key_create_response_data.rb +1 -0
  77. data/lib/schematic/types/api_key_integration_response_data.rb +11 -0
  78. data/lib/schematic/types/api_key_response_data.rb +1 -0
  79. data/lib/schematic/types/audit_log_list_response_data.rb +1 -0
  80. data/lib/schematic/types/audit_log_response_data.rb +1 -0
  81. data/lib/schematic/types/billing_credit_bundle_view.rb +1 -1
  82. data/lib/schematic/types/billing_credit_view.rb +1 -0
  83. data/lib/schematic/types/billing_plan_credit_grant_response_data.rb +1 -0
  84. data/lib/schematic/types/billing_price_response_data.rb +1 -0
  85. data/lib/schematic/types/billing_price_view.rb +1 -0
  86. data/lib/schematic/types/billing_product_for_subscription_response_data.rb +1 -0
  87. data/lib/schematic/types/billing_product_plan_response_data.rb +1 -0
  88. data/lib/schematic/types/billing_product_price_response_data.rb +1 -0
  89. data/lib/schematic/types/billing_strategy.rb +13 -0
  90. data/lib/schematic/types/change_subscription_internal_request_body.rb +1 -0
  91. data/lib/schematic/types/change_subscription_request_body.rb +1 -0
  92. data/lib/schematic/types/charge_type.rb +1 -0
  93. data/lib/schematic/types/checkout_subscription.rb +1 -0
  94. data/lib/schematic/types/clerk_integration_config.rb +10 -0
  95. data/lib/schematic/types/company_matching_criteria.rb +12 -0
  96. data/lib/schematic/types/company_plan_credit_grant_view.rb +40 -0
  97. data/lib/schematic/types/company_plan_detail_response_data.rb +4 -1
  98. data/lib/schematic/types/company_plan_with_billing_sub_view.rb +1 -1
  99. data/lib/schematic/types/create_billing_plan_credit_grant_request_body.rb +1 -0
  100. data/lib/schematic/types/create_custom_plan_bundle_plan_request_body.rb +12 -0
  101. data/lib/schematic/types/create_entitlement_in_bundle_request_body.rb +5 -0
  102. data/lib/schematic/types/create_event_request_body.rb +3 -0
  103. data/lib/schematic/types/credit_currency_price.rb +10 -0
  104. data/lib/schematic/types/credit_lease_response_data.rb +16 -0
  105. data/lib/schematic/types/currency_price_request_body.rb +3 -0
  106. data/lib/schematic/types/custom_plan_billing_response_data.rb +1 -0
  107. data/lib/schematic/types/data_event_payload.rb +3 -0
  108. data/lib/schematic/types/duplicate_plan_entitlements_response_response_data.rb +1 -0
  109. data/lib/schematic/types/entitlement_currency_prices_response_data.rb +1 -0
  110. data/lib/schematic/types/event_body_track.rb +1 -0
  111. data/lib/schematic/types/event_detail_response_data.rb +2 -0
  112. data/lib/schematic/types/event_response_data.rb +1 -0
  113. data/lib/schematic/types/feature_company_response_data.rb +1 -0
  114. data/lib/schematic/types/feature_usage_response_data.rb +1 -0
  115. data/lib/schematic/types/feature_view.rb +1 -0
  116. data/lib/schematic/types/integration_capabilities.rb +11 -0
  117. data/lib/schematic/types/integration_config.rb +16 -0
  118. data/lib/schematic/types/integration_response_data.rb +13 -0
  119. data/lib/schematic/types/integration_state.rb +13 -0
  120. data/lib/schematic/types/integration_type.rb +1 -0
  121. data/lib/schematic/types/integrations_data_set_response_data.rb +9 -0
  122. data/lib/schematic/types/integrations_list_response_data.rb +15 -0
  123. data/lib/schematic/types/integrations_response_data.rb +13 -0
  124. data/lib/schematic/types/mark_custom_plan_billing_paid_request_body.rb +23 -0
  125. data/lib/schematic/types/migration_error_code.rb +21 -0
  126. data/lib/schematic/types/orb_integration_config.rb +9 -0
  127. data/lib/schematic/types/plan_credit_grant_view.rb +1 -0
  128. data/lib/schematic/types/plan_currency_price_request_body.rb +1 -0
  129. data/lib/schematic/types/plan_currency_prices_response_data.rb +1 -0
  130. data/lib/schematic/types/plan_detail_response_data.rb +3 -0
  131. data/lib/schematic/types/plan_entitlement_response_data.rb +2 -0
  132. data/lib/schematic/types/plan_group_plan_detail_response_data.rb +4 -1
  133. data/lib/schematic/types/plan_price_cadence.rb +13 -0
  134. data/lib/schematic/types/plan_version_company_migration_response_data.rb +1 -0
  135. data/lib/schematic/types/plan_version_migration_response_data.rb +1 -0
  136. data/lib/schematic/types/plan_view_public_response_data.rb +4 -1
  137. data/lib/schematic/types/release_credit_lease_request_body.rb +23 -0
  138. data/lib/schematic/types/rules_engine_schema_version.rb +1 -1
  139. data/lib/schematic/types/stripe_integration_config.rb +14 -0
  140. data/lib/schematic/types/update_auto_topup_override_request_body.rb +12 -0
  141. data/lib/schematic/types/update_billing_plan_credit_grant_request_body.rb +1 -0
  142. data/lib/schematic/types/upsert_billing_product_request_body.rb +3 -0
  143. data/lib/schematic/types/usage_based_entitlement_request_body.rb +5 -0
  144. data/lib/schematic/types/usage_based_entitlement_response_data.rb +2 -0
  145. data/lib/schematic/types/work_os_integration_config.rb +10 -0
  146. data/lib/schematic/version.rb +1 -1
  147. data/lib/schematic/wasm/rulesengine.wasm +0 -0
  148. data/lib/schematic.rb +55 -10
  149. data/reference.md +1355 -188
  150. metadata +48 -2
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schematic
4
+ module Credits
5
+ module Types
6
+ class ReleaseCreditLeaseResponse < Internal::Types::Model
7
+ field :data, -> { Schematic::Types::CreditLeaseResponseData }, optional: false, nullable: false
8
+ field :params, -> { Internal::Types::Hash[String, Object] }, optional: false, nullable: false
9
+ end
10
+ end
11
+ end
12
+ end
@@ -16,25 +16,42 @@ module Schematic
16
16
  COMPANY_MAP_FIELDS = %i[credit_balances keys traits].freeze
17
17
  COMPANY_ARRAY_FIELDS = %i[billing_product_ids entitlements plan_ids plan_version_ids rules].freeze
18
18
 
19
+ # Partials don't carry refreshed entitlements, so when their derived
20
+ # fields change in another part of the company we sync them here to match
21
+ # server behavior (see schematic-python merge.partial_company):
22
+ # - credit_remaining <- credit_balances[credit_id]
23
+ # - usage <- metric value matching (event_name, metric_period, month_reset)
24
+ # Both are skipped when the partial also sends entitlements wholesale.
19
25
  def partial_company(existing, partial_data)
20
26
  return existing unless partial_data.is_a?(Hash)
21
27
 
22
28
  result = deep_copy(existing)
29
+ entitlements_in_partial = partial_data.key?(:entitlements) || partial_data.key?("entitlements")
30
+ updated_balances = nil
31
+ metrics_updated = false
23
32
 
24
33
  partial_data.each do |key, value|
25
34
  sym_key = key.to_sym
26
35
  if COMPANY_MAP_FIELDS.include?(sym_key)
27
36
  result[sym_key] ||= {}
28
37
  result[sym_key] = result[sym_key].merge(value) if value.is_a?(Hash)
38
+ updated_balances = (value.is_a?(Hash) ? value : {}) if sym_key == :credit_balances
29
39
  elsif COMPANY_ARRAY_FIELDS.include?(sym_key)
30
40
  result[sym_key] = value if value.is_a?(Array)
31
41
  elsif sym_key == :metrics
32
42
  result[sym_key] = upsert_metrics(result[sym_key] || [], value || [])
43
+ metrics_updated = true
33
44
  else
34
45
  result[sym_key] = value
35
46
  end
36
47
  end
37
48
 
49
+ if (updated_balances&.any? || metrics_updated) && !entitlements_in_partial
50
+ result[:entitlements] = sync_entitlements(
51
+ result[:entitlements], result[:metrics], updated_balances, metrics_updated
52
+ )
53
+ end
54
+
38
55
  result
39
56
  end
40
57
 
@@ -90,6 +107,60 @@ module Schematic
90
107
  def get_metric_field(metric, field)
91
108
  metric[field] || metric[field.to_s]
92
109
  end
110
+
111
+ # Re-derive entitlement usage / credit_remaining from the merged metrics
112
+ # and the just-updated credit balances. Mirrors schematic-python so that
113
+ # entitlement usage reflects DataStream track events immediately.
114
+ def sync_entitlements(entitlements, metrics, updated_balances, metrics_updated)
115
+ return entitlements unless entitlements.is_a?(Array) && !entitlements.empty?
116
+
117
+ metrics_lookup = {}
118
+ if metrics_updated && metrics.is_a?(Array)
119
+ metrics.each do |metric|
120
+ next unless metric.is_a?(Hash)
121
+
122
+ key = [
123
+ get_metric_field(metric, :event_subtype) || "",
124
+ get_metric_field(metric, :period) || "",
125
+ get_metric_field(metric, :month_reset) || ""
126
+ ]
127
+ value = get_metric_field(metric, :value)
128
+ metrics_lookup[key] = value.nil? ? 0 : value
129
+ end
130
+ end
131
+
132
+ entitlements.map do |ent|
133
+ next ent unless ent.is_a?(Hash)
134
+
135
+ new_ent = deep_copy(ent)
136
+
137
+ credit_id = get_metric_field(ent, :credit_id)
138
+ if updated_balances && credit_id
139
+ present, balance = fetch_balance(updated_balances, credit_id)
140
+ new_ent[:credit_remaining] = balance if present
141
+ end
142
+
143
+ event_name = get_metric_field(ent, :event_name)
144
+ unless metrics_lookup.empty? || event_name.nil?
145
+ period = get_metric_field(ent, :metric_period) || "all_time"
146
+ month_reset = get_metric_field(ent, :month_reset) || "first_of_month"
147
+ matched = metrics_lookup[[event_name, period, month_reset]]
148
+ new_ent[:usage] = matched unless matched.nil?
149
+ end
150
+
151
+ new_ent
152
+ end
153
+ end
154
+
155
+ # The partial's credit_balances may be keyed by string or symbol depending
156
+ # on how the message was parsed, while an entitlement's credit_id is a
157
+ # string value, so check both key forms.
158
+ def fetch_balance(balances, credit_id)
159
+ return [true, balances[credit_id]] if balances.key?(credit_id)
160
+ return [true, balances[credit_id.to_sym]] if balances.key?(credit_id.to_sym)
161
+
162
+ [false, nil]
163
+ end
93
164
  end
94
165
  end
95
166
  end
@@ -6,6 +6,8 @@ require "uri"
6
6
  require "json"
7
7
  require "websocket"
8
8
 
9
+ require_relative "../version"
10
+
9
11
  module Schematic
10
12
  module DataStream
11
13
  WRITE_WAIT = 10 # seconds
@@ -27,6 +29,14 @@ module Schematic
27
29
  MESSAGE_TYPE_DELETE = "delete"
28
30
  MESSAGE_TYPE_ERROR = "error"
29
31
 
32
+ # Headers attached to the WebSocket handshake so the backend can distinguish
33
+ # direct-SDK connections from the schematic-datastream-replicator and
34
+ # correlate either to a specific release. Mode is always "direct" here —
35
+ # replicator mode in this SDK doesn't open a WebSocket at all.
36
+ CLIENT_NAME = "schematic-ruby"
37
+ DATASTREAM_MODE_DIRECT = "direct"
38
+ UNKNOWN_VERSION = "unknown"
39
+
30
40
  class WebSocketClient
31
41
  attr_reader :url, :connected, :ready
32
42
 
@@ -154,7 +164,7 @@ module Schematic
154
164
  def perform_handshake
155
165
  @handshake = WebSocket::Handshake::Client.new(
156
166
  url: @url,
157
- headers: { "X-Schematic-Api-Key" => @api_key }
167
+ headers: handshake_headers
158
168
  )
159
169
 
160
170
  @socket.write(@handshake.to_s)
@@ -310,6 +320,27 @@ module Schematic
310
320
  )
311
321
  @write_mutex.synchronize { @socket&.write(frame.to_s) }
312
322
  end
323
+
324
+ # Headers attached to the WebSocket handshake. The mode/client headers let
325
+ # the backend tell direct-SDK connections apart from the
326
+ # schematic-datastream-replicator and correlate them to a release.
327
+ def handshake_headers
328
+ {
329
+ "X-Schematic-Api-Key" => @api_key,
330
+ "X-Schematic-Datastream-Mode" => DATASTREAM_MODE_DIRECT,
331
+ "X-Schematic-Client" => CLIENT_NAME,
332
+ "X-Schematic-Client-Version" => sdk_version
333
+ }
334
+ end
335
+
336
+ # Resolves the SDK version reported in handshake headers. Schematic::VERSION
337
+ # is stamped into the Fern-generated lib/schematic/version.rb on each release;
338
+ # fall back to "unknown" if the constant is missing (e.g. a partial checkout).
339
+ def sdk_version
340
+ return Schematic::VERSION if defined?(Schematic::VERSION) && !Schematic::VERSION.to_s.empty?
341
+
342
+ UNKNOWN_VERSION
343
+ end
313
344
  end
314
345
  end
315
346
  end
@@ -350,6 +350,7 @@ module Schematic
350
350
  # @option params [Hash[String, String], nil] :company_keys
351
351
  # @option params [String, nil] :feature_ids
352
352
  # @option params [Boolean, nil] :include_usage_aggregation
353
+ # @option params [Schematic::Types::BillingProviderType, nil] :managed_by
353
354
  # @option params [String, nil] :q
354
355
  # @option params [Boolean, nil] :without_negative_entitlements
355
356
  # @option params [Integer, nil] :limit
@@ -358,12 +359,13 @@ module Schematic
358
359
  # @return [Schematic::Entitlements::Types::ListFeatureUsageResponse]
359
360
  def list_feature_usage(request_options: {}, **params)
360
361
  params = Schematic::Internal::Types::Utils.normalize_keys(params)
361
- query_param_names = %i[company_id company_keys feature_ids include_usage_aggregation q without_negative_entitlements limit offset]
362
+ query_param_names = %i[company_id company_keys feature_ids include_usage_aggregation managed_by q without_negative_entitlements limit offset]
362
363
  query_params = {}
363
364
  query_params["company_id"] = params[:company_id] if params.key?(:company_id)
364
365
  query_params["company_keys"] = params[:company_keys] if params.key?(:company_keys)
365
366
  query_params["feature_ids"] = params[:feature_ids] if params.key?(:feature_ids)
366
367
  query_params["include_usage_aggregation"] = params[:include_usage_aggregation] if params.key?(:include_usage_aggregation)
368
+ query_params["managed_by"] = params[:managed_by] if params.key?(:managed_by)
367
369
  query_params["q"] = params[:q] if params.key?(:q)
368
370
  query_params["without_negative_entitlements"] = params[:without_negative_entitlements] if params.key?(:without_negative_entitlements)
369
371
  query_params["limit"] = params[:limit] if params.key?(:limit)
@@ -448,6 +450,7 @@ module Schematic
448
450
  # @option params [Hash[String, String], nil] :company_keys
449
451
  # @option params [String, nil] :feature_ids
450
452
  # @option params [Boolean, nil] :include_usage_aggregation
453
+ # @option params [Schematic::Types::BillingProviderType, nil] :managed_by
451
454
  # @option params [String, nil] :q
452
455
  # @option params [Boolean, nil] :without_negative_entitlements
453
456
  # @option params [Integer, nil] :limit
@@ -456,12 +459,13 @@ module Schematic
456
459
  # @return [Schematic::Entitlements::Types::CountFeatureUsageResponse]
457
460
  def count_feature_usage(request_options: {}, **params)
458
461
  params = Schematic::Internal::Types::Utils.normalize_keys(params)
459
- query_param_names = %i[company_id company_keys feature_ids include_usage_aggregation q without_negative_entitlements limit offset]
462
+ query_param_names = %i[company_id company_keys feature_ids include_usage_aggregation managed_by q without_negative_entitlements limit offset]
460
463
  query_params = {}
461
464
  query_params["company_id"] = params[:company_id] if params.key?(:company_id)
462
465
  query_params["company_keys"] = params[:company_keys] if params.key?(:company_keys)
463
466
  query_params["feature_ids"] = params[:feature_ids] if params.key?(:feature_ids)
464
467
  query_params["include_usage_aggregation"] = params[:include_usage_aggregation] if params.key?(:include_usage_aggregation)
468
+ query_params["managed_by"] = params[:managed_by] if params.key?(:managed_by)
465
469
  query_params["q"] = params[:q] if params.key?(:q)
466
470
  query_params["without_negative_entitlements"] = params[:without_negative_entitlements] if params.key?(:without_negative_entitlements)
467
471
  query_params["limit"] = params[:limit] if params.key?(:limit)
@@ -10,6 +10,7 @@ module Schematic
10
10
  field :feature_ids, -> { Internal::Types::Array[String] }, optional: true, nullable: false
11
11
  field :include_usage_aggregation, -> { Internal::Types::Boolean }, optional: true, nullable: false
12
12
  field :limit, -> { Integer }, optional: true, nullable: false
13
+ field :managed_by, -> { Schematic::Types::BillingProviderType }, optional: true, nullable: false
13
14
  field :offset, -> { Integer }, optional: true, nullable: false
14
15
  field :q, -> { String }, optional: true, nullable: false
15
16
  field :without_negative_entitlements, -> { Internal::Types::Boolean }, optional: true, nullable: false
@@ -8,6 +8,7 @@ module Schematic
8
8
  field :company_keys, -> { Internal::Types::Hash[String, String] }, optional: true, nullable: false
9
9
  field :feature_ids, -> { String }, optional: true, nullable: false
10
10
  field :include_usage_aggregation, -> { Internal::Types::Boolean }, optional: true, nullable: false
11
+ field :managed_by, -> { Schematic::Types::BillingProviderType }, optional: true, nullable: false
11
12
  field :q, -> { String }, optional: true, nullable: false
12
13
  field :without_negative_entitlements, -> { Internal::Types::Boolean }, optional: true, nullable: false
13
14
  field :limit, -> { Integer }, optional: true, nullable: false
@@ -23,8 +23,13 @@ module Schematic
23
23
  field :plan_version_id, -> { String }, optional: true, nullable: false
24
24
  field :price_behavior, -> { Schematic::Types::EntitlementPriceBehavior }, optional: true, nullable: false
25
25
  field :price_tiers, -> { Internal::Types::Array[Schematic::Types::CreatePriceTierRequestBody] }, optional: true, nullable: false
26
+ field :quarterly_metered_price_id, -> { String }, optional: true, nullable: false
27
+ field :quarterly_price_tiers, -> { Internal::Types::Array[Schematic::Types::CreatePriceTierRequestBody] }, optional: true, nullable: false
28
+ field :quarterly_unit_price, -> { Integer }, optional: true, nullable: false
29
+ field :quarterly_unit_price_decimal, -> { String }, optional: true, nullable: false
26
30
  field :soft_limit, -> { Integer }, optional: true, nullable: false
27
31
  field :tier_mode, -> { Schematic::Types::BillingTiersMode }, optional: true, nullable: false
32
+ field :usage_quantity, -> { Integer }, optional: true, nullable: false
28
33
  field :value_bool, -> { Internal::Types::Boolean }, optional: true, nullable: false
29
34
  field :value_credit_id, -> { String }, optional: true, nullable: false
30
35
  field :value_numeric, -> { Integer }, optional: true, nullable: false
@@ -21,8 +21,13 @@ module Schematic
21
21
  field :plan_version_id, -> { String }, optional: true, nullable: false
22
22
  field :price_behavior, -> { Schematic::Types::EntitlementPriceBehavior }, optional: true, nullable: false
23
23
  field :price_tiers, -> { Internal::Types::Array[Schematic::Types::CreatePriceTierRequestBody] }, optional: true, nullable: false
24
+ field :quarterly_metered_price_id, -> { String }, optional: true, nullable: false
25
+ field :quarterly_price_tiers, -> { Internal::Types::Array[Schematic::Types::CreatePriceTierRequestBody] }, optional: true, nullable: false
26
+ field :quarterly_unit_price, -> { Integer }, optional: true, nullable: false
27
+ field :quarterly_unit_price_decimal, -> { String }, optional: true, nullable: false
24
28
  field :soft_limit, -> { Integer }, optional: true, nullable: false
25
29
  field :tier_mode, -> { Schematic::Types::BillingTiersMode }, optional: true, nullable: false
30
+ field :usage_quantity, -> { Integer }, optional: true, nullable: false
26
31
  field :value_bool, -> { Internal::Types::Boolean }, optional: true, nullable: false
27
32
  field :value_credit_id, -> { String }, optional: true, nullable: false
28
33
  field :value_numeric, -> { Integer }, optional: true, nullable: false
@@ -10,6 +10,7 @@ module Schematic
10
10
  field :feature_ids, -> { Internal::Types::Array[String] }, optional: true, nullable: false
11
11
  field :include_usage_aggregation, -> { Internal::Types::Boolean }, optional: true, nullable: false
12
12
  field :limit, -> { Integer }, optional: true, nullable: false
13
+ field :managed_by, -> { Schematic::Types::BillingProviderType }, optional: true, nullable: false
13
14
  field :offset, -> { Integer }, optional: true, nullable: false
14
15
  field :q, -> { String }, optional: true, nullable: false
15
16
  field :without_negative_entitlements, -> { Internal::Types::Boolean }, optional: true, nullable: false
@@ -8,6 +8,7 @@ module Schematic
8
8
  field :company_keys, -> { Internal::Types::Hash[String, String] }, optional: true, nullable: false
9
9
  field :feature_ids, -> { String }, optional: true, nullable: false
10
10
  field :include_usage_aggregation, -> { Internal::Types::Boolean }, optional: true, nullable: false
11
+ field :managed_by, -> { Schematic::Types::BillingProviderType }, optional: true, nullable: false
11
12
  field :q, -> { String }, optional: true, nullable: false
12
13
  field :without_negative_entitlements, -> { Internal::Types::Boolean }, optional: true, nullable: false
13
14
  field :limit, -> { Integer }, optional: true, nullable: false
@@ -19,8 +19,13 @@ module Schematic
19
19
  field :overage_billing_product_id, -> { String }, optional: true, nullable: false
20
20
  field :price_behavior, -> { Schematic::Types::EntitlementPriceBehavior }, optional: true, nullable: false
21
21
  field :price_tiers, -> { Internal::Types::Array[Schematic::Types::CreatePriceTierRequestBody] }, optional: true, nullable: false
22
+ field :quarterly_metered_price_id, -> { String }, optional: true, nullable: false
23
+ field :quarterly_price_tiers, -> { Internal::Types::Array[Schematic::Types::CreatePriceTierRequestBody] }, optional: true, nullable: false
24
+ field :quarterly_unit_price, -> { Integer }, optional: true, nullable: false
25
+ field :quarterly_unit_price_decimal, -> { String }, optional: true, nullable: false
22
26
  field :soft_limit, -> { Integer }, optional: true, nullable: false
23
27
  field :tier_mode, -> { Schematic::Types::BillingTiersMode }, optional: true, nullable: false
28
+ field :usage_quantity, -> { Integer }, optional: true, nullable: false
24
29
  field :value_bool, -> { Internal::Types::Boolean }, optional: true, nullable: false
25
30
  field :value_credit_id, -> { String }, optional: true, nullable: false
26
31
  field :value_numeric, -> { Integer }, optional: true, nullable: false
@@ -26,6 +26,7 @@ module Schematic
26
26
  @stopped = false
27
27
  @flushing = false
28
28
  @flush_done = ConditionVariable.new
29
+ @stop_cv = ConditionVariable.new
29
30
 
30
31
  start_periodic_flush unless @offline
31
32
  end
@@ -77,6 +78,10 @@ module Schematic
77
78
  @mutex.synchronize do
78
79
  @stopped = true
79
80
 
81
+ # Wake the periodic flush thread so it sees @stopped immediately
82
+ # instead of sleeping out the rest of @interval.
83
+ @stop_cv.broadcast
84
+
80
85
  # Wait for any in-flight flush to complete before our final flush,
81
86
  # so we don't skip events that arrived during the in-flight batch.
82
87
  @flush_done.wait(@mutex, 30) if @flushing
@@ -92,8 +97,11 @@ module Schematic
92
97
  def start_periodic_flush
93
98
  @flush_thread = Thread.new do
94
99
  loop do
95
- sleep(@interval)
96
- break if @stopped
100
+ should_break = @mutex.synchronize do
101
+ @stop_cv.wait(@mutex, @interval) unless @stopped
102
+ @stopped
103
+ end
104
+ break if should_break
97
105
 
98
106
  begin
99
107
  flush
@@ -168,13 +176,19 @@ module Schematic
168
176
  # Transform to capture service payload format (differs from Fern API):
169
177
  # - Field is `type` not `event_type`
170
178
  # - Each event includes `api_key`
179
+ # Optional metadata (idempotency_key, trusted_client_clock, backfill) is
180
+ # only included when the caller set it, so we never send explicit nulls.
171
181
  def event_to_capture_payload(event)
172
- {
182
+ payload = {
173
183
  api_key: @api_key,
174
184
  type: event[:event_type],
175
185
  body: event[:body],
176
186
  sent_at: event[:sent_at] || Time.now.utc.iso8601
177
187
  }
188
+ payload[:idempotency_key] = event[:idempotency_key] unless event[:idempotency_key].nil?
189
+ payload[:trusted_client_clock] = event[:trusted_client_clock] unless event[:trusted_client_clock].nil?
190
+ payload[:backfill] = event[:backfill] unless event[:backfill].nil?
191
+ payload
178
192
  end
179
193
  end
180
194
  end
@@ -97,6 +97,7 @@ module Schematic
97
97
  # @option params [String, nil] :event_subtype
98
98
  # @option params [Schematic::Types::EventType, nil] :event_types
99
99
  # @option params [String, nil] :flag_id
100
+ # @option params [String, nil] :idempotency_key
100
101
  # @option params [String, nil] :user_id
101
102
  # @option params [Integer, nil] :limit
102
103
  # @option params [Integer, nil] :offset
@@ -104,12 +105,13 @@ module Schematic
104
105
  # @return [Schematic::Events::Types::ListEventsResponse]
105
106
  def list_events(request_options: {}, **params)
106
107
  params = Schematic::Internal::Types::Utils.normalize_keys(params)
107
- query_param_names = %i[company_id event_subtype event_types flag_id user_id limit offset]
108
+ query_param_names = %i[company_id event_subtype event_types flag_id idempotency_key user_id limit offset]
108
109
  query_params = {}
109
110
  query_params["company_id"] = params[:company_id] if params.key?(:company_id)
110
111
  query_params["event_subtype"] = params[:event_subtype] if params.key?(:event_subtype)
111
112
  query_params["event_types"] = params[:event_types] if params.key?(:event_types)
112
113
  query_params["flag_id"] = params[:flag_id] if params.key?(:flag_id)
114
+ query_params["idempotency_key"] = params[:idempotency_key] if params.key?(:idempotency_key)
113
115
  query_params["user_id"] = params[:user_id] if params.key?(:user_id)
114
116
  query_params["limit"] = params[:limit] if params.key?(:limit)
115
117
  query_params["offset"] = params[:offset] if params.key?(:offset)
@@ -9,6 +9,7 @@ module Schematic
9
9
  field :event_subtype, -> { String }, optional: true, nullable: false
10
10
  field :event_types, -> { Internal::Types::Array[Schematic::Types::EventType] }, optional: true, nullable: false
11
11
  field :flag_id, -> { String }, optional: true, nullable: false
12
+ field :idempotency_key, -> { String }, optional: true, nullable: false
12
13
  field :limit, -> { Integer }, optional: true, nullable: false
13
14
  field :offset, -> { Integer }, optional: true, nullable: false
14
15
  field :user_id, -> { String }, optional: true, nullable: false
@@ -8,6 +8,7 @@ module Schematic
8
8
  field :event_subtype, -> { String }, optional: true, nullable: false
9
9
  field :event_types, -> { Schematic::Types::EventType }, optional: true, nullable: false
10
10
  field :flag_id, -> { String }, optional: true, nullable: false
11
+ field :idempotency_key, -> { String }, optional: true, nullable: false
11
12
  field :user_id, -> { String }, optional: true, nullable: false
12
13
  field :limit, -> { Integer }, optional: true, nullable: false
13
14
  field :offset, -> { Integer }, optional: true, nullable: false
@@ -20,6 +20,7 @@ module Schematic
20
20
  # @option params [Boolean, nil] :boolean_require_event
21
21
  # @option params [Schematic::Types::FeatureType, nil] :feature_type
22
22
  # @option params [String, nil] :ids
23
+ # @option params [Schematic::Types::BillingProviderType, nil] :managed_by
23
24
  # @option params [String, nil] :plan_version_id
24
25
  # @option params [String, nil] :q
25
26
  # @option params [String, nil] :without_company_override_for
@@ -30,11 +31,12 @@ module Schematic
30
31
  # @return [Schematic::Features::Types::ListFeaturesResponse]
31
32
  def list_features(request_options: {}, **params)
32
33
  params = Schematic::Internal::Types::Utils.normalize_keys(params)
33
- query_param_names = %i[boolean_require_event feature_type ids plan_version_id q without_company_override_for without_plan_entitlement_for limit offset]
34
+ query_param_names = %i[boolean_require_event feature_type ids managed_by plan_version_id q without_company_override_for without_plan_entitlement_for limit offset]
34
35
  query_params = {}
35
36
  query_params["boolean_require_event"] = params[:boolean_require_event] if params.key?(:boolean_require_event)
36
37
  query_params["feature_type"] = params[:feature_type] if params.key?(:feature_type)
37
38
  query_params["ids"] = params[:ids] if params.key?(:ids)
39
+ query_params["managed_by"] = params[:managed_by] if params.key?(:managed_by)
38
40
  query_params["plan_version_id"] = params[:plan_version_id] if params.key?(:plan_version_id)
39
41
  query_params["q"] = params[:q] if params.key?(:q)
40
42
  query_params["without_company_override_for"] = params[:without_company_override_for] if params.key?(:without_company_override_for)
@@ -239,6 +241,7 @@ module Schematic
239
241
  # @option params [Boolean, nil] :boolean_require_event
240
242
  # @option params [Schematic::Types::FeatureType, nil] :feature_type
241
243
  # @option params [String, nil] :ids
244
+ # @option params [Schematic::Types::BillingProviderType, nil] :managed_by
242
245
  # @option params [String, nil] :plan_version_id
243
246
  # @option params [String, nil] :q
244
247
  # @option params [String, nil] :without_company_override_for
@@ -249,11 +252,12 @@ module Schematic
249
252
  # @return [Schematic::Features::Types::CountFeaturesResponse]
250
253
  def count_features(request_options: {}, **params)
251
254
  params = Schematic::Internal::Types::Utils.normalize_keys(params)
252
- query_param_names = %i[boolean_require_event feature_type ids plan_version_id q without_company_override_for without_plan_entitlement_for limit offset]
255
+ query_param_names = %i[boolean_require_event feature_type ids managed_by plan_version_id q without_company_override_for without_plan_entitlement_for limit offset]
253
256
  query_params = {}
254
257
  query_params["boolean_require_event"] = params[:boolean_require_event] if params.key?(:boolean_require_event)
255
258
  query_params["feature_type"] = params[:feature_type] if params.key?(:feature_type)
256
259
  query_params["ids"] = params[:ids] if params.key?(:ids)
260
+ query_params["managed_by"] = params[:managed_by] if params.key?(:managed_by)
257
261
  query_params["plan_version_id"] = params[:plan_version_id] if params.key?(:plan_version_id)
258
262
  query_params["q"] = params[:q] if params.key?(:q)
259
263
  query_params["without_company_override_for"] = params[:without_company_override_for] if params.key?(:without_company_override_for)
@@ -9,6 +9,7 @@ module Schematic
9
9
  field :feature_type, -> { Internal::Types::Array[Schematic::Types::FeatureType] }, optional: true, nullable: false
10
10
  field :ids, -> { Internal::Types::Array[String] }, optional: true, nullable: false
11
11
  field :limit, -> { Integer }, optional: true, nullable: false
12
+ field :managed_by, -> { Schematic::Types::BillingProviderType }, optional: true, nullable: false
12
13
  field :offset, -> { Integer }, optional: true, nullable: false
13
14
  field :plan_version_id, -> { String }, optional: true, nullable: false
14
15
  field :q, -> { String }, optional: true, nullable: false
@@ -7,6 +7,7 @@ module Schematic
7
7
  field :boolean_require_event, -> { Internal::Types::Boolean }, optional: true, nullable: false
8
8
  field :feature_type, -> { Schematic::Types::FeatureType }, optional: true, nullable: false
9
9
  field :ids, -> { String }, optional: true, nullable: false
10
+ field :managed_by, -> { Schematic::Types::BillingProviderType }, optional: true, nullable: false
10
11
  field :plan_version_id, -> { String }, optional: true, nullable: false
11
12
  field :q, -> { String }, optional: true, nullable: false
12
13
  field :without_company_override_for, -> { String }, optional: true, nullable: false
@@ -9,6 +9,7 @@ module Schematic
9
9
  field :feature_type, -> { Internal::Types::Array[Schematic::Types::FeatureType] }, optional: true, nullable: false
10
10
  field :ids, -> { Internal::Types::Array[String] }, optional: true, nullable: false
11
11
  field :limit, -> { Integer }, optional: true, nullable: false
12
+ field :managed_by, -> { Schematic::Types::BillingProviderType }, optional: true, nullable: false
12
13
  field :offset, -> { Integer }, optional: true, nullable: false
13
14
  field :plan_version_id, -> { String }, optional: true, nullable: false
14
15
  field :q, -> { String }, optional: true, nullable: false
@@ -7,6 +7,7 @@ module Schematic
7
7
  field :boolean_require_event, -> { Internal::Types::Boolean }, optional: true, nullable: false
8
8
  field :feature_type, -> { Schematic::Types::FeatureType }, optional: true, nullable: false
9
9
  field :ids, -> { String }, optional: true, nullable: false
10
+ field :managed_by, -> { Schematic::Types::BillingProviderType }, optional: true, nullable: false
10
11
  field :plan_version_id, -> { String }, optional: true, nullable: false
11
12
  field :q, -> { String }, optional: true, nullable: false
12
13
  field :without_company_override_for, -> { String }, optional: true, nullable: false