@voltro/plugin-billing 0.83.1 → 0.85.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/dist/index.d.ts CHANGED
@@ -16,6 +16,7 @@ import { Subject } from '@voltro/protocol';
16
16
  import { TableIndex } from '@voltro/database';
17
17
  import { TableLike } from '@voltro/database';
18
18
  import { VoltroPlugin } from '@voltro/protocol';
19
+ import { YieldableError } from 'effect/Cause';
19
20
 
20
21
  export declare const assertBillingProductionReady: (input: {
21
22
  readonly env: NodeJS.ProcessEnv;
@@ -93,15 +94,13 @@ export declare const billingEgressOf: (provider: Pick<BillingProvider, "name">)
93
94
  export declare class BillingError extends BillingError_base {
94
95
  }
95
96
 
96
- declare const BillingError_base: Schema.TaggedErrorClass<BillingError, "BillingError", {
97
- readonly _tag: Schema.tag<"BillingError">;
98
- } & {
97
+ declare const BillingError_base: Schema.Class<BillingError, Schema.TaggedStruct<"BillingError", {
99
98
  /** Where the failure originated — provider name or an internal stage. */
100
- source: typeof Schema.String;
101
- message: typeof Schema.String;
99
+ readonly source: Schema.String;
100
+ readonly message: Schema.String;
102
101
  /** Retryable? The service retries `transient` failures on a Schedule. */
103
- transient: typeof Schema.Boolean;
104
- }>;
102
+ readonly transient: Schema.Boolean;
103
+ }>, YieldableError>;
105
104
 
106
105
  /**
107
106
  * The normalized event union a `BillingProvider.normalizeEvent` produces
@@ -420,7 +419,7 @@ export declare type BillingProviderName = 'stripe' | 'mock';
420
419
  export declare class BillingService extends BillingService_base {
421
420
  }
422
421
 
423
- declare const BillingService_base: Context.TagClass<BillingService, "@voltro/plugin-billing/BillingService", BillingServiceShape>;
422
+ declare const BillingService_base: Context.ServiceClass<BillingService, "@voltro/plugin-billing/BillingService", BillingServiceShape>;
424
423
 
425
424
  /** Wrap a built service in a `Layer` for the plugin's `services` field. */
426
425
  export declare const billingServiceLayer: (service: BillingServiceShape) => Layer.Layer<BillingService, never, never>;
@@ -1012,18 +1011,16 @@ export declare interface EntitlementDecision {
1012
1011
  export declare class EntitlementExceeded extends EntitlementExceeded_base {
1013
1012
  }
1014
1013
 
1015
- declare const EntitlementExceeded_base: Schema.TaggedErrorClass<EntitlementExceeded, "EntitlementExceeded", {
1016
- readonly _tag: Schema.tag<"EntitlementExceeded">;
1017
- } & {
1014
+ declare const EntitlementExceeded_base: Schema.Class<EntitlementExceeded, Schema.TaggedStruct<"EntitlementExceeded", {
1018
1015
  /** The entitlement key that was exhausted (`'aiCalls'`). */
1019
- entitlement: typeof Schema.String;
1016
+ readonly entitlement: Schema.String;
1020
1017
  /** The static limit for the caller's plan. */
1021
- limit: typeof Schema.Number;
1018
+ readonly limit: Schema.Number;
1022
1019
  /** How much was already used in the current window. */
1023
- used: typeof Schema.Number;
1020
+ readonly used: Schema.Number;
1024
1021
  /** The cost the rejected call would have charged. */
1025
- cost: typeof Schema.Number;
1026
- }>;
1022
+ readonly cost: Schema.Number;
1023
+ }>, YieldableError>;
1027
1024
 
1028
1025
  /** An entitlement limit: a finite quota or the unbounded `'unlimited'`. */
1029
1026
  export declare type EntitlementLimit = number | 'unlimited';
@@ -1839,17 +1836,15 @@ declare interface SubscriptionChangeResult {
1839
1836
  export declare class SubscriptionLocked extends SubscriptionLocked_base {
1840
1837
  }
1841
1838
 
1842
- declare const SubscriptionLocked_base: Schema.TaggedErrorClass<SubscriptionLocked, "SubscriptionLocked", {
1843
- readonly _tag: Schema.tag<"SubscriptionLocked">;
1844
- } & {
1845
- tenantId: typeof Schema.String;
1839
+ declare const SubscriptionLocked_base: Schema.Class<SubscriptionLocked, Schema.TaggedStruct<"SubscriptionLocked", {
1840
+ readonly tenantId: Schema.String;
1846
1841
  /** The subscription status at the time of the refusal (`'pastDue'`). */
1847
- status: typeof Schema.String;
1842
+ readonly status: Schema.String;
1848
1843
  /** ISO timestamp at which the grace period expired. */
1849
- lockedSince: typeof Schema.String;
1844
+ readonly lockedSince: Schema.String;
1850
1845
  /** `'hard'` (limits fell to the free plan) or `'soft'` (report only). */
1851
- lockout: typeof Schema.String;
1852
- }>;
1846
+ readonly lockout: Schema.String;
1847
+ }>, YieldableError>;
1853
1848
 
1854
1849
  /** Fields a mid-cycle / reconcile patch may set on the tenant's row. */
1855
1850
  export declare interface SubscriptionPatch {
package/dist/index.js CHANGED
@@ -863,9 +863,9 @@ var fe = (e, t, n, r) => ({
863
863
  return t === null ? null : yield* n.customerEmail(t.providerCustomerId);
864
864
  }), E = (e) => {
865
865
  let t = f.portalReturnUrl;
866
- return t === void 0 ? v.succeed(null) : w(e, t).pipe(v.map((e) => e.url), v.catchAll(() => v.succeed(null)));
866
+ return t === void 0 ? v.succeed(null) : w(e, t).pipe(v.map((e) => e.url), v.catch(() => v.succeed(null)));
867
867
  }, te = (e, t, n, r, i) => v.gen(function* () {
868
- let a = yield* T(e.tenantId).pipe(v.catchAll(() => v.succeed(null))), o = yield* E(e.tenantId), s = t.lockedSince !== null, c = Ie({
868
+ let a = yield* T(e.tenantId).pipe(v.catch(() => v.succeed(null))), o = yield* E(e.tenantId), s = t.lockedSince !== null, c = Ie({
869
869
  stepId: n,
870
870
  locked: s,
871
871
  graceEndsAt: i,
@@ -891,7 +891,7 @@ var fe = (e, t, n, r) => ({
891
891
  delivered: f.notify !== void 0 && a !== null
892
892
  });
893
893
  let u = f.notify;
894
- u !== void 0 && (yield* u(l).pipe(v.catchAllCause((t) => v.sync(() => {
894
+ u !== void 0 && (yield* u(l).pipe(v.catchCause((t) => v.sync(() => {
895
895
  J.warn("billing dunning notify failed", {
896
896
  tenant: e.tenantId,
897
897
  step: n,
@@ -901,7 +901,7 @@ var fe = (e, t, n, r) => ({
901
901
  }), D = (e) => v.gen(function* () {
902
902
  let t = yield* d.stores.subscriptions.getByTenant(e);
903
903
  if (t === null) return Pe(null, f, s(), e);
904
- let r = yield* n.fetchSubscription(t.providerSubscriptionId).pipe(v.catchAll((t) => v.sync(() => (J.warn("billing dunning reconcile: provider unreachable, not escalating", {
904
+ let r = yield* n.fetchSubscription(t.providerSubscriptionId).pipe(v.catch((t) => v.sync(() => (J.warn("billing dunning reconcile: provider unreachable, not escalating", {
905
905
  tenant: e,
906
906
  source: t.source,
907
907
  message: t.message
@@ -935,7 +935,7 @@ var fe = (e, t, n, r) => ({
935
935
  return a;
936
936
  }), O = () => v.gen(function* () {
937
937
  let e = yield* d.stores.subscriptions.listByStatus("pastDue"), t = 0;
938
- for (let n of e) yield* D(n.tenantId).pipe(v.catchAll((e) => v.sync(() => {
938
+ for (let n of e) yield* D(n.tenantId).pipe(v.catch((e) => v.sync(() => {
939
939
  J.warn("billing dunning sweep: tenant failed", {
940
940
  tenant: n.tenantId,
941
941
  message: e.message
@@ -989,7 +989,7 @@ var fe = (e, t, n, r) => ({
989
989
  });
990
990
  case "customerUnlinked": return d.stores.customers.removeByProviderCustomerId(e.providerCustomerId).pipe(v.asVoid);
991
991
  }
992
- }, A = (e) => k(e).pipe(v.zipRight(ne(e))), re = (t, r) => v.gen(function* () {
992
+ }, A = (e) => k(e).pipe(v.andThen(ne(e))), re = (t, r) => v.gen(function* () {
993
993
  yield* c(t, "change"), yield* R(t);
994
994
  let o = yield* d.stores.subscriptions.getByTenant(t);
995
995
  if (o === null) return yield* v.fail(new e({
@@ -1118,7 +1118,7 @@ var fe = (e, t, n, r) => ({
1118
1118
  };
1119
1119
  }), I = (e) => {
1120
1120
  let n = t.isTenantClosed;
1121
- return n === void 0 ? v.succeed(!1) : n(e).pipe(v.catchAll((t) => v.sync(() => (J.warn("billing: could not tell whether a tenant is closed — leaving it", {
1121
+ return n === void 0 ? v.succeed(!1) : n(e).pipe(v.catch((t) => v.sync(() => (J.warn("billing: could not tell whether a tenant is closed — leaving it", {
1122
1122
  tenant: e,
1123
1123
  message: t.message
1124
1124
  }), !1))));
@@ -1166,7 +1166,7 @@ var fe = (e, t, n, r) => ({
1166
1166
  };
1167
1167
  }), se = (e) => v.forEach(e, (e) => {
1168
1168
  let n = t.onEvent?.[e._tag];
1169
- return n === void 0 ? v.void : n(e).pipe(v.catchAllCause((t) => v.sync(() => {
1169
+ return n === void 0 ? v.void : n(e).pipe(v.catchCause((t) => v.sync(() => {
1170
1170
  J.error("billing: onEvent failed for a correction — the next sync of this tenant retries it", {
1171
1171
  event: e._tag,
1172
1172
  cause: String(t)
@@ -1235,7 +1235,7 @@ var fe = (e, t, n, r) => ({
1235
1235
  J.error("billing reconcile: a closed tenant still has a paying subscription — closing it", {
1236
1236
  tenant: t,
1237
1237
  subscription: r.providerSubscriptionId
1238
- }), (yield* F(t).pipe(v.map(() => !0), v.catchAll((e) => v.sync(() => (J.error("billing reconcile: closing a closed tenant failed — retried next run", {
1238
+ }), (yield* F(t).pipe(v.map(() => !0), v.catch((e) => v.sync(() => (J.error("billing reconcile: closing a closed tenant failed — retried next run", {
1239
1239
  tenant: t,
1240
1240
  message: e.message
1241
1241
  }), !1))))) && p.add(t), c.add(t);
@@ -1335,7 +1335,7 @@ var fe = (e, t, n, r) => ({
1335
1335
  if (!e.global && !e.sticky) return e;
1336
1336
  let t = St.get(e);
1337
1337
  return t === void 0 && (t = new RegExp(e.source, e.flags.replace(/[gy]/g, "")), St.set(e, t)), t;
1338
- }, wt = (e, t) => typeof e == "string" ? t === e : Ct(e).test(t), Tt = (e, t, n) => Object.entries(e).filter(([, e]) => e.from === "rpc" && (e.kind === void 0 || e.kind === n) && wt(e.match, t)).map(([e]) => e), Et = (e, t, n) => Object.entries(e).filter(([, e]) => e.from === "cdc" && e.table === t && (e.op ?? "insert") === n).map(([e]) => e), Dt = (e) => Object.entries(e).filter(([, e]) => e.from === "ai").map(([e, t]) => [e, t.metric ?? "tokens"]), Ot = (e) => e.tenantId, kt = (e, t, n, r) => v.forEach(n, (n) => e.reportUsage(t, n, r).pipe(v.catchAll(() => v.void)), { discard: !0 }), At = (e, t) => (n, r) => {
1338
+ }, wt = (e, t) => typeof e == "string" ? t === e : Ct(e).test(t), Tt = (e, t, n) => Object.entries(e).filter(([, e]) => e.from === "rpc" && (e.kind === void 0 || e.kind === n) && wt(e.match, t)).map(([e]) => e), Et = (e, t, n) => Object.entries(e).filter(([, e]) => e.from === "cdc" && e.table === t && (e.op ?? "insert") === n).map(([e]) => e), Dt = (e) => Object.entries(e).filter(([, e]) => e.from === "ai").map(([e, t]) => [e, t.metric ?? "tokens"]), Ot = (e) => e.tenantId, kt = (e, t, n, r) => v.forEach(n, (n) => e.reportUsage(t, n, r).pipe(v.catch(() => v.void)), { discard: !0 }), At = (e, t) => (n, r) => {
1339
1339
  let i = Tt(t, r.tag, r.kind);
1340
1340
  if (i.length === 0) return n;
1341
1341
  let a = Ot(r.subject);
@@ -1386,10 +1386,10 @@ var fe = (e, t, n, r) => ({
1386
1386
  for (let [t, n] of i) for (let [r, i] of c) {
1387
1387
  let a = n === "costMicroUsd" ? i.cost : i.tokens;
1388
1388
  if (a <= 0) continue;
1389
- let o = a - (yield* e.checkEntitlement(r, t, 0).pipe(v.map((e) => e.used), v.catchAll(() => v.succeed(0))));
1390
- o > 0 && (yield* e.reportUsage(r, t, o).pipe(v.catchAll(() => v.void)));
1389
+ let o = a - (yield* e.checkEntitlement(r, t, 0).pipe(v.map((e) => e.used), v.catch(() => v.succeed(0))));
1390
+ o > 0 && (yield* e.reportUsage(r, t, o).pipe(v.catch(() => v.void)));
1391
1391
  }
1392
- }), It = (e, t, n, r) => Ft(e, t, n, r).pipe(v.andThen(e.flushUsage().pipe(v.catchAll(() => v.void)))), Lt = (e) => Object.values(e).some((e) => e.from === "cdc"), Rt = (e) => e === void 0 ? 0 : e === "unlimited" ? Infinity : e, zt = (e) => {
1392
+ }), It = (e, t, n, r) => Ft(e, t, n, r).pipe(v.andThen(e.flushUsage().pipe(v.catch(() => v.void)))), Lt = (e) => Object.values(e).some((e) => e.from === "cdc"), Rt = (e) => e === void 0 ? 0 : e === "unlimited" ? Infinity : e, zt = (e) => {
1393
1393
  let t = /* @__PURE__ */ new Map();
1394
1394
  for (let [n, r] of Object.entries(e)) r.priceId !== void 0 && t.set(r.priceId, n);
1395
1395
  return {
@@ -2483,7 +2483,7 @@ var fe = (e, t, n, r) => ({
2483
2483
  i.createdAt !== null && Date.now() - i.createdAt.getTime() > 3e5 && e.onLateDelivery?.();
2484
2484
  for (let t of s) {
2485
2485
  let n = e.onEvent?.[t._tag];
2486
- n !== void 0 && await v.runPromise(n(t).pipe(v.tapErrorCause((e) => v.sync(() => {
2486
+ n !== void 0 && await v.runPromise(n(t).pipe(v.tapCause((e) => v.sync(() => {
2487
2487
  Hn.error("billing onEvent side effect failed — answering 500 so the provider redelivers", {
2488
2488
  event: t._tag,
2489
2489
  cause: String(e)
@@ -2868,7 +2868,7 @@ var fe = (e, t, n, r) => ({
2868
2868
  handler: () => E.stores.usage.pending().pipe(v.map((e) => ({
2869
2869
  kind: "json",
2870
2870
  data: { usage: e }
2871
- })), v.catchAll((e) => v.succeed(A(500, `${e.source} failed`))))
2871
+ })), v.catch((e) => v.succeed(A(500, `${e.source} failed`))))
2872
2872
  }], j = [
2873
2873
  {
2874
2874
  schema: e,
@@ -2915,7 +2915,7 @@ var fe = (e, t, n, r) => ({
2915
2915
  let o = 0;
2916
2916
  for (let e of a) await v.runPromise(T.syncCustomer(e).pipe(v.flatMap((e) => v.forEach(e.events, (e) => {
2917
2917
  let n = t.onEvent?.[e._tag];
2918
- return n === void 0 ? v.void : n(e).pipe(v.catchAllCause((t) => v.sync(() => {
2918
+ return n === void 0 ? v.void : n(e).pipe(v.catchCause((t) => v.sync(() => {
2919
2919
  V.error("billing catch-up: onEvent failed for a correction", {
2920
2920
  event: e._tag,
2921
2921
  cause: String(t)
@@ -2923,7 +2923,7 @@ var fe = (e, t, n, r) => ({
2923
2923
  })));
2924
2924
  }, { discard: !0 })), v.tap(() => v.sync(() => {
2925
2925
  o += 1;
2926
- })), v.catchAll((e) => v.sync(() => {
2926
+ })), v.catch((e) => v.sync(() => {
2927
2927
  V.error("billing catch-up: syncing a customer failed — the provider redelivers its events", { message: e.message });
2928
2928
  }))));
2929
2929
  V.info("billing catch-up", {
@@ -3001,7 +3001,7 @@ var fe = (e, t, n, r) => ({
3001
3001
  if (t === void 0) return;
3002
3002
  let a = Date.now();
3003
3003
  (async () => {
3004
- await Wt(t, Ut(a, n), e, a) && await v.runPromise((i ? It(T, t, r) : T.flushUsage()).pipe(v.catchAll(() => v.void)));
3004
+ await Wt(t, Ut(a, n), e, a) && await v.runPromise((i ? It(T, t, r) : T.flushUsage()).pipe(v.catch(() => v.void)));
3005
3005
  })();
3006
3006
  }, n), B.unref?.();
3007
3007
  }
package/dist/rpc.d.ts CHANGED
@@ -2,6 +2,7 @@ import { ActionProcedureDescriptor } from '@voltro/protocol';
2
2
  import { PluginRpcClientDescriptor } from '@voltro/protocol';
3
3
  import { QueryProcedureDescriptor } from '@voltro/protocol';
4
4
  import { Schema } from 'effect';
5
+ import { YieldableError } from 'effect/Cause';
5
6
 
6
7
  /**
7
8
  * A billing failure. `transient: true` marks failures the service retries
@@ -13,15 +14,13 @@ import { Schema } from 'effect';
13
14
  declare class BillingError extends BillingError_base {
14
15
  }
15
16
 
16
- declare const BillingError_base: Schema.TaggedErrorClass<BillingError, "BillingError", {
17
- readonly _tag: Schema.tag<"BillingError">;
18
- } & {
17
+ declare const BillingError_base: Schema.Class<BillingError, Schema.TaggedStruct<"BillingError", {
19
18
  /** Where the failure originated — provider name or an internal stage. */
20
- source: typeof Schema.String;
21
- message: typeof Schema.String;
19
+ readonly source: Schema.String;
20
+ readonly message: Schema.String;
22
21
  /** Retryable? The service retries `transient` failures on a Schedule. */
23
- transient: typeof Schema.Boolean;
24
- }>;
22
+ readonly transient: Schema.Boolean;
23
+ }>, YieldableError>;
25
24
 
26
25
  /** Declared for the codegen (`VoltroPlugin.rpcClientDescriptors`) so each tag is
27
26
  * emitted into the generated client group. Kept in lockstep with the exports. */
@@ -30,33 +29,33 @@ export declare const billingRpcClientImports: ReadonlyArray<PluginRpcClientDescr
30
29
  /** The customer's own cancellation: active until the paid period ends, then
31
30
  * ended. `cancelAt` on the answer is when. */
32
31
  export declare const cancelSubscriptionDescriptor: ActionProcedureDescriptor<"billing.cancel", Schema.Struct<{}>, Schema.Struct<{
33
- subscription: Schema.Struct<{
34
- plan: typeof Schema.String;
35
- status: typeof Schema.String;
36
- quantity: typeof Schema.Number;
37
- currentPeriodEnd: Schema.NullOr<typeof Schema.String>;
38
- cancelAt: Schema.NullOr<typeof Schema.String>;
32
+ readonly subscription: Schema.Struct<{
33
+ readonly plan: Schema.String;
34
+ readonly status: Schema.String;
35
+ readonly quantity: Schema.Number;
36
+ readonly currentPeriodEnd: Schema.NullOr<Schema.String>;
37
+ readonly cancelAt: Schema.NullOr<Schema.String>;
39
38
  }>;
40
39
  }>, typeof BillingError>;
41
40
 
42
41
  export declare const changePlanDescriptor: ActionProcedureDescriptor<"billing.changePlan", Schema.Struct<{
43
- plan: typeof Schema.String;
42
+ readonly plan: Schema.String;
44
43
  }>, Schema.Struct<{
45
- plan: typeof Schema.String;
46
- quantity: typeof Schema.Number;
44
+ readonly plan: Schema.String;
45
+ readonly quantity: Schema.Number;
47
46
  /** Integer minor-unit settlement: > 0 charge, < 0 credit, 0 at boundary. */
48
- prorationMinor: typeof Schema.Number;
49
- currency: typeof Schema.String;
47
+ readonly prorationMinor: Schema.Number;
48
+ readonly currency: Schema.String;
50
49
  }>, typeof BillingError>;
51
50
 
52
51
  export declare const changeSeatsDescriptor: ActionProcedureDescriptor<"billing.changeSeats", Schema.Struct<{
53
- quantity: typeof Schema.Number;
52
+ readonly quantity: Schema.Number;
54
53
  }>, Schema.Struct<{
55
- plan: typeof Schema.String;
56
- quantity: typeof Schema.Number;
54
+ readonly plan: Schema.String;
55
+ readonly quantity: Schema.Number;
57
56
  /** Integer minor-unit settlement: > 0 charge, < 0 credit, 0 at boundary. */
58
- prorationMinor: typeof Schema.Number;
59
- currency: typeof Schema.String;
57
+ readonly prorationMinor: Schema.Number;
58
+ readonly currency: Schema.String;
60
59
  }>, typeof BillingError>;
61
60
 
62
61
  /**
@@ -67,85 +66,85 @@ export declare const changeSeatsDescriptor: ActionProcedureDescriptor<"billing.c
67
66
  * would fail encode at the boundary).
68
67
  */
69
68
  export declare const entitlementStatusDescriptor: QueryProcedureDescriptor<"billing.entitlementStatus", Schema.Struct<{}>, Schema.Struct<{
70
- plan: typeof Schema.String;
71
- billedPlan: typeof Schema.String;
72
- status: typeof Schema.String;
73
- entitled: typeof Schema.Boolean;
74
- inGrace: typeof Schema.Boolean;
75
- graceEndsAt: Schema.NullOr<typeof Schema.String>;
76
- lockedSince: Schema.NullOr<typeof Schema.String>;
77
- lockout: typeof Schema.String;
69
+ readonly plan: Schema.String;
70
+ readonly billedPlan: Schema.String;
71
+ readonly status: Schema.String;
72
+ readonly entitled: Schema.Boolean;
73
+ readonly inGrace: Schema.Boolean;
74
+ readonly graceEndsAt: Schema.NullOr<Schema.String>;
75
+ readonly lockedSince: Schema.NullOr<Schema.String>;
76
+ readonly lockout: Schema.String;
78
77
  }>, typeof BillingError>;
79
78
 
80
79
  /** The provider's invoice history. `hostedUrl` / `pdfUrl` are the provider's
81
80
  * own pages — we never render an invoice ourselves. */
82
81
  export declare const invoicesDescriptor: QueryProcedureDescriptor<"billing.invoices", Schema.Struct<{}>, Schema.Struct<{
83
- invoices: Schema.Array$<Schema.Struct<{
84
- providerInvoiceId: typeof Schema.String;
85
- amountMinor: typeof Schema.Number;
86
- currency: typeof Schema.String;
87
- status: typeof Schema.String;
88
- createdAt: Schema.NullOr<typeof Schema.String>;
89
- hostedUrl: Schema.NullOr<typeof Schema.String>;
90
- pdfUrl: Schema.NullOr<typeof Schema.String>;
82
+ readonly invoices: Schema.$Array<Schema.Struct<{
83
+ readonly providerInvoiceId: Schema.String;
84
+ readonly amountMinor: Schema.Number;
85
+ readonly currency: Schema.String;
86
+ readonly status: Schema.String;
87
+ readonly createdAt: Schema.NullOr<Schema.String>;
88
+ readonly hostedUrl: Schema.NullOr<Schema.String>;
89
+ readonly pdfUrl: Schema.NullOr<Schema.String>;
91
90
  }>>;
92
91
  }>, typeof BillingError>;
93
92
 
94
93
  export declare const portalUrlDescriptor: ActionProcedureDescriptor<"billing.portalUrl", Schema.Struct<{
95
- returnUrl: typeof Schema.String;
94
+ readonly returnUrl: Schema.String;
96
95
  }>, Schema.Struct<{
97
- url: typeof Schema.String;
96
+ readonly url: Schema.String;
98
97
  }>, typeof BillingError>;
99
98
 
100
99
  /** What a plan/seat change would cost, from the provider's invoice preview.
101
100
  * Quote THIS in a confirmation dialog — a locally-estimated figure differs
102
101
  * from the charge by the provider's rounding, tax and credit balance. */
103
102
  export declare const previewChangeDescriptor: ActionProcedureDescriptor<"billing.previewChange", Schema.Struct<{
104
- plan: Schema.optional<typeof Schema.String>;
105
- quantity: Schema.optional<typeof Schema.Number>;
103
+ readonly plan: Schema.optional<Schema.String>;
104
+ readonly quantity: Schema.optional<Schema.Number>;
106
105
  }>, Schema.Struct<{
107
- plan: typeof Schema.String;
108
- quantity: typeof Schema.Number;
106
+ readonly plan: Schema.String;
107
+ readonly quantity: Schema.Number;
109
108
  /** Integer minor-unit settlement: > 0 charge, < 0 credit, 0 at boundary. */
110
- prorationMinor: typeof Schema.Number;
111
- currency: typeof Schema.String;
109
+ readonly prorationMinor: Schema.Number;
110
+ readonly currency: Schema.String;
112
111
  }>, typeof BillingError>;
113
112
 
114
113
  export declare const reportUsageDescriptor: ActionProcedureDescriptor<"billing.reportUsage", Schema.Struct<{
115
- key: typeof Schema.String;
116
- quantity: typeof Schema.Number;
114
+ readonly key: Schema.String;
115
+ readonly quantity: Schema.Number;
117
116
  }>, Schema.Struct<{
118
- ok: typeof Schema.Boolean;
117
+ readonly ok: Schema.Boolean;
119
118
  }>, typeof BillingError>;
120
119
 
121
120
  /** Take back a cancellation before the period ends. */
122
121
  export declare const resumeSubscriptionDescriptor: ActionProcedureDescriptor<"billing.resume", Schema.Struct<{}>, Schema.Struct<{
123
- subscription: Schema.Struct<{
124
- plan: typeof Schema.String;
125
- status: typeof Schema.String;
126
- quantity: typeof Schema.Number;
127
- currentPeriodEnd: Schema.NullOr<typeof Schema.String>;
128
- cancelAt: Schema.NullOr<typeof Schema.String>;
122
+ readonly subscription: Schema.Struct<{
123
+ readonly plan: Schema.String;
124
+ readonly status: Schema.String;
125
+ readonly quantity: Schema.Number;
126
+ readonly currentPeriodEnd: Schema.NullOr<Schema.String>;
127
+ readonly cancelAt: Schema.NullOr<Schema.String>;
129
128
  }>;
130
129
  }>, typeof BillingError>;
131
130
 
132
131
  export declare const startCheckoutDescriptor: ActionProcedureDescriptor<"billing.startCheckout", Schema.Struct<{
133
- plan: typeof Schema.String;
134
- successUrl: typeof Schema.String;
135
- cancelUrl: typeof Schema.String;
132
+ readonly plan: Schema.String;
133
+ readonly successUrl: Schema.String;
134
+ readonly cancelUrl: Schema.String;
136
135
  /** Seats to buy up front. Omit for 1. */
137
- quantity: Schema.optional<typeof Schema.Number>;
136
+ readonly quantity: Schema.optional<Schema.Number>;
138
137
  }>, Schema.Struct<{
139
- url: typeof Schema.String;
138
+ readonly url: Schema.String;
140
139
  }>, typeof BillingError>;
141
140
 
142
141
  export declare const subscriptionDescriptor: QueryProcedureDescriptor<"billing.subscription", Schema.Struct<{}>, Schema.Struct<{
143
- subscription: Schema.NullOr<Schema.Struct<{
144
- plan: typeof Schema.String;
145
- status: typeof Schema.String;
146
- quantity: typeof Schema.Number;
147
- currentPeriodEnd: Schema.NullOr<typeof Schema.String>;
148
- cancelAt: Schema.NullOr<typeof Schema.String>;
142
+ readonly subscription: Schema.NullOr<Schema.Struct<{
143
+ readonly plan: Schema.String;
144
+ readonly status: Schema.String;
145
+ readonly quantity: Schema.Number;
146
+ readonly currentPeriodEnd: Schema.NullOr<Schema.String>;
147
+ readonly cancelAt: Schema.NullOr<Schema.String>;
149
148
  }>>;
150
149
  }>, typeof BillingError>;
151
150
 
@@ -153,12 +152,12 @@ export declare const subscriptionDescriptor: QueryProcedureDescriptor<"billing.s
153
152
  * its current subscription. Call it on the return from checkout or the
154
153
  * portal, and when a billing page loads. */
155
154
  export declare const syncDescriptor: ActionProcedureDescriptor<"billing.sync", Schema.Struct<{}>, Schema.Struct<{
156
- subscription: Schema.NullOr<Schema.Struct<{
157
- plan: typeof Schema.String;
158
- status: typeof Schema.String;
159
- quantity: typeof Schema.Number;
160
- currentPeriodEnd: Schema.NullOr<typeof Schema.String>;
161
- cancelAt: Schema.NullOr<typeof Schema.String>;
155
+ readonly subscription: Schema.NullOr<Schema.Struct<{
156
+ readonly plan: Schema.String;
157
+ readonly status: Schema.String;
158
+ readonly quantity: Schema.Number;
159
+ readonly currentPeriodEnd: Schema.NullOr<Schema.String>;
160
+ readonly cancelAt: Schema.NullOr<Schema.String>;
162
161
  }>>;
163
162
  }>, typeof BillingError>;
164
163
 
package/dist/types.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Context } from 'effect';
2
2
  import { Effect } from 'effect';
3
3
  import { Schema } from 'effect';
4
+ import { YieldableError } from 'effect/Cause';
4
5
 
5
6
  /**
6
7
  * What a billing call would do to what the tenant pays — the unit an app's
@@ -20,15 +21,13 @@ export declare type BillingAction = 'checkout' | 'change' | 'resume' | 'portal'
20
21
  export declare class BillingError extends BillingError_base {
21
22
  }
22
23
 
23
- declare const BillingError_base: Schema.TaggedErrorClass<BillingError, "BillingError", {
24
- readonly _tag: Schema.tag<"BillingError">;
25
- } & {
24
+ declare const BillingError_base: Schema.Class<BillingError, Schema.TaggedStruct<"BillingError", {
26
25
  /** Where the failure originated — provider name or an internal stage. */
27
- source: typeof Schema.String;
28
- message: typeof Schema.String;
26
+ readonly source: Schema.String;
27
+ readonly message: Schema.String;
29
28
  /** Retryable? The service retries `transient` failures on a Schedule. */
30
- transient: typeof Schema.Boolean;
31
- }>;
29
+ readonly transient: Schema.Boolean;
30
+ }>, YieldableError>;
32
31
 
33
32
  /**
34
33
  * The normalized event union a `BillingProvider.normalizeEvent` produces
@@ -229,7 +228,7 @@ export declare interface BillingProvider {
229
228
  export declare class BillingService extends BillingService_base {
230
229
  }
231
230
 
232
- declare const BillingService_base: Context.TagClass<BillingService, "@voltro/plugin-billing/BillingService", BillingServiceShape>;
231
+ declare const BillingService_base: Context.ServiceClass<BillingService, "@voltro/plugin-billing/BillingService", BillingServiceShape>;
233
232
 
234
233
  export declare interface BillingServiceShape {
235
234
  /** Read the tenant's subscription row; null when none exists. */
@@ -428,18 +427,16 @@ export declare interface EntitlementDecision {
428
427
  export declare class EntitlementExceeded extends EntitlementExceeded_base {
429
428
  }
430
429
 
431
- declare const EntitlementExceeded_base: Schema.TaggedErrorClass<EntitlementExceeded, "EntitlementExceeded", {
432
- readonly _tag: Schema.tag<"EntitlementExceeded">;
433
- } & {
430
+ declare const EntitlementExceeded_base: Schema.Class<EntitlementExceeded, Schema.TaggedStruct<"EntitlementExceeded", {
434
431
  /** The entitlement key that was exhausted (`'aiCalls'`). */
435
- entitlement: typeof Schema.String;
432
+ readonly entitlement: Schema.String;
436
433
  /** The static limit for the caller's plan. */
437
- limit: typeof Schema.Number;
434
+ readonly limit: Schema.Number;
438
435
  /** How much was already used in the current window. */
439
- used: typeof Schema.Number;
436
+ readonly used: Schema.Number;
440
437
  /** The cost the rejected call would have charged. */
441
- cost: typeof Schema.Number;
442
- }>;
438
+ readonly cost: Schema.Number;
439
+ }>, YieldableError>;
443
440
 
444
441
  /** An entitlement limit: a finite quota or the unbounded `'unlimited'`. */
445
442
  export declare type EntitlementLimit = number | 'unlimited';
@@ -660,17 +657,15 @@ export declare interface SubscriptionChangeResult {
660
657
  export declare class SubscriptionLocked extends SubscriptionLocked_base {
661
658
  }
662
659
 
663
- declare const SubscriptionLocked_base: Schema.TaggedErrorClass<SubscriptionLocked, "SubscriptionLocked", {
664
- readonly _tag: Schema.tag<"SubscriptionLocked">;
665
- } & {
666
- tenantId: typeof Schema.String;
660
+ declare const SubscriptionLocked_base: Schema.Class<SubscriptionLocked, Schema.TaggedStruct<"SubscriptionLocked", {
661
+ readonly tenantId: Schema.String;
667
662
  /** The subscription status at the time of the refusal (`'pastDue'`). */
668
- status: typeof Schema.String;
663
+ readonly status: Schema.String;
669
664
  /** ISO timestamp at which the grace period expired. */
670
- lockedSince: typeof Schema.String;
665
+ readonly lockedSince: Schema.String;
671
666
  /** `'hard'` (limits fell to the free plan) or `'soft'` (report only). */
672
- lockout: typeof Schema.String;
673
- }>;
667
+ readonly lockout: Schema.String;
668
+ }>, YieldableError>;
674
669
 
675
670
  export declare type SubscriptionStatus = 'active' | 'trialing' | 'pastDue' | 'canceled' | 'incomplete';
676
671
 
package/dist/types.js CHANGED
@@ -14,6 +14,6 @@ var n = class extends t.TaggedError()("BillingError", {
14
14
  limit: t.Number,
15
15
  used: t.Number,
16
16
  cost: t.Number
17
- }) {}, a = "free", o = class extends e.Tag("@voltro/plugin-billing/BillingService")() {};
17
+ }) {}, a = "free", o = class extends e.Service()("@voltro/plugin-billing/BillingService") {};
18
18
  //#endregion
19
19
  export { n as BillingError, o as BillingService, a as DEFAULT_PLAN, i as EntitlementExceeded, r as SubscriptionLocked };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/plugin-billing",
3
- "version": "0.83.1",
3
+ "version": "0.85.0",
4
4
  "description": "Billing on the official Stripe SDK — subscriptions, plans, entitlements and usage metering. Proration, failed-payment retries, tax, promotion codes, trials and the checkout seat stepper are Stripe's own; the plugin adds the entitlement engine, the enforce interceptor, typed BillingError/EntitlementExceeded, the /billing/webhook mount with Stripe's signature verification, the BillingService Tag, requireEntitlement(), and a browser-safe useStartCheckout() hook. Money is integer minor units end-to-end.",
5
5
  "keywords": [
6
6
  "voltro",
@@ -48,14 +48,14 @@
48
48
  "node": ">=24.0.0"
49
49
  },
50
50
  "dependencies": {
51
- "@voltro/database": "0.83.1",
52
- "@voltro/env": "0.83.1",
53
- "@voltro/logger": "0.83.1",
54
- "@voltro/plugin-webhooks": "0.83.1",
55
- "@voltro/protocol": "0.83.1"
51
+ "@voltro/database": "0.85.0",
52
+ "@voltro/env": "0.85.0",
53
+ "@voltro/logger": "0.85.0",
54
+ "@voltro/plugin-webhooks": "0.85.0",
55
+ "@voltro/protocol": "0.85.0"
56
56
  },
57
57
  "peerDependencies": {
58
- "effect": "^3.22.2",
58
+ "effect": "4.0.1",
59
59
  "react": "^19.0.0",
60
60
  "stripe": "^22.6.1"
61
61
  },