supabase-rb-rb

API Reference

Auto-generated reference for the supabase-billing gem — every public module, class, method, constant, and attribute extracted from the source.

This page is generated by pnpm run gen:billing-api from the supabase-billing source. Edit the gem (then re-run the script) — do not hand-edit this file. See docs/scripts/gen-billing-api.mjs for the generator.

The script reads:

  • supabase-billing/lib/ — every .rb file (excluding model templates, which are rendered separately below)
  • lib/generators/supabase_billing/install/templates/app/models/billing — model declarations (associations, table mappings)

Sections below mirror the source-file layout. Module / class headings use their fully-qualified Ruby names; method headings prefix instance methods with # and class methods with . (matching YARD convention).

Library

lib/generators/supabase_billing/install/install_generator.rb

class SupabaseBilling::Generators::InstallGenerator < ::Rails::Generators::Base

rails g supabase_billing:install (US-001).

Emits the canonical billing schema migration: a single timestamped migration under db/migrate/ that creates the eight canonical tables (billing_customers, plans, entitlements, plan_entitlements, subscriptions, subscription_items, usage_limits, usage_events) plus the four provider-mapping tables (provider_customers, provider_subscriptions, provider_products, provider_events), along with the Supabase RLS policies that scope reads to the authenticated user via auth.uid().

Preflights that supabase-rails is installed (Gemfile + initializer) before doing anything — the gem builds on supabase-rails and refuses to run without it.

Constants

  • SUPPORTED_PROVIDERS = %w[stripe adapty].freeze
  • SUPPORTED_STRIPE_INGESTION = %w[webhook sync_engine].freeze
  • POST_INSTALL_SEPARATOR = ("=" * 72).freeze
  • BILLING_MODEL_FILES = (multi-line literal)

Methods

.next_migration_number

def self.next_migration_number(_dirname)

Rails' built-in timestamp for migration filenames. Mirrors ActiveRecord::Generators::Migration#next_migration_number so the generator works without ActiveRecord loaded.

#preflight_supabase_rails

def preflight_supabase_rails

#preflight_providers

def preflight_providers

#create_migration_file

def create_migration_file

#create_models

def create_models

#create_initializer

def create_initializer

#create_yaml_config

def create_yaml_config

#include_acts_billable_in_user_model

def include_acts_billable_in_user_model

Wires the entitlement engine into the host app's User model (US-005). The model is generated by rails g supabase:user_model and lives at app/models/user.rb; the include Acts::Billable line is the one-shot bridge that exposes user.entitled?, user.subscribed?, etc.

Idempotent: if the line is already present we skip the injection, so reruns don't double-include the concern.

#mount_engine_in_host_routes

def mount_engine_in_host_routes

Mounts the Supabase::Billing::Engine at /supabase_billing so the host app exposes the webhook endpoints. Idempotent: if a mount line is already present, we skip the injection.

In :sync_engine mode the engine is still mounted, but its config/routes.rb draws zero routes (see AC: "in :sync_engine mode, the /supabase_billing/webhooks/stripe route is not mounted"). The mount itself is cheap; what controls visibility is the engine's internal routeset.

#print_post_install_checklist

def print_post_install_checklist

#providers

def providers

Memoized, parsed and validated provider list. Raises (or prompts interactively if no flag) when zero providers would be selected.

#parse_providers

def parse_providers(raw)

#prompt_for_providers

def prompt_for_providers

#validate_stripe_ingestion!

def validate_stripe_ingestion!

#include_rls?

def include_rls?

--- Template hooks (referenced from create_supabase_billing_schema.rb.tt) ---

#stripe_ingestion

def stripe_ingestion

#provider_list

def provider_list

#supabase_rails_in_gemfile?

def supabase_rails_in_gemfile?

--- Preflight helpers --------------------------------------------------

#supabase_rails_initializer_present?

def supabase_rails_initializer_present?

lib/supabase/billing.rb

module Supabase::Billing

Methods

#configure

def configure

#config

def config

#reset_config!

def reset_config!

#debug

def debug(user)

#sync_status

def sync_status(user)

module SupabaseBilling

Top-level convenience module so SupabaseBilling.configure reads as well as Supabase::Billing.configure. Declared as a distinct module (not a constant alias) so the generator's existing module SupabaseBilling namespace keeps inferring supabase_billing:install.

