@stigmer/react 3.39.1-dev.20260928194002 → 3.40.1
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/billing/AutoRechargeCard.js +1 -1
- package/billing/AutoRechargeCard.js.map +1 -1
- package/billing/BillingSection.d.ts +18 -1
- package/billing/BillingSection.d.ts.map +1 -1
- package/billing/BillingSection.js +21 -11
- package/billing/BillingSection.js.map +1 -1
- package/billing/ChangePlanDialog.d.ts +46 -0
- package/billing/ChangePlanDialog.d.ts.map +1 -0
- package/billing/ChangePlanDialog.js +90 -0
- package/billing/ChangePlanDialog.js.map +1 -0
- package/billing/CreditPackGrid.d.ts +1 -1
- package/billing/CreditPackGrid.js +1 -1
- package/billing/LowBalanceBanner.js +1 -1
- package/billing/LowBalanceBanner.js.map +1 -1
- package/billing/PaymentMethodCard.d.ts +9 -1
- package/billing/PaymentMethodCard.d.ts.map +1 -1
- package/billing/PaymentMethodCard.js +2 -2
- package/billing/PaymentMethodCard.js.map +1 -1
- package/billing/PlanCard.d.ts +27 -0
- package/billing/PlanCard.d.ts.map +1 -0
- package/billing/PlanCard.js +68 -0
- package/billing/PlanCard.js.map +1 -0
- package/billing/PlanPicker.d.ts +34 -0
- package/billing/PlanPicker.d.ts.map +1 -0
- package/billing/PlanPicker.js +46 -0
- package/billing/PlanPicker.js.map +1 -0
- package/billing/PlanSection.d.ts +45 -0
- package/billing/PlanSection.d.ts.map +1 -0
- package/billing/PlanSection.js +136 -0
- package/billing/PlanSection.js.map +1 -0
- package/billing/UpgradeNotice.d.ts +47 -0
- package/billing/UpgradeNotice.d.ts.map +1 -0
- package/billing/UpgradeNotice.js +49 -0
- package/billing/UpgradeNotice.js.map +1 -0
- package/billing/credit-packs.d.ts.map +1 -1
- package/billing/credit-packs.js +4 -1
- package/billing/credit-packs.js.map +1 -1
- package/billing/index.d.ts +26 -1
- package/billing/index.d.ts.map +1 -1
- package/billing/index.js +12 -0
- package/billing/index.js.map +1 -1
- package/billing/plan-features.d.ts +60 -0
- package/billing/plan-features.d.ts.map +1 -0
- package/billing/plan-features.js +128 -0
- package/billing/plan-features.js.map +1 -0
- package/billing/plan-state.d.ts +43 -0
- package/billing/plan-state.d.ts.map +1 -0
- package/billing/plan-state.js +69 -0
- package/billing/plan-state.js.map +1 -0
- package/billing/redirect.d.ts +31 -0
- package/billing/redirect.d.ts.map +1 -0
- package/billing/redirect.js +30 -0
- package/billing/redirect.js.map +1 -0
- package/billing/useBillingAccount.d.ts +10 -1
- package/billing/useBillingAccount.d.ts.map +1 -1
- package/billing/useBillingAccount.js +2 -2
- package/billing/useBillingAccount.js.map +1 -1
- package/billing/useChangePlan.d.ts +51 -0
- package/billing/useChangePlan.d.ts.map +1 -0
- package/billing/useChangePlan.js +61 -0
- package/billing/useChangePlan.js.map +1 -0
- package/billing/useCreateBillingPortalSession.d.ts +6 -3
- package/billing/useCreateBillingPortalSession.d.ts.map +1 -1
- package/billing/useCreateBillingPortalSession.js +11 -4
- package/billing/useCreateBillingPortalSession.js.map +1 -1
- package/billing/useCreateCheckoutSession.d.ts +7 -5
- package/billing/useCreateCheckoutSession.d.ts.map +1 -1
- package/billing/useCreateCheckoutSession.js +5 -3
- package/billing/useCreateCheckoutSession.js.map +1 -1
- package/billing/useCreatePaymentMethodSetupSession.d.ts +28 -0
- package/billing/useCreatePaymentMethodSetupSession.d.ts.map +1 -0
- package/billing/useCreatePaymentMethodSetupSession.js +50 -0
- package/billing/useCreatePaymentMethodSetupSession.js.map +1 -0
- package/billing/useEntitlements.d.ts +46 -0
- package/billing/useEntitlements.d.ts.map +1 -0
- package/billing/useEntitlements.js +37 -0
- package/billing/useEntitlements.js.map +1 -0
- package/billing/usePeriodEstimate.d.ts +35 -0
- package/billing/usePeriodEstimate.d.ts.map +1 -0
- package/billing/usePeriodEstimate.js +29 -0
- package/billing/usePeriodEstimate.js.map +1 -0
- package/billing/usePlans.d.ts +38 -0
- package/billing/usePlans.d.ts.map +1 -0
- package/billing/usePlans.js +33 -0
- package/billing/usePlans.js.map +1 -0
- package/billing/useSubscription.d.ts +39 -0
- package/billing/useSubscription.d.ts.map +1 -0
- package/billing/useSubscription.js +40 -0
- package/billing/useSubscription.js.map +1 -0
- package/channel-app/ChannelAppDetailPanel.d.ts +5 -0
- package/channel-app/ChannelAppDetailPanel.d.ts.map +1 -1
- package/channel-app/ChannelAppDetailPanel.js +9 -3
- package/channel-app/ChannelAppDetailPanel.js.map +1 -1
- package/channel-app/ChannelAppListPanel.d.ts +13 -4
- package/channel-app/ChannelAppListPanel.d.ts.map +1 -1
- package/channel-app/ChannelAppListPanel.js +5 -5
- package/channel-app/ChannelAppListPanel.js.map +1 -1
- package/channel-app/copy.d.ts +15 -0
- package/channel-app/copy.d.ts.map +1 -0
- package/channel-app/copy.js +15 -0
- package/channel-app/copy.js.map +1 -0
- package/index.d.ts +4 -2
- package/index.d.ts.map +1 -1
- package/index.js +4 -1
- package/index.js.map +1 -1
- package/internal/features.d.ts +11 -0
- package/internal/features.d.ts.map +1 -0
- package/internal/features.js +42 -0
- package/internal/features.js.map +1 -0
- package/licenses/license-format.d.ts +5 -3
- package/licenses/license-format.d.ts.map +1 -1
- package/licenses/license-format.js +10 -19
- package/licenses/license-format.js.map +1 -1
- package/package.json +5 -5
- package/plan-catalog/PlanCatalogConsole.d.ts +22 -0
- package/plan-catalog/PlanCatalogConsole.d.ts.map +1 -0
- package/plan-catalog/PlanCatalogConsole.js +90 -0
- package/plan-catalog/PlanCatalogConsole.js.map +1 -0
- package/plan-catalog/PlanCreateForm.d.ts +17 -0
- package/plan-catalog/PlanCreateForm.d.ts.map +1 -0
- package/plan-catalog/PlanCreateForm.js +52 -0
- package/plan-catalog/PlanCreateForm.js.map +1 -0
- package/plan-catalog/PlansAccessNotice.d.ts +10 -0
- package/plan-catalog/PlansAccessNotice.d.ts.map +1 -0
- package/plan-catalog/PlansAccessNotice.js +13 -0
- package/plan-catalog/PlansAccessNotice.js.map +1 -0
- package/plan-catalog/index.d.ts +8 -0
- package/plan-catalog/index.d.ts.map +1 -0
- package/plan-catalog/index.js +10 -0
- package/plan-catalog/index.js.map +1 -0
- package/plan-catalog/plan-draft.d.ts +30 -0
- package/plan-catalog/plan-draft.d.ts.map +1 -0
- package/plan-catalog/plan-draft.js +91 -0
- package/plan-catalog/plan-draft.js.map +1 -0
- package/plan-catalog/usePlanMutations.d.ts +42 -0
- package/plan-catalog/usePlanMutations.d.ts.map +1 -0
- package/plan-catalog/usePlanMutations.js +57 -0
- package/plan-catalog/usePlanMutations.js.map +1 -0
- package/settings/ChannelAppsSection.d.ts +7 -0
- package/settings/ChannelAppsSection.d.ts.map +1 -1
- package/settings/ChannelAppsSection.js +15 -2
- package/settings/ChannelAppsSection.js.map +1 -1
- package/settings/TeamsSection.d.ts.map +1 -1
- package/settings/TeamsSection.js +19 -2
- package/settings/TeamsSection.js.map +1 -1
- package/settings/settings-nav.d.ts.map +1 -1
- package/settings/settings-nav.js +7 -1
- package/settings/settings-nav.js.map +1 -1
- package/settings/useSettingsNavGroups.d.ts.map +1 -1
- package/settings/useSettingsNavGroups.js +4 -1
- package/settings/useSettingsNavGroups.js.map +1 -1
- package/src/billing/AutoRechargeCard.tsx +2 -2
- package/src/billing/BillingSection.tsx +68 -11
- package/src/billing/ChangePlanDialog.tsx +221 -0
- package/src/billing/CreditPackGrid.tsx +1 -1
- package/src/billing/LowBalanceBanner.tsx +1 -1
- package/src/billing/PaymentMethodCard.tsx +28 -2
- package/src/billing/PlanCard.tsx +171 -0
- package/src/billing/PlanPicker.tsx +178 -0
- package/src/billing/PlanSection.tsx +234 -0
- package/src/billing/UpgradeNotice.tsx +95 -0
- package/src/billing/credit-packs.ts +4 -1
- package/src/billing/index.ts +26 -1
- package/src/billing/plan-features.ts +162 -0
- package/src/billing/plan-state.ts +92 -0
- package/src/billing/redirect.ts +45 -0
- package/src/billing/useBillingAccount.ts +12 -0
- package/src/billing/useChangePlan.ts +115 -0
- package/src/billing/useCreateBillingPortalSession.ts +17 -6
- package/src/billing/useCreateCheckoutSession.ts +12 -7
- package/src/billing/useCreatePaymentMethodSetupSession.ts +77 -0
- package/src/billing/useEntitlements.ts +80 -0
- package/src/billing/usePeriodEstimate.ts +59 -0
- package/src/billing/usePlans.ts +65 -0
- package/src/billing/useSubscription.ts +70 -0
- package/src/channel-app/ChannelAppDetailPanel.tsx +179 -158
- package/src/channel-app/ChannelAppListPanel.tsx +14 -4
- package/src/channel-app/copy.ts +16 -0
- package/src/index.ts +54 -0
- package/src/internal/features.ts +49 -0
- package/src/licenses/license-format.ts +10 -19
- package/src/plan-catalog/PlanCatalogConsole.tsx +197 -0
- package/src/plan-catalog/PlanCreateForm.tsx +167 -0
- package/src/plan-catalog/PlansAccessNotice.tsx +20 -0
- package/src/plan-catalog/index.ts +14 -0
- package/src/plan-catalog/plan-draft.ts +116 -0
- package/src/plan-catalog/usePlanMutations.ts +94 -0
- package/src/settings/ChannelAppsSection.tsx +19 -2
- package/src/settings/TeamsSection.tsx +20 -2
- package/src/settings/settings-nav.ts +7 -0
- package/src/settings/useSettingsNavGroups.ts +8 -1
- package/src/team/CreateTeamForm.tsx +12 -3
- package/src/team/TeamMembersPanel.tsx +6 -2
- package/team/CreateTeamForm.d.ts +6 -1
- package/team/CreateTeamForm.d.ts.map +1 -1
- package/team/CreateTeamForm.js +4 -2
- package/team/CreateTeamForm.js.map +1 -1
- package/team/TeamMembersPanel.d.ts.map +1 -1
- package/team/TeamMembersPanel.js +3 -1
- package/team/TeamMembersPanel.js.map +1 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// What a plan offers, as the console shows it: which plans are offered and
|
|
2
|
+
// in what order, what each includes, and the formatting of its terms and
|
|
3
|
+
// periods.
|
|
4
|
+
//
|
|
5
|
+
// A plan's features render from its entitlements through the shared
|
|
6
|
+
// vocabulary (../internal/features.ts), never from the plan's stored
|
|
7
|
+
// description: a plan row is immutable once seeded, and the description is
|
|
8
|
+
// free text that can promise a feature before it is built. The console
|
|
9
|
+
// shows only what an organization can use today.
|
|
10
|
+
import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
11
|
+
import { PlanInstrument } from "@stigmer/protos/ai/stigmer/billing/plan/v1/spec_pb";
|
|
12
|
+
import { PlanLifecycle } from "@stigmer/protos/ai/stigmer/billing/plan/v1/status_pb";
|
|
13
|
+
import { Feature } from "@stigmer/protos/ai/stigmer/platform/v1/entitlement_pb";
|
|
14
|
+
import { FEATURE_COPY, isNamedFeature } from "../internal/features.js";
|
|
15
|
+
import { formatCreditBalance } from "./format.js";
|
|
16
|
+
// BigInt(0), not a literal: the docs site compiles this source for a
|
|
17
|
+
// target below ES2020, which has no BigInt literal syntax.
|
|
18
|
+
const ZERO = BigInt(0);
|
|
19
|
+
/**
|
|
20
|
+
* Features a plan may list ahead of the gate that serves them, which
|
|
21
|
+
* Stigmer Cloud does not offer yet. The console leaves them out of every
|
|
22
|
+
* comparison. Bring-your-own provider keys leaves this set when the proxy
|
|
23
|
+
* uses an organization's own key.
|
|
24
|
+
*/
|
|
25
|
+
export const NOT_YET_OFFERED = new Set([Feature.byo_provider_keys]);
|
|
26
|
+
/** The features `entitlements` grant that Cloud offers today, in contract order. */
|
|
27
|
+
export function offeredFeatures(entitlements) {
|
|
28
|
+
const listed = entitlements?.features ?? [];
|
|
29
|
+
return [...new Set(listed)]
|
|
30
|
+
.filter((feature) => isNamedFeature(feature) && !NOT_YET_OFFERED.has(feature))
|
|
31
|
+
.sort((a, b) => a - b)
|
|
32
|
+
.map((feature) => ({ feature, ...FEATURE_COPY[feature] }));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The plans an organization can subscribe to, cheapest monthly minimum
|
|
36
|
+
* first, so a comparison reads upward from Free; equal minimums keep the
|
|
37
|
+
* catalog's order. Retired rows and prepaid instruments are left out.
|
|
38
|
+
*/
|
|
39
|
+
export function buyablePlans(plans) {
|
|
40
|
+
return plans
|
|
41
|
+
.filter((plan) => plan.spec?.instrument === PlanInstrument.subscription && plan.status?.lifecycle === PlanLifecycle.active)
|
|
42
|
+
.map((plan, index) => ({ plan, index }))
|
|
43
|
+
.sort((a, b) => compareMinimums(a.plan, b.plan) || a.index - b.index)
|
|
44
|
+
.map(({ plan }) => plan);
|
|
45
|
+
}
|
|
46
|
+
/** The cheapest plan that can be bought and includes `feature`, if any. */
|
|
47
|
+
export function lowestPlanWith(plans, feature) {
|
|
48
|
+
return buyablePlans(plans).find((plan) => offeredFeatures(plan.spec?.entitlements).some((offered) => offered.feature === feature));
|
|
49
|
+
}
|
|
50
|
+
/** What `from` offers that `to` does not: what a switch stops the organization creating. */
|
|
51
|
+
export function featuresLost(from, to) {
|
|
52
|
+
const kept = new Set(offeredFeatures(to.spec?.entitlements).map((offered) => offered.feature));
|
|
53
|
+
return offeredFeatures(from?.spec?.entitlements).filter((offered) => !kept.has(offered.feature));
|
|
54
|
+
}
|
|
55
|
+
function compareMinimums(a, b) {
|
|
56
|
+
const left = a.spec?.terms?.monthlyMinimumMicros ?? ZERO;
|
|
57
|
+
const right = b.spec?.terms?.monthlyMinimumMicros ?? ZERO;
|
|
58
|
+
return left === right ? 0 : left < right ? -1 : 1;
|
|
59
|
+
}
|
|
60
|
+
/** A plan's monthly minimum, e.g. "$99.00/month". */
|
|
61
|
+
export function formatMonthlyMinimum(terms) {
|
|
62
|
+
return `${formatCreditBalance(terms?.monthlyMinimumMicros ?? ZERO)}/month`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A plan's usage share as its terms state it, for operators who read terms,
|
|
66
|
+
* e.g. "or 10% of provider cost, whichever is greater; the commission
|
|
67
|
+
* already paid on tokens counts toward it". Empty when the plan has no
|
|
68
|
+
* usage share.
|
|
69
|
+
*/
|
|
70
|
+
export function formatUsageShare(terms) {
|
|
71
|
+
const percent = sharePercent(terms);
|
|
72
|
+
return percent === ""
|
|
73
|
+
? ""
|
|
74
|
+
: `or ${percent} of provider cost, whichever is greater; the commission already paid on tokens counts toward it`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The same share as a customer reads it: usage stays paid from credits,
|
|
78
|
+
* and the commission on it counts toward the minimum up to the spend at
|
|
79
|
+
* which the plan costs nothing extra, e.g. "Usage is still paid from
|
|
80
|
+
* credits. The 10% commission on it counts toward the minimum, so from
|
|
81
|
+
* $990.00 a month in provider costs the plan costs nothing extra." Empty
|
|
82
|
+
* when the plan has no usage share.
|
|
83
|
+
*/
|
|
84
|
+
export function explainUsageShare(terms) {
|
|
85
|
+
const percent = sharePercent(terms);
|
|
86
|
+
if (percent === "") {
|
|
87
|
+
return "";
|
|
88
|
+
}
|
|
89
|
+
const basisPoints = BigInt(terms?.usageShareBasisPoints ?? 0);
|
|
90
|
+
// The provider cost whose share equals the minimum: past it, the share is the plan's cost and the commission pays it.
|
|
91
|
+
const breakEven = ((terms?.monthlyMinimumMicros ?? ZERO) * BigInt(10_000)) / basisPoints;
|
|
92
|
+
return (`Usage is still paid from credits. The ${percent} commission on it counts toward the minimum, ` +
|
|
93
|
+
`so from ${formatCreditBalance(breakEven)} a month in provider costs the plan costs nothing extra.`);
|
|
94
|
+
}
|
|
95
|
+
/** The usage share as a percentage, e.g. "10%" or "12.50%"; empty when there is none. */
|
|
96
|
+
export function sharePercent(terms) {
|
|
97
|
+
const basisPoints = terms?.usageShareBasisPoints ?? 0;
|
|
98
|
+
if (basisPoints === 0) {
|
|
99
|
+
return "";
|
|
100
|
+
}
|
|
101
|
+
return `${basisPoints % 100 === 0 ? `${basisPoints / 100}` : (basisPoints / 100).toFixed(2)}%`;
|
|
102
|
+
}
|
|
103
|
+
/** The managed organizations a plan includes and what each beyond costs, or empty. */
|
|
104
|
+
export function formatManagedOrganizations(entitlements, terms) {
|
|
105
|
+
if (!(entitlements?.features ?? []).includes(Feature.managed_organizations)) {
|
|
106
|
+
return "";
|
|
107
|
+
}
|
|
108
|
+
const included = entitlements?.limits?.includedManagedOrganizations;
|
|
109
|
+
const fee = terms?.perExtraOrganizationMicros ?? ZERO;
|
|
110
|
+
if (included === undefined) {
|
|
111
|
+
return "Unlimited managed organizations";
|
|
112
|
+
}
|
|
113
|
+
const beyond = fee > ZERO ? `, then ${formatCreditBalance(fee)}/month each` : "";
|
|
114
|
+
return `${included} managed organization${included === 1 ? "" : "s"} included${beyond}`;
|
|
115
|
+
}
|
|
116
|
+
const DAY = new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", year: "numeric", timeZone: "UTC" });
|
|
117
|
+
/**
|
|
118
|
+
* A period boundary as a UTC calendar day, e.g. "Feb 28, 2027". Periods
|
|
119
|
+
* run anniversary to anniversary in UTC, the rule the invoice follows.
|
|
120
|
+
*/
|
|
121
|
+
export function formatPeriodDay(timestamp) {
|
|
122
|
+
return timestamp === undefined ? "" : formatDay(timestampDate(timestamp));
|
|
123
|
+
}
|
|
124
|
+
/** An instant as its UTC calendar day, the way {@link formatPeriodDay} shows a period boundary. */
|
|
125
|
+
export function formatDay(date) {
|
|
126
|
+
return DAY.format(date);
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=plan-features.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-features.js","sourceRoot":"","sources":["../src/billing/plan-features.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Plan } from "@stigmer/protos/ai/stigmer/billing/plan/v1/api_pb";
|
|
2
|
+
import type { Subscription } from "@stigmer/protos/ai/stigmer/billing/subscription/v1/api_pb";
|
|
3
|
+
/** An organization's standing on its plan. */
|
|
4
|
+
export type PlanStanding = {
|
|
5
|
+
readonly kind: "free";
|
|
6
|
+
} | {
|
|
7
|
+
readonly kind: "active";
|
|
8
|
+
readonly planId: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly kind: "past-due";
|
|
11
|
+
readonly planId: string;
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: "ending";
|
|
14
|
+
readonly planId: string;
|
|
15
|
+
readonly endsAt: Date;
|
|
16
|
+
};
|
|
17
|
+
/** What choosing a plan (or Free) would do. */
|
|
18
|
+
export type PlanMove = {
|
|
19
|
+
readonly kind: "subscribe";
|
|
20
|
+
readonly to: Plan;
|
|
21
|
+
} | {
|
|
22
|
+
readonly kind: "switch";
|
|
23
|
+
readonly fromPlanId: string;
|
|
24
|
+
readonly to: Plan;
|
|
25
|
+
} | {
|
|
26
|
+
readonly kind: "resume";
|
|
27
|
+
readonly to: Plan;
|
|
28
|
+
} | {
|
|
29
|
+
readonly kind: "cancel";
|
|
30
|
+
readonly fromPlanId: string;
|
|
31
|
+
readonly endsAt: Date;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The standing a stored subscription gives at `now`: the engine's live
|
|
35
|
+
* rule (active, past due, or canceled but not yet at its period's end),
|
|
36
|
+
* else Free. `null` (never subscribed) is Free.
|
|
37
|
+
*/
|
|
38
|
+
export declare function planStanding(subscription: Subscription | null, now: Date): PlanStanding;
|
|
39
|
+
/** The move choosing `target` (a plan, or `"free"`) makes from `standing`, or `null` for none. */
|
|
40
|
+
export declare function planMove(standing: PlanStanding, target: Plan | "free", periodEnd: Date | undefined): PlanMove | null;
|
|
41
|
+
/** The plan id in force for `standing`, or empty on Free. */
|
|
42
|
+
export declare function standingPlanId(standing: PlanStanding): string;
|
|
43
|
+
//# sourceMappingURL=plan-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-state.d.ts","sourceRoot":"","sources":["../src/billing/plan-state.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mDAAmD,CAAC;AAC9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2DAA2D,CAAC;AAG9F,8CAA8C;AAC9C,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC;AAEhF,+CAA+C;AAC/C,MAAM,MAAM,QAAQ,GAChB;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GACjD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GAC3E;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GAC9C;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC;AAEpF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,EAAE,GAAG,EAAE,IAAI,GAAG,YAAY,CAiBvF;AAED,kGAAkG;AAClG,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,IAAI,GAAG,MAAM,EACrB,SAAS,EAAE,IAAI,GAAG,SAAS,GAC1B,QAAQ,GAAG,IAAI,CAuBjB;AAED,6DAA6D;AAC7D,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAE7D"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Where an organization stands on its plan, and what choosing a plan
|
|
2
|
+
// would do, decided the way the server decides it (the subscription
|
|
3
|
+
// engine's moves), so the confirm step states the move the server makes.
|
|
4
|
+
//
|
|
5
|
+
// subscribe no live plan: a monthly period opens now on the plan
|
|
6
|
+
// switch a live plan, another chosen: this period closes early,
|
|
7
|
+
// billed for the time it ran, and a new one opens now
|
|
8
|
+
// resume the plan being canceled, chosen again: the cancel is
|
|
9
|
+
// withdrawn and the period runs on
|
|
10
|
+
// cancel Free chosen on a live plan: the plan runs to its period's
|
|
11
|
+
// end, then the organization is on Free
|
|
12
|
+
//
|
|
13
|
+
// Choosing the plan already in force, or Free while on Free or already
|
|
14
|
+
// canceling, is no move at all.
|
|
15
|
+
import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
16
|
+
import { SubscriptionState } from "@stigmer/protos/ai/stigmer/billing/subscription/v1/status_pb";
|
|
17
|
+
/**
|
|
18
|
+
* The standing a stored subscription gives at `now`: the engine's live
|
|
19
|
+
* rule (active, past due, or canceled but not yet at its period's end),
|
|
20
|
+
* else Free. `null` (never subscribed) is Free.
|
|
21
|
+
*/
|
|
22
|
+
export function planStanding(subscription, now) {
|
|
23
|
+
const status = subscription?.status;
|
|
24
|
+
const planId = subscription?.spec?.planId ?? "";
|
|
25
|
+
switch (status?.state) {
|
|
26
|
+
case SubscriptionState.active:
|
|
27
|
+
return { kind: "active", planId };
|
|
28
|
+
case SubscriptionState.past_due:
|
|
29
|
+
return { kind: "past-due", planId };
|
|
30
|
+
case SubscriptionState.canceled: {
|
|
31
|
+
const end = status.currentPeriodEnd === undefined ? undefined : timestampDate(status.currentPeriodEnd);
|
|
32
|
+
return end !== undefined && now.getTime() < end.getTime()
|
|
33
|
+
? { kind: "ending", planId, endsAt: end }
|
|
34
|
+
: { kind: "free" };
|
|
35
|
+
}
|
|
36
|
+
default:
|
|
37
|
+
return { kind: "free" };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** The move choosing `target` (a plan, or `"free"`) makes from `standing`, or `null` for none. */
|
|
41
|
+
export function planMove(standing, target, periodEnd) {
|
|
42
|
+
if (target === "free") {
|
|
43
|
+
if (standing.kind === "active" || standing.kind === "past-due") {
|
|
44
|
+
return periodEnd === undefined ? null : { kind: "cancel", fromPlanId: standing.planId, endsAt: periodEnd };
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const targetId = target.metadata?.id ?? "";
|
|
49
|
+
switch (standing.kind) {
|
|
50
|
+
case "free":
|
|
51
|
+
return { kind: "subscribe", to: target };
|
|
52
|
+
case "ending":
|
|
53
|
+
return targetId === standing.planId
|
|
54
|
+
? { kind: "resume", to: target }
|
|
55
|
+
: { kind: "switch", fromPlanId: standing.planId, to: target };
|
|
56
|
+
case "active":
|
|
57
|
+
case "past-due":
|
|
58
|
+
return targetId === standing.planId ? null : { kind: "switch", fromPlanId: standing.planId, to: target };
|
|
59
|
+
default: {
|
|
60
|
+
const exhaustive = standing;
|
|
61
|
+
throw new Error(`unknown plan standing ${JSON.stringify(exhaustive)}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** The plan id in force for `standing`, or empty on Free. */
|
|
66
|
+
export function standingPlanId(standing) {
|
|
67
|
+
return standing.kind === "free" ? "" : standing.planId;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=plan-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-state.js","sourceRoot":"","sources":["../src/billing/plan-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a billing flow leaves the app for a Stripe-hosted page, and where
|
|
3
|
+
* Stripe sends the person back.
|
|
4
|
+
*
|
|
5
|
+
* By default the console navigates its own window to Stripe and Stripe
|
|
6
|
+
* returns to the host's billing page on the same origin: right for a web
|
|
7
|
+
* console. A host whose window cannot host a third-party page, such as a
|
|
8
|
+
* desktop webview whose origin is not a web address Stripe can return to,
|
|
9
|
+
* passes a {@link BillingRedirect}: `openUrl` opens the page elsewhere
|
|
10
|
+
* (the system browser), and `returnUrl` names a real web page for Stripe
|
|
11
|
+
* to return to. The person finishes there; the host's reads refresh when
|
|
12
|
+
* its window regains focus, because the state lives on the server.
|
|
13
|
+
*/
|
|
14
|
+
/** The host's seam for leaving the app to a Stripe-hosted page. */
|
|
15
|
+
export interface BillingRedirect {
|
|
16
|
+
/**
|
|
17
|
+
* Opens a Stripe-hosted page. Absent, the current window navigates to
|
|
18
|
+
* it. Desktop hosts open the system browser.
|
|
19
|
+
*/
|
|
20
|
+
readonly openUrl?: (url: string) => void | Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* The absolute URL of the billing page Stripe returns to, without a
|
|
23
|
+
* query. Absent, the current origin's `/settings/billing`.
|
|
24
|
+
*/
|
|
25
|
+
readonly returnUrl?: string;
|
|
26
|
+
}
|
|
27
|
+
/** The billing page Stripe returns to, per the redirect or the current origin. */
|
|
28
|
+
export declare function billingReturnUrl(redirect: BillingRedirect | undefined): string;
|
|
29
|
+
/** Leaves for a Stripe-hosted page through the redirect, or by navigating this window. */
|
|
30
|
+
export declare function leaveForStripe(url: string, redirect: BillingRedirect | undefined): Promise<void>;
|
|
31
|
+
//# sourceMappingURL=redirect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect.d.ts","sourceRoot":"","sources":["../src/billing/redirect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,CAM9E;AAED,0FAA0F;AAC1F,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a billing flow leaves the app for a Stripe-hosted page, and where
|
|
3
|
+
* Stripe sends the person back.
|
|
4
|
+
*
|
|
5
|
+
* By default the console navigates its own window to Stripe and Stripe
|
|
6
|
+
* returns to the host's billing page on the same origin: right for a web
|
|
7
|
+
* console. A host whose window cannot host a third-party page, such as a
|
|
8
|
+
* desktop webview whose origin is not a web address Stripe can return to,
|
|
9
|
+
* passes a {@link BillingRedirect}: `openUrl` opens the page elsewhere
|
|
10
|
+
* (the system browser), and `returnUrl` names a real web page for Stripe
|
|
11
|
+
* to return to. The person finishes there; the host's reads refresh when
|
|
12
|
+
* its window regains focus, because the state lives on the server.
|
|
13
|
+
*/
|
|
14
|
+
/** The billing page Stripe returns to, per the redirect or the current origin. */
|
|
15
|
+
export function billingReturnUrl(redirect) {
|
|
16
|
+
if (redirect?.returnUrl !== undefined) {
|
|
17
|
+
return redirect.returnUrl;
|
|
18
|
+
}
|
|
19
|
+
const origin = typeof window === "undefined" ? "" : window.location.origin;
|
|
20
|
+
return `${origin}/settings/billing`;
|
|
21
|
+
}
|
|
22
|
+
/** Leaves for a Stripe-hosted page through the redirect, or by navigating this window. */
|
|
23
|
+
export async function leaveForStripe(url, redirect) {
|
|
24
|
+
if (redirect?.openUrl !== undefined) {
|
|
25
|
+
await redirect.openUrl(url);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
window.location.href = url;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=redirect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redirect.js","sourceRoot":"","sources":["../src/billing/redirect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAgBH,kFAAkF;AAClF,MAAM,UAAU,gBAAgB,CAAC,QAAqC;IACpE,IAAI,QAAQ,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,QAAQ,CAAC,SAAS,CAAC;IAC5B,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;IAC3E,OAAO,GAAG,MAAM,mBAAmB,CAAC;AACtC,CAAC;AAED,0FAA0F;AAC1F,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAW,EAAE,QAAqC;IACrF,IAAI,QAAQ,EAAE,OAAO,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IACD,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC;AAC7B,CAAC"}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { BillingAccount } from "@stigmer/protos/ai/stigmer/billing/v1/billing_account_pb";
|
|
2
|
+
/** Options for {@link useBillingAccount}. */
|
|
3
|
+
export interface UseBillingAccountOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Re-read the account when the window regains focus: for a host that
|
|
6
|
+
* sends Stripe's pages to another window (the system browser), so a card
|
|
7
|
+
* saved there shows on return. Default `false`.
|
|
8
|
+
*/
|
|
9
|
+
readonly refetchOnWindowFocus?: boolean;
|
|
10
|
+
}
|
|
2
11
|
/** Return value of {@link useBillingAccount}. */
|
|
3
12
|
export interface UseBillingAccountReturn {
|
|
4
13
|
/** The billing account, or `null` before the first successful fetch. */
|
|
@@ -36,5 +45,5 @@ export interface UseBillingAccountReturn {
|
|
|
36
45
|
* return <div>Balance: {formatCreditBalance(account.balance?.availableMicros)}</div>;
|
|
37
46
|
* ```
|
|
38
47
|
*/
|
|
39
|
-
export declare function useBillingAccount(orgId: string | null): UseBillingAccountReturn;
|
|
48
|
+
export declare function useBillingAccount(orgId: string | null, options?: UseBillingAccountOptions): UseBillingAccountReturn;
|
|
40
49
|
//# sourceMappingURL=useBillingAccount.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBillingAccount.d.ts","sourceRoot":"","sources":["../src/billing/useBillingAccount.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAI/F,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IACxC,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"useBillingAccount.d.ts","sourceRoot":"","sources":["../src/billing/useBillingAccount.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAI/F,6CAA6C;AAC7C,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACzC;AAED,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IACxC,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,OAAO,CAAC,EAAE,wBAAwB,GACjC,uBAAuB,CAczB"}
|
|
@@ -25,11 +25,11 @@ import { useFetch } from "../internal/useFetch.js";
|
|
|
25
25
|
* return <div>Balance: {formatCreditBalance(account.balance?.availableMicros)}</div>;
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
|
-
export function useBillingAccount(orgId) {
|
|
28
|
+
export function useBillingAccount(orgId, options) {
|
|
29
29
|
const stigmer = useStigmer();
|
|
30
30
|
const { data: account, isLoading, isRefetching, error, refetch } = useFetch(orgId
|
|
31
31
|
? () => stigmer.billing.getOrCreateBillingAccount(orgId)
|
|
32
|
-
: null, [orgId, stigmer], null);
|
|
32
|
+
: null, [orgId, stigmer], null, { refetchOnWindowFocus: options?.refetchOnWindowFocus ?? false });
|
|
33
33
|
return { account, isLoading, isRefetching, error, refetch };
|
|
34
34
|
}
|
|
35
35
|
//# sourceMappingURL=useBillingAccount.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBillingAccount.js","sourceRoot":"","sources":["../src/billing/useBillingAccount.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAOb,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"useBillingAccount.js","sourceRoot":"","sources":["../src/billing/useBillingAccount.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAOb,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AA0BnD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAoB,EACpB,OAAkC;IAElC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,QAAQ,CACzE,KAAK;QACH,CAAC,CAAC,GAAG,EAAE,CACH,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,KAAK,CAAC;QACpD,CAAC,CAAC,IAAI,EACR,CAAC,KAAK,EAAE,OAAO,CAAC,EAChB,IAA6B,EAC7B,EAAE,oBAAoB,EAAE,OAAO,EAAE,oBAAoB,IAAI,KAAK,EAAE,CACjE,CAAC;IAEF,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Subscription } from "@stigmer/protos/ai/stigmer/billing/subscription/v1/api_pb";
|
|
2
|
+
/** Return value of {@link useChangePlan}. */
|
|
3
|
+
export interface UseChangePlanReturn {
|
|
4
|
+
/**
|
|
5
|
+
* Move the organization onto a plan: subscribe (from Free), switch, or
|
|
6
|
+
* resume a canceled plan by choosing it again. A switch takes effect
|
|
7
|
+
* now: the current period closes early, billed for the time it ran, and
|
|
8
|
+
* a new monthly period opens on the new plan. Nothing is charged at the
|
|
9
|
+
* moment of the change; every period is collected when it closes.
|
|
10
|
+
*
|
|
11
|
+
* Refused with the `PAYMENT_METHOD_REQUIRED` reason when the
|
|
12
|
+
* organization has no saved card (see
|
|
13
|
+
* {@link useCreatePaymentMethodSetupSession}). Resolves with the
|
|
14
|
+
* subscription as it stands after the change.
|
|
15
|
+
*/
|
|
16
|
+
readonly changePlan: (orgId: string, planId: string) => Promise<Subscription>;
|
|
17
|
+
/** `true` while a change is in flight. */
|
|
18
|
+
readonly isSubmitting: boolean;
|
|
19
|
+
/** Error from the last failed attempt, or `null` when healthy. */
|
|
20
|
+
readonly error: Error | null;
|
|
21
|
+
/** Reset `error` to `null`. */
|
|
22
|
+
readonly clearError: () => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Behaviour hook that moves an organization onto a plan.
|
|
26
|
+
*
|
|
27
|
+
* The caller needs `can_manage_billing` on the organization (its admins).
|
|
28
|
+
* Refetch the subscription, entitlements and estimate after a change.
|
|
29
|
+
*/
|
|
30
|
+
export declare function useChangePlan(): UseChangePlanReturn;
|
|
31
|
+
/** Return value of {@link useCancelSubscription}. */
|
|
32
|
+
export interface UseCancelSubscriptionReturn {
|
|
33
|
+
/**
|
|
34
|
+
* Cancel the organization's subscription. It keeps its plan to the end
|
|
35
|
+
* of the current period and is on Free after it; nothing it built is
|
|
36
|
+
* deleted. Choosing the same plan again before then resumes it.
|
|
37
|
+
*/
|
|
38
|
+
readonly cancel: (orgId: string) => Promise<Subscription>;
|
|
39
|
+
/** `true` while a cancel is in flight. */
|
|
40
|
+
readonly isSubmitting: boolean;
|
|
41
|
+
/** Error from the last failed attempt, or `null` when healthy. */
|
|
42
|
+
readonly error: Error | null;
|
|
43
|
+
/** Reset `error` to `null`. */
|
|
44
|
+
readonly clearError: () => void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Behaviour hook that cancels an organization's subscription at the end
|
|
48
|
+
* of its period. The caller needs `can_manage_billing` on the organization.
|
|
49
|
+
*/
|
|
50
|
+
export declare function useCancelSubscription(): UseCancelSubscriptionReturn;
|
|
51
|
+
//# sourceMappingURL=useChangePlan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useChangePlan.d.ts","sourceRoot":"","sources":["../src/billing/useChangePlan.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2DAA2D,CAAC;AAQ9F,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9E,0CAA0C;IAC1C,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,mBAAmB,CA2BnD;AAED,qDAAqD;AACrD,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1D,0CAA0C;IAC1C,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC;CACjC;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,2BAA2B,CAwBnE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useMemo, useState } from "react";
|
|
3
|
+
import { create } from "@bufbuild/protobuf";
|
|
4
|
+
import { CancelSubscriptionInputSchema, ChangePlanInputSchema, } from "@stigmer/protos/ai/stigmer/billing/subscription/v1/io_pb";
|
|
5
|
+
import { useStigmer } from "../hooks.js";
|
|
6
|
+
import { toError } from "../internal/toError.js";
|
|
7
|
+
/**
|
|
8
|
+
* Behaviour hook that moves an organization onto a plan.
|
|
9
|
+
*
|
|
10
|
+
* The caller needs `can_manage_billing` on the organization (its admins).
|
|
11
|
+
* Refetch the subscription, entitlements and estimate after a change.
|
|
12
|
+
*/
|
|
13
|
+
export function useChangePlan() {
|
|
14
|
+
const stigmer = useStigmer();
|
|
15
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
16
|
+
const [error, setError] = useState(null);
|
|
17
|
+
const changePlan = useCallback(async (orgId, planId) => {
|
|
18
|
+
setIsSubmitting(true);
|
|
19
|
+
setError(null);
|
|
20
|
+
try {
|
|
21
|
+
return await stigmer.subscription.changePlan(create(ChangePlanInputSchema, { orgId, planId }));
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
const err = toError(e);
|
|
25
|
+
setError(err);
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
setIsSubmitting(false);
|
|
30
|
+
}
|
|
31
|
+
}, [stigmer.subscription]);
|
|
32
|
+
const clearError = useCallback(() => setError(null), []);
|
|
33
|
+
return useMemo(() => ({ changePlan, isSubmitting, error, clearError }), [changePlan, isSubmitting, error, clearError]);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Behaviour hook that cancels an organization's subscription at the end
|
|
37
|
+
* of its period. The caller needs `can_manage_billing` on the organization.
|
|
38
|
+
*/
|
|
39
|
+
export function useCancelSubscription() {
|
|
40
|
+
const stigmer = useStigmer();
|
|
41
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
42
|
+
const [error, setError] = useState(null);
|
|
43
|
+
const cancel = useCallback(async (orgId) => {
|
|
44
|
+
setIsSubmitting(true);
|
|
45
|
+
setError(null);
|
|
46
|
+
try {
|
|
47
|
+
return await stigmer.subscription.cancel(create(CancelSubscriptionInputSchema, { orgId }));
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
const err = toError(e);
|
|
51
|
+
setError(err);
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
setIsSubmitting(false);
|
|
56
|
+
}
|
|
57
|
+
}, [stigmer.subscription]);
|
|
58
|
+
const clearError = useCallback(() => setError(null), []);
|
|
59
|
+
return useMemo(() => ({ cancel, isSubmitting, error, clearError }), [cancel, isSubmitting, error, clearError]);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=useChangePlan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useChangePlan.js","sourceRoot":"","sources":["../src/billing/useChangePlan.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import { type BillingRedirect } from "./redirect.js";
|
|
1
2
|
/** Return value of {@link useCreateBillingPortalSession}. */
|
|
2
3
|
export interface UseCreateBillingPortalSessionReturn {
|
|
3
4
|
/**
|
|
4
5
|
* Open the Stripe Customer Portal for payment method management.
|
|
5
6
|
*
|
|
6
|
-
* On success,
|
|
7
|
-
*
|
|
7
|
+
* On success, leaves for the Stripe-hosted portal page: through
|
|
8
|
+
* `redirect.openUrl` when given, else by navigating this window. The
|
|
9
|
+
* portal returns to `redirect.returnUrl` when given, else to the page
|
|
10
|
+
* the person is on.
|
|
8
11
|
*/
|
|
9
12
|
readonly openPortal: (orgId: string) => Promise<void>;
|
|
10
13
|
/** `true` while the portal session is being created. */
|
|
@@ -31,5 +34,5 @@ export interface UseCreateBillingPortalSessionReturn {
|
|
|
31
34
|
* </button>
|
|
32
35
|
* ```
|
|
33
36
|
*/
|
|
34
|
-
export declare function useCreateBillingPortalSession(): UseCreateBillingPortalSessionReturn;
|
|
37
|
+
export declare function useCreateBillingPortalSession(redirect?: BillingRedirect): UseCreateBillingPortalSessionReturn;
|
|
35
38
|
//# sourceMappingURL=useCreateBillingPortalSession.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCreateBillingPortalSession.d.ts","sourceRoot":"","sources":["../src/billing/useCreateBillingPortalSession.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useCreateBillingPortalSession.d.ts","sourceRoot":"","sources":["../src/billing/useCreateBillingPortalSession.ts"],"names":[],"mappings":"AAKA,OAAO,EAAoC,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAEvF,6DAA6D;AAC7D,MAAM,WAAW,mCAAmC;IAClD;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,wDAAwD;IACxD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,CAAC,EAAE,eAAe,GACzB,mCAAmC,CAyCrC"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { useCallback, useState } from "react";
|
|
3
3
|
import { useStigmer } from "../hooks.js";
|
|
4
4
|
import { toError } from "../internal/toError.js";
|
|
5
|
+
import { billingReturnUrl, leaveForStripe } from "./redirect.js";
|
|
5
6
|
/**
|
|
6
7
|
* Behavior hook that opens the Stripe Customer Portal for payment
|
|
7
8
|
* method management.
|
|
@@ -19,8 +20,10 @@ import { toError } from "../internal/toError.js";
|
|
|
19
20
|
* </button>
|
|
20
21
|
* ```
|
|
21
22
|
*/
|
|
22
|
-
export function useCreateBillingPortalSession() {
|
|
23
|
+
export function useCreateBillingPortalSession(redirect) {
|
|
23
24
|
const stigmer = useStigmer();
|
|
25
|
+
const openUrl = redirect?.openUrl;
|
|
26
|
+
const pinnedReturnUrl = redirect?.returnUrl;
|
|
24
27
|
const [isLoading, setIsLoading] = useState(false);
|
|
25
28
|
const [error, setError] = useState(null);
|
|
26
29
|
const clearError = useCallback(() => setError(null), []);
|
|
@@ -28,13 +31,17 @@ export function useCreateBillingPortalSession() {
|
|
|
28
31
|
setIsLoading(true);
|
|
29
32
|
setError(null);
|
|
30
33
|
try {
|
|
31
|
-
const returnUrl =
|
|
34
|
+
const returnUrl = pinnedReturnUrl !== undefined
|
|
35
|
+
? billingReturnUrl({ returnUrl: pinnedReturnUrl })
|
|
36
|
+
: typeof window !== "undefined"
|
|
37
|
+
? window.location.href
|
|
38
|
+
: "";
|
|
32
39
|
const response = await stigmer.billing.createBillingPortalSession({
|
|
33
40
|
orgId,
|
|
34
41
|
returnUrl,
|
|
35
42
|
});
|
|
36
43
|
if (response.portalUrl) {
|
|
37
|
-
|
|
44
|
+
await leaveForStripe(response.portalUrl, { openUrl });
|
|
38
45
|
}
|
|
39
46
|
}
|
|
40
47
|
catch (err) {
|
|
@@ -44,7 +51,7 @@ export function useCreateBillingPortalSession() {
|
|
|
44
51
|
finally {
|
|
45
52
|
setIsLoading(false);
|
|
46
53
|
}
|
|
47
|
-
}, [stigmer]);
|
|
54
|
+
}, [stigmer, openUrl, pinnedReturnUrl]);
|
|
48
55
|
return { openPortal, isLoading, error, clearError };
|
|
49
56
|
}
|
|
50
57
|
//# sourceMappingURL=useCreateBillingPortalSession.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCreateBillingPortalSession.js","sourceRoot":"","sources":["../src/billing/useCreateBillingPortalSession.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"useCreateBillingPortalSession.js","sourceRoot":"","sources":["../src/billing/useCreateBillingPortalSession.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAwB,MAAM,eAAe,CAAC;AAqBvF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,6BAA6B,CAC3C,QAA0B;IAE1B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,QAAQ,EAAE,OAAO,CAAC;IAClC,MAAM,eAAe,GAAG,QAAQ,EAAE,SAAS,CAAC;IAC5C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IAEzD,MAAM,UAAU,GAAG,WAAW,CAC5B,KAAK,EAAE,KAAa,EAAiB,EAAE;QACrC,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,IAAI,CAAC;YACH,MAAM,SAAS,GACb,eAAe,KAAK,SAAS;gBAC3B,CAAC,CAAC,gBAAgB,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;gBAClD,CAAC,CAAC,OAAO,MAAM,KAAK,WAAW;oBAC7B,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI;oBACtB,CAAC,CAAC,EAAE,CAAC;YAEX,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,0BAA0B,CAAC;gBAChE,KAAK;gBACL,SAAS;aACV,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;gBACvB,MAAM,cAAc,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YACvB,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EACD,CAAC,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,CACpC,CAAC;IAEF,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AACtD,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { CreateCreditCheckoutSessionResponse } from "@stigmer/protos/ai/stigmer/billing/v1/io_pb";
|
|
2
|
+
import { type BillingRedirect } from "./redirect.js";
|
|
2
3
|
/** Parameters for {@link useCreateCheckoutSession}'s `createSession` callback. */
|
|
3
4
|
export interface CreateCheckoutSessionInput {
|
|
4
5
|
/** Organization purchasing credits. */
|
|
5
6
|
readonly orgId: string;
|
|
6
|
-
/** Credit pack to purchase
|
|
7
|
+
/** Credit pack to purchase: its id, e.g. "starter", "growth" or "team" (the pack named Scale). */
|
|
7
8
|
readonly packId: string;
|
|
8
9
|
/** URL to redirect to after successful payment. */
|
|
9
10
|
readonly successUrl: string;
|
|
@@ -15,9 +16,10 @@ export interface UseCreateCheckoutSessionReturn {
|
|
|
15
16
|
/**
|
|
16
17
|
* Create a Stripe Checkout Session and redirect the user.
|
|
17
18
|
*
|
|
18
|
-
* On success,
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* On success, leaves for the Stripe-hosted checkout page: through the
|
|
20
|
+
* hook's `redirect.openUrl` when given, else by navigating this window.
|
|
21
|
+
* The promise resolves with the response before the redirect occurs,
|
|
22
|
+
* allowing callers to perform cleanup if needed.
|
|
21
23
|
*/
|
|
22
24
|
readonly createSession: (input: CreateCheckoutSessionInput) => Promise<CreateCreditCheckoutSessionResponse>;
|
|
23
25
|
/** `true` while the checkout session is being created. */
|
|
@@ -50,5 +52,5 @@ export interface UseCreateCheckoutSessionReturn {
|
|
|
50
52
|
* };
|
|
51
53
|
* ```
|
|
52
54
|
*/
|
|
53
|
-
export declare function useCreateCheckoutSession(): UseCreateCheckoutSessionReturn;
|
|
55
|
+
export declare function useCreateCheckoutSession(redirect?: BillingRedirect): UseCreateCheckoutSessionReturn;
|
|
54
56
|
//# sourceMappingURL=useCreateCheckoutSession.d.ts.map
|