@schematichq/schematic-react 1.6.0 → 1.8.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/README.md CHANGED
@@ -165,6 +165,40 @@ const MyComponent = () => {
165
165
 
166
166
  These values refresh with each flag check. For a balance that also updates on the credit partials arriving between checks, pass `creditId` to [`useSchematicCreditBalance`](#credit-balances) instead.
167
167
 
168
+ ### Usage warnings
169
+
170
+ If a usage warning is configured on the entitlement, the hook returns it as `warningTiers`, so you can warn a customer before they hit the limit rather than after:
171
+
172
+ | Property | Type | Description |
173
+ | --- | --- | --- |
174
+ | `warningTiers` | `WarningTier[] \| undefined` | The usage warning thresholds configured on the entitlement, each a `{ key, value }` pair in the entitlement's usage units. `undefined` when none are configured |
175
+ | `softLimit` | `number \| undefined` | For usage-based pricing, the soft limit for overage charges or the next tier boundary |
176
+
177
+ The dashboard writes a single tier under the key `default`.
178
+
179
+ ```tsx
180
+ import { useSchematicEntitlement } from "@schematichq/schematic-react";
181
+ import { Feature, ApproachingLimit } from "./components";
182
+
183
+ const MyComponent = () => {
184
+ const { featureUsage, warningTiers } =
185
+ useSchematicEntitlement("my-flag-key");
186
+
187
+ const warning = warningTiers?.find((tier) => tier.key === "default");
188
+ const approachingLimit =
189
+ typeof featureUsage === "number" &&
190
+ typeof warning?.value === "number" &&
191
+ featureUsage >= warning.value;
192
+
193
+ return (
194
+ <>
195
+ {approachingLimit && <ApproachingLimit limit={warning.value} />}
196
+ <Feature />
197
+ </>
198
+ );
199
+ };
200
+ ```
201
+
168
202
  ### Company plan information
169
203
 
170
204
  To access the current company's plan and trial status, you can use the `useSchematicPlan` hook:
@@ -36,6 +36,7 @@ __export(index_exports, {
36
36
  INVOICE_PAGE_SIZE: () => INVOICE_PAGE_SIZE,
37
37
  InvoiceStatus: () => InvoiceStatus,
38
38
  RuleType: () => RuleType,
39
+ SINGLETON: () => SINGLETON,
39
40
  Schematic: () => Schematic,
40
41
  SchematicI18nContext: () => SchematicI18nContext,
41
42
  SchematicI18nProvider: () => SchematicI18nProvider,
@@ -57,11 +58,12 @@ __export(index_exports, {
57
58
  useSchematicLocale: () => useSchematicLocale,
58
59
  useSchematicPlan: () => useSchematicPlan,
59
60
  useSchematicStrings: () => useSchematicStrings,
60
- useSchematicTranslate: () => useSchematicTranslate
61
+ useSchematicTranslate: () => useSchematicTranslate,
62
+ useUpcomingInvoice: () => useUpcomingInvoice
61
63
  });
62
64
  module.exports = __toCommonJS(index_exports);
63
65
 
64
- // node_modules/.pnpm/@schematichq+schematic-js@1.7.0/node_modules/@schematichq/schematic-js/dist/schematic.esm.js
66
+ // node_modules/.pnpm/@schematichq+schematic-js@1.8.0/node_modules/@schematichq/schematic-js/dist/schematic.esm.js
65
67
  var __create2 = Object.create;
66
68
  var __defProp2 = Object.defineProperty;
67
69
  var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
@@ -1166,7 +1168,8 @@ var CheckFlagReturnFromJSON = (json) => {
1166
1168
  ruleType: ruleType == null ? void 0 : ruleType,
1167
1169
  softLimit: entitlement?.softLimit == null ? void 0 : entitlement.softLimit,
1168
1170
  userId: userId == null ? void 0 : userId,
1169
- value
1171
+ value,
1172
+ warningTiers: entitlement?.warningTiers == null ? void 0 : entitlement.warningTiers
1170
1173
  };
1171
1174
  };
1172
1175
  var CheckPlanReturnFromJSON = (json) => {
@@ -1193,7 +1196,7 @@ var CreditBalancesFromJSON = (json) => {
1193
1196
  }
1194
1197
  return balances;
1195
1198
  };
1196
- var cacheVersion = "bb56e75d";
1199
+ var cacheVersion = "7b920cf4";
1197
1200
  function contextString(context) {
1198
1201
  const sortedContext = Object.keys(context).reduce((acc, key) => {
1199
1202
  const sortedKeys = Object.keys(
@@ -1208,13 +1211,18 @@ function contextString(context) {
1208
1211
  }, {});
1209
1212
  return JSON.stringify(sortedContext);
1210
1213
  }
1211
- var version = "1.7.0";
1214
+ var version = "1.8.0";
1215
+ var SINGLETON = {};
1212
1216
  var models_exports = {};
1213
1217
  __export2(models_exports, {
1214
1218
  ApiErrorFromJSON: () => ApiErrorFromJSON,
1215
1219
  ApiErrorFromJSONTyped: () => ApiErrorFromJSONTyped,
1216
1220
  ApiErrorToJSON: () => ApiErrorToJSON,
1217
1221
  ApiErrorToJSONTyped: () => ApiErrorToJSONTyped,
1222
+ CompanyDiscountResponseDataFromJSON: () => CompanyDiscountResponseDataFromJSON,
1223
+ CompanyDiscountResponseDataFromJSONTyped: () => CompanyDiscountResponseDataFromJSONTyped,
1224
+ CompanyDiscountResponseDataToJSON: () => CompanyDiscountResponseDataToJSON,
1225
+ CompanyDiscountResponseDataToJSONTyped: () => CompanyDiscountResponseDataToJSONTyped,
1218
1226
  CompanyInvoiceResponseDataFromJSON: () => CompanyInvoiceResponseDataFromJSON,
1219
1227
  CompanyInvoiceResponseDataFromJSONTyped: () => CompanyInvoiceResponseDataFromJSONTyped,
1220
1228
  CompanyInvoiceResponseDataToJSON: () => CompanyInvoiceResponseDataToJSON,
@@ -1223,6 +1231,10 @@ __export2(models_exports, {
1223
1231
  CompanyInvoicesResponseDataFromJSONTyped: () => CompanyInvoicesResponseDataFromJSONTyped,
1224
1232
  CompanyInvoicesResponseDataToJSON: () => CompanyInvoicesResponseDataToJSON,
1225
1233
  CompanyInvoicesResponseDataToJSONTyped: () => CompanyInvoicesResponseDataToJSONTyped,
1234
+ CompanyUpcomingInvoiceResponseDataFromJSON: () => CompanyUpcomingInvoiceResponseDataFromJSON,
1235
+ CompanyUpcomingInvoiceResponseDataFromJSONTyped: () => CompanyUpcomingInvoiceResponseDataFromJSONTyped,
1236
+ CompanyUpcomingInvoiceResponseDataToJSON: () => CompanyUpcomingInvoiceResponseDataToJSON,
1237
+ CompanyUpcomingInvoiceResponseDataToJSONTyped: () => CompanyUpcomingInvoiceResponseDataToJSONTyped,
1226
1238
  GetCompanyInvoicesParamsFromJSON: () => GetCompanyInvoicesParamsFromJSON,
1227
1239
  GetCompanyInvoicesParamsFromJSONTyped: () => GetCompanyInvoicesParamsFromJSONTyped,
1228
1240
  GetCompanyInvoicesParamsToJSON: () => GetCompanyInvoicesParamsToJSON,
@@ -1231,16 +1243,23 @@ __export2(models_exports, {
1231
1243
  GetCompanyInvoicesResponseFromJSONTyped: () => GetCompanyInvoicesResponseFromJSONTyped,
1232
1244
  GetCompanyInvoicesResponseToJSON: () => GetCompanyInvoicesResponseToJSON,
1233
1245
  GetCompanyInvoicesResponseToJSONTyped: () => GetCompanyInvoicesResponseToJSONTyped,
1246
+ GetCompanyUpcomingInvoiceResponseFromJSON: () => GetCompanyUpcomingInvoiceResponseFromJSON,
1247
+ GetCompanyUpcomingInvoiceResponseFromJSONTyped: () => GetCompanyUpcomingInvoiceResponseFromJSONTyped,
1248
+ GetCompanyUpcomingInvoiceResponseToJSON: () => GetCompanyUpcomingInvoiceResponseToJSON,
1249
+ GetCompanyUpcomingInvoiceResponseToJSONTyped: () => GetCompanyUpcomingInvoiceResponseToJSONTyped,
1234
1250
  InvoiceStatus: () => InvoiceStatus,
1235
1251
  InvoiceStatusFromJSON: () => InvoiceStatusFromJSON,
1236
1252
  InvoiceStatusFromJSONTyped: () => InvoiceStatusFromJSONTyped,
1237
1253
  InvoiceStatusToJSON: () => InvoiceStatusToJSON,
1238
1254
  InvoiceStatusToJSONTyped: () => InvoiceStatusToJSONTyped,
1239
1255
  instanceOfApiError: () => instanceOfApiError,
1256
+ instanceOfCompanyDiscountResponseData: () => instanceOfCompanyDiscountResponseData,
1240
1257
  instanceOfCompanyInvoiceResponseData: () => instanceOfCompanyInvoiceResponseData,
1241
1258
  instanceOfCompanyInvoicesResponseData: () => instanceOfCompanyInvoicesResponseData,
1259
+ instanceOfCompanyUpcomingInvoiceResponseData: () => instanceOfCompanyUpcomingInvoiceResponseData,
1242
1260
  instanceOfGetCompanyInvoicesParams: () => instanceOfGetCompanyInvoicesParams,
1243
1261
  instanceOfGetCompanyInvoicesResponse: () => instanceOfGetCompanyInvoicesResponse,
1262
+ instanceOfGetCompanyUpcomingInvoiceResponse: () => instanceOfGetCompanyUpcomingInvoiceResponse,
1244
1263
  instanceOfInvoiceStatus: () => instanceOfInvoiceStatus
1245
1264
  });
1246
1265
  function instanceOfApiError(value) {
@@ -1269,6 +1288,46 @@ function ApiErrorToJSONTyped(value, ignoreDiscriminator = false) {
1269
1288
  error: value["error"]
1270
1289
  };
1271
1290
  }
1291
+ function instanceOfCompanyDiscountResponseData(value) {
1292
+ if (!("couponName" in value) || value["couponName"] === void 0)
1293
+ return false;
1294
+ if (!("duration" in value) || value["duration"] === void 0) return false;
1295
+ return true;
1296
+ }
1297
+ function CompanyDiscountResponseDataFromJSON(json) {
1298
+ return CompanyDiscountResponseDataFromJSONTyped(json, false);
1299
+ }
1300
+ function CompanyDiscountResponseDataFromJSONTyped(json, ignoreDiscriminator) {
1301
+ if (json == null) {
1302
+ return json;
1303
+ }
1304
+ return {
1305
+ amountOff: json["amount_off"] == null ? void 0 : json["amount_off"],
1306
+ couponName: json["coupon_name"],
1307
+ currency: json["currency"] == null ? void 0 : json["currency"],
1308
+ customerFacingCode: json["customer_facing_code"] == null ? void 0 : json["customer_facing_code"],
1309
+ duration: json["duration"],
1310
+ durationInMonths: json["duration_in_months"] == null ? void 0 : json["duration_in_months"],
1311
+ percentOff: json["percent_off"] == null ? void 0 : json["percent_off"]
1312
+ };
1313
+ }
1314
+ function CompanyDiscountResponseDataToJSON(json) {
1315
+ return CompanyDiscountResponseDataToJSONTyped(json, false);
1316
+ }
1317
+ function CompanyDiscountResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
1318
+ if (value == null) {
1319
+ return value;
1320
+ }
1321
+ return {
1322
+ amount_off: value["amountOff"],
1323
+ coupon_name: value["couponName"],
1324
+ currency: value["currency"],
1325
+ customer_facing_code: value["customerFacingCode"],
1326
+ duration: value["duration"],
1327
+ duration_in_months: value["durationInMonths"],
1328
+ percent_off: value["percentOff"]
1329
+ };
1330
+ }
1272
1331
  var InvoiceStatus = {
1273
1332
  Draft: "draft",
1274
1333
  Open: "open",
@@ -1372,6 +1431,55 @@ function CompanyInvoicesResponseDataToJSONTyped(value, ignoreDiscriminator = fal
1372
1431
  )
1373
1432
  };
1374
1433
  }
1434
+ function instanceOfCompanyUpcomingInvoiceResponseData(value) {
1435
+ if (!("amountDue" in value) || value["amountDue"] === void 0) return false;
1436
+ if (!("currency" in value) || value["currency"] === void 0) return false;
1437
+ if (!("customerBalanceApplied" in value) || value["customerBalanceApplied"] === void 0)
1438
+ return false;
1439
+ if (!("customerBalanceRemaining" in value) || value["customerBalanceRemaining"] === void 0)
1440
+ return false;
1441
+ if (!("discounts" in value) || value["discounts"] === void 0) return false;
1442
+ if (!("subtotal" in value) || value["subtotal"] === void 0) return false;
1443
+ return true;
1444
+ }
1445
+ function CompanyUpcomingInvoiceResponseDataFromJSON(json) {
1446
+ return CompanyUpcomingInvoiceResponseDataFromJSONTyped(json, false);
1447
+ }
1448
+ function CompanyUpcomingInvoiceResponseDataFromJSONTyped(json, ignoreDiscriminator) {
1449
+ if (json == null) {
1450
+ return json;
1451
+ }
1452
+ return {
1453
+ amountDue: json["amount_due"],
1454
+ currency: json["currency"],
1455
+ customerBalanceApplied: json["customer_balance_applied"],
1456
+ customerBalanceRemaining: json["customer_balance_remaining"],
1457
+ discounts: json["discounts"].map(
1458
+ CompanyDiscountResponseDataFromJSON
1459
+ ),
1460
+ dueDate: json["due_date"] == null ? void 0 : new Date(json["due_date"]),
1461
+ subtotal: json["subtotal"]
1462
+ };
1463
+ }
1464
+ function CompanyUpcomingInvoiceResponseDataToJSON(json) {
1465
+ return CompanyUpcomingInvoiceResponseDataToJSONTyped(json, false);
1466
+ }
1467
+ function CompanyUpcomingInvoiceResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
1468
+ if (value == null) {
1469
+ return value;
1470
+ }
1471
+ return {
1472
+ amount_due: value["amountDue"],
1473
+ currency: value["currency"],
1474
+ customer_balance_applied: value["customerBalanceApplied"],
1475
+ customer_balance_remaining: value["customerBalanceRemaining"],
1476
+ discounts: value["discounts"].map(
1477
+ CompanyDiscountResponseDataToJSON
1478
+ ),
1479
+ due_date: value["dueDate"] == null ? void 0 : value["dueDate"].toISOString(),
1480
+ subtotal: value["subtotal"]
1481
+ };
1482
+ }
1375
1483
  function instanceOfGetCompanyInvoicesParams(value) {
1376
1484
  return true;
1377
1485
  }
@@ -1430,6 +1538,35 @@ function GetCompanyInvoicesResponseToJSONTyped(value, ignoreDiscriminator = fals
1430
1538
  params: GetCompanyInvoicesParamsToJSON(value["params"])
1431
1539
  };
1432
1540
  }
1541
+ function instanceOfGetCompanyUpcomingInvoiceResponse(value) {
1542
+ if (!("data" in value) || value["data"] === void 0) return false;
1543
+ if (!("params" in value) || value["params"] === void 0) return false;
1544
+ return true;
1545
+ }
1546
+ function GetCompanyUpcomingInvoiceResponseFromJSON(json) {
1547
+ return GetCompanyUpcomingInvoiceResponseFromJSONTyped(json, false);
1548
+ }
1549
+ function GetCompanyUpcomingInvoiceResponseFromJSONTyped(json, ignoreDiscriminator) {
1550
+ if (json == null) {
1551
+ return json;
1552
+ }
1553
+ return {
1554
+ data: CompanyUpcomingInvoiceResponseDataFromJSON(json["data"]),
1555
+ params: json["params"]
1556
+ };
1557
+ }
1558
+ function GetCompanyUpcomingInvoiceResponseToJSON(json) {
1559
+ return GetCompanyUpcomingInvoiceResponseToJSONTyped(json, false);
1560
+ }
1561
+ function GetCompanyUpcomingInvoiceResponseToJSONTyped(value, ignoreDiscriminator = false) {
1562
+ if (value == null) {
1563
+ return value;
1564
+ }
1565
+ return {
1566
+ data: CompanyUpcomingInvoiceResponseDataToJSON(value["data"]),
1567
+ params: value["params"]
1568
+ };
1569
+ }
1433
1570
  var DEFAULT_INVOICE_QUERY = {};
1434
1571
  function normalizeInvoiceQuery(query) {
1435
1572
  const { includePending, ...rest } = query;
@@ -1645,6 +1782,11 @@ var SchematicSession = class {
1645
1782
  throw new SchematicApiError(status, path, rejected);
1646
1783
  }
1647
1784
  }
1785
+ if (options.noContentOn?.includes(response.status) === true) {
1786
+ await discardBody(response);
1787
+ await stillOurs();
1788
+ return void 0;
1789
+ }
1648
1790
  const parsed = await readBody(response);
1649
1791
  await stillOurs();
1650
1792
  if (!response.ok) {
@@ -1737,6 +1879,18 @@ var SchematicBillingClient = class {
1737
1879
  return { invoices: decoded.invoices, count: decoded.count };
1738
1880
  });
1739
1881
  }
1882
+ fetchUpcomingInvoice() {
1883
+ const path = "/company/upcoming-invoice";
1884
+ return this.session.request(path, { noContentOn: [204] }).then((body) => {
1885
+ if (body === void 0) {
1886
+ return null;
1887
+ }
1888
+ if (body === null || typeof body !== "object" || !("data" in body)) {
1889
+ throw new Error(`Malformed response from ${path}`);
1890
+ }
1891
+ return GetCompanyUpcomingInvoiceResponseFromJSON(body).data;
1892
+ });
1893
+ }
1740
1894
  };
1741
1895
  var anonymousIdKey = "schematicId";
1742
1896
  var flagStateCachePrefix = "schematicCache";
@@ -3845,33 +3999,40 @@ var BillingStore = class {
3845
3999
  constructor(_client, initialData = {}, options = {}) {
3846
4000
  this._client = _client;
3847
4001
  this._pageSize = options.pageSize ?? INVOICE_PAGE_SIZE;
4002
+ const readiness = () => this._connected ? READINESS[this._client.sessionStatus] : "waiting";
3848
4003
  this.invoices = new KeyedResource(
3849
4004
  (query, current) => this._reloadWindow(
3850
4005
  query,
3851
4006
  Math.max(this._pageSize, current?.invoices.length ?? 0)
3852
4007
  ),
3853
- // Waiting until connected; then a session still pending stays
3854
- // pending, and one that has ended settles empty rather than recording
3855
- // the client's refusal as an error.
3856
- {
3857
- readiness: () => this._connected ? READINESS[this._client.sessionStatus] : "waiting"
3858
- }
4008
+ { readiness }
4009
+ );
4010
+ this.upcomingInvoice = new KeyedResource(
4011
+ () => this._client.fetchUpcomingInvoice(),
4012
+ { readiness }
3859
4013
  );
4014
+ const held = { key: initialData.sessionKey };
3860
4015
  if (initialData.invoices !== void 0) {
3861
- this._held = {
4016
+ held.invoices = {
3862
4017
  // Normalized the way the hook normalizes, or the caller asking for
3863
4018
  // it fetches the same page again.
3864
4019
  params: normalizeInvoiceQuery2(
3865
4020
  initialData.params?.invoices ?? DEFAULT_INVOICE_QUERY
3866
4021
  ),
3867
- data: initialData.invoices,
3868
- key: initialData.sessionKey
4022
+ data: initialData.invoices
3869
4023
  };
4024
+ }
4025
+ if (initialData.upcomingInvoice !== void 0) {
4026
+ held.upcomingInvoice = initialData.upcomingInvoice;
4027
+ }
4028
+ if (held.invoices !== void 0 || held.upcomingInvoice !== void 0) {
4029
+ this._held = held;
3870
4030
  this._settleSeed(claimFrom(options.session) ?? claimOf(this._client));
3871
4031
  }
3872
4032
  }
3873
4033
  _client;
3874
4034
  invoices;
4035
+ upcomingInvoice;
3875
4036
  _pageSize;
3876
4037
  _unsubscribe;
3877
4038
  _connected = false;
@@ -3941,7 +4102,12 @@ var BillingStore = class {
3941
4102
  }
3942
4103
  this._held = void 0;
3943
4104
  if (verdict === "adopt") {
3944
- this.invoices.seed(held.params, held.data);
4105
+ if (held.invoices !== void 0) {
4106
+ this.invoices.seed(held.invoices.params, held.invoices.data);
4107
+ }
4108
+ if (held.upcomingInvoice !== void 0) {
4109
+ this.upcomingInvoice.seed(SINGLETON, held.upcomingInvoice);
4110
+ }
3945
4111
  this._seedKey = held.key;
3946
4112
  this._seeded = true;
3947
4113
  }
@@ -4043,7 +4209,10 @@ var BillingStore = class {
4043
4209
  return this._client.fetchInvoices({ ...query, limit, offset });
4044
4210
  }
4045
4211
  };
4046
- var RESOURCE_NAMES = ["invoices"];
4212
+ var RESOURCE_NAMES = [
4213
+ "invoices",
4214
+ "upcomingInvoice"
4215
+ ];
4047
4216
 
4048
4217
  // src/billing/context.tsx
4049
4218
  var import_react2 = require("react");
@@ -4194,6 +4363,9 @@ function useInvoices(query = DEFAULT_INVOICE_QUERY) {
4194
4363
  );
4195
4364
  return (0, import_react3.useMemo)(() => ({ ...handle, loadMore }), [handle, loadMore]);
4196
4365
  }
4366
+ function useUpcomingInvoice() {
4367
+ return useBillingResource("upcomingInvoice", SINGLETON);
4368
+ }
4197
4369
  function useInvalidateBillingData() {
4198
4370
  return useBillingDataSource().invalidateAll;
4199
4371
  }
@@ -4313,7 +4485,7 @@ function staticSource(data) {
4313
4485
  }
4314
4486
 
4315
4487
  // src/version.ts
4316
- var version2 = "1.6.0";
4488
+ var version2 = "1.8.0";
4317
4489
 
4318
4490
  // src/context/schematic.tsx
4319
4491
  var import_jsx_runtime4 = require("react/jsx-runtime");
@@ -34,7 +34,7 @@ declare type BaseSchematicProviderProps = Omit<SchematicJS.SchematicOptions, "cl
34
34
  */
35
35
  session?: SessionInput;
36
36
  /** A billing client; schematic-js supplies one when omitted. */
37
- billingClient?: BillingClient;
37
+ billingClient?: BillingProviderClient;
38
38
  /**
39
39
  * Prefetched billing data, so the first render is complete (SSR). Rows
40
40
  * stamped with their session paint on the first render only if `session`
@@ -53,6 +53,12 @@ declare namespace billingApi {
53
53
  ApiErrorToJSON,
54
54
  ApiErrorToJSONTyped,
55
55
  ApiError,
56
+ instanceOfCompanyDiscountResponseData,
57
+ CompanyDiscountResponseDataFromJSON,
58
+ CompanyDiscountResponseDataFromJSONTyped,
59
+ CompanyDiscountResponseDataToJSON,
60
+ CompanyDiscountResponseDataToJSONTyped,
61
+ CompanyDiscountResponseData,
56
62
  instanceOfCompanyInvoiceResponseData,
57
63
  CompanyInvoiceResponseDataFromJSON,
58
64
  CompanyInvoiceResponseDataFromJSONTyped,
@@ -65,6 +71,12 @@ declare namespace billingApi {
65
71
  CompanyInvoicesResponseDataToJSON,
66
72
  CompanyInvoicesResponseDataToJSONTyped,
67
73
  CompanyInvoicesResponseData,
74
+ instanceOfCompanyUpcomingInvoiceResponseData,
75
+ CompanyUpcomingInvoiceResponseDataFromJSON,
76
+ CompanyUpcomingInvoiceResponseDataFromJSONTyped,
77
+ CompanyUpcomingInvoiceResponseDataToJSON,
78
+ CompanyUpcomingInvoiceResponseDataToJSONTyped,
79
+ CompanyUpcomingInvoiceResponseData,
68
80
  instanceOfGetCompanyInvoicesParams,
69
81
  GetCompanyInvoicesParamsFromJSON,
70
82
  GetCompanyInvoicesParamsFromJSONTyped,
@@ -77,6 +89,12 @@ declare namespace billingApi {
77
89
  GetCompanyInvoicesResponseToJSON,
78
90
  GetCompanyInvoicesResponseToJSONTyped,
79
91
  GetCompanyInvoicesResponse,
92
+ instanceOfGetCompanyUpcomingInvoiceResponse,
93
+ GetCompanyUpcomingInvoiceResponseFromJSON,
94
+ GetCompanyUpcomingInvoiceResponseFromJSONTyped,
95
+ GetCompanyUpcomingInvoiceResponseToJSON,
96
+ GetCompanyUpcomingInvoiceResponseToJSONTyped,
97
+ GetCompanyUpcomingInvoiceResponse,
80
98
  instanceOfInvoiceStatus,
81
99
  InvoiceStatusFromJSON,
82
100
  InvoiceStatusFromJSONTyped,
@@ -91,8 +109,10 @@ declare namespace billingApi {
91
109
  * rest of what `hydrate` serves — and the checkout calls that change them
92
110
  * join this interface as their endpoints ship.
93
111
  */
94
- export declare interface BillingClient {
112
+ declare interface BillingClient {
95
113
  fetchInvoices(params: InvoicesRequest): Promise<InvoicesResult>;
114
+ /** `null` when the company has no next bill. */
115
+ fetchUpcomingInvoice(): Promise<UpcomingInvoice | null>;
96
116
  readonly sessionStatus: SessionStatus;
97
117
  readonly sessionKey: string | undefined;
98
118
  setSession(session: SessionInput): void;
@@ -107,9 +127,9 @@ declare type BillingClientOptions = SessionOptions;
107
127
  * non-default query is claimed rather than refetched by the element.
108
128
  */
109
129
  export declare type BillingData = {
110
- [K in BillingResourceName]?: BillingResources[K];
130
+ [K in BillingResourceName_2]?: BillingResources_2[K];
111
131
  } & {
112
- params?: Partial<BillingResourceParams>;
132
+ params?: Partial<BillingResourceParams_2>;
113
133
  /**
114
134
  * A prefetch outlives the render that made it — a cached page, a session
115
135
  * resolving to somebody else — so a store adopts it only for the session
@@ -162,17 +182,32 @@ export declare type BillingDataStatus = {
162
182
  };
163
183
 
164
184
  declare interface BillingPrefetchOptions {
165
- names?: BillingResourceName[];
185
+ /**
186
+ * The resources the page renders, and no default: each one is a request
187
+ * on the server — the upcoming invoice is a live provider preview — and
188
+ * the list grows with every element, so a page names what it needs rather
189
+ * than paying for everything.
190
+ */
191
+ names: BillingResourceName_2[];
166
192
  /** The invoice query to prefetch for; the element must ask the same one. */
167
193
  invoices?: InvoiceQuery;
168
194
  }
169
195
 
170
196
  /**
171
- * Provides the billing hooks from a `BillingStore` over a `BillingClient`.
197
+ * Provides the billing hooks from a `BillingStore` over a `BillingProviderClient`.
172
198
  * Rendered by `SchematicProvider`; usable on its own with a client.
173
199
  */
174
200
  export declare function BillingProvider({ billingClient, children, initialData, locale, onMissingString, session, strings, translate, }: BillingProviderProps): React_2.JSX.Element;
175
201
 
202
+ /**
203
+ * What `BillingProvider` asks of its client: the session it reads under, and
204
+ * the fetch behind each resource above. schematic-js's `SchematicBillingClient`
205
+ * satisfies it, and so does a host's own client that implements only this
206
+ * much. Named apart from schematic-js's `BillingClient`, which is the whole
207
+ * interface; this is the part the hooks here call.
208
+ */
209
+ export declare type BillingProviderClient = Pick<BillingClient, "sessionStatus" | "sessionKey" | "setSession" | "onSessionChange" | "fetchInvoices" | "fetchUpcomingInvoice">;
210
+
176
211
  declare interface BillingProviderDataProps {
177
212
  /**
178
213
  * Required: this provider does not build one, and without it every hook
@@ -180,7 +215,7 @@ declare interface BillingProviderDataProps {
180
215
  * `SchematicProvider` constructs one from its publishable key and renders
181
216
  * this underneath, which is the usual path.
182
217
  */
183
- billingClient?: BillingClient;
218
+ billingClient?: BillingProviderClient;
184
219
  /**
185
220
  * Read once, at mount. A prefetch stamped with its session paints on the
186
221
  * first render only if `session` is stated on that render; under
@@ -210,13 +245,21 @@ declare interface BillingProviderDataProps {
210
245
  */
211
246
  export declare type BillingProviderProps = BillingProviderDataProps & SchematicI18nConfig;
212
247
 
213
- export declare type BillingResourceName = keyof BillingResources;
248
+ /** The resources this package serves; a key of schematic-js's contract. */
249
+ export declare type BillingResourceName = "invoices" | "upcomingInvoice";
250
+
251
+ declare type BillingResourceName_2 = keyof BillingResources_2;
252
+
253
+ export declare type BillingResourceParams = Pick<BillingResourceParams_2, BillingResourceName>;
214
254
 
215
255
  /** `Record<string, never>` marks a singleton; anything else is keyed. */
216
- export declare interface BillingResourceParams {
256
+ declare interface BillingResourceParams_2 {
217
257
  invoices: InvoiceQuery;
258
+ upcomingInvoice: Record<string, never>;
218
259
  }
219
260
 
261
+ export declare type BillingResources = Pick<BillingResources_2, BillingResourceName>;
262
+
220
263
  /**
221
264
  * Nothing in the store, the hooks, or the resource keys may be addressed by
222
265
  * company or user id: users and companies are many-to-many, and a token names
@@ -224,9 +267,15 @@ export declare interface BillingResourceParams {
224
267
  * pair, as `sessionKey` writes it — and a store that keeps more than one
225
268
  * session's data keys it by that and serves only the active one.
226
269
  */
227
- export declare interface BillingResources {
270
+ declare interface BillingResources_2 {
228
271
  /** `GET /company/invoices?limit&offset&include_pending`. */
229
272
  invoices: InvoicePage;
273
+ /**
274
+ * `GET /company/upcoming-invoice`. `null` is a loaded value — the company
275
+ * has no next bill, which the endpoint reports as a 204 — so only
276
+ * `undefined` means the resource has not loaded.
277
+ */
278
+ upcomingInvoice: UpcomingInvoice | null;
230
279
  }
231
280
 
232
281
  declare type BooleanListenerFn = (value: boolean) => void;
@@ -397,6 +446,8 @@ export declare type CheckFlagReturn = {
397
446
  userId?: string;
398
447
  /** A boolean flag check result; for feature entitlements, this represents whether further consumption of the feature is permitted */
399
448
  value: boolean;
449
+ /** Customer-defined usage warning thresholds configured on this entitlement */
450
+ warningTiers?: WarningTier[];
400
451
  };
401
452
 
402
453
  declare const CheckFlagReturnFromJSON: (json: any) => CheckFlagReturn;
@@ -507,6 +558,67 @@ export declare interface CompanyCreditBalance {
507
558
  settled: number;
508
559
  }
509
560
 
561
+ /**
562
+ * Schematic API
563
+ * Schematic API
564
+ *
565
+ * The version of the OpenAPI document: 0.1
566
+ *
567
+ *
568
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
569
+ * https://openapi-generator.tech
570
+ * Do not edit the class manually.
571
+ */
572
+ /**
573
+ *
574
+ * @export
575
+ * @interface CompanyDiscountResponseData
576
+ */
577
+ declare interface CompanyDiscountResponseData {
578
+ /**
579
+ *
580
+ * @type {number}
581
+ * @memberof CompanyDiscountResponseData
582
+ */
583
+ amountOff?: number | null;
584
+ /**
585
+ *
586
+ * @type {string}
587
+ * @memberof CompanyDiscountResponseData
588
+ */
589
+ couponName: string;
590
+ /**
591
+ *
592
+ * @type {string}
593
+ * @memberof CompanyDiscountResponseData
594
+ */
595
+ currency?: string | null;
596
+ /**
597
+ *
598
+ * @type {string}
599
+ * @memberof CompanyDiscountResponseData
600
+ */
601
+ customerFacingCode?: string | null;
602
+ /**
603
+ * Provider vocabulary: once, repeating, or forever.
604
+ * @type {string}
605
+ * @memberof CompanyDiscountResponseData
606
+ */
607
+ duration: string;
608
+ /**
609
+ *
610
+ * @type {number}
611
+ * @memberof CompanyDiscountResponseData
612
+ */
613
+ durationInMonths?: number | null;
614
+ /**
615
+ *
616
+ * @type {number}
617
+ * @memberof CompanyDiscountResponseData
618
+ */
619
+ percentOff?: number | null;
620
+ }
621
+
510
622
  /**
511
623
  *
512
624
  * @export
@@ -557,6 +669,56 @@ declare interface CompanyInvoiceResponseData {
557
669
  url?: string | null;
558
670
  }
559
671
 
672
+ /**
673
+ *
674
+ * @export
675
+ * @interface CompanyUpcomingInvoiceResponseData
676
+ */
677
+ declare interface CompanyUpcomingInvoiceResponseData {
678
+ /**
679
+ *
680
+ * @type {number}
681
+ * @memberof CompanyUpcomingInvoiceResponseData
682
+ */
683
+ amountDue: number;
684
+ /**
685
+ *
686
+ * @type {string}
687
+ * @memberof CompanyUpcomingInvoiceResponseData
688
+ */
689
+ currency: string;
690
+ /**
691
+ * How much of the company's existing balance this invoice consumes.
692
+ * @type {number}
693
+ * @memberof CompanyUpcomingInvoiceResponseData
694
+ */
695
+ customerBalanceApplied: number;
696
+ /**
697
+ * Balance left over after this invoice.
698
+ * @type {number}
699
+ * @memberof CompanyUpcomingInvoiceResponseData
700
+ */
701
+ customerBalanceRemaining: number;
702
+ /**
703
+ * Only active discounts that reduce the bill.
704
+ * @type {Array<CompanyDiscountResponseData>}
705
+ * @memberof CompanyUpcomingInvoiceResponseData
706
+ */
707
+ discounts: Array<CompanyDiscountResponseData>;
708
+ /**
709
+ *
710
+ * @type {Date}
711
+ * @memberof CompanyUpcomingInvoiceResponseData
712
+ */
713
+ dueDate?: Date | null;
714
+ /**
715
+ * Amount before discounts and tax.
716
+ * @type {number}
717
+ * @memberof CompanyUpcomingInvoiceResponseData
718
+ */
719
+ subtotal: number;
720
+ }
721
+
560
722
  /** A company's lease-aware balance for a single credit type */
561
723
  export declare type CreditBalance = {
562
724
  /** Spendable balance including any open lease hold (remaining + reserved); the number to display to end users */
@@ -612,6 +774,8 @@ declare function DatastreamCompanyPlanFromJSON(json: any): DatastreamCompanyPlan
612
774
 
613
775
  export declare const DEFAULT_INVOICE_QUERY: InvoiceQuery;
614
776
 
777
+ export declare type Discount = CompanyDiscountResponseData;
778
+
615
779
  declare type EmptyListenerFn = () => void;
616
780
 
617
781
  /**
@@ -879,7 +1043,7 @@ declare interface FeatureEntitlement {
879
1043
  * Server prefetch for a provider's `initialData`. A resource that fails is
880
1044
  * left out rather than thrown, so one of them cannot block a page.
881
1045
  */
882
- declare function fetchBillingData(client: BillingClient, options?: BillingPrefetchOptions): Promise<BillingData>;
1046
+ declare function fetchBillingData(client: BillingClient, options: BillingPrefetchOptions): Promise<BillingData>;
883
1047
 
884
1048
  declare type FlagCheckListenerFn = CheckFlagReturnListenerFn | EmptyListenerFn;
885
1049
 
@@ -989,6 +1153,14 @@ declare type PlanListenerFn = CheckPlanReturnListenerFn | EmptyListenerFn;
989
1153
  declare interface RequestOptions {
990
1154
  method?: string;
991
1155
  body?: unknown;
1156
+ /**
1157
+ * Success statuses that carry no body — a 204 for a resource that is
1158
+ * legitimately absent. The request resolves `undefined` for them, which
1159
+ * is distinct from a body that parsed to `null`. A 401 is never one — the
1160
+ * refresh and retry run first, and only what comes back from that is
1161
+ * judged.
1162
+ */
1163
+ noContentOn?: number[];
992
1164
  }
993
1165
 
994
1166
  export declare interface ResourceHandle<T> extends ResourceState<T> {
@@ -1318,6 +1490,7 @@ declare class SchematicBillingClient implements BillingClient {
1318
1490
  setSession(session: SessionInput): void;
1319
1491
  onSessionChange(listener: (event: SessionEvent) => void): () => void;
1320
1492
  fetchInvoices(params: InvoicesRequest): Promise<InvoicesResult>;
1493
+ fetchUpcomingInvoice(): Promise<UpcomingInvoice | null>;
1321
1494
  }
1322
1495
 
1323
1496
  /** Context for checking flags and sending events */
@@ -1386,9 +1559,9 @@ declare namespace SchematicJS {
1386
1559
  BillingClientOptions,
1387
1560
  BillingData,
1388
1561
  BillingPrefetchOptions,
1389
- BillingResourceName,
1390
- BillingResourceParams,
1391
- BillingResources,
1562
+ BillingResourceName_2 as BillingResourceName,
1563
+ BillingResourceParams_2 as BillingResourceParams,
1564
+ BillingResources_2 as BillingResources,
1392
1565
  BooleanListenerFn,
1393
1566
  CheckFlagResponseData,
1394
1567
  CheckFlagReturn,
@@ -1399,13 +1572,16 @@ declare namespace SchematicJS {
1399
1572
  CheckPlanReturnFromJSON,
1400
1573
  CheckPlanReturnListenerFn,
1401
1574
  CompanyCreditBalance,
1575
+ CompanyDiscountResponseData,
1402
1576
  CompanyInvoiceResponseData,
1577
+ CompanyUpcomingInvoiceResponseData,
1403
1578
  CreditBalance,
1404
1579
  CreditBalanceListenerFn,
1405
1580
  CreditBalances,
1406
1581
  CreditBalancesFromJSON,
1407
1582
  CreditBalancesListenerFn,
1408
1583
  DEFAULT_INVOICE_QUERY,
1584
+ Discount,
1409
1585
  EmptyListenerFn,
1410
1586
  Event_2 as Event,
1411
1587
  EventBody,
@@ -1440,11 +1616,14 @@ declare namespace SchematicJS {
1440
1616
  SessionInput,
1441
1617
  SessionOptions,
1442
1618
  SessionStatus,
1619
+ SINGLETON,
1443
1620
  StoragePersister,
1444
1621
  TOKEN_CACHE_SIZE,
1445
1622
  Traits,
1446
1623
  TrialStatus,
1447
- UsagePeriod
1624
+ UpcomingInvoice,
1625
+ UsagePeriod,
1626
+ WarningTier
1448
1627
  }
1449
1628
  }
1450
1629
 
@@ -1617,6 +1796,9 @@ declare interface SessionOptions {
1617
1796
 
1618
1797
  export declare type SessionStatus = "pending" | "active" | "ended";
1619
1798
 
1799
+ /** The params of every singleton resource. */
1800
+ export declare const SINGLETON: Record<string, never>;
1801
+
1620
1802
  /** Optional type for implementing custom client-side storage */
1621
1803
  export declare type StoragePersister = {
1622
1804
  setItem(key: string, value: any): void;
@@ -1674,6 +1856,8 @@ export declare const TrialStatus: {
1674
1856
 
1675
1857
  export declare type TrialStatus = (typeof TrialStatus)[keyof typeof TrialStatus];
1676
1858
 
1859
+ export declare type UpcomingInvoice = CompanyUpcomingInvoiceResponseData;
1860
+
1677
1861
  export declare enum UsagePeriod {
1678
1862
  ALL_TIME = "all_time",
1679
1863
  CURRENT_DAY = "current_day",
@@ -1744,6 +1928,13 @@ export declare function useSchematicStrings(): StringOverrides | undefined;
1744
1928
 
1745
1929
  export declare function useSchematicTranslate(): Translate | undefined;
1746
1930
 
1931
+ /**
1932
+ * The company's next bill. `data` is `null` when there is nothing to bill —
1933
+ * no subscription, which the endpoint reports as a 204 — so an element can
1934
+ * render an empty state; `data === undefined` is what means not loaded yet.
1935
+ */
1936
+ export declare function useUpcomingInvoice(): ResourceHandle<UpcomingInvoice | null>;
1937
+
1747
1938
  /**
1748
1939
  * Schematic API
1749
1940
  * Schematic API
@@ -1760,7 +1951,7 @@ export declare function useSchematicTranslate(): Translate | undefined;
1760
1951
  * @export
1761
1952
  * @interface WarningTier
1762
1953
  */
1763
- declare interface WarningTier {
1954
+ export declare interface WarningTier {
1764
1955
  /**
1765
1956
  * A customer-defined identifier for the warning tier
1766
1957
  * @type {string}
@@ -1,4 +1,4 @@
1
- // node_modules/.pnpm/@schematichq+schematic-js@1.7.0/node_modules/@schematichq/schematic-js/dist/schematic.esm.js
1
+ // node_modules/.pnpm/@schematichq+schematic-js@1.8.0/node_modules/@schematichq/schematic-js/dist/schematic.esm.js
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -1103,7 +1103,8 @@ var CheckFlagReturnFromJSON = (json) => {
1103
1103
  ruleType: ruleType == null ? void 0 : ruleType,
1104
1104
  softLimit: entitlement?.softLimit == null ? void 0 : entitlement.softLimit,
1105
1105
  userId: userId == null ? void 0 : userId,
1106
- value
1106
+ value,
1107
+ warningTiers: entitlement?.warningTiers == null ? void 0 : entitlement.warningTiers
1107
1108
  };
1108
1109
  };
1109
1110
  var CheckPlanReturnFromJSON = (json) => {
@@ -1130,7 +1131,7 @@ var CreditBalancesFromJSON = (json) => {
1130
1131
  }
1131
1132
  return balances;
1132
1133
  };
1133
- var cacheVersion = "bb56e75d";
1134
+ var cacheVersion = "7b920cf4";
1134
1135
  function contextString(context) {
1135
1136
  const sortedContext = Object.keys(context).reduce((acc, key) => {
1136
1137
  const sortedKeys = Object.keys(
@@ -1145,13 +1146,18 @@ function contextString(context) {
1145
1146
  }, {});
1146
1147
  return JSON.stringify(sortedContext);
1147
1148
  }
1148
- var version = "1.7.0";
1149
+ var version = "1.8.0";
1150
+ var SINGLETON = {};
1149
1151
  var models_exports = {};
1150
1152
  __export(models_exports, {
1151
1153
  ApiErrorFromJSON: () => ApiErrorFromJSON,
1152
1154
  ApiErrorFromJSONTyped: () => ApiErrorFromJSONTyped,
1153
1155
  ApiErrorToJSON: () => ApiErrorToJSON,
1154
1156
  ApiErrorToJSONTyped: () => ApiErrorToJSONTyped,
1157
+ CompanyDiscountResponseDataFromJSON: () => CompanyDiscountResponseDataFromJSON,
1158
+ CompanyDiscountResponseDataFromJSONTyped: () => CompanyDiscountResponseDataFromJSONTyped,
1159
+ CompanyDiscountResponseDataToJSON: () => CompanyDiscountResponseDataToJSON,
1160
+ CompanyDiscountResponseDataToJSONTyped: () => CompanyDiscountResponseDataToJSONTyped,
1155
1161
  CompanyInvoiceResponseDataFromJSON: () => CompanyInvoiceResponseDataFromJSON,
1156
1162
  CompanyInvoiceResponseDataFromJSONTyped: () => CompanyInvoiceResponseDataFromJSONTyped,
1157
1163
  CompanyInvoiceResponseDataToJSON: () => CompanyInvoiceResponseDataToJSON,
@@ -1160,6 +1166,10 @@ __export(models_exports, {
1160
1166
  CompanyInvoicesResponseDataFromJSONTyped: () => CompanyInvoicesResponseDataFromJSONTyped,
1161
1167
  CompanyInvoicesResponseDataToJSON: () => CompanyInvoicesResponseDataToJSON,
1162
1168
  CompanyInvoicesResponseDataToJSONTyped: () => CompanyInvoicesResponseDataToJSONTyped,
1169
+ CompanyUpcomingInvoiceResponseDataFromJSON: () => CompanyUpcomingInvoiceResponseDataFromJSON,
1170
+ CompanyUpcomingInvoiceResponseDataFromJSONTyped: () => CompanyUpcomingInvoiceResponseDataFromJSONTyped,
1171
+ CompanyUpcomingInvoiceResponseDataToJSON: () => CompanyUpcomingInvoiceResponseDataToJSON,
1172
+ CompanyUpcomingInvoiceResponseDataToJSONTyped: () => CompanyUpcomingInvoiceResponseDataToJSONTyped,
1163
1173
  GetCompanyInvoicesParamsFromJSON: () => GetCompanyInvoicesParamsFromJSON,
1164
1174
  GetCompanyInvoicesParamsFromJSONTyped: () => GetCompanyInvoicesParamsFromJSONTyped,
1165
1175
  GetCompanyInvoicesParamsToJSON: () => GetCompanyInvoicesParamsToJSON,
@@ -1168,16 +1178,23 @@ __export(models_exports, {
1168
1178
  GetCompanyInvoicesResponseFromJSONTyped: () => GetCompanyInvoicesResponseFromJSONTyped,
1169
1179
  GetCompanyInvoicesResponseToJSON: () => GetCompanyInvoicesResponseToJSON,
1170
1180
  GetCompanyInvoicesResponseToJSONTyped: () => GetCompanyInvoicesResponseToJSONTyped,
1181
+ GetCompanyUpcomingInvoiceResponseFromJSON: () => GetCompanyUpcomingInvoiceResponseFromJSON,
1182
+ GetCompanyUpcomingInvoiceResponseFromJSONTyped: () => GetCompanyUpcomingInvoiceResponseFromJSONTyped,
1183
+ GetCompanyUpcomingInvoiceResponseToJSON: () => GetCompanyUpcomingInvoiceResponseToJSON,
1184
+ GetCompanyUpcomingInvoiceResponseToJSONTyped: () => GetCompanyUpcomingInvoiceResponseToJSONTyped,
1171
1185
  InvoiceStatus: () => InvoiceStatus,
1172
1186
  InvoiceStatusFromJSON: () => InvoiceStatusFromJSON,
1173
1187
  InvoiceStatusFromJSONTyped: () => InvoiceStatusFromJSONTyped,
1174
1188
  InvoiceStatusToJSON: () => InvoiceStatusToJSON,
1175
1189
  InvoiceStatusToJSONTyped: () => InvoiceStatusToJSONTyped,
1176
1190
  instanceOfApiError: () => instanceOfApiError,
1191
+ instanceOfCompanyDiscountResponseData: () => instanceOfCompanyDiscountResponseData,
1177
1192
  instanceOfCompanyInvoiceResponseData: () => instanceOfCompanyInvoiceResponseData,
1178
1193
  instanceOfCompanyInvoicesResponseData: () => instanceOfCompanyInvoicesResponseData,
1194
+ instanceOfCompanyUpcomingInvoiceResponseData: () => instanceOfCompanyUpcomingInvoiceResponseData,
1179
1195
  instanceOfGetCompanyInvoicesParams: () => instanceOfGetCompanyInvoicesParams,
1180
1196
  instanceOfGetCompanyInvoicesResponse: () => instanceOfGetCompanyInvoicesResponse,
1197
+ instanceOfGetCompanyUpcomingInvoiceResponse: () => instanceOfGetCompanyUpcomingInvoiceResponse,
1181
1198
  instanceOfInvoiceStatus: () => instanceOfInvoiceStatus
1182
1199
  });
1183
1200
  function instanceOfApiError(value) {
@@ -1206,6 +1223,46 @@ function ApiErrorToJSONTyped(value, ignoreDiscriminator = false) {
1206
1223
  error: value["error"]
1207
1224
  };
1208
1225
  }
1226
+ function instanceOfCompanyDiscountResponseData(value) {
1227
+ if (!("couponName" in value) || value["couponName"] === void 0)
1228
+ return false;
1229
+ if (!("duration" in value) || value["duration"] === void 0) return false;
1230
+ return true;
1231
+ }
1232
+ function CompanyDiscountResponseDataFromJSON(json) {
1233
+ return CompanyDiscountResponseDataFromJSONTyped(json, false);
1234
+ }
1235
+ function CompanyDiscountResponseDataFromJSONTyped(json, ignoreDiscriminator) {
1236
+ if (json == null) {
1237
+ return json;
1238
+ }
1239
+ return {
1240
+ amountOff: json["amount_off"] == null ? void 0 : json["amount_off"],
1241
+ couponName: json["coupon_name"],
1242
+ currency: json["currency"] == null ? void 0 : json["currency"],
1243
+ customerFacingCode: json["customer_facing_code"] == null ? void 0 : json["customer_facing_code"],
1244
+ duration: json["duration"],
1245
+ durationInMonths: json["duration_in_months"] == null ? void 0 : json["duration_in_months"],
1246
+ percentOff: json["percent_off"] == null ? void 0 : json["percent_off"]
1247
+ };
1248
+ }
1249
+ function CompanyDiscountResponseDataToJSON(json) {
1250
+ return CompanyDiscountResponseDataToJSONTyped(json, false);
1251
+ }
1252
+ function CompanyDiscountResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
1253
+ if (value == null) {
1254
+ return value;
1255
+ }
1256
+ return {
1257
+ amount_off: value["amountOff"],
1258
+ coupon_name: value["couponName"],
1259
+ currency: value["currency"],
1260
+ customer_facing_code: value["customerFacingCode"],
1261
+ duration: value["duration"],
1262
+ duration_in_months: value["durationInMonths"],
1263
+ percent_off: value["percentOff"]
1264
+ };
1265
+ }
1209
1266
  var InvoiceStatus = {
1210
1267
  Draft: "draft",
1211
1268
  Open: "open",
@@ -1309,6 +1366,55 @@ function CompanyInvoicesResponseDataToJSONTyped(value, ignoreDiscriminator = fal
1309
1366
  )
1310
1367
  };
1311
1368
  }
1369
+ function instanceOfCompanyUpcomingInvoiceResponseData(value) {
1370
+ if (!("amountDue" in value) || value["amountDue"] === void 0) return false;
1371
+ if (!("currency" in value) || value["currency"] === void 0) return false;
1372
+ if (!("customerBalanceApplied" in value) || value["customerBalanceApplied"] === void 0)
1373
+ return false;
1374
+ if (!("customerBalanceRemaining" in value) || value["customerBalanceRemaining"] === void 0)
1375
+ return false;
1376
+ if (!("discounts" in value) || value["discounts"] === void 0) return false;
1377
+ if (!("subtotal" in value) || value["subtotal"] === void 0) return false;
1378
+ return true;
1379
+ }
1380
+ function CompanyUpcomingInvoiceResponseDataFromJSON(json) {
1381
+ return CompanyUpcomingInvoiceResponseDataFromJSONTyped(json, false);
1382
+ }
1383
+ function CompanyUpcomingInvoiceResponseDataFromJSONTyped(json, ignoreDiscriminator) {
1384
+ if (json == null) {
1385
+ return json;
1386
+ }
1387
+ return {
1388
+ amountDue: json["amount_due"],
1389
+ currency: json["currency"],
1390
+ customerBalanceApplied: json["customer_balance_applied"],
1391
+ customerBalanceRemaining: json["customer_balance_remaining"],
1392
+ discounts: json["discounts"].map(
1393
+ CompanyDiscountResponseDataFromJSON
1394
+ ),
1395
+ dueDate: json["due_date"] == null ? void 0 : new Date(json["due_date"]),
1396
+ subtotal: json["subtotal"]
1397
+ };
1398
+ }
1399
+ function CompanyUpcomingInvoiceResponseDataToJSON(json) {
1400
+ return CompanyUpcomingInvoiceResponseDataToJSONTyped(json, false);
1401
+ }
1402
+ function CompanyUpcomingInvoiceResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
1403
+ if (value == null) {
1404
+ return value;
1405
+ }
1406
+ return {
1407
+ amount_due: value["amountDue"],
1408
+ currency: value["currency"],
1409
+ customer_balance_applied: value["customerBalanceApplied"],
1410
+ customer_balance_remaining: value["customerBalanceRemaining"],
1411
+ discounts: value["discounts"].map(
1412
+ CompanyDiscountResponseDataToJSON
1413
+ ),
1414
+ due_date: value["dueDate"] == null ? void 0 : value["dueDate"].toISOString(),
1415
+ subtotal: value["subtotal"]
1416
+ };
1417
+ }
1312
1418
  function instanceOfGetCompanyInvoicesParams(value) {
1313
1419
  return true;
1314
1420
  }
@@ -1367,6 +1473,35 @@ function GetCompanyInvoicesResponseToJSONTyped(value, ignoreDiscriminator = fals
1367
1473
  params: GetCompanyInvoicesParamsToJSON(value["params"])
1368
1474
  };
1369
1475
  }
1476
+ function instanceOfGetCompanyUpcomingInvoiceResponse(value) {
1477
+ if (!("data" in value) || value["data"] === void 0) return false;
1478
+ if (!("params" in value) || value["params"] === void 0) return false;
1479
+ return true;
1480
+ }
1481
+ function GetCompanyUpcomingInvoiceResponseFromJSON(json) {
1482
+ return GetCompanyUpcomingInvoiceResponseFromJSONTyped(json, false);
1483
+ }
1484
+ function GetCompanyUpcomingInvoiceResponseFromJSONTyped(json, ignoreDiscriminator) {
1485
+ if (json == null) {
1486
+ return json;
1487
+ }
1488
+ return {
1489
+ data: CompanyUpcomingInvoiceResponseDataFromJSON(json["data"]),
1490
+ params: json["params"]
1491
+ };
1492
+ }
1493
+ function GetCompanyUpcomingInvoiceResponseToJSON(json) {
1494
+ return GetCompanyUpcomingInvoiceResponseToJSONTyped(json, false);
1495
+ }
1496
+ function GetCompanyUpcomingInvoiceResponseToJSONTyped(value, ignoreDiscriminator = false) {
1497
+ if (value == null) {
1498
+ return value;
1499
+ }
1500
+ return {
1501
+ data: CompanyUpcomingInvoiceResponseDataToJSON(value["data"]),
1502
+ params: value["params"]
1503
+ };
1504
+ }
1370
1505
  var DEFAULT_INVOICE_QUERY = {};
1371
1506
  function normalizeInvoiceQuery(query) {
1372
1507
  const { includePending, ...rest } = query;
@@ -1582,6 +1717,11 @@ var SchematicSession = class {
1582
1717
  throw new SchematicApiError(status, path, rejected);
1583
1718
  }
1584
1719
  }
1720
+ if (options.noContentOn?.includes(response.status) === true) {
1721
+ await discardBody(response);
1722
+ await stillOurs();
1723
+ return void 0;
1724
+ }
1585
1725
  const parsed = await readBody(response);
1586
1726
  await stillOurs();
1587
1727
  if (!response.ok) {
@@ -1674,6 +1814,18 @@ var SchematicBillingClient = class {
1674
1814
  return { invoices: decoded.invoices, count: decoded.count };
1675
1815
  });
1676
1816
  }
1817
+ fetchUpcomingInvoice() {
1818
+ const path = "/company/upcoming-invoice";
1819
+ return this.session.request(path, { noContentOn: [204] }).then((body) => {
1820
+ if (body === void 0) {
1821
+ return null;
1822
+ }
1823
+ if (body === null || typeof body !== "object" || !("data" in body)) {
1824
+ throw new Error(`Malformed response from ${path}`);
1825
+ }
1826
+ return GetCompanyUpcomingInvoiceResponseFromJSON(body).data;
1827
+ });
1828
+ }
1677
1829
  };
1678
1830
  var anonymousIdKey = "schematicId";
1679
1831
  var flagStateCachePrefix = "schematicCache";
@@ -3782,33 +3934,40 @@ var BillingStore = class {
3782
3934
  constructor(_client, initialData = {}, options = {}) {
3783
3935
  this._client = _client;
3784
3936
  this._pageSize = options.pageSize ?? INVOICE_PAGE_SIZE;
3937
+ const readiness = () => this._connected ? READINESS[this._client.sessionStatus] : "waiting";
3785
3938
  this.invoices = new KeyedResource(
3786
3939
  (query, current) => this._reloadWindow(
3787
3940
  query,
3788
3941
  Math.max(this._pageSize, current?.invoices.length ?? 0)
3789
3942
  ),
3790
- // Waiting until connected; then a session still pending stays
3791
- // pending, and one that has ended settles empty rather than recording
3792
- // the client's refusal as an error.
3793
- {
3794
- readiness: () => this._connected ? READINESS[this._client.sessionStatus] : "waiting"
3795
- }
3943
+ { readiness }
3944
+ );
3945
+ this.upcomingInvoice = new KeyedResource(
3946
+ () => this._client.fetchUpcomingInvoice(),
3947
+ { readiness }
3796
3948
  );
3949
+ const held = { key: initialData.sessionKey };
3797
3950
  if (initialData.invoices !== void 0) {
3798
- this._held = {
3951
+ held.invoices = {
3799
3952
  // Normalized the way the hook normalizes, or the caller asking for
3800
3953
  // it fetches the same page again.
3801
3954
  params: normalizeInvoiceQuery2(
3802
3955
  initialData.params?.invoices ?? DEFAULT_INVOICE_QUERY
3803
3956
  ),
3804
- data: initialData.invoices,
3805
- key: initialData.sessionKey
3957
+ data: initialData.invoices
3806
3958
  };
3959
+ }
3960
+ if (initialData.upcomingInvoice !== void 0) {
3961
+ held.upcomingInvoice = initialData.upcomingInvoice;
3962
+ }
3963
+ if (held.invoices !== void 0 || held.upcomingInvoice !== void 0) {
3964
+ this._held = held;
3807
3965
  this._settleSeed(claimFrom(options.session) ?? claimOf(this._client));
3808
3966
  }
3809
3967
  }
3810
3968
  _client;
3811
3969
  invoices;
3970
+ upcomingInvoice;
3812
3971
  _pageSize;
3813
3972
  _unsubscribe;
3814
3973
  _connected = false;
@@ -3878,7 +4037,12 @@ var BillingStore = class {
3878
4037
  }
3879
4038
  this._held = void 0;
3880
4039
  if (verdict === "adopt") {
3881
- this.invoices.seed(held.params, held.data);
4040
+ if (held.invoices !== void 0) {
4041
+ this.invoices.seed(held.invoices.params, held.invoices.data);
4042
+ }
4043
+ if (held.upcomingInvoice !== void 0) {
4044
+ this.upcomingInvoice.seed(SINGLETON, held.upcomingInvoice);
4045
+ }
3882
4046
  this._seedKey = held.key;
3883
4047
  this._seeded = true;
3884
4048
  }
@@ -3980,7 +4144,10 @@ var BillingStore = class {
3980
4144
  return this._client.fetchInvoices({ ...query, limit, offset });
3981
4145
  }
3982
4146
  };
3983
- var RESOURCE_NAMES = ["invoices"];
4147
+ var RESOURCE_NAMES = [
4148
+ "invoices",
4149
+ "upcomingInvoice"
4150
+ ];
3984
4151
 
3985
4152
  // src/billing/context.tsx
3986
4153
  import { createContext as createContext2, useContext as useContext2, useMemo as useMemo2 } from "react";
@@ -4131,6 +4298,9 @@ function useInvoices(query = DEFAULT_INVOICE_QUERY) {
4131
4298
  );
4132
4299
  return useMemo3(() => ({ ...handle, loadMore }), [handle, loadMore]);
4133
4300
  }
4301
+ function useUpcomingInvoice() {
4302
+ return useBillingResource("upcomingInvoice", SINGLETON);
4303
+ }
4134
4304
  function useInvalidateBillingData() {
4135
4305
  return useBillingDataSource().invalidateAll;
4136
4306
  }
@@ -4250,7 +4420,7 @@ function staticSource(data) {
4250
4420
  }
4251
4421
 
4252
4422
  // src/version.ts
4253
- var version2 = "1.6.0";
4423
+ var version2 = "1.8.0";
4254
4424
 
4255
4425
  // src/context/schematic.tsx
4256
4426
  import { jsx as jsx4 } from "react/jsx-runtime";
@@ -4474,6 +4644,7 @@ export {
4474
4644
  INVOICE_PAGE_SIZE,
4475
4645
  InvoiceStatus,
4476
4646
  RuleType,
4647
+ SINGLETON,
4477
4648
  Schematic,
4478
4649
  SchematicI18nContext,
4479
4650
  SchematicI18nProvider,
@@ -4495,7 +4666,8 @@ export {
4495
4666
  useSchematicLocale,
4496
4667
  useSchematicPlan,
4497
4668
  useSchematicStrings,
4498
- useSchematicTranslate
4669
+ useSchematicTranslate,
4670
+ useUpcomingInvoice
4499
4671
  };
4500
4672
  /*! Bundled license information:
4501
4673
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schematichq/schematic-react",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "main": "dist/schematic-react.cjs.js",
5
5
  "module": "dist/schematic-react.esm.js",
6
6
  "types": "dist/schematic-react.d.ts",
@@ -34,24 +34,24 @@
34
34
  "devDependencies": {
35
35
  "@eslint/js": "^10.0.1",
36
36
  "@microsoft/api-extractor": "^7.59.1",
37
- "@schematichq/schematic-js": "^1.7.0",
38
- "@testing-library/dom": "^10.4.1",
37
+ "@schematichq/schematic-js": "^1.8.0",
38
+ "@testing-library/dom": "^10.4.2",
39
39
  "@testing-library/jest-dom": "^7.0.1",
40
40
  "@testing-library/react": "^16.3.3",
41
- "@types/react": "^19.2.18",
41
+ "@types/react": "^19.3.0",
42
42
  "@vitest/browser": "^5.0.0",
43
43
  "esbuild": "^0.28.2",
44
- "eslint": "^10.10.0",
44
+ "eslint": "^10.11.0",
45
45
  "eslint-plugin-import": "^2.32.0",
46
46
  "eslint-plugin-react": "^7.37.5",
47
47
  "eslint-plugin-react-hooks": "^7.1.1",
48
48
  "globals": "^17.12.0",
49
- "happy-dom": "^20.14.0",
49
+ "happy-dom": "^20.14.5",
50
50
  "husky": "^9.1.7",
51
- "jsdom": "^30.0.1",
52
- "prettier": "^3.9.6",
53
- "react": "^19.2.8",
54
- "react-dom": "^19.2.8",
51
+ "jsdom": "^30.1.0",
52
+ "prettier": "^3.9.8",
53
+ "react": "^19.3.0",
54
+ "react-dom": "^19.3.0",
55
55
  "typescript": "^6.0.3",
56
56
  "typescript-eslint": "^8.70.0",
57
57
  "vitest": "^5.0.0"