@happyvertical/smrt-subscriptions 0.30.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.
Files changed (59) hide show
  1. package/AGENTS.md +26 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/__smrt-register__.d.ts +2 -0
  6. package/dist/__smrt-register__.d.ts.map +1 -0
  7. package/dist/collections/SubscriptionPlanCollection.d.ts +9 -0
  8. package/dist/collections/SubscriptionPlanCollection.d.ts.map +1 -0
  9. package/dist/collections/TenantSubscriptionCollection.d.ts +29 -0
  10. package/dist/collections/TenantSubscriptionCollection.d.ts.map +1 -0
  11. package/dist/collections/TenantUsageMetricCollection.d.ts +28 -0
  12. package/dist/collections/TenantUsageMetricCollection.d.ts.map +1 -0
  13. package/dist/collections/index.d.ts +4 -0
  14. package/dist/collections/index.d.ts.map +1 -0
  15. package/dist/index.d.ts +6 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +1271 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/manifest.json +1291 -0
  20. package/dist/models/SubscriptionPlan.d.ts +30 -0
  21. package/dist/models/SubscriptionPlan.d.ts.map +1 -0
  22. package/dist/models/TenantSubscription.d.ts +59 -0
  23. package/dist/models/TenantSubscription.d.ts.map +1 -0
  24. package/dist/models/TenantUsageMetric.d.ts +35 -0
  25. package/dist/models/TenantUsageMetric.d.ts.map +1 -0
  26. package/dist/models/index.d.ts +4 -0
  27. package/dist/models/index.d.ts.map +1 -0
  28. package/dist/services/index.d.ts +5 -0
  29. package/dist/services/index.d.ts.map +1 -0
  30. package/dist/services/subscription-resolver.d.ts +96 -0
  31. package/dist/services/subscription-resolver.d.ts.map +1 -0
  32. package/dist/services/threshold-evaluator.d.ts +4 -0
  33. package/dist/services/threshold-evaluator.d.ts.map +1 -0
  34. package/dist/services/usage-meter.d.ts +32 -0
  35. package/dist/services/usage-meter.d.ts.map +1 -0
  36. package/dist/smrt-knowledge.json +883 -0
  37. package/dist/svelte/PlanPicker.svelte +82 -0
  38. package/dist/svelte/PlanPicker.svelte.d.ts +10 -0
  39. package/dist/svelte/PlanPicker.svelte.d.ts.map +1 -0
  40. package/dist/svelte/SubscriptionSummary.svelte +65 -0
  41. package/dist/svelte/SubscriptionSummary.svelte.d.ts +8 -0
  42. package/dist/svelte/SubscriptionSummary.svelte.d.ts.map +1 -0
  43. package/dist/svelte/UsageThresholds.svelte +71 -0
  44. package/dist/svelte/UsageThresholds.svelte.d.ts +8 -0
  45. package/dist/svelte/UsageThresholds.svelte.d.ts.map +1 -0
  46. package/dist/svelte/i18n.d.ts +5 -0
  47. package/dist/svelte/i18n.d.ts.map +1 -0
  48. package/dist/svelte/i18n.js +9 -0
  49. package/dist/svelte/index.d.ts +4 -0
  50. package/dist/svelte/index.d.ts.map +1 -0
  51. package/dist/svelte/index.js +3 -0
  52. package/dist/types.d.ts +175 -0
  53. package/dist/types.d.ts.map +1 -0
  54. package/dist/types.js +2 -0
  55. package/dist/types.js.map +1 -0
  56. package/dist/utils.d.ts +59 -0
  57. package/dist/utils.d.ts.map +1 -0
  58. package/package.json +80 -0
  59. package/scripts/migrate-1454-drop-legacy-conflict-index.ts +110 -0
