@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.
- package/AGENTS.md +26 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/__smrt-register__.d.ts +2 -0
- package/dist/__smrt-register__.d.ts.map +1 -0
- package/dist/collections/SubscriptionPlanCollection.d.ts +9 -0
- package/dist/collections/SubscriptionPlanCollection.d.ts.map +1 -0
- package/dist/collections/TenantSubscriptionCollection.d.ts +29 -0
- package/dist/collections/TenantSubscriptionCollection.d.ts.map +1 -0
- package/dist/collections/TenantUsageMetricCollection.d.ts +28 -0
- package/dist/collections/TenantUsageMetricCollection.d.ts.map +1 -0
- package/dist/collections/index.d.ts +4 -0
- package/dist/collections/index.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1271 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.json +1291 -0
- package/dist/models/SubscriptionPlan.d.ts +30 -0
- package/dist/models/SubscriptionPlan.d.ts.map +1 -0
- package/dist/models/TenantSubscription.d.ts +59 -0
- package/dist/models/TenantSubscription.d.ts.map +1 -0
- package/dist/models/TenantUsageMetric.d.ts +35 -0
- package/dist/models/TenantUsageMetric.d.ts.map +1 -0
- package/dist/models/index.d.ts +4 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/subscription-resolver.d.ts +96 -0
- package/dist/services/subscription-resolver.d.ts.map +1 -0
- package/dist/services/threshold-evaluator.d.ts +4 -0
- package/dist/services/threshold-evaluator.d.ts.map +1 -0
- package/dist/services/usage-meter.d.ts +32 -0
- package/dist/services/usage-meter.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +883 -0
- package/dist/svelte/PlanPicker.svelte +82 -0
- package/dist/svelte/PlanPicker.svelte.d.ts +10 -0
- package/dist/svelte/PlanPicker.svelte.d.ts.map +1 -0
- package/dist/svelte/SubscriptionSummary.svelte +65 -0
- package/dist/svelte/SubscriptionSummary.svelte.d.ts +8 -0
- package/dist/svelte/SubscriptionSummary.svelte.d.ts.map +1 -0
- package/dist/svelte/UsageThresholds.svelte +71 -0
- package/dist/svelte/UsageThresholds.svelte.d.ts +8 -0
- package/dist/svelte/UsageThresholds.svelte.d.ts.map +1 -0
- package/dist/svelte/i18n.d.ts +5 -0
- package/dist/svelte/i18n.d.ts.map +1 -0
- package/dist/svelte/i18n.js +9 -0
- package/dist/svelte/index.d.ts +4 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +3 -0
- package/dist/types.d.ts +175 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +59 -0
- package/dist/utils.d.ts.map +1 -0
- package/package.json +80 -0
- package/scripts/migrate-1454-drop-legacy-conflict-index.ts +110 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { SubscriptionPlan } from '../models/SubscriptionPlan.js';
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
plans = [],
|
|
6
|
+
selectedPlanKey = null,
|
|
7
|
+
onSelect,
|
|
8
|
+
}: {
|
|
9
|
+
plans?: SubscriptionPlan[];
|
|
10
|
+
selectedPlanKey?: string | null;
|
|
11
|
+
onSelect?: (plan: SubscriptionPlan) => void;
|
|
12
|
+
} = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<div class="smrt-plan-picker">
|
|
16
|
+
{#each plans as plan (plan.id)}
|
|
17
|
+
<button
|
|
18
|
+
aria-pressed={plan.planKey === selectedPlanKey}
|
|
19
|
+
class:selected={plan.planKey === selectedPlanKey}
|
|
20
|
+
class="smrt-plan-picker__plan"
|
|
21
|
+
type="button"
|
|
22
|
+
onclick={() => onSelect?.(plan)}
|
|
23
|
+
>
|
|
24
|
+
<span class="smrt-plan-picker__name">{plan.name}</span>
|
|
25
|
+
<span class="smrt-plan-picker__price">
|
|
26
|
+
{new Intl.NumberFormat(undefined, {
|
|
27
|
+
style: 'currency',
|
|
28
|
+
currency: plan.currency,
|
|
29
|
+
}).format(plan.priceAmount)}
|
|
30
|
+
<small>/ {plan.billingInterval}</small>
|
|
31
|
+
</span>
|
|
32
|
+
{#if plan.description}
|
|
33
|
+
<span class="smrt-plan-picker__description">{plan.description}</span>
|
|
34
|
+
{/if}
|
|
35
|
+
<span class="smrt-plan-picker__features">
|
|
36
|
+
{plan.getFeatureKeys().length} features
|
|
37
|
+
</span>
|
|
38
|
+
</button>
|
|
39
|
+
{/each}
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<style>
|
|
43
|
+
.smrt-plan-picker {
|
|
44
|
+
display: grid;
|
|
45
|
+
gap: 0.75rem;
|
|
46
|
+
grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.smrt-plan-picker__plan {
|
|
50
|
+
align-items: flex-start;
|
|
51
|
+
background: var(--smrt-color-surface, #fff);
|
|
52
|
+
border: 1px solid var(--smrt-color-outline-variant, #d8dde6);
|
|
53
|
+
border-radius: var(--smrt-radius-md, 8px);
|
|
54
|
+
color: inherit;
|
|
55
|
+
cursor: pointer;
|
|
56
|
+
display: grid;
|
|
57
|
+
gap: 0.45rem;
|
|
58
|
+
padding: 1rem;
|
|
59
|
+
text-align: left;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.smrt-plan-picker__plan.selected {
|
|
63
|
+
border-color: var(--smrt-color-primary, #2563eb);
|
|
64
|
+
box-shadow: 0 0 0 1px var(--smrt-color-primary, #2563eb);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.smrt-plan-picker__name {
|
|
68
|
+
font-weight: var(--smrt-typography-weight-bold, 650);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.smrt-plan-picker__price {
|
|
72
|
+
font-size: var(--smrt-typography-title-large-size, 1.25rem);
|
|
73
|
+
font-weight: var(--smrt-typography-weight-bold, 700);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.smrt-plan-picker__price small,
|
|
77
|
+
.smrt-plan-picker__description,
|
|
78
|
+
.smrt-plan-picker__features {
|
|
79
|
+
color: var(--smrt-color-on-surface-variant, #64748b);
|
|
80
|
+
font-size: var(--smrt-typography-body-medium-size, 0.875rem);
|
|
81
|
+
}
|
|
82
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SubscriptionPlan } from '../models/SubscriptionPlan.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
plans?: SubscriptionPlan[];
|
|
4
|
+
selectedPlanKey?: string | null;
|
|
5
|
+
onSelect?: (plan: SubscriptionPlan) => void;
|
|
6
|
+
};
|
|
7
|
+
declare const PlanPicker: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type PlanPicker = ReturnType<typeof PlanPicker>;
|
|
9
|
+
export default PlanPicker;
|
|
10
|
+
//# sourceMappingURL=PlanPicker.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlanPicker.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/PlanPicker.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAErE,KAAK,gBAAgB,GAAI;IACxB,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC7C,CAAC;AAoCF,QAAA,MAAM,UAAU,sDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
3
|
+
import type { EntitlementResolution } from '../types.js';
|
|
4
|
+
import { M } from './i18n.js';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
resolution = null,
|
|
8
|
+
}: {
|
|
9
|
+
resolution?: EntitlementResolution | null;
|
|
10
|
+
} = $props();
|
|
11
|
+
|
|
12
|
+
const { t } = useI18n();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<section class="smrt-subscription-summary">
|
|
16
|
+
<div>
|
|
17
|
+
<p class="smrt-subscription-summary__label">{t(M['subscriptions.summary.current_plan'])}</p>
|
|
18
|
+
<h2>{resolution?.planKey ?? t(M['subscriptions.summary.no_active_plan'])}</h2>
|
|
19
|
+
</div>
|
|
20
|
+
<dl>
|
|
21
|
+
<div>
|
|
22
|
+
<dt>Status</dt>
|
|
23
|
+
<dd>{resolution?.status ?? 'none'}</dd>
|
|
24
|
+
</div>
|
|
25
|
+
<div>
|
|
26
|
+
<dt>Features</dt>
|
|
27
|
+
<dd>{resolution?.featureKeys.length ?? 0}</dd>
|
|
28
|
+
</div>
|
|
29
|
+
<div>
|
|
30
|
+
<dt>Thresholds</dt>
|
|
31
|
+
<dd>{resolution?.thresholds.length ?? 0}</dd>
|
|
32
|
+
</div>
|
|
33
|
+
</dl>
|
|
34
|
+
</section>
|
|
35
|
+
|
|
36
|
+
<style>
|
|
37
|
+
.smrt-subscription-summary {
|
|
38
|
+
align-items: center;
|
|
39
|
+
display: flex;
|
|
40
|
+
gap: 1rem;
|
|
41
|
+
justify-content: space-between;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.smrt-subscription-summary h2,
|
|
45
|
+
.smrt-subscription-summary__label {
|
|
46
|
+
margin: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.smrt-subscription-summary__label,
|
|
50
|
+
.smrt-subscription-summary dt {
|
|
51
|
+
color: var(--smrt-color-on-surface-variant, #64748b);
|
|
52
|
+
font-size: var(--smrt-typography-label-medium-size, 0.8rem);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.smrt-subscription-summary dl {
|
|
56
|
+
display: flex;
|
|
57
|
+
gap: 1rem;
|
|
58
|
+
margin: 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.smrt-subscription-summary dd {
|
|
62
|
+
font-weight: var(--smrt-typography-weight-bold, 650);
|
|
63
|
+
margin: 0;
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { EntitlementResolution } from '../types.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
resolution?: EntitlementResolution | null;
|
|
4
|
+
};
|
|
5
|
+
declare const SubscriptionSummary: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
6
|
+
type SubscriptionSummary = ReturnType<typeof SubscriptionSummary>;
|
|
7
|
+
export default SubscriptionSummary;
|
|
8
|
+
//# sourceMappingURL=SubscriptionSummary.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubscriptionSummary.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/SubscriptionSummary.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAGxD,KAAK,gBAAgB,GAAI;IACxB,UAAU,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;CAC3C,CAAC;AAsCF,QAAA,MAAM,mBAAmB,sDAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ThresholdEvaluation } from '../types.js';
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
evaluations = [],
|
|
6
|
+
}: {
|
|
7
|
+
evaluations?: ThresholdEvaluation[];
|
|
8
|
+
} = $props();
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<div class="smrt-usage-thresholds">
|
|
12
|
+
{#each evaluations as evaluation (`${evaluation.threshold.metricKey}:${evaluation.usage.windowStart.toISOString()}`)}
|
|
13
|
+
<article
|
|
14
|
+
class:warn={evaluation.state === 'warn'}
|
|
15
|
+
class:blocked={evaluation.state === 'blocked'}
|
|
16
|
+
class="smrt-usage-thresholds__row"
|
|
17
|
+
>
|
|
18
|
+
<div class="smrt-usage-thresholds__header">
|
|
19
|
+
<strong>{evaluation.threshold.label ?? evaluation.threshold.metricKey}</strong>
|
|
20
|
+
<span>{evaluation.usage.quantity} / {evaluation.threshold.limit}</span>
|
|
21
|
+
</div>
|
|
22
|
+
<progress
|
|
23
|
+
aria-label={`${evaluation.threshold.label ?? evaluation.threshold.metricKey} usage`}
|
|
24
|
+
max="1"
|
|
25
|
+
value={Number.isFinite(evaluation.ratio)
|
|
26
|
+
? Math.min(1, evaluation.ratio)
|
|
27
|
+
: 1}
|
|
28
|
+
></progress>
|
|
29
|
+
<p>{evaluation.state}</p>
|
|
30
|
+
</article>
|
|
31
|
+
{/each}
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<style>
|
|
35
|
+
.smrt-usage-thresholds {
|
|
36
|
+
display: grid;
|
|
37
|
+
gap: 0.75rem;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.smrt-usage-thresholds__row {
|
|
41
|
+
border: 1px solid var(--smrt-color-outline-variant, #d8dde6);
|
|
42
|
+
border-radius: var(--smrt-radius-md, 8px);
|
|
43
|
+
display: grid;
|
|
44
|
+
gap: 0.45rem;
|
|
45
|
+
padding: 0.875rem;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.smrt-usage-thresholds__row.warn {
|
|
49
|
+
border-color: var(--smrt-color-warning, #d97706);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.smrt-usage-thresholds__row.blocked {
|
|
53
|
+
border-color: var(--smrt-color-error, #dc2626);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.smrt-usage-thresholds__header {
|
|
57
|
+
align-items: center;
|
|
58
|
+
display: flex;
|
|
59
|
+
justify-content: space-between;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.smrt-usage-thresholds p {
|
|
63
|
+
color: var(--smrt-color-on-surface-variant, #64748b);
|
|
64
|
+
font-size: var(--smrt-typography-body-medium-size, 0.875rem);
|
|
65
|
+
margin: 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.smrt-usage-thresholds progress {
|
|
69
|
+
inline-size: 100%;
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ThresholdEvaluation } from '../types.js';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
evaluations?: ThresholdEvaluation[];
|
|
4
|
+
};
|
|
5
|
+
declare const UsageThresholds: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
6
|
+
type UsageThresholds = ReturnType<typeof UsageThresholds>;
|
|
7
|
+
export default UsageThresholds;
|
|
8
|
+
//# sourceMappingURL=UsageThresholds.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UsageThresholds.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/UsageThresholds.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEtD,KAAK,gBAAgB,GAAI;IACxB,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACrC,CAAC;AA4BF,QAAA,MAAM,eAAe,sDAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/svelte/i18n.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,CAAC;;;CAGZ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* smrt-subscriptions UI message catalog (S13 #1418).
|
|
3
|
+
* Keys: `subscriptions.<component>.<descriptor>`.
|
|
4
|
+
*/
|
|
5
|
+
import { defineMessages } from '@happyvertical/smrt-ui/i18n';
|
|
6
|
+
export const M = defineMessages({
|
|
7
|
+
'subscriptions.summary.current_plan': 'Current plan',
|
|
8
|
+
'subscriptions.summary.no_active_plan': 'No active plan',
|
|
9
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { SmrtClassOptions } from '@happyvertical/smrt-core';
|
|
2
|
+
import { SubscriptionPlan } from './models/SubscriptionPlan.js';
|
|
3
|
+
import { TenantSubscription } from './models/TenantSubscription.js';
|
|
4
|
+
export type SubscriptionStatus = 'active' | 'canceled' | 'incomplete' | 'past_due' | 'trialing' | 'unpaid';
|
|
5
|
+
export type SubscriptionPlanStatus = 'active' | 'archived' | 'draft';
|
|
6
|
+
export type BillingInterval = 'day' | 'week' | 'month' | 'year';
|
|
7
|
+
export type ThresholdEnforcement = 'observe' | 'warn' | 'block';
|
|
8
|
+
export type ThresholdWindow = 'day' | 'week' | 'month' | 'year' | 'rolling';
|
|
9
|
+
export type SubscriberKind = 'tenant' | 'external';
|
|
10
|
+
/**
|
|
11
|
+
* Discriminated union identifying who a subscription/usage record is for.
|
|
12
|
+
*
|
|
13
|
+
* - `tenant`: the subscriber IS the owning tenant — preserves the existing
|
|
14
|
+
* single-tenant SaaS shape end-to-end.
|
|
15
|
+
* - `external`: the subscriber is a caller-defined identity (opaque to this
|
|
16
|
+
* package) scoped under an issuing `tenantId`. The `externalId` is a free-form
|
|
17
|
+
* string that the caller namespaces (e.g. `buyer-contact:abc123`). Use this
|
|
18
|
+
* for B2C buyers, anonymous-email subscribers, agent identities, etc.
|
|
19
|
+
*
|
|
20
|
+
* For both kinds, `tenantId` carries the owning/issuing tenant scope.
|
|
21
|
+
*/
|
|
22
|
+
export type Subscriber = {
|
|
23
|
+
kind: 'tenant';
|
|
24
|
+
tenantId: string;
|
|
25
|
+
} | {
|
|
26
|
+
kind: 'external';
|
|
27
|
+
tenantId: string;
|
|
28
|
+
externalId: string;
|
|
29
|
+
};
|
|
30
|
+
export interface PlanFeatureGrant {
|
|
31
|
+
featureKey: string;
|
|
32
|
+
enabled?: boolean;
|
|
33
|
+
metadata?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
export interface PlanThreshold {
|
|
36
|
+
metricKey: string;
|
|
37
|
+
limit: number;
|
|
38
|
+
window: ThresholdWindow;
|
|
39
|
+
enforcement: ThresholdEnforcement;
|
|
40
|
+
label?: string;
|
|
41
|
+
warningRatio?: number;
|
|
42
|
+
metadata?: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
export interface UsageWindow {
|
|
45
|
+
start: Date;
|
|
46
|
+
end: Date;
|
|
47
|
+
}
|
|
48
|
+
export interface UsageMetricRecord {
|
|
49
|
+
/**
|
|
50
|
+
* Owning/issuing tenant scope. For `subscriberKind: 'tenant'` records this is
|
|
51
|
+
* also the subscriber. For `'external'` records this is the issuer.
|
|
52
|
+
*/
|
|
53
|
+
tenantId: string;
|
|
54
|
+
/**
|
|
55
|
+
* Defaults to `'tenant'` when omitted — preserves the historical single-tenant
|
|
56
|
+
* shape for existing callers.
|
|
57
|
+
*/
|
|
58
|
+
subscriberKind?: SubscriberKind;
|
|
59
|
+
/**
|
|
60
|
+
* Required when `subscriberKind` is `'external'`. Caller-namespaced opaque
|
|
61
|
+
* identifier (e.g. `buyer-contact:abc123`).
|
|
62
|
+
*/
|
|
63
|
+
subscriberExternalId?: string;
|
|
64
|
+
metricKey: string;
|
|
65
|
+
quantity: number;
|
|
66
|
+
windowStart: Date;
|
|
67
|
+
windowEnd: Date;
|
|
68
|
+
source?: string;
|
|
69
|
+
sourceId?: string;
|
|
70
|
+
dimensions?: Record<string, unknown>;
|
|
71
|
+
}
|
|
72
|
+
export interface UsageSummary {
|
|
73
|
+
/** Owning/issuing tenant scope. */
|
|
74
|
+
tenantId: string;
|
|
75
|
+
/** Subscriber kind this summary represents. Defaults to `'tenant'`. */
|
|
76
|
+
subscriberKind?: SubscriberKind;
|
|
77
|
+
/** Set when `subscriberKind === 'external'`. */
|
|
78
|
+
subscriberExternalId?: string;
|
|
79
|
+
metricKey: string;
|
|
80
|
+
quantity: number;
|
|
81
|
+
windowStart: Date;
|
|
82
|
+
windowEnd: Date;
|
|
83
|
+
}
|
|
84
|
+
export interface AiUsageSummary {
|
|
85
|
+
tenantId: string;
|
|
86
|
+
promptTokens: number;
|
|
87
|
+
completionTokens: number;
|
|
88
|
+
totalTokens: number;
|
|
89
|
+
estimatedCost: number;
|
|
90
|
+
requestCount: number;
|
|
91
|
+
windowStart: Date;
|
|
92
|
+
windowEnd: Date;
|
|
93
|
+
}
|
|
94
|
+
export interface ThresholdEvaluation {
|
|
95
|
+
threshold: PlanThreshold;
|
|
96
|
+
usage: UsageSummary;
|
|
97
|
+
ratio: number;
|
|
98
|
+
state: 'ok' | 'warn' | 'blocked';
|
|
99
|
+
allowed: boolean;
|
|
100
|
+
remaining: number;
|
|
101
|
+
}
|
|
102
|
+
export interface EntitlementResolution {
|
|
103
|
+
/** Issuing/owning tenant scope. */
|
|
104
|
+
tenantId: string;
|
|
105
|
+
/**
|
|
106
|
+
* The subscriber identity this resolution was computed for.
|
|
107
|
+
*
|
|
108
|
+
* Always populated at runtime by `SubscriptionResolver.resolveEntitlements`,
|
|
109
|
+
* but kept optional on the interface so downstream code that constructs
|
|
110
|
+
* or mocks `EntitlementResolution` (pre-#1454) continues to typecheck
|
|
111
|
+
* without code changes.
|
|
112
|
+
*/
|
|
113
|
+
subscriber?: Subscriber;
|
|
114
|
+
planId: string | null;
|
|
115
|
+
planKey: string | null;
|
|
116
|
+
subscriptionId: string | null;
|
|
117
|
+
status: SubscriptionStatus | 'none';
|
|
118
|
+
featureKeys: string[];
|
|
119
|
+
thresholds: PlanThreshold[];
|
|
120
|
+
thresholdEvaluations: ThresholdEvaluation[];
|
|
121
|
+
allowed: boolean;
|
|
122
|
+
}
|
|
123
|
+
export interface EntitlementResolutionContext {
|
|
124
|
+
/**
|
|
125
|
+
* Current subscription for the requested subscriber. Set to `null` when a
|
|
126
|
+
* caller has already resolved that no current subscription exists.
|
|
127
|
+
*/
|
|
128
|
+
subscription?: TenantSubscription | null;
|
|
129
|
+
/**
|
|
130
|
+
* Plan for `subscription.planId`. Set to `null` when the caller has already
|
|
131
|
+
* resolved the plan as absent or inactive.
|
|
132
|
+
*/
|
|
133
|
+
plan?: SubscriptionPlan | null;
|
|
134
|
+
}
|
|
135
|
+
export interface SubscriptionResolverOptions {
|
|
136
|
+
now?: Date;
|
|
137
|
+
usageWindows?: Partial<Record<ThresholdWindow, UsageWindow>>;
|
|
138
|
+
/**
|
|
139
|
+
* Request-scoped context that lets repeated entitlement checks reuse an
|
|
140
|
+
* already-loaded subscription and plan instead of re-querying readers.
|
|
141
|
+
*/
|
|
142
|
+
context?: EntitlementResolutionContext;
|
|
143
|
+
}
|
|
144
|
+
export interface UsageMeterOptions {
|
|
145
|
+
classOptions?: SmrtClassOptions;
|
|
146
|
+
}
|
|
147
|
+
export interface RecordUsageOptions extends UsageMetricRecord {
|
|
148
|
+
}
|
|
149
|
+
export interface SummarizeUsageOptions {
|
|
150
|
+
/** Owning/issuing tenant scope. */
|
|
151
|
+
tenantId: string;
|
|
152
|
+
/** Defaults to `'tenant'`. */
|
|
153
|
+
subscriberKind?: SubscriberKind;
|
|
154
|
+
/** Required when `subscriberKind === 'external'`. */
|
|
155
|
+
subscriberExternalId?: string;
|
|
156
|
+
metricKey: string;
|
|
157
|
+
window: UsageWindow;
|
|
158
|
+
}
|
|
159
|
+
export interface SummarizeUsageBatchOptions {
|
|
160
|
+
/** Owning/issuing tenant scope. */
|
|
161
|
+
tenantId: string;
|
|
162
|
+
/** Defaults to `'tenant'`. */
|
|
163
|
+
subscriberKind?: SubscriberKind;
|
|
164
|
+
/** Required when `subscriberKind === 'external'`. */
|
|
165
|
+
subscriberExternalId?: string;
|
|
166
|
+
metricKeys: string[];
|
|
167
|
+
window: UsageWindow;
|
|
168
|
+
}
|
|
169
|
+
export interface SummarizeAiUsageOptions {
|
|
170
|
+
tenantId: string;
|
|
171
|
+
window: UsageWindow;
|
|
172
|
+
}
|
|
173
|
+
export type JsonObject = Record<string, unknown>;
|
|
174
|
+
export type { SmrtClassOptions };
|
|
175
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { JsonObject, PlanFeatureGrant, PlanThreshold, Subscriber, SubscriberKind, ThresholdWindow, UsageWindow } from './types.js';
|
|
2
|
+
export declare function parseJsonArray<T>(value: string, fallback?: T[]): T[];
|
|
3
|
+
export declare function parseJsonObject<T extends JsonObject>(value: string, fallback: T): T;
|
|
4
|
+
export declare function stringifyJson(value: unknown): string;
|
|
5
|
+
export declare function normalizeFeatureGrants(grants: Array<string | PlanFeatureGrant>): PlanFeatureGrant[];
|
|
6
|
+
/**
|
|
7
|
+
* Coerce inputs from the legacy tenant-only API into a {@link Subscriber}.
|
|
8
|
+
*
|
|
9
|
+
* Existing callers that pass only `tenantId` (with optional `subscriberKind` /
|
|
10
|
+
* `subscriberExternalId` fields, e.g. on `RecordUsageOptions`) get normalized
|
|
11
|
+
* into the discriminated union exactly once at the boundary. This is the only
|
|
12
|
+
* place that contains "if kind is omitted, default to tenant" logic — every
|
|
13
|
+
* other site works with a typed `Subscriber`.
|
|
14
|
+
*
|
|
15
|
+
* Throws when:
|
|
16
|
+
* - `subscriberKind === 'external'` is requested without a non-empty
|
|
17
|
+
* `subscriberExternalId` (the XOR invariant is the whole point), or
|
|
18
|
+
* - the input carries a non-empty `subscriberExternalId` but the kind resolves
|
|
19
|
+
* to `'tenant'` (silent re-scoping would write buyer-scoped usage as tenant
|
|
20
|
+
* usage, which then disappears from external summaries).
|
|
21
|
+
*/
|
|
22
|
+
export declare function normalizeSubscriber(input: {
|
|
23
|
+
tenantId: string;
|
|
24
|
+
subscriberKind?: SubscriberKind | null;
|
|
25
|
+
subscriberExternalId?: string | null;
|
|
26
|
+
}): Subscriber;
|
|
27
|
+
/**
|
|
28
|
+
* Project a {@link Subscriber} back onto column values for persistence or query
|
|
29
|
+
* filters. Counterpart to {@link normalizeSubscriber}.
|
|
30
|
+
*/
|
|
31
|
+
export declare function subscriberToColumns(subscriber: Subscriber): {
|
|
32
|
+
tenantId: string;
|
|
33
|
+
subscriberKind: SubscriberKind;
|
|
34
|
+
subscriberExternalId: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Enforce the subscriber XOR invariant on a row's columns. Used by both the
|
|
38
|
+
* model constructors (catches construction-time mistakes) and the
|
|
39
|
+
* `validateBeforeSave` override (catches mutations applied via the
|
|
40
|
+
* generated PUT/PATCH update path that bypass the constructor).
|
|
41
|
+
*
|
|
42
|
+
* Defensive about types because both call sites can receive JSON or untyped
|
|
43
|
+
* fixture data via the generated REST/CLI surface — `null` arriving in place
|
|
44
|
+
* of `''` would otherwise slip past an `=== ''` check, land in the
|
|
45
|
+
* `(tenant_id, subscriber_kind, subscriber_external_id)` conflict key, and
|
|
46
|
+
* (on Postgres) not collide with other NULLs while `findCurrentForSubscriber`
|
|
47
|
+
* keeps querying by a string external id.
|
|
48
|
+
*
|
|
49
|
+
* @param modelName - Prepended to error messages so callers can tell whether
|
|
50
|
+
* the failure originated in `TenantSubscription` or `TenantUsageMetric`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function assertSubscriberInvariant(modelName: string, fields: {
|
|
53
|
+
subscriberKind: unknown;
|
|
54
|
+
subscriberExternalId: unknown;
|
|
55
|
+
}): void;
|
|
56
|
+
export declare function getWindowForThreshold(thresholdWindow: ThresholdWindow, now?: Date): UsageWindow;
|
|
57
|
+
export declare function getWindowKey(window: UsageWindow): string;
|
|
58
|
+
export declare function isValidThreshold(threshold: PlanThreshold): boolean;
|
|
59
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,cAAc,EAEd,eAAe,EACf,WAAW,EACZ,MAAM,YAAY,CAAC;AAepB,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,CAAC,EAAO,GAAG,CAAC,EAAE,CAWxE;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,UAAU,EAClD,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,GACV,CAAC,CAaH;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC,GACvC,gBAAgB,EAAE,CAIpB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACvC,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC,GAAG,UAAU,CAuCb;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,oBAAoB,EAAE,MAAM,CAAC;CAC9B,CAaA;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IACN,cAAc,EAAE,OAAO,CAAC;IACxB,oBAAoB,EAAE,OAAO,CAAC;CAC/B,GACA,IAAI,CAmCN;AASD,wBAAgB,qBAAqB,CACnC,eAAe,EAAE,eAAe,EAChC,GAAG,OAAa,GACf,WAAW,CAgBb;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAExD;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CAalE"}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@happyvertical/smrt-subscriptions",
|
|
3
|
+
"version": "0.30.0",
|
|
4
|
+
"description": "Tenant subscriptions, entitlement resolution, usage thresholds, and subscription UI for SMRT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"scripts",
|
|
11
|
+
"CLAUDE.md",
|
|
12
|
+
"AGENTS.md"
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./manifest": "./dist/manifest.json",
|
|
20
|
+
"./manifest.json": "./dist/manifest.json",
|
|
21
|
+
"./svelte": {
|
|
22
|
+
"types": "./dist/svelte/index.d.ts",
|
|
23
|
+
"svelte": "./dist/svelte/index.js",
|
|
24
|
+
"import": "./dist/svelte/index.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@happyvertical/sql": "^0.74.7",
|
|
29
|
+
"@happyvertical/smrt-ui": "0.30.0",
|
|
30
|
+
"@happyvertical/smrt-tenancy": "0.30.0",
|
|
31
|
+
"@happyvertical/smrt-core": "0.30.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"svelte": "^5.18.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"svelte": {
|
|
38
|
+
"optional": true
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@sveltejs/package": "^2.5.7",
|
|
43
|
+
"@types/node": "24.10.9",
|
|
44
|
+
"svelte": "^5.18.0",
|
|
45
|
+
"svelte-check": "^4.3.5",
|
|
46
|
+
"typescript": "^5.9.3",
|
|
47
|
+
"vite": "^7.3.1",
|
|
48
|
+
"vitest": "^4.0.17",
|
|
49
|
+
"@happyvertical/smrt-vitest": "0.30.0"
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"smrt",
|
|
53
|
+
"subscriptions",
|
|
54
|
+
"billing",
|
|
55
|
+
"entitlements",
|
|
56
|
+
"multi-tenant"
|
|
57
|
+
],
|
|
58
|
+
"author": "HappyVertical",
|
|
59
|
+
"license": "MIT",
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"registry": "https://registry.npmjs.org",
|
|
62
|
+
"access": "public"
|
|
63
|
+
},
|
|
64
|
+
"repository": {
|
|
65
|
+
"type": "git",
|
|
66
|
+
"url": "https://github.com/happyvertical/smrt.git",
|
|
67
|
+
"directory": "packages/subscriptions"
|
|
68
|
+
},
|
|
69
|
+
"scripts": {
|
|
70
|
+
"build": "vite build --mode library && svelte-package -i src/svelte -o dist/svelte --tsconfig tsconfig.svelte.json",
|
|
71
|
+
"build:watch": "vite build --mode library --watch",
|
|
72
|
+
"check": "pnpm exec svelte-check --tsconfig ./tsconfig.svelte.json",
|
|
73
|
+
"typecheck": "tsc --noEmit && node ../../scripts/svelte-check-a11y.mjs --tsconfig ./tsconfig.svelte.json",
|
|
74
|
+
"clean": "rm -rf dist",
|
|
75
|
+
"dev": "vite dev",
|
|
76
|
+
"test": "vitest run",
|
|
77
|
+
"test:watch": "vitest",
|
|
78
|
+
"verify:pack": "node ../../scripts/verify-package-types-exports.js ."
|
|
79
|
+
}
|
|
80
|
+
}
|