@happyvertical/smrt-subscriptions 0.57.1 → 0.57.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.
- package/README.md +46 -2
- package/dist/collections/SubscriptionPlanCollection.d.ts +3 -1
- package/dist/collections/SubscriptionPlanCollection.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +86 -12
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +151 -35
- package/dist/models/SubscriptionPlan.d.ts +13 -4
- package/dist/models/SubscriptionPlan.d.ts.map +1 -1
- package/dist/models/TenantSubscription.d.ts +3 -1
- package/dist/models/TenantSubscription.d.ts.map +1 -1
- package/dist/services/subscription-resolver.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +76 -11
- package/dist/svelte/PlanPicker.svelte +21 -4
- package/dist/svelte/PlanPicker.svelte.d.ts +3 -0
- package/dist/svelte/PlanPicker.svelte.d.ts.map +1 -1
- package/dist/svelte/i18n.d.ts +4 -0
- package/dist/svelte/i18n.d.ts.map +1 -1
- package/dist/svelte/i18n.js +4 -0
- package/dist/types.d.ts +14 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/scripts/migrate-3829-drop-legacy-plan-key-index.ts +39 -0
- package/scripts/plan-key.ts +10 -0
package/README.md
CHANGED
|
@@ -41,9 +41,28 @@ subscription and plan.
|
|
|
41
41
|
|
|
42
42
|
## Core model
|
|
43
43
|
|
|
44
|
-
- `SubscriptionPlan`
|
|
44
|
+
- `SubscriptionPlan` is tenant-scoped by `(tenantId, planKey)` and stores
|
|
45
|
+
feature grants, thresholds, and a `free`, `fixed`, or `pay_what_you_can`
|
|
46
|
+
pricing mode. Amounts (`priceAmount`, `minimumAmount`, and
|
|
47
|
+
`suggestedAmount`) are integer minor units. Provider bindings are optional
|
|
48
|
+
metadata (`externalProvider`, `providerProductId`, `providerPriceId`).
|
|
45
49
|
- `TenantSubscription` binds a tenant or external subscriber to a plan over an
|
|
46
|
-
effective period
|
|
50
|
+
effective period and records its chosen `agreedAmount` in integer minor
|
|
51
|
+
units for pay-what-you-can plans. Such subscriptions require an amount at
|
|
52
|
+
least the plan minimum; free/fixed subscriptions must leave it null.
|
|
53
|
+
Free and pay-what-you-can plans require `priceAmount: 0`; fixed plans use
|
|
54
|
+
`priceAmount`. Monthly commerce period-close bills tenant subscribers using
|
|
55
|
+
their agreed amount for pay-what-you-can, never the suggested amount, and
|
|
56
|
+
skips free plans. External subscriber invoice routing remains host-owned. Pricing
|
|
57
|
+
mode and minimum are immutable after the plan is saved; create a
|
|
58
|
+
new plan instead (effective-dated transitions are tracked in #4032).
|
|
59
|
+
Invalid legacy pricing fails only its payer group at period close and reports
|
|
60
|
+
the subscription ID while other payer groups continue. Ordinary subscription
|
|
61
|
+
writes resolve only their own tenant's plans or legacy global plans; trusted
|
|
62
|
+
system-context billing can link a seller's plan to its child tenant.
|
|
63
|
+
Entitlement resolution validates plan ownership on both reader and supplied
|
|
64
|
+
context paths; trusted seller-to-child resolution requires explicit system
|
|
65
|
+
context too.
|
|
47
66
|
- `TenantUsageMetric` is immutable, idempotent usage evidence.
|
|
48
67
|
- `SubscriptionResolver` combines current subscription, plan, and batched usage
|
|
49
68
|
summaries into one entitlement decision.
|
|
@@ -61,6 +80,31 @@ subscribers add a stable external discriminator. Utilities such as
|
|
|
61
80
|
`normalizeSubscriber()` and `assertSubscriberInvariant()` keep that identity
|
|
62
81
|
coherent.
|
|
63
82
|
|
|
83
|
+
## Upgrade note
|
|
84
|
+
|
|
85
|
+
`SubscriptionPlanCollection.findByPlanKey` now requires `(tenantId, planKey)`;
|
|
86
|
+
pass `null` explicitly for legacy global plans. Update callers from the old
|
|
87
|
+
single-argument signature. Pricing mode and minimum cannot be edited after
|
|
88
|
+
persistence, even before the first subscriber, so a concurrent signup cannot
|
|
89
|
+
observe terms that change mode underneath it. Existing fixed-price edits and
|
|
90
|
+
current-period entitlement versioning remain separate work in #4032; this
|
|
91
|
+
foundation does not provide immutable period snapshots. Concurrent first creates
|
|
92
|
+
for one `(tenantId, planKey)` use a strict insert: one succeeds and a collision
|
|
93
|
+
fails without changing the winner. Retry by reading the existing plan; a
|
|
94
|
+
sequential create with matching mode/minimum retains natural-key upsert behavior.
|
|
95
|
+
Retrying different pricing mode/minimum is rejected. The provider-neutral price
|
|
96
|
+
lookup falls back to legacy Stripe IDs when the binding is Stripe or unspecified;
|
|
97
|
+
explicit bindings to other providers do not use that fallback. PlanPicker accepts
|
|
98
|
+
optional pricing mode, minimum and suggested amounts, labeling free plans and
|
|
99
|
+
PWYC terms explicitly instead of displaying them as zero fixed-price plans.
|
|
100
|
+
|
|
101
|
+
Existing databases created before #3829 may retain the global
|
|
102
|
+
`_smrt_subscription_plans_plan_key_idx` on older migration runners. Run
|
|
103
|
+
`scripts/migrate-3829-drop-legacy-plan-key-index.ts` after the ordinary manifest
|
|
104
|
+
migration so different tenants can reuse a plan key. The script supports SQLite
|
|
105
|
+
and PostgreSQL and refuses DuckDB, whose inline unique constraint needs a
|
|
106
|
+
reviewed table rebuild.
|
|
107
|
+
|
|
64
108
|
## Thresholds and spending
|
|
65
109
|
|
|
66
110
|
Thresholds define a metric key, time window, limit, and enforcement behavior.
|
|
@@ -2,8 +2,10 @@ import { SmrtCollection } from '@happyvertical/smrt-core';
|
|
|
2
2
|
import { SubscriptionPlan } from '../models/SubscriptionPlan.js';
|
|
3
3
|
export declare class SubscriptionPlanCollection extends SmrtCollection<SubscriptionPlan> {
|
|
4
4
|
static readonly _itemClass: typeof SubscriptionPlan;
|
|
5
|
-
findByPlanKey(planKey: string): Promise<SubscriptionPlan | null>;
|
|
5
|
+
findByPlanKey(tenantId: string | null, planKey: string): Promise<SubscriptionPlan | null>;
|
|
6
6
|
findActive(): Promise<SubscriptionPlan[]>;
|
|
7
|
+
findByProviderPriceId(providerPriceId: string): Promise<SubscriptionPlan | null>;
|
|
8
|
+
/** @deprecated Provider-neutral integrations should use findByProviderPriceId. */
|
|
7
9
|
findByStripePriceId(stripePriceId: string): Promise<SubscriptionPlan | null>;
|
|
8
10
|
}
|
|
9
11
|
//# sourceMappingURL=SubscriptionPlanCollection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriptionPlanCollection.d.ts","sourceRoot":"","sources":["../../src/collections/SubscriptionPlanCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,qBAAa,0BAA2B,SAAQ,cAAc,CAAC,gBAAgB,CAAC;IAC9E,MAAM,CAAC,QAAQ,CAAC,UAAU,0BAAoB;IAExC,aAAa,
|
|
1
|
+
{"version":3,"file":"SubscriptionPlanCollection.d.ts","sourceRoot":"","sources":["../../src/collections/SubscriptionPlanCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,qBAAa,0BAA2B,SAAQ,cAAc,CAAC,gBAAgB,CAAC;IAC9E,MAAM,CAAC,QAAQ,CAAC,UAAU,0BAAoB;IAExC,aAAa,CACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAK7B,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAOzC,qBAAqB,CACzB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAanC,kFAAkF;IAC5E,mBAAmB,CACvB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;CAIpC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,6 @@ export type { PriceBookKind, PricingStrategy, SpendingBasis, SpendingPeriod, Spe
|
|
|
13
13
|
export { BillingAdjustment, BillingAdjustmentCollection, ClientCharge, ClientChargeCollection, CreditGrant, CreditGrantCollection, isCurrencyCode, isPriceBookKind, PriceBook, PriceBookAssignment, PriceBookCollection, PricingRule, PricingRuleCollection, RetailCharge, RetailChargeCollection, SpendingPolicy, SpendingPolicyCollection, SubscriptionPlan, TenantSubscription, TenantUsageMetric, } from './models/index.js';
|
|
14
14
|
export type { AssignPriceBooksInput, AutoTopUpGrant, AutoTopUpHook, AutoTopUpRequest, BillingRelationshipReader, CommercialBillingStorage, CommercialUsageServiceOptions, CustomPricingContext, CustomPricingStrategy, DefinePriceBookPriceInput, DelegatedSpendingPolicyInput, GrantChildCreditInput, GrantCreditInput, PriceBookAssignmentView, PriceBookLeg, PriceUsageOptions, RateUsageOptions, ResellerBillingAction, ResellerBillingErrorCode, ResellerBillingServiceOptions, SpendingDecision, SpendingEvaluationInput, SpendingPolicyEvaluatorExtensions, SpendingPolicyEvaluatorOptions, UsageRating, } from './services/index.js';
|
|
15
15
|
export { assertCommercialBillingStorageSupported, CommercialBillingStorageConfigurationError, CommercialUsageService, evaluateThreshold, evaluateThresholds, ResellerBillingError, ResellerBillingService, SpendingPolicyEvaluator, type SubscriptionPlanReader, SubscriptionResolver, type SubscriptionResolverReaders, type TenantSubscriptionReader, TenantUsageMeter, UnsupportedCommercialBillingStorageError, type UsageSummaryReader, } from './services/index.js';
|
|
16
|
-
export type { AiUsageSummary, BillingInterval, EntitlementResolution, EntitlementResolutionContext, JsonObject, PlanFeatureGrant, PlanThreshold, RecordUsageOptions, Subscriber, SubscriberKind, SubscriptionPlanStatus, SubscriptionResolverOptions, SubscriptionStatus, SummarizeAiUsageOptions, SummarizeUsageBatchOptions, SummarizeUsageOptions, ThresholdEnforcement, ThresholdEvaluation, ThresholdWindow, UsageMeterOptions, UsageMetricRecord, UsageSummary, UsageWindow, } from './types.js';
|
|
16
|
+
export type { AiUsageSummary, BillingInterval, EntitlementResolution, EntitlementResolutionContext, JsonObject, PlanFeatureGrant, PlanThreshold, PricingMode, RecordUsageOptions, Subscriber, SubscriberKind, SubscriptionPlanStatus, SubscriptionResolverOptions, SubscriptionStatus, SummarizeAiUsageOptions, SummarizeUsageBatchOptions, SummarizeUsageOptions, ThresholdEnforcement, ThresholdEvaluation, ThresholdWindow, UsageMeterOptions, UsageMetricRecord, UsageSummary, UsageWindow, } from './types.js';
|
|
17
17
|
export { assertSubscriberInvariant, getWindowForThreshold, getWindowKey, isValidThreshold, normalizeFeatureGrants, normalizeSubscriber, subscriberToColumns, } from './utils.js';
|
|
18
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,wBAAwB,CAAC;AAEhC,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,qCAAqC,EACrC,qCAAqC,EACrC,2BAA2B,EAC3B,wCAAwC,GACzC,MAAM,iCAAiC,CAAC;AACzC,YAAY,EACV,aAAa,EACb,eAAe,EACf,aAAa,EACb,cAAc,EACd,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,YAAY,EACZ,sBAAsB,EACtB,WAAW,EACX,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,YAAY,EACZ,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EACxB,6BAA6B,EAC7B,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,4BAA4B,EAC5B,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,EACvB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,6BAA6B,EAC7B,gBAAgB,EAChB,uBAAuB,EACvB,iCAAiC,EACjC,8BAA8B,EAC9B,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uCAAuC,EACvC,0CAA0C,EAC1C,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,sBAAsB,EAC3B,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,gBAAgB,EAChB,wCAAwC,EACxC,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,4BAA4B,EAC5B,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,sBAAsB,EACtB,2BAA2B,EAC3B,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,wBAAwB,CAAC;AAEhC,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,qCAAqC,EACrC,qCAAqC,EACrC,2BAA2B,EAC3B,wCAAwC,GACzC,MAAM,iCAAiC,CAAC;AACzC,YAAY,EACV,aAAa,EACb,eAAe,EACf,aAAa,EACb,cAAc,EACd,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,YAAY,EACZ,sBAAsB,EACtB,WAAW,EACX,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,YAAY,EACZ,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EACxB,6BAA6B,EAC7B,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,4BAA4B,EAC5B,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,EACvB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,6BAA6B,EAC7B,gBAAgB,EAChB,uBAAuB,EACvB,iCAAiC,EACjC,8BAA8B,EAC9B,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uCAAuC,EACvC,0CAA0C,EAC1C,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,sBAAsB,EAC3B,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,gBAAgB,EAChB,wCAAwC,EACxC,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,4BAA4B,EAC5B,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,sBAAsB,EACtB,2BAA2B,EAC3B,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|