github.com/dracory/subscriptionstore
subscriptionstore provides a complete data layer for plans and subscriptions. It wraps SQL persistence behind interfaces so you can manage billing tiers, trial status, renewals, and custom metadata through a consistent API.
Highlights
- Plan & subscription entities – fluent getters/setters, metadata helpers, dirty tracking, soft-delete markers, and status helpers.
- Interface-first design – stores and queries are defined via interfaces for easy testing and extension.
- Query builders – filter by user, plan, status, date ranges, trial flags, pagination, ordering, and column selections.
- Metadata support – JSON metas across plans and subscriptions for custom fields (limits, pricing data, flags).
-
Multi-database ready – uses Goqu + shared
sbhelpers to target SQLite, MySQL, PostgreSQL, etc.
Creating a Store
store, err := subscriptionstore.NewStore(subscriptionstore.NewStoreOptions{
DB: db,
PlanTableName: "subscription_plan",
SubscriptionTableName:"subscription",
AutomigrateEnabled: true,
DebugEnabled: false,
})
if err != nil {
log.Fatal(err)
}
- Automigration creates both plan and subscription tables with indexes.
- Debug logging prints SQL for troubleshooting.
Working with Plans
plan := subscriptionstore.NewPlan().
SetName("Pro").
SetPrice("19.99").
SetCurrency("USD").
SetInterval("monthly").
SetStatus(subscriptionstore.PLAN_STATUS_ACTIVE)
if err := store.PlanCreate(ctx, plan); err != nil {
log.Fatal(err)
}
plan.SetDescription("Pro tier with advanced analytics")
if err := store.PlanUpdate(ctx, plan); err != nil {
log.Fatal(err)
}
- Plans support helper predicates (e.g.,
IsActive). - Metas enable custom limits, features, or entitlements.
Subscriptions
sub := subscriptionstore.NewSubscription().
SetPlanID(plan.ID()).
SetUserID(userID).
SetStatus(subscriptionstore.SUBSCRIPTION_STATUS_ACTIVE).
SetCurrentPeriodEnd(subscriptionstore.NowPlusInterval("monthly"))
if err := store.SubscriptionCreate(ctx, sub); err != nil {
log.Fatal(err)
}
subs, err := store.SubscriptionList(ctx, subscriptionstore.NewSubscriptionQuery().
SetUserID(userID).
SetStatus(subscriptionstore.SUBSCRIPTION_STATUS_ACTIVE))
-
Track trials (
SetTrialEndsAt), cancellation (SetCanceledAt), and auto-renewal metadata. SubscriptionUpdatepersists only dirty fields.
Querying
PlanQueryfilters by status, price range, IDs, name like, etc.-
SubscriptionQueryfilters by user, plan, status, trial status, date ranges, and includes soft-deleted records when requested. - Use
PlanCount,SubscriptionCountfor pagination.
Metadata & Soft Deletion
-
SetMetas,Meta,UpsertMetasattach metadata for usage limits, upgrade prompts, or integration IDs. -
Soft-delete helpers (
PlanSoftDelete,SubscriptionSoftDelete) retain history while hiding from default queries.
Related Topics
- Design Principles – revisit the shared store architecture.
- Entities & Interfaces – learn how subscriptionstore leverages dataobject patterns.
- Testing – repository includes SQLite-backed tests for realistic coverage.
- Create Your Own Store – extend to billing integrations or custom lifecycle logic.