package/AGENTS.md ADDED
@@ -0,0 +1,26 @@
1
+ # @happyvertical/smrt-subscriptions
2
+
3
+ Tenant subscriptions, plan features, usage thresholds, and entitlement
4
+ resolution for SMRT applications.
5
+
6
+ ## Validation
7
+
8
+ ```bash
9
+ pnpm --filter @happyvertical/smrt-subscriptions test
10
+ pnpm --filter @happyvertical/smrt-subscriptions typecheck
11
+ pnpm --filter @happyvertical/smrt-subscriptions build
12
+ ```
13
+
14
+ ## Notes
15
+
16
+ - Keep Stripe-specific fields as provider binding metadata. Runtime Stripe API
17
+ calls belong in the HappyVertical SDK accounting provider.
18
+ - Thresholds are evaluated from tenant usage metrics and optional AI usage
19
+ summaries. Resolve multiple thresholds with the batch usage path where
20
+ available; do not bypass tenant context in application code.
21
+ - Use `SubscriptionResolver.create()` or an explicitly injected
22
+ `SubscriptionResolver` once per request when resolving entitlements multiple
23
+ times. Load and pass `EntitlementResolutionContext` to avoid re-reading the
24
+ current subscription and plan.
25
+ - Subscription UI components should stay provider-neutral and receive actions
26
+ from the host app.
package/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ @AGENTS.md
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright <2025> <Happy Vertical Corporation>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
1
+ {"version":"5.9.3"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=__smrt-register__.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"__smrt-register__.d.ts","sourceRoot":"","sources":["../src/__smrt-register__.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import { SmrtCollection } from '@happyvertical/smrt-core';
2
+ import { SubscriptionPlan } from '../models/SubscriptionPlan.js';
3
+ export declare class SubscriptionPlanCollection extends SmrtCollection<SubscriptionPlan> {
4
+ static readonly _itemClass: typeof SubscriptionPlan;
5
+ findByPlanKey(planKey: string): Promise<SubscriptionPlan | null>;
6
+ findActive(): Promise<SubscriptionPlan[]>;
7
+ findByStripePriceId(stripePriceId: string): Promise<SubscriptionPlan | null>;
8
+ }
9
+ //# sourceMappingURL=SubscriptionPlanCollection.d.ts.map
@@ -0,0 +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,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKhE,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAOzC,mBAAmB,CACvB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;CAIpC"}
@@ -0,0 +1,29 @@
1
+ import { SmrtCollection } from '@happyvertical/smrt-core';
2
+ import { TenantSubscription } from '../models/TenantSubscription.js';
3
+ import { Subscriber } from '../types.js';
4
+ export declare class TenantSubscriptionCollection extends SmrtCollection<TenantSubscription> {
5
+ static readonly _itemClass: typeof TenantSubscription;
6
+ /**
7
+ * List subscriptions whose owning tenant scope is `tenantId`. Includes both
8
+ * `'tenant'`-kind (subscriber == owner) and `'external'`-kind (subscriber is
9
+ * an external identity scoped under this tenant) rows.
10
+ */
11
+ findByTenant(tenantId: string): Promise<TenantSubscription[]>;
12
+ /**
13
+ * Legacy single-tenant accessor: returns the current subscription where the
14
+ * tenant IS the subscriber (`subscriberKind = 'tenant'`). External-kind rows
15
+ * scoped under this tenant are intentionally excluded so existing callers
16
+ * are not surprised by buyer/agent subscriptions.
17
+ */
18
+ findCurrentForTenant(tenantId: string, now?: Date): Promise<TenantSubscription | null>;
19
+ /**
20
+ * Polymorphic current-subscription accessor.
21
+ *
22
+ * For `'tenant'` subscribers we match rows with `subscriberKind = 'tenant'`
23
+ * under the same `tenantId`. For `'external'` subscribers we match by
24
+ * `(tenantId, subscriberExternalId)` with `subscriberKind = 'external'`.
25
+ */
26
+ findCurrentForSubscriber(subscriber: Subscriber, now?: Date): Promise<TenantSubscription | null>;
27
+ findByStripeSubscriptionId(stripeSubscriptionId: string): Promise<TenantSubscription | null>;
28
+ }
29
+ //# sourceMappingURL=TenantSubscriptionCollection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TenantSubscriptionCollection.d.ts","sourceRoot":"","sources":["../../src/collections/TenantSubscriptionCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,qBAAa,4BAA6B,SAAQ,cAAc,CAAC,kBAAkB,CAAC;IAClF,MAAM,CAAC,QAAQ,CAAC,UAAU,4BAAsB;IAEhD;;;;OAIG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAOnE;;;;;OAKG;IACG,oBAAoB,CACxB,QAAQ,EAAE,MAAM,EAChB,GAAG,OAAa,GACf,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAIrC;;;;;;OAMG;IACG,wBAAwB,CAC5B,UAAU,EAAE,UAAU,EACtB,GAAG,OAAa,GACf,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAoB/B,0BAA0B,CAC9B,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;CAOtC"}
@@ -0,0 +1,28 @@
1
+ import { SmrtCollection } from '@happyvertical/smrt-core';
2
+ import { TenantUsageMetric } from '../models/TenantUsageMetric.js';
3
+ import { AiUsageSummary, RecordUsageOptions, SummarizeAiUsageOptions, SummarizeUsageBatchOptions, SummarizeUsageOptions, UsageSummary } from '../types.js';
4
+ export declare class TenantUsageMetricCollection extends SmrtCollection<TenantUsageMetric> {
5
+ static readonly _itemClass: typeof TenantUsageMetric;
6
+ recordUsage(options: RecordUsageOptions): Promise<TenantUsageMetric>;
7
+ /**
8
+ * Legacy accessor — finds metrics for `subscriberKind = 'tenant'` under the
9
+ * given tenant. External-kind rows scoped to the same tenant are excluded.
10
+ */
11
+ findByTenantAndMetric(tenantId: string, metricKey: string): Promise<TenantUsageMetric[]>;
12
+ summarizeUsage(options: SummarizeUsageOptions): Promise<UsageSummary>;
13
+ summarizeUsageBatch(options: SummarizeUsageBatchOptions): Promise<UsageSummary[]>;
14
+ /**
15
+ * Summarize persisted AI usage for a tenant within a window.
16
+ *
17
+ * Reads the framework `_smrt_ai_usage` system table via a raw aggregate
18
+ * query. This deliberately uses `this.db.query` rather than the inherited
19
+ * `query()`: those rows are framework usage records, not `TenantUsageMetric`
20
+ * instances, so model hydration would discard the aggregate columns. Tenant
21
+ * scoping is applied explicitly through the `tenant_id` filter.
22
+ *
23
+ * Named distinctly from the inherited `SmrtClass.summarizeAiUsage` (which
24
+ * returns grouped stats across all tenants) to avoid overriding it.
25
+ */
26
+ summarizeTenantAiUsage(options: SummarizeAiUsageOptions): Promise<AiUsageSummary>;
27
+ }
28
+ //# sourceMappingURL=TenantUsageMetricCollection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TenantUsageMetricCollection.d.ts","sourceRoot":"","sources":["../../src/collections/TenantUsageMetricCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,YAAY,EACb,MAAM,aAAa,CAAC;AAOrB,qBAAa,2BAA4B,SAAQ,cAAc,CAAC,iBAAiB,CAAC;IAChF,MAAM,CAAC,QAAQ,CAAC,UAAU,2BAAqB;IAEzC,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAsB1E;;;OAGG;IACG,qBAAqB,CACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAOzB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,YAAY,CAAC;IAsCrE,mBAAmB,CACvB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,YAAY,EAAE,CAAC;IAqE1B;;;;;;;;;;;OAWG;IACG,sBAAsB,CAC1B,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,cAAc,CAAC;CA6B3B"}
@@ -0,0 +1,4 @@
1
+ export { SubscriptionPlanCollection } from './SubscriptionPlanCollection.js';
2
+ export { TenantSubscriptionCollection } from './TenantSubscriptionCollection.js';
3
+ export { TenantUsageMetricCollection } from './TenantUsageMetricCollection.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/collections/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AACjF,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { SubscriptionPlanCollection, TenantSubscriptionCollection, TenantUsageMetricCollection, } from './collections/index.js';
2
+ export { SubscriptionPlan, TenantSubscription, TenantUsageMetric, } from './models/index.js';
3
+ export { evaluateThreshold, evaluateThresholds, type SubscriptionPlanReader, SubscriptionResolver, type SubscriptionResolverReaders, type TenantSubscriptionReader, TenantUsageMeter, type UsageSummaryReader, } from './services/index.js';
4
+ 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';
5
+ export { assertSubscriberInvariant, getWindowForThreshold, getWindowKey, isValidThreshold, normalizeFeatureGrants, normalizeSubscriber, subscriberToColumns, } from './utils.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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;AAChC,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,sBAAsB,EAC3B,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,gBAAgB,EAChB,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"}