Declared before the rails-dependent requires below so that the engine's isolate_namespace ::SupabaseBilling (loaded via the railtie) finds the constant already in place.

Methods

.configure

def self.configure(&block)

.config

def self.config

.debug

def self.debug(user)

.sync_status

def self.sync_status(user)

lib/supabase/billing/acts/billable.rb

Acts::Billable is the entitlement engine's public API: include it on the host app's User model (the one generated by rails g supabase:user_model) and the four AC methods — subscribed?, plan, entitled?(:key), limit(:key) — read from the canonical Billing::* tables, with safe defaults when the user has no subscription.

Results cache per-request via Supabase::Billing::Current so a single controller action that calls entitled?(:foo) multiple times only hits the DB once. Disable via Supabase::Billing.config.cache_entitlements_per_request = false for apps that need always-fresh reads.

Defined as a top-level Acts::Billable module so the AC-literal include Acts::Billable form works in a host User model. The Supabase::Billing::Acts::Billable constant below is a one-way alias so internal code can resolve via the gem's namespace.

module Acts

Acts::Billable is the entitlement engine's public API: include it on the host app's User model (the one generated by rails g supabase:user_model) and the four AC methods — subscribed?, plan, entitled?(:key), limit(:key) — read from the canonical Billing::* tables, with safe defaults when the user has no subscription.

Results cache per-request via Supabase::Billing::Current so a single controller action that calls entitled?(:foo) multiple times only hits the DB once. Disable via Supabase::Billing.config.cache_entitlements_per_request = false for apps that need always-fresh reads.

Defined as a top-level Acts::Billable module so the AC-literal include Acts::Billable form works in a host User model. The Supabase::Billing::Acts::Billable constant below is a one-way alias so internal code can resolve via the gem's namespace.

module Acts::Billable

Associations

  • has_one :billing_customer

Constants

  • ACTIVE_SUBSCRIPTION_STATUSES = %w[active trialing].freeze

Methods

#subscribed?

def subscribed?

#plan

def plan

#entitled?

def entitled?(entitlement_key)

#limit

def limit(entitlement_key)

#usage

def usage(entitlement_key)

Returns the total usage recorded against entitlement_key in the current billing period (the active subscription's current_period_start / current_period_end). Returns 0 when the user has no billing_customer, no active subscription, or the entitlement doesn't exist.

#remaining

def remaining(entitlement_key)

Returns limit(:key) - usage(:key), or nil when the entitlement has no numeric cap (i.e. unlimited, no subscription, or boolean entitlement).

#record_usage

def record_usage(entitlement_key, amount: 1, recorded_at: nil)

Records a usage event against the user's billing_customer and invalidates the per-request cache for the entitlement so a subsequent limit(:key) / entitled?(:key) / usage(:key) / remaining(:key) re-reads from the DB.

#acts_billable_invalidate_cache

def acts_billable_invalidate_cache(entitlement_key = nil)

Drops the cached entitlement values for this user. Pass an entitlement key to drop only that key's entries (both entitled? and limit); pass nil to drop everything for this user.

#acts_billable_active_subscription

def acts_billable_active_subscription

#acts_billable_usage_for

def acts_billable_usage_for(entitlement_key)

Sums usage_events.amount for the user's current billing period. Period boundaries come from the active subscription's current_period_start / current_period_end; without a subscription or without a configured period_start, we fall back to "no lower bound" so usage is still observable for self-hosted flows that haven't wired the period anchor yet.

#acts_billable_plan_entitlement_for

def acts_billable_plan_entitlement_for(entitlement_key)

#acts_billable_cached

def acts_billable_cached(method, entitlement_key = nil)

#acts_billable_const

def acts_billable_const(name)

lib/supabase/billing/adapters/adapty/event_processor.rb

class Supabase::Billing::Adapters::Adapty::EventProcessor

Processes a parsed Adapty webhook event payload (Hash) by:

  1. Storing the raw event in provider_events for replay/debugging.
  2. Upserting the matching provider_subscriptions row keyed off the Adapty profile_id (subscription events) or transaction_id (non-subscription purchases).
  3. Reflecting state into the canonical subscriptions row.

Handles the seven AC-mandated events:

  • subscription_started
  • subscription_renewed
  • subscription_cancelled
  • subscription_expired
  • subscription_refunded
  • non_subscription_purchase
  • access_level_updated

Adapty's customer_user_id is the Supabase auth.users.id UUID string (mobile clients call Adapty.identify(session.user.id.uuidString) after sign-in). We normalize incoming UUIDs to lowercase before the billing_customers.user_id lookup — Adapty's server-to-server calls send uppercase per their convention, but Postgres uuid comparisons are case-insensitive in storage; we lowercase explicitly so a string comparison against users.id (uuid) coerces cleanly.

Unknown event types / unknown users / unmapped products are logged and skipped rather than raised so a single bad row never poisons the webhook endpoint.

Constants

  • HANDLED_EVENT_TYPES = (multi-line literal)
  • DEFAULT_MODEL_NAMES = (multi-line literal)
  • PROVIDER = "adapty"
  • EVENT_STATUS_MAP = (multi-line literal)

Attributes

  • attr_reader :logger
  • attr_reader :config

Methods

#initialize

def initialize(models: nil, logger: nil, config: Supabase::Billing.config, now: nil)

#call

def call(event)

Process a single Adapty event Hash (already parsed from JSON). Returns true if the event was handled (or intentionally skipped), false only when the event payload is malformed.

#now

def now

#models

def models

#resolve_models

def resolve_models

#extract_event_id

def extract_event_id(event)

---- event id + storage --------------------------------------------- Adapty supplies an event_id field on every server-to-server webhook; fall back to a deterministic synthetic id derived from (profile_id, event_type, event_datetime) when absent so the provider_events.provider_event_id unique index still gives us idempotency.

#store_provider_event

def store_provider_event(event_id, event_type, event)

#mark_event_processed

def mark_event_processed(event_id)

#event_payload_hash

def event_payload_hash(event)

#handle_event

def handle_event(event_type, event)

---- dispatch -------------------------------------------------------

#handle_subscription_event

def handle_subscription_event(event_type, billing_customer, plan, props)

---- subscription event handling ------------------------------------

#upsert_provider_subscription

def upsert_provider_subscription(provider_subscription_id, event_type, props)

#upsert_canonical_subscription

def upsert_canonical_subscription(event_type:, billing_customer:, plan:, props:)

#find_or_initialize_subscription_for

def find_or_initialize_subscription_for(billing_customer, props)

#canonical_status

def canonical_status(event_type, props)

#handle_non_subscription_purchase

def handle_non_subscription_purchase(billing_customer, plan, props)

---- non-subscription purchase --------------------------------------

#lookup_billing_customer

def lookup_billing_customer(customer_user_id, props)

---- lookups + linking ----------------------------------------------

#lookup_plan_for_product

def lookup_plan_for_product(vendor_product_id, access_level_id)
def link_provider_customer(billing_customer, props)

#normalize_user_id

def normalize_user_id(raw)

---- helpers -------------------------------------------------------- Webhook payloads are normalized to lowercase before the DB lookup (Adapty's server-to-server API calls send uppercase per their convention; mobile SDKs typically send mixed/uppercase). Returns nil for blank/invalid input.

#event_properties

def event_properties(event)

#parse_time

def parse_time(value)

#truthy?

def truthy?(value)

#log

def log(level, message)

lib/supabase/billing/adapters/adapty/signature_verifier.rb

class Supabase::Billing::Adapters::Adapty::SignatureVerifier

Verifies the Authorization header on an incoming Adapty webhook against the configured Adapty webhook secret using a constant-time comparison. Adapty's server-to-server webhook scheme is a shared secret passed verbatim in Authorization (no HMAC over the body), so verification here is a fixed-length secret equality check.

Implemented in-gem (not via the adapty gem) so the gem stays dependency-free at runtime.

Methods

.verify!

def self.verify!(authorization_header:, secret:)

#initialize

def initialize(authorization_header:, secret:)

#verify!

def verify!

#secure_compare

def secure_compare(a, b)

lib/supabase/billing/adapters/stripe/event_processor.rb

class Supabase::Billing::Adapters::Stripe::EventProcessor

Processes a parsed Stripe event payload (Hash) by:

  1. Storing the raw event in provider_events for replay/debugging.
  2. Upserting the matching provider_subscriptions row.
  3. Reflecting state into the canonical subscriptions row.

Currently handles the four AC-mandated events:

  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted
  • invoice.payment_succeeded

Unknown event types / unknown Stripe customers / unknown Stripe prices are logged and skipped rather than raised so a single bad row never poisons the webhook endpoint.

Models are resolved lazily via constant lookup at call-time so the gem stays decoupled from the host app's autoloader; specs inject explicit models: to run against an isolated AR setup.

Constants

  • HANDLED_EVENT_TYPES = (multi-line literal)
  • DEFAULT_MODEL_NAMES = (multi-line literal)
  • PROVIDER = "stripe"
  • STATUS_MAP = (multi-line literal)

Attributes

  • attr_reader :logger
  • attr_reader :config

Methods

#initialize

def initialize(models: nil, logger: nil, config: Supabase::Billing.config, now: nil)

#call

def call(event)

Process a single Stripe event Hash (already parsed from JSON). Returns true if the event was handled (or intentionally skipped), false only when the event payload is malformed.

#now

def now

#models

def models

#resolve_models

def resolve_models

#store_provider_event

def store_provider_event(event_id, event_type, event)

---- event storage ---------------------------------------------------

#mark_event_processed

def mark_event_processed(event_id)

#event_payload_hash

def event_payload_hash(event)

#handle_subscription_upsert

def handle_subscription_upsert(event)

---- customer.subscription.created / .updated -----------------------

#upsert_provider_subscription

def upsert_provider_subscription(stripe_sub_id, sub_object)

#upsert_canonical_subscription

def upsert_canonical_subscription(billing_customer:, plan:, sub_object:)

#find_or_initialize_subscription_for

def find_or_initialize_subscription_for(billing_customer, sub_object)

The provider_subscriptions row links to the canonical row by subscription_id. On the first event for a Stripe sub, the provider row exists but has no subscription_id, so we look up by the most recent existing canonical sub for this customer, or build a fresh one.

#handle_subscription_deleted

def handle_subscription_deleted(event)

---- customer.subscription.deleted ----------------------------------

#handle_invoice_payment_succeeded

def handle_invoice_payment_succeeded(event)

---- invoice.payment_succeeded --------------------------------------

#lookup_billing_customer

def lookup_billing_customer(stripe_customer_id)

---- lookups + helpers ----------------------------------------------

#lookup_plan_for_price

def lookup_plan_for_price(price_id)

#first_price_id

def first_price_id(sub_object)

#dig

def dig(hash, *keys)

#epoch_to_time

def epoch_to_time(value)

#log

def log(level, message)

lib/supabase/billing/adapters/stripe/signature_verifier.rb

class Supabase::Billing::Adapters::Stripe::SignatureVerifier

Verifies the Stripe-Signature header on an incoming webhook against the configured webhook secret using Stripe's documented scheme: HMAC-SHA256 of "#{timestamp}.#{payload}" keyed by the secret, compared in constant time, with a tolerance window on the timestamp to reject obviously-replayed events.

Implemented in-gem (not via the stripe gem) so the gem stays dependency-free at runtime.

Constants

  • DEFAULT_TOLERANCE = 300 # 5 minutes, matching Stripe's recommendation

Methods

.verify!

def self.verify!(payload:, signature_header:, secret:, tolerance: DEFAULT_TOLERANCE, now: Time.now)

#initialize

def initialize(payload:, signature_header:, secret:, tolerance: DEFAULT_TOLERANCE, now: Time.now)

#verify!

def verify!

#parse_header

def parse_header(header)

#compute_signature

def compute_signature(timestamp, payload, secret)

#secure_compare

def secure_compare(a, b)

lib/supabase/billing/adapters/stripe/sync_engine_preflight.rb

class Supabase::Billing::Adapters::Stripe::SyncEnginePreflight

Verifies that the stripe.* schema produced by stripe/stripe-sync-engine exists with the columns this adapter depends on. Run once at boot when stripe_ingestion = :sync_engine.

If drift is detected, raises SchemaDriftError naming the supported sync-engine version range so the developer can pin their stripe-sync-engine deployment to a compatible release rather than ship wrong entitlements silently.

Constants

  • SUPPORTED_SYNC_ENGINE_VERSIONS = ">= 0.62.0, < 1.0.0"
  • SCHEMA_NAME = "stripe"
  • EXPECTED_SCHEMA = (multi-line literal)

Attributes

  • attr_reader :connection

Methods

.run!

def self.run!(connection)

#initialize

def initialize(connection)

#run!

def run!

#ensure_schema_present!

def ensure_schema_present!

#existing_tables

def existing_tables

#columns_for

def columns_for(table)

#raise_drift!

def raise_drift!(detail)

lib/supabase/billing/adapters/stripe/sync_engine_reflector.rb

class Supabase::Billing::Adapters::Stripe::SyncEngineReflector

In :sync_engine mode, no webhook endpoint is mounted. stripe/stripe-sync-engine populates the stripe.* schema asynchronously from Stripe's API; this reflector reads from those tables and projects state into the canonical subscriptions / provider_subscriptions rows so the entitlement API (user.entitled?) returns the same answer in both ingestion modes.

Unknown / unmapped customers and prices are logged and skipped, never raised — matching the webhook adapter's behavior so swapping modes can't break existing apps.

Constants

  • DEFAULT_MODEL_NAMES = (multi-line literal)
  • PROVIDER = "stripe"

Attributes

  • attr_reader :logger

Methods

#initialize

def initialize(connection:, models: nil, logger: nil)

#call

def call

#models

def models

#resolve_models

def resolve_models

#reflect_subscription

def reflect_subscription(row)

#first_price_id_for

def first_price_id_for(stripe_sub_id)

#upsert_provider_subscription

def upsert_provider_subscription(stripe_sub_id, row)

#upsert_canonical_subscription

def upsert_canonical_subscription(billing_customer:, plan:, row:, status:)

#lookup_billing_customer

def lookup_billing_customer(stripe_customer_id)

#lookup_plan_for_price

def lookup_plan_for_price(price_id)

#to_time

def to_time(value)

#log

def log(msg)

lib/supabase/billing/configuration.rb

class Supabase::Billing::Configuration

Constants

  • STRIPE_INGESTION_MODES = %i[webhook sync_engine].freeze

Attributes

  • attr_accessor :adapty_webhook_secret
  • attr_accessor :stripe_webhook_secret
  • attr_reader :stripe_ingestion
  • attr_reader :plans

Methods

#initialize

def initialize

#stripe_ingestion=

def stripe_ingestion=(mode)

#plan

def plan(key, name: nil, **metadata, &block)

#plan_keys

def plan_keys

#fetch_plan

def fetch_plan(key)

lib/supabase/billing/current.rb

class Supabase::Billing::Current < ActiveSupport::CurrentAttributes

Request-scoped storage for the entitlement cache. Rails resets ActiveSupport::CurrentAttributes subclasses between requests via the executor, so the cache is automatically cleared at the request boundary — no manual reset hook required.

The cache is keyed on [user_id, method, entitlement_key] (or [user_id, method] for subscribed? / plan). Acts::Billable owns the keying scheme; this class is just the storage.

Methods

#entitlement_cache

def entitlement_cache

lib/supabase/billing/debug.rb

module Supabase::Billing::Debug

Console-friendly inspectors for a single user's canonical billing state. Built for the "I got a support ticket, what's actually in the DB for this user?" workflow — every value is JSON-serializable (Strings / Hashes / Arrays / Numerics / Booleans / nil / ISO-8601 timestamps) so the output can be pasted into a ticket or piped through JSON.generate without further marshalling.

Safe defaults everywhere: missing billing_customer, missing subscription, missing plan, missing entitlement link all degrade to nil / [] / {} rather than raising. A nil user is also tolerated so a console session can probe the helpers without having a User instance handy.

Constants

  • PROVIDERS = %w[stripe adapty].freeze
  • ACTIVE_SUBSCRIPTION_STATUSES = %w[active trialing].freeze

Methods

#debug

def debug(user)

#sync_status

def sync_status(user)

#billing_customer_for

def billing_customer_for(user)

#active_subscriptions_for

def active_subscriptions_for(customer)

#entitlements_for

def entitlements_for(plan)

#usage_for

def usage_for(customer, subscription, entitlements)

#sync_status_for_provider

def sync_status_for_provider(customer, provider)

#last_provider_customer_timestamp

def last_provider_customer_timestamp(customer, provider)

#last_provider_subscription_timestamp

def last_provider_subscription_timestamp(customer, provider)

#serialize_customer

def serialize_customer(customer, user)

#serialize_subscription

def serialize_subscription(subscription)

#serialize_plan

def serialize_plan(plan)

#entitlement_value

def entitlement_value(link)

#safe_const

def safe_const(name)

#stringify_id

def stringify_id(id)

#iso

def iso(time)

lib/supabase/billing/engine.rb

class Supabase::Billing::Engine < ::Rails::Engine

Mountable Rails engine that exposes the Stripe (and, in later stories, Adapty) webhook endpoints. The engine is isolated so supabase_billing lives in its own URL/helper namespace.

The actual route mount is conditional on Supabase::Billing.config.stripe_ingestion:

  • :webhook — mounts POST /webhooks/stripe.
  • :sync_engine — no Stripe webhook route is mounted; reflection reads from the stripe.* schema instead.

AC: the two modes are mutually exclusive — there is no hybrid ingestion path in the MVP.

lib/supabase/billing/plan.rb

class Supabase::Billing::Plan

Constants

  • VALID_ENTITLEMENT_VALUE_DESC = "Numeric, true, or false"

Attributes

  • attr_reader :key
  • attr_reader :name
  • attr_reader :metadata

Methods

#initialize

def initialize(key, name: nil, **metadata)

#entitlements

def entitlements(hash = nil)

#entitlement

def entitlement(entitlement_key, value:)

#stripe_prices

def stripe_prices(prices = nil)

#adapty_products

def adapty_products(products = nil)

#to_h

def to_h

#add_entitlement

def add_entitlement(entitlement_key, value)

#valid_entitlement_value?

def valid_entitlement_value?(value)

#coerce_provider_ids

def coerce_provider_ids(value, field)

lib/supabase/billing/railtie.rb

class Supabase::Billing::Railtie < ::Rails::Railtie

Exposes the supabase_billing:* rake tasks to the host Rails app and wires the boot-time sync-engine preflight (US-006) when the adapter is configured for :sync_engine ingestion.

lib/supabase/billing/sync.rb

class Supabase::Billing::Sync

Reconciles the DSL-declared plans + entitlements into the host app's ActiveRecord tables. Idempotent: rerunning makes no changes if nothing in the DSL has changed since the last sync.

Plans that disappear from the DSL are archived (their archived_at column is stamped) rather than hard-deleted, so historical subscriptions still resolve their plan reference.

Models are resolved lazily via constant lookup at call-time so the gem can be required outside a Rails app; tests inject explicit model classes to run against an isolated AR setup.

Constants

  • DEFAULT_MODEL_NAMES = (multi-line literal)

Attributes

  • attr_reader :config
  • attr_reader :logger

Methods

#total

def total

#initialize

def initialize(config: Supabase::Billing.config, logger: nil, models: nil, now: nil)

#call

def call

#result

def result

#now

def now

#models

def models

#resolve_models

def resolve_models

#ar_transaction

def ar_transaction(&block)

#sync_entitlements

def sync_entitlements

---- entitlements ------------------------------------------------------

#entitlement_kinds

def entitlement_kinds

Hash of { entitlement_key(Symbol) => "numeric" | "boolean" } collected across every plan in the DSL. Raises if the same key appears with incompatible kinds (numeric in one plan, boolean in another).

#kind_for

def kind_for(value)
def sync_plans_and_links

---- plans + plan_entitlements + provider_products --------------------

#upsert_plan

def upsert_plan(dsl_plan)

#sync_plan_entitlements

def sync_plan_entitlements(plan_record, dsl_plan, entitlement_records_by_key)

#sync_provider_products

def sync_provider_products(plan_record, dsl_plan)

#archive_removed_plans

def archive_removed_plans

---- archival ---------------------------------------------------------

#dsl_plans

def dsl_plans

---- shared helpers ---------------------------------------------------

#log_action

def log_action(action, resource, key, details = nil)

lib/supabase/billing/version.rb

module Supabase::Billing

Constants

  • VERSION = "0.1.0"

Models

lib/generators/supabase_billing/install/templates/app/models/billing/application_record.rb.tt

class Billing::ApplicationRecord < ::ApplicationRecord

lib/generators/supabase_billing/install/templates/app/models/billing/billing_customer.rb.tt

class Billing::BillingCustomer < ApplicationRecord

Table: billing_customers

Associations

  • belongs_to :user::User
  • has_many :subscriptionsBilling::Subscription
  • has_many :provider_customersBilling::ProviderCustomer
  • has_many :usage_eventsBilling::UsageEvent

lib/generators/supabase_billing/install/templates/app/models/billing/entitlement.rb.tt

class Billing::Entitlement < ApplicationRecord

Table: entitlements

Associations

  • has_many :plan_entitlementsBilling::PlanEntitlement
  • has_many :plansBilling::Plan
  • has_many :usage_limitsBilling::UsageLimit
  • has_many :usage_eventsBilling::UsageEvent

lib/generators/supabase_billing/install/templates/app/models/billing/plan.rb.tt

class Billing::Plan < ApplicationRecord

Table: plans

Associations

  • has_many :plan_entitlementsBilling::PlanEntitlement
  • has_many :entitlements
  • has_many :subscriptionsBilling::Subscription
  • has_many :provider_productsBilling::ProviderProduct

lib/generators/supabase_billing/install/templates/app/models/billing/plan_entitlement.rb.tt

class Billing::PlanEntitlement < ApplicationRecord

Table: plan_entitlements

Associations

  • belongs_to :planBilling::Plan
  • belongs_to :entitlementBilling::Entitlement

lib/generators/supabase_billing/install/templates/app/models/billing/provider_customer.rb.tt

class Billing::ProviderCustomer < ApplicationRecord

Table: provider_customers

Associations

  • belongs_to :billing_customerBilling::BillingCustomer

lib/generators/supabase_billing/install/templates/app/models/billing/provider_event.rb.tt

class Billing::ProviderEvent < ApplicationRecord

Table: provider_events

lib/generators/supabase_billing/install/templates/app/models/billing/provider_product.rb.tt

class Billing::ProviderProduct < ApplicationRecord

Table: provider_products

Associations

  • belongs_to :planBilling::Plan

lib/generators/supabase_billing/install/templates/app/models/billing/provider_subscription.rb.tt

class Billing::ProviderSubscription < ApplicationRecord

Table: provider_subscriptions

Associations

  • belongs_to :subscriptionBilling::Subscription

lib/generators/supabase_billing/install/templates/app/models/billing/subscription.rb.tt

class Billing::Subscription < ApplicationRecord

Table: subscriptions

Associations

  • belongs_to :billing_customerBilling::BillingCustomer
  • belongs_to :planBilling::Plan
  • has_many :subscription_itemsBilling::SubscriptionItem
  • has_many :usage_limitsBilling::UsageLimit
  • has_many :provider_subscriptionsBilling::ProviderSubscription

lib/generators/supabase_billing/install/templates/app/models/billing/subscription_item.rb.tt

class Billing::SubscriptionItem < ApplicationRecord

Table: subscription_items

Associations

  • belongs_to :subscriptionBilling::Subscription

lib/generators/supabase_billing/install/templates/app/models/billing/usage_event.rb.tt

class Billing::UsageEvent < ApplicationRecord

Table: usage_events

Associations

  • belongs_to :billing_customerBilling::BillingCustomer
  • belongs_to :entitlementBilling::Entitlement

lib/generators/supabase_billing/install/templates/app/models/billing/usage_limit.rb.tt

class Billing::UsageLimit < ApplicationRecord

Table: usage_limits

Associations

  • belongs_to :subscriptionBilling::Subscription
  • belongs_to :entitlementBilling::Entitlement

On this page

Librarylib/generators/supabase_billing/install/install_generator.rbclass SupabaseBilling::Generators::InstallGenerator < ::Rails::Generators::Base.next_migration_number#preflight_supabase_rails#preflight_providers#create_migration_file#create_models#create_initializer#create_yaml_config#include_acts_billable_in_user_model#mount_engine_in_host_routes#print_post_install_checklist#providers#parse_providers#prompt_for_providers#validate_stripe_ingestion!#include_rls?#stripe_ingestion#provider_list#supabase_rails_in_gemfile?#supabase_rails_initializer_present?lib/supabase/billing.rbmodule Supabase::Billing#configure#config#reset_config!#debug#sync_statusmodule SupabaseBilling.configure.config.debug.sync_statuslib/supabase/billing/acts/billable.rbmodule Actsmodule Acts::Billable#subscribed?#plan#entitled?#limit#usage#remaining#record_usage#acts_billable_invalidate_cache#acts_billable_active_subscription#acts_billable_usage_for#acts_billable_plan_entitlement_for#acts_billable_cached#acts_billable_constlib/supabase/billing/adapters/adapty/event_processor.rbclass Supabase::Billing::Adapters::Adapty::EventProcessor#initialize#call#now#models#resolve_models#extract_event_id#store_provider_event#mark_event_processed#event_payload_hash#handle_event#handle_subscription_event#upsert_provider_subscription#upsert_canonical_subscription#find_or_initialize_subscription_for#canonical_status#handle_non_subscription_purchase#lookup_billing_customer#lookup_plan_for_product#link_provider_customer#normalize_user_id#event_properties#parse_time#truthy?#loglib/supabase/billing/adapters/adapty/signature_verifier.rbclass Supabase::Billing::Adapters::Adapty::SignatureVerifier.verify!#initialize#verify!#secure_comparelib/supabase/billing/adapters/stripe/event_processor.rbclass Supabase::Billing::Adapters::Stripe::EventProcessor#initialize#call#now#models#resolve_models#store_provider_event#mark_event_processed#event_payload_hash#handle_subscription_upsert#upsert_provider_subscription#upsert_canonical_subscription#find_or_initialize_subscription_for#handle_subscription_deleted#handle_invoice_payment_succeeded#lookup_billing_customer#lookup_plan_for_price#first_price_id#dig#epoch_to_time#loglib/supabase/billing/adapters/stripe/signature_verifier.rbclass Supabase::Billing::Adapters::Stripe::SignatureVerifier.verify!#initialize#verify!#parse_header#compute_signature#secure_comparelib/supabase/billing/adapters/stripe/sync_engine_preflight.rbclass Supabase::Billing::Adapters::Stripe::SyncEnginePreflight.run!#initialize#run!#ensure_schema_present!#existing_tables#columns_for#raise_drift!lib/supabase/billing/adapters/stripe/sync_engine_reflector.rbclass Supabase::Billing::Adapters::Stripe::SyncEngineReflector#initialize#call#models#resolve_models#reflect_subscription#first_price_id_for#upsert_provider_subscription#upsert_canonical_subscription#lookup_billing_customer#lookup_plan_for_price#to_time#loglib/supabase/billing/configuration.rbclass Supabase::Billing::Configuration#initialize#stripe_ingestion=#plan#plan_keys#fetch_planlib/supabase/billing/current.rbclass Supabase::Billing::Current < ActiveSupport::CurrentAttributes#entitlement_cachelib/supabase/billing/debug.rbmodule Supabase::Billing::Debug#debug#sync_status#billing_customer_for#active_subscriptions_for#entitlements_for#usage_for#sync_status_for_provider#last_provider_customer_timestamp#last_provider_subscription_timestamp#serialize_customer#serialize_subscription#serialize_plan#entitlement_value#safe_const#stringify_id#isolib/supabase/billing/engine.rbclass Supabase::Billing::Engine < ::Rails::Enginelib/supabase/billing/plan.rbclass Supabase::Billing::Plan#initialize#entitlements#entitlement#stripe_prices#adapty_products#to_h#add_entitlement#valid_entitlement_value?#coerce_provider_idslib/supabase/billing/railtie.rbclass Supabase::Billing::Railtie < ::Rails::Railtielib/supabase/billing/sync.rbclass Supabase::Billing::Sync#total#initialize#call#result#now#models#resolve_models#ar_transaction#sync_entitlements#entitlement_kinds#kind_for#sync_plans_and_links#upsert_plan#sync_plan_entitlements#sync_provider_products#archive_removed_plans#dsl_plans#log_actionlib/supabase/billing/version.rbmodule Supabase::BillingModelslib/generators/supabase_billing/install/templates/app/models/billing/application_record.rb.ttclass Billing::ApplicationRecord < ::ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/billing_customer.rb.ttclass Billing::BillingCustomer < ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/entitlement.rb.ttclass Billing::Entitlement < ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/plan.rb.ttclass Billing::Plan < ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/plan_entitlement.rb.ttclass Billing::PlanEntitlement < ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/provider_customer.rb.ttclass Billing::ProviderCustomer < ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/provider_event.rb.ttclass Billing::ProviderEvent < ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/provider_product.rb.ttclass Billing::ProviderProduct < ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/provider_subscription.rb.ttclass Billing::ProviderSubscription < ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/subscription.rb.ttclass Billing::Subscription < ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/subscription_item.rb.ttclass Billing::SubscriptionItem < ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/usage_event.rb.ttclass Billing::UsageEvent < ApplicationRecordlib/generators/supabase_billing/install/templates/app/models/billing/usage_limit.rb.ttclass Billing::UsageLimit < ApplicationRecord