@schematichq/schematic-react 1.5.0 → 1.7.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.
@@ -1,4 +1,4 @@
1
- // 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;
@@ -12,6 +12,10 @@ var __commonJS = (cb, mod) => function __require() {
12
12
  throw mod = 0, e;
13
13
  }
14
14
  };
15
+ var __export = (target, all) => {
16
+ for (var name in all)
17
+ __defProp(target, name, { get: all[name], enumerable: true });
18
+ };
15
19
  var __copyProps = (to, from, except, desc) => {
16
20
  if (from && typeof from === "object" || typeof from === "function") {
17
21
  for (let key of __getOwnPropNames(from))
@@ -29,7 +33,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
33
  mod
30
34
  ));
31
35
  var require_browser_polyfill = __commonJS({
32
- "node_modules/cross-fetch/dist/browser-polyfill.js"(exports) {
36
+ "node_modules/.pnpm/cross-fetch@4.1.0/node_modules/cross-fetch/dist/browser-polyfill.js"(exports) {
33
37
  (function(self2) {
34
38
  var irrelevant = (function(exports2) {
35
39
  var g = typeof globalThis !== "undefined" && globalThis || typeof self2 !== "undefined" && self2 || // eslint-disable-next-line no-undef
@@ -613,6 +617,18 @@ function MetricPeriodMonthResetFromJSON(json) {
613
617
  function MetricPeriodMonthResetFromJSONTyped(json, ignoreDiscriminator) {
614
618
  return json;
615
619
  }
620
+ function WarningTierFromJSON(json) {
621
+ return WarningTierFromJSONTyped(json, false);
622
+ }
623
+ function WarningTierFromJSONTyped(json, ignoreDiscriminator) {
624
+ if (json == null) {
625
+ return json;
626
+ }
627
+ return {
628
+ key: json["key"],
629
+ value: json["value"]
630
+ };
631
+ }
616
632
  function MetricPeriodFromJSON(json) {
617
633
  return MetricPeriodFromJSONTyped(json, false);
618
634
  }
@@ -644,7 +660,8 @@ function FeatureEntitlementFromJSONTyped(json, ignoreDiscriminator) {
644
660
  monthReset: json["month_reset"] == null ? void 0 : MetricPeriodMonthResetFromJSON(json["month_reset"]),
645
661
  softLimit: json["soft_limit"] == null ? void 0 : json["soft_limit"],
646
662
  usage: json["usage"] == null ? void 0 : json["usage"],
647
- valueType: EntitlementValueTypeFromJSON(json["value_type"])
663
+ valueType: EntitlementValueTypeFromJSON(json["value_type"]),
664
+ warningTiers: json["warning_tiers"] == null ? void 0 : json["warning_tiers"].map(WarningTierFromJSON)
648
665
  };
649
666
  }
650
667
  function RuleTypeFromJSON(json) {
@@ -1014,6 +1031,7 @@ function EventBodyFlagCheckToJSONTyped(value, ignoreDiscriminator = false) {
1014
1031
  error: value["error"],
1015
1032
  flag_id: value["flagId"],
1016
1033
  flag_key: value["flagKey"],
1034
+ preflight: value["preflight"],
1017
1035
  reason: value["reason"],
1018
1036
  req_company: value["reqCompany"],
1019
1037
  req_user: value["reqUser"],
@@ -1085,7 +1103,8 @@ var CheckFlagReturnFromJSON = (json) => {
1085
1103
  ruleType: ruleType == null ? void 0 : ruleType,
1086
1104
  softLimit: entitlement?.softLimit == null ? void 0 : entitlement.softLimit,
1087
1105
  userId: userId == null ? void 0 : userId,
1088
- value
1106
+ value,
1107
+ warningTiers: entitlement?.warningTiers == null ? void 0 : entitlement.warningTiers
1089
1108
  };
1090
1109
  };
1091
1110
  var CheckPlanReturnFromJSON = (json) => {
@@ -1112,7 +1131,7 @@ var CreditBalancesFromJSON = (json) => {
1112
1131
  }
1113
1132
  return balances;
1114
1133
  };
1115
- var cacheVersion = "bb56e75d";
1134
+ var cacheVersion = "7b920cf4";
1116
1135
  function contextString(context) {
1117
1136
  const sortedContext = Object.keys(context).reduce((acc, key) => {
1118
1137
  const sortedKeys = Object.keys(
@@ -1127,16 +1146,695 @@ function contextString(context) {
1127
1146
  }, {});
1128
1147
  return JSON.stringify(sortedContext);
1129
1148
  }
1130
- var version = "1.5.0";
1149
+ var version = "1.8.0";
1150
+ var models_exports = {};
1151
+ __export(models_exports, {
1152
+ ApiErrorFromJSON: () => ApiErrorFromJSON,
1153
+ ApiErrorFromJSONTyped: () => ApiErrorFromJSONTyped,
1154
+ ApiErrorToJSON: () => ApiErrorToJSON,
1155
+ ApiErrorToJSONTyped: () => ApiErrorToJSONTyped,
1156
+ CompanyDiscountResponseDataFromJSON: () => CompanyDiscountResponseDataFromJSON,
1157
+ CompanyDiscountResponseDataFromJSONTyped: () => CompanyDiscountResponseDataFromJSONTyped,
1158
+ CompanyDiscountResponseDataToJSON: () => CompanyDiscountResponseDataToJSON,
1159
+ CompanyDiscountResponseDataToJSONTyped: () => CompanyDiscountResponseDataToJSONTyped,
1160
+ CompanyInvoiceResponseDataFromJSON: () => CompanyInvoiceResponseDataFromJSON,
1161
+ CompanyInvoiceResponseDataFromJSONTyped: () => CompanyInvoiceResponseDataFromJSONTyped,
1162
+ CompanyInvoiceResponseDataToJSON: () => CompanyInvoiceResponseDataToJSON,
1163
+ CompanyInvoiceResponseDataToJSONTyped: () => CompanyInvoiceResponseDataToJSONTyped,
1164
+ CompanyInvoicesResponseDataFromJSON: () => CompanyInvoicesResponseDataFromJSON,
1165
+ CompanyInvoicesResponseDataFromJSONTyped: () => CompanyInvoicesResponseDataFromJSONTyped,
1166
+ CompanyInvoicesResponseDataToJSON: () => CompanyInvoicesResponseDataToJSON,
1167
+ CompanyInvoicesResponseDataToJSONTyped: () => CompanyInvoicesResponseDataToJSONTyped,
1168
+ CompanyUpcomingInvoiceResponseDataFromJSON: () => CompanyUpcomingInvoiceResponseDataFromJSON,
1169
+ CompanyUpcomingInvoiceResponseDataFromJSONTyped: () => CompanyUpcomingInvoiceResponseDataFromJSONTyped,
1170
+ CompanyUpcomingInvoiceResponseDataToJSON: () => CompanyUpcomingInvoiceResponseDataToJSON,
1171
+ CompanyUpcomingInvoiceResponseDataToJSONTyped: () => CompanyUpcomingInvoiceResponseDataToJSONTyped,
1172
+ GetCompanyInvoicesParamsFromJSON: () => GetCompanyInvoicesParamsFromJSON,
1173
+ GetCompanyInvoicesParamsFromJSONTyped: () => GetCompanyInvoicesParamsFromJSONTyped,
1174
+ GetCompanyInvoicesParamsToJSON: () => GetCompanyInvoicesParamsToJSON,
1175
+ GetCompanyInvoicesParamsToJSONTyped: () => GetCompanyInvoicesParamsToJSONTyped,
1176
+ GetCompanyInvoicesResponseFromJSON: () => GetCompanyInvoicesResponseFromJSON,
1177
+ GetCompanyInvoicesResponseFromJSONTyped: () => GetCompanyInvoicesResponseFromJSONTyped,
1178
+ GetCompanyInvoicesResponseToJSON: () => GetCompanyInvoicesResponseToJSON,
1179
+ GetCompanyInvoicesResponseToJSONTyped: () => GetCompanyInvoicesResponseToJSONTyped,
1180
+ GetCompanyUpcomingInvoiceResponseFromJSON: () => GetCompanyUpcomingInvoiceResponseFromJSON,
1181
+ GetCompanyUpcomingInvoiceResponseFromJSONTyped: () => GetCompanyUpcomingInvoiceResponseFromJSONTyped,
1182
+ GetCompanyUpcomingInvoiceResponseToJSON: () => GetCompanyUpcomingInvoiceResponseToJSON,
1183
+ GetCompanyUpcomingInvoiceResponseToJSONTyped: () => GetCompanyUpcomingInvoiceResponseToJSONTyped,
1184
+ InvoiceStatus: () => InvoiceStatus,
1185
+ InvoiceStatusFromJSON: () => InvoiceStatusFromJSON,
1186
+ InvoiceStatusFromJSONTyped: () => InvoiceStatusFromJSONTyped,
1187
+ InvoiceStatusToJSON: () => InvoiceStatusToJSON,
1188
+ InvoiceStatusToJSONTyped: () => InvoiceStatusToJSONTyped,
1189
+ instanceOfApiError: () => instanceOfApiError,
1190
+ instanceOfCompanyDiscountResponseData: () => instanceOfCompanyDiscountResponseData,
1191
+ instanceOfCompanyInvoiceResponseData: () => instanceOfCompanyInvoiceResponseData,
1192
+ instanceOfCompanyInvoicesResponseData: () => instanceOfCompanyInvoicesResponseData,
1193
+ instanceOfCompanyUpcomingInvoiceResponseData: () => instanceOfCompanyUpcomingInvoiceResponseData,
1194
+ instanceOfGetCompanyInvoicesParams: () => instanceOfGetCompanyInvoicesParams,
1195
+ instanceOfGetCompanyInvoicesResponse: () => instanceOfGetCompanyInvoicesResponse,
1196
+ instanceOfGetCompanyUpcomingInvoiceResponse: () => instanceOfGetCompanyUpcomingInvoiceResponse,
1197
+ instanceOfInvoiceStatus: () => instanceOfInvoiceStatus
1198
+ });
1199
+ function instanceOfApiError(value) {
1200
+ if (!("error" in value) || value["error"] === void 0) return false;
1201
+ return true;
1202
+ }
1203
+ function ApiErrorFromJSON(json) {
1204
+ return ApiErrorFromJSONTyped(json, false);
1205
+ }
1206
+ function ApiErrorFromJSONTyped(json, ignoreDiscriminator) {
1207
+ if (json == null) {
1208
+ return json;
1209
+ }
1210
+ return {
1211
+ error: json["error"]
1212
+ };
1213
+ }
1214
+ function ApiErrorToJSON(json) {
1215
+ return ApiErrorToJSONTyped(json, false);
1216
+ }
1217
+ function ApiErrorToJSONTyped(value, ignoreDiscriminator = false) {
1218
+ if (value == null) {
1219
+ return value;
1220
+ }
1221
+ return {
1222
+ error: value["error"]
1223
+ };
1224
+ }
1225
+ function instanceOfCompanyDiscountResponseData(value) {
1226
+ if (!("couponName" in value) || value["couponName"] === void 0)
1227
+ return false;
1228
+ if (!("duration" in value) || value["duration"] === void 0) return false;
1229
+ return true;
1230
+ }
1231
+ function CompanyDiscountResponseDataFromJSON(json) {
1232
+ return CompanyDiscountResponseDataFromJSONTyped(json, false);
1233
+ }
1234
+ function CompanyDiscountResponseDataFromJSONTyped(json, ignoreDiscriminator) {
1235
+ if (json == null) {
1236
+ return json;
1237
+ }
1238
+ return {
1239
+ amountOff: json["amount_off"] == null ? void 0 : json["amount_off"],
1240
+ couponName: json["coupon_name"],
1241
+ currency: json["currency"] == null ? void 0 : json["currency"],
1242
+ customerFacingCode: json["customer_facing_code"] == null ? void 0 : json["customer_facing_code"],
1243
+ duration: json["duration"],
1244
+ durationInMonths: json["duration_in_months"] == null ? void 0 : json["duration_in_months"],
1245
+ percentOff: json["percent_off"] == null ? void 0 : json["percent_off"]
1246
+ };
1247
+ }
1248
+ function CompanyDiscountResponseDataToJSON(json) {
1249
+ return CompanyDiscountResponseDataToJSONTyped(json, false);
1250
+ }
1251
+ function CompanyDiscountResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
1252
+ if (value == null) {
1253
+ return value;
1254
+ }
1255
+ return {
1256
+ amount_off: value["amountOff"],
1257
+ coupon_name: value["couponName"],
1258
+ currency: value["currency"],
1259
+ customer_facing_code: value["customerFacingCode"],
1260
+ duration: value["duration"],
1261
+ duration_in_months: value["durationInMonths"],
1262
+ percent_off: value["percentOff"]
1263
+ };
1264
+ }
1265
+ var InvoiceStatus = {
1266
+ Draft: "draft",
1267
+ Open: "open",
1268
+ Paid: "paid",
1269
+ Uncollectible: "uncollectible",
1270
+ Void: "void"
1271
+ };
1272
+ function instanceOfInvoiceStatus(value) {
1273
+ for (const key in InvoiceStatus) {
1274
+ if (Object.prototype.hasOwnProperty.call(InvoiceStatus, key)) {
1275
+ if (InvoiceStatus[key] === value) {
1276
+ return true;
1277
+ }
1278
+ }
1279
+ }
1280
+ return false;
1281
+ }
1282
+ function InvoiceStatusFromJSON(json) {
1283
+ return InvoiceStatusFromJSONTyped(json, false);
1284
+ }
1285
+ function InvoiceStatusFromJSONTyped(json, ignoreDiscriminator) {
1286
+ return json;
1287
+ }
1288
+ function InvoiceStatusToJSON(value) {
1289
+ return value;
1290
+ }
1291
+ function InvoiceStatusToJSONTyped(value, ignoreDiscriminator) {
1292
+ return value;
1293
+ }
1294
+ function instanceOfCompanyInvoiceResponseData(value) {
1295
+ if (!("amountDue" in value) || value["amountDue"] === void 0) return false;
1296
+ if (!("createdAt" in value) || value["createdAt"] === void 0) return false;
1297
+ if (!("currency" in value) || value["currency"] === void 0) return false;
1298
+ if (!("id" in value) || value["id"] === void 0) return false;
1299
+ return true;
1300
+ }
1301
+ function CompanyInvoiceResponseDataFromJSON(json) {
1302
+ return CompanyInvoiceResponseDataFromJSONTyped(json, false);
1303
+ }
1304
+ function CompanyInvoiceResponseDataFromJSONTyped(json, ignoreDiscriminator) {
1305
+ if (json == null) {
1306
+ return json;
1307
+ }
1308
+ return {
1309
+ amountDue: json["amount_due"],
1310
+ createdAt: new Date(json["created_at"]),
1311
+ currency: json["currency"],
1312
+ dueDate: json["due_date"] == null ? void 0 : new Date(json["due_date"]),
1313
+ id: json["id"],
1314
+ status: json["status"] == null ? void 0 : InvoiceStatusFromJSON(json["status"]),
1315
+ url: json["url"] == null ? void 0 : json["url"]
1316
+ };
1317
+ }
1318
+ function CompanyInvoiceResponseDataToJSON(json) {
1319
+ return CompanyInvoiceResponseDataToJSONTyped(json, false);
1320
+ }
1321
+ function CompanyInvoiceResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
1322
+ if (value == null) {
1323
+ return value;
1324
+ }
1325
+ return {
1326
+ amount_due: value["amountDue"],
1327
+ created_at: value["createdAt"].toISOString(),
1328
+ currency: value["currency"],
1329
+ due_date: value["dueDate"] == null ? void 0 : value["dueDate"].toISOString(),
1330
+ id: value["id"],
1331
+ status: InvoiceStatusToJSON(value["status"]),
1332
+ url: value["url"]
1333
+ };
1334
+ }
1335
+ function instanceOfCompanyInvoicesResponseData(value) {
1336
+ if (!("count" in value) || value["count"] === void 0) return false;
1337
+ if (!("invoices" in value) || value["invoices"] === void 0) return false;
1338
+ return true;
1339
+ }
1340
+ function CompanyInvoicesResponseDataFromJSON(json) {
1341
+ return CompanyInvoicesResponseDataFromJSONTyped(json, false);
1342
+ }
1343
+ function CompanyInvoicesResponseDataFromJSONTyped(json, ignoreDiscriminator) {
1344
+ if (json == null) {
1345
+ return json;
1346
+ }
1347
+ return {
1348
+ count: json["count"],
1349
+ invoices: json["invoices"].map(
1350
+ CompanyInvoiceResponseDataFromJSON
1351
+ )
1352
+ };
1353
+ }
1354
+ function CompanyInvoicesResponseDataToJSON(json) {
1355
+ return CompanyInvoicesResponseDataToJSONTyped(json, false);
1356
+ }
1357
+ function CompanyInvoicesResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
1358
+ if (value == null) {
1359
+ return value;
1360
+ }
1361
+ return {
1362
+ count: value["count"],
1363
+ invoices: value["invoices"].map(
1364
+ CompanyInvoiceResponseDataToJSON
1365
+ )
1366
+ };
1367
+ }
1368
+ function instanceOfCompanyUpcomingInvoiceResponseData(value) {
1369
+ if (!("amountDue" in value) || value["amountDue"] === void 0) return false;
1370
+ if (!("currency" in value) || value["currency"] === void 0) return false;
1371
+ if (!("customerBalanceApplied" in value) || value["customerBalanceApplied"] === void 0)
1372
+ return false;
1373
+ if (!("customerBalanceRemaining" in value) || value["customerBalanceRemaining"] === void 0)
1374
+ return false;
1375
+ if (!("discounts" in value) || value["discounts"] === void 0) return false;
1376
+ if (!("subtotal" in value) || value["subtotal"] === void 0) return false;
1377
+ return true;
1378
+ }
1379
+ function CompanyUpcomingInvoiceResponseDataFromJSON(json) {
1380
+ return CompanyUpcomingInvoiceResponseDataFromJSONTyped(json, false);
1381
+ }
1382
+ function CompanyUpcomingInvoiceResponseDataFromJSONTyped(json, ignoreDiscriminator) {
1383
+ if (json == null) {
1384
+ return json;
1385
+ }
1386
+ return {
1387
+ amountDue: json["amount_due"],
1388
+ currency: json["currency"],
1389
+ customerBalanceApplied: json["customer_balance_applied"],
1390
+ customerBalanceRemaining: json["customer_balance_remaining"],
1391
+ discounts: json["discounts"].map(
1392
+ CompanyDiscountResponseDataFromJSON
1393
+ ),
1394
+ dueDate: json["due_date"] == null ? void 0 : new Date(json["due_date"]),
1395
+ subtotal: json["subtotal"]
1396
+ };
1397
+ }
1398
+ function CompanyUpcomingInvoiceResponseDataToJSON(json) {
1399
+ return CompanyUpcomingInvoiceResponseDataToJSONTyped(json, false);
1400
+ }
1401
+ function CompanyUpcomingInvoiceResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
1402
+ if (value == null) {
1403
+ return value;
1404
+ }
1405
+ return {
1406
+ amount_due: value["amountDue"],
1407
+ currency: value["currency"],
1408
+ customer_balance_applied: value["customerBalanceApplied"],
1409
+ customer_balance_remaining: value["customerBalanceRemaining"],
1410
+ discounts: value["discounts"].map(
1411
+ CompanyDiscountResponseDataToJSON
1412
+ ),
1413
+ due_date: value["dueDate"] == null ? void 0 : value["dueDate"].toISOString(),
1414
+ subtotal: value["subtotal"]
1415
+ };
1416
+ }
1417
+ function instanceOfGetCompanyInvoicesParams(value) {
1418
+ return true;
1419
+ }
1420
+ function GetCompanyInvoicesParamsFromJSON(json) {
1421
+ return GetCompanyInvoicesParamsFromJSONTyped(json, false);
1422
+ }
1423
+ function GetCompanyInvoicesParamsFromJSONTyped(json, ignoreDiscriminator) {
1424
+ if (json == null) {
1425
+ return json;
1426
+ }
1427
+ return {
1428
+ includePending: json["include_pending"] == null ? void 0 : json["include_pending"],
1429
+ limit: json["limit"] == null ? void 0 : json["limit"],
1430
+ offset: json["offset"] == null ? void 0 : json["offset"]
1431
+ };
1432
+ }
1433
+ function GetCompanyInvoicesParamsToJSON(json) {
1434
+ return GetCompanyInvoicesParamsToJSONTyped(json, false);
1435
+ }
1436
+ function GetCompanyInvoicesParamsToJSONTyped(value, ignoreDiscriminator = false) {
1437
+ if (value == null) {
1438
+ return value;
1439
+ }
1440
+ return {
1441
+ include_pending: value["includePending"],
1442
+ limit: value["limit"],
1443
+ offset: value["offset"]
1444
+ };
1445
+ }
1446
+ function instanceOfGetCompanyInvoicesResponse(value) {
1447
+ if (!("data" in value) || value["data"] === void 0) return false;
1448
+ if (!("params" in value) || value["params"] === void 0) return false;
1449
+ return true;
1450
+ }
1451
+ function GetCompanyInvoicesResponseFromJSON(json) {
1452
+ return GetCompanyInvoicesResponseFromJSONTyped(json, false);
1453
+ }
1454
+ function GetCompanyInvoicesResponseFromJSONTyped(json, ignoreDiscriminator) {
1455
+ if (json == null) {
1456
+ return json;
1457
+ }
1458
+ return {
1459
+ data: CompanyInvoicesResponseDataFromJSON(json["data"]),
1460
+ params: GetCompanyInvoicesParamsFromJSON(json["params"])
1461
+ };
1462
+ }
1463
+ function GetCompanyInvoicesResponseToJSON(json) {
1464
+ return GetCompanyInvoicesResponseToJSONTyped(json, false);
1465
+ }
1466
+ function GetCompanyInvoicesResponseToJSONTyped(value, ignoreDiscriminator = false) {
1467
+ if (value == null) {
1468
+ return value;
1469
+ }
1470
+ return {
1471
+ data: CompanyInvoicesResponseDataToJSON(value["data"]),
1472
+ params: GetCompanyInvoicesParamsToJSON(value["params"])
1473
+ };
1474
+ }
1475
+ function instanceOfGetCompanyUpcomingInvoiceResponse(value) {
1476
+ if (!("data" in value) || value["data"] === void 0) return false;
1477
+ if (!("params" in value) || value["params"] === void 0) return false;
1478
+ return true;
1479
+ }
1480
+ function GetCompanyUpcomingInvoiceResponseFromJSON(json) {
1481
+ return GetCompanyUpcomingInvoiceResponseFromJSONTyped(json, false);
1482
+ }
1483
+ function GetCompanyUpcomingInvoiceResponseFromJSONTyped(json, ignoreDiscriminator) {
1484
+ if (json == null) {
1485
+ return json;
1486
+ }
1487
+ return {
1488
+ data: CompanyUpcomingInvoiceResponseDataFromJSON(json["data"]),
1489
+ params: json["params"]
1490
+ };
1491
+ }
1492
+ function GetCompanyUpcomingInvoiceResponseToJSON(json) {
1493
+ return GetCompanyUpcomingInvoiceResponseToJSONTyped(json, false);
1494
+ }
1495
+ function GetCompanyUpcomingInvoiceResponseToJSONTyped(value, ignoreDiscriminator = false) {
1496
+ if (value == null) {
1497
+ return value;
1498
+ }
1499
+ return {
1500
+ data: CompanyUpcomingInvoiceResponseDataToJSON(value["data"]),
1501
+ params: value["params"]
1502
+ };
1503
+ }
1504
+ var DEFAULT_INVOICE_QUERY = {};
1505
+ function normalizeInvoiceQuery(query) {
1506
+ const { includePending, ...rest } = query;
1507
+ return includePending === true ? { ...rest, includePending: true } : rest;
1508
+ }
1509
+ var SchematicApiError = class extends Error {
1510
+ constructor(status, path, body) {
1511
+ super(
1512
+ typeof body === "object" && body !== null && "error" in body ? String(body.error) : `Request to ${path} failed with status ${status}`
1513
+ );
1514
+ this.status = status;
1515
+ this.path = path;
1516
+ this.body = body;
1517
+ this.name = "SchematicApiError";
1518
+ }
1519
+ status;
1520
+ path;
1521
+ body;
1522
+ };
1523
+ var DEFAULT_API_URL = "https://api.schematichq.com";
1524
+ var TOKEN_CACHE_SIZE = 10;
1525
+ function sessionKey(session) {
1526
+ return JSON.stringify([session.company, session.user ?? null]);
1527
+ }
1528
+ var SchematicSession = class {
1529
+ _apiUrl;
1530
+ _headers;
1531
+ _fetch;
1532
+ _session;
1533
+ _tokens = /* @__PURE__ */ new Map();
1534
+ _resolving = /* @__PURE__ */ new Map();
1535
+ /**
1536
+ * Bumped when the session's identity changes, and only then — the object
1537
+ * itself is replaced on every render. Anything asking "is this still the
1538
+ * session I started under?" counts generations rather than comparing.
1539
+ */
1540
+ _generation = 0;
1541
+ _listeners = /* @__PURE__ */ new Set();
1542
+ constructor(options = {}) {
1543
+ this._session = options.session;
1544
+ this._apiUrl = (options.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, "");
1545
+ this._headers = options.additionalHeaders ?? {};
1546
+ this._fetch = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
1547
+ }
1548
+ get key() {
1549
+ return this._session === null || this._session === void 0 ? void 0 : sessionKey(this._session);
1550
+ }
1551
+ get status() {
1552
+ if (this._session === void 0) {
1553
+ return "pending";
1554
+ }
1555
+ return this._session === null ? "ended" : "active";
1556
+ }
1557
+ /** Only a statement that changes which pair is read counts as a change. */
1558
+ set(session) {
1559
+ if (session === void 0) {
1560
+ return;
1561
+ }
1562
+ const previous = this._session;
1563
+ this._session = session;
1564
+ if (session === null) {
1565
+ if (previous === null) {
1566
+ return;
1567
+ }
1568
+ this._tokens.clear();
1569
+ this._resolving.clear();
1570
+ this._generation += 1;
1571
+ this._emit({ type: "ended" });
1572
+ return;
1573
+ }
1574
+ if (previous !== null && previous !== void 0) {
1575
+ if (previous.company === session.company && (previous.user ?? null) === (session.user ?? null)) {
1576
+ return;
1577
+ }
1578
+ this._generation += 1;
1579
+ this._emit({ type: "changed" });
1580
+ return;
1581
+ }
1582
+ this._generation += 1;
1583
+ this._emit({ type: "started" });
1584
+ }
1585
+ onChange(listener) {
1586
+ this._listeners.add(listener);
1587
+ return () => {
1588
+ this._listeners.delete(listener);
1589
+ };
1590
+ }
1591
+ _emit(event) {
1592
+ for (const listener of this._listeners) {
1593
+ listener(event);
1594
+ }
1595
+ }
1596
+ _cached(key) {
1597
+ const cached = this._tokens.get(key);
1598
+ if (cached === void 0) {
1599
+ return void 0;
1600
+ }
1601
+ if (cached.expiresAt !== void 0 && cached.expiresAt.getTime() <= Date.now()) {
1602
+ this._tokens.delete(key);
1603
+ return void 0;
1604
+ }
1605
+ this._tokens.delete(key);
1606
+ this._tokens.set(key, cached);
1607
+ return cached;
1608
+ }
1609
+ _cache(key, resolved) {
1610
+ this._tokens.delete(key);
1611
+ this._tokens.set(key, resolved);
1612
+ while (this._tokens.size > TOKEN_CACHE_SIZE) {
1613
+ const oldest = this._tokens.keys().next();
1614
+ if (oldest.done === true) {
1615
+ break;
1616
+ }
1617
+ this._tokens.delete(oldest.value);
1618
+ }
1619
+ }
1620
+ /**
1621
+ * The credential for a session, minted if this one is not held. `force`
1622
+ * retires what is held first: the caller is a request the API has just
1623
+ * rejected.
1624
+ */
1625
+ resolveToken(session, force) {
1626
+ const { token } = session;
1627
+ if (typeof token === "string") {
1628
+ return Promise.resolve(token);
1629
+ }
1630
+ const key = sessionKey(session);
1631
+ if (!force) {
1632
+ const cached = this._cached(key);
1633
+ if (cached !== void 0) {
1634
+ return Promise.resolve(cached.token);
1635
+ }
1636
+ } else {
1637
+ this._tokens.delete(key);
1638
+ }
1639
+ const inflight = this._resolving.get(key);
1640
+ if (inflight !== void 0 && inflight.sessionGeneration === this._generation && (!force || inflight.forced)) {
1641
+ return inflight.promise;
1642
+ }
1643
+ const provider = token;
1644
+ const sessionGeneration = this._generation;
1645
+ const owns = () => this._resolving.get(key)?.promise === promise;
1646
+ const promise = Promise.resolve().then(() => provider()).then((result) => {
1647
+ const { resolved, stamped } = asResolvedToken(result, session);
1648
+ if (owns() && (this._generation === sessionGeneration || stamped)) {
1649
+ this._cache(key, resolved);
1650
+ }
1651
+ return resolved.token;
1652
+ }).finally(() => {
1653
+ if (owns()) {
1654
+ this._resolving.delete(key);
1655
+ }
1656
+ });
1657
+ this._resolving.set(key, { promise, forced: force, sessionGeneration });
1658
+ return promise;
1659
+ }
1660
+ /**
1661
+ * Sends a request under the active session's credential, refreshing once
1662
+ * and retrying if the API rejects it. Rejects rather than answering when
1663
+ * the session changes while the request is in flight: the rows would
1664
+ * otherwise come back as the answer to a question asked for another pair.
1665
+ */
1666
+ async request(path, options = {}) {
1667
+ const { method = "GET", body } = options;
1668
+ const send = async (credential2) => this._fetch(`${this._apiUrl}${path}`, {
1669
+ method,
1670
+ headers: {
1671
+ "Accept": "application/json",
1672
+ ...body === void 0 ? {} : { "Content-Type": "application/json" },
1673
+ ...this._headers,
1674
+ "X-Schematic-Api-Key": credential2
1675
+ },
1676
+ ...body === void 0 ? {} : { body: JSON.stringify(body) }
1677
+ });
1678
+ const session = this._session;
1679
+ if (session === null) {
1680
+ throw new Error("There is no session to read data for.");
1681
+ }
1682
+ if (session === void 0) {
1683
+ throw new Error("A session is required to read data.");
1684
+ }
1685
+ const provider = session.token;
1686
+ const generation = this._generation;
1687
+ const stillOurs = async (response2) => {
1688
+ if (this._generation === generation) {
1689
+ return;
1690
+ }
1691
+ if (response2 !== void 0) {
1692
+ await discardBody(response2);
1693
+ }
1694
+ throw new Error("The session changed while this request was in flight.");
1695
+ };
1696
+ const credential = await this.resolveToken(session, false);
1697
+ if (this._generation !== generation) {
1698
+ throw new Error("The session changed before this request was sent.");
1699
+ }
1700
+ let response = await send(credential);
1701
+ await stillOurs(response);
1702
+ if (response.status === 401 && typeof provider === "function" && this._generation === generation) {
1703
+ const status = response.status;
1704
+ const rejected = await readBody(response);
1705
+ let retried = false;
1706
+ const current = this._session;
1707
+ if (this._generation === generation && current !== null && current !== void 0) {
1708
+ const refreshed = await this.resolveToken(current, true);
1709
+ if (this._generation === generation) {
1710
+ response = await send(refreshed);
1711
+ await stillOurs(response);
1712
+ retried = true;
1713
+ }
1714
+ }
1715
+ if (!retried) {
1716
+ throw new SchematicApiError(status, path, rejected);
1717
+ }
1718
+ }
1719
+ if (options.noContentOn?.includes(response.status) === true) {
1720
+ await discardBody(response);
1721
+ await stillOurs();
1722
+ return void 0;
1723
+ }
1724
+ const parsed = await readBody(response);
1725
+ await stillOurs();
1726
+ if (!response.ok) {
1727
+ throw new SchematicApiError(response.status, path, parsed);
1728
+ }
1729
+ return parsed;
1730
+ }
1731
+ };
1732
+ function asResolvedToken(result, session) {
1733
+ if (typeof result === "string") {
1734
+ return { resolved: { token: result }, stamped: false };
1735
+ }
1736
+ const token = result?.token;
1737
+ if (typeof token !== "string" || token === "") {
1738
+ throw new Error("The access token provider did not return a token.");
1739
+ }
1740
+ if (result.company !== void 0 && result.company !== session.company || result.user !== void 0 && session.user !== void 0 && result.user !== session.user) {
1741
+ throw new Error(
1742
+ "The access token provider returned a token for a different session."
1743
+ );
1744
+ }
1745
+ const stamped = result.company !== void 0 && (session.user === void 0 || result.user !== void 0);
1746
+ return { resolved: { token, expiresAt: asDate(result.expiresAt) }, stamped };
1747
+ }
1748
+ function asDate(value) {
1749
+ if (value === void 0 || value === null) {
1750
+ return void 0;
1751
+ }
1752
+ const date = value instanceof Date ? value : new Date(value);
1753
+ return Number.isNaN(date.getTime()) ? void 0 : date;
1754
+ }
1755
+ async function discardBody(response) {
1756
+ try {
1757
+ await response.body?.cancel();
1758
+ } catch {
1759
+ }
1760
+ }
1761
+ async function readBody(response) {
1762
+ const text = await response.text();
1763
+ if (text === "") {
1764
+ return null;
1765
+ }
1766
+ try {
1767
+ return JSON.parse(text);
1768
+ } catch {
1769
+ return text;
1770
+ }
1771
+ }
1772
+ var INVOICE_PAGE_SIZE = 12;
1773
+ var INVOICE_MAX_PAGE_SIZE = 250;
1774
+ var SchematicBillingClient = class {
1775
+ /**
1776
+ * Public so a second client over the same surface can be constructed on
1777
+ * this one rather than minting tokens of its own.
1778
+ */
1779
+ session;
1780
+ constructor(options = {}) {
1781
+ this.session = options instanceof SchematicSession ? options : new SchematicSession(options);
1782
+ }
1783
+ get sessionKey() {
1784
+ return this.session.key;
1785
+ }
1786
+ get sessionStatus() {
1787
+ return this.session.status;
1788
+ }
1789
+ setSession(session) {
1790
+ this.session.set(session);
1791
+ }
1792
+ onSessionChange(listener) {
1793
+ return this.session.onChange(listener);
1794
+ }
1795
+ fetchInvoices(params) {
1796
+ const query = new URLSearchParams({
1797
+ limit: String(Math.min(params.limit, INVOICE_MAX_PAGE_SIZE)),
1798
+ offset: String(params.offset)
1799
+ });
1800
+ if (params.includePending !== void 0) {
1801
+ query.set("include_pending", String(params.includePending));
1802
+ }
1803
+ const path = `/company/invoices?${query}`;
1804
+ return this.session.request(path).then((body) => {
1805
+ if (body === null || typeof body !== "object" || !("data" in body)) {
1806
+ throw new Error(`Malformed response from ${path}`);
1807
+ }
1808
+ const data = body.data;
1809
+ if (data == null || data.invoices == null) {
1810
+ return { invoices: [], count: 0 };
1811
+ }
1812
+ const decoded = GetCompanyInvoicesResponseFromJSON(body).data;
1813
+ return { invoices: decoded.invoices, count: decoded.count };
1814
+ });
1815
+ }
1816
+ fetchUpcomingInvoice() {
1817
+ const path = "/company/upcoming-invoice";
1818
+ return this.session.request(path, { noContentOn: [204] }).then((body) => {
1819
+ if (body === void 0) {
1820
+ return null;
1821
+ }
1822
+ if (body === null || typeof body !== "object" || !("data" in body)) {
1823
+ throw new Error(`Malformed response from ${path}`);
1824
+ }
1825
+ return GetCompanyUpcomingInvoiceResponseFromJSON(body).data;
1826
+ });
1827
+ }
1828
+ };
1131
1829
  var anonymousIdKey = "schematicId";
1132
1830
  var flagStateCachePrefix = "schematicCache";
1133
1831
  var flagStateCacheMaxContexts = 10;
1134
1832
  var flagStateCacheDefaultMaxAgeMs = 7 * 24 * 60 * 60 * 1e3;
1135
1833
  var emptyCreditBalances = Object.freeze({});
1136
1834
  var Schematic = class {
1137
- additionalHeaders = {};
1835
+ _additionalHeaders = {};
1138
1836
  apiKey;
1139
- apiUrl = "https://api.schematichq.com";
1837
+ _apiUrl = "https://api.schematichq.com";
1140
1838
  conn = null;
1141
1839
  context = {};
1142
1840
  debugEnabled = false;
@@ -1216,7 +1914,7 @@ var Schematic = class {
1216
1914
  if (this.offlineEnabled) {
1217
1915
  this.setIsPending(false);
1218
1916
  }
1219
- this.additionalHeaders = {
1917
+ this._additionalHeaders = {
1220
1918
  "X-Schematic-Client-Version": `schematic-js@${version}`,
1221
1919
  ...options?.additionalHeaders ?? {}
1222
1920
  };
@@ -1232,7 +1930,7 @@ var Schematic = class {
1232
1930
  }
1233
1931
  this.hydrateFlagStateFromCache();
1234
1932
  if (options?.apiUrl !== void 0) {
1235
- this.apiUrl = options.apiUrl;
1933
+ this._apiUrl = options.apiUrl;
1236
1934
  }
1237
1935
  if (options?.eventUrl !== void 0) {
1238
1936
  this.eventUrl = options.eventUrl;
@@ -1297,6 +1995,12 @@ var Schematic = class {
1297
1995
  this.debug("Initialized with debug mode enabled");
1298
1996
  }
1299
1997
  }
1998
+ get apiUrl() {
1999
+ return this._apiUrl;
2000
+ }
2001
+ get additionalHeaders() {
2002
+ return { ...this._additionalHeaders };
2003
+ }
1300
2004
  /**
1301
2005
  * Resolve fallback value according to priority order:
1302
2006
  * 1. Callsite fallback value (if provided)
@@ -1382,11 +2086,11 @@ var Schematic = class {
1382
2086
  return resolvedFallbackResult.value;
1383
2087
  }
1384
2088
  if (!this.useWebSocket) {
1385
- const requestUrl = `${this.apiUrl}/flags/${key}/check`;
2089
+ const requestUrl = `${this._apiUrl}/flags/${key}/check`;
1386
2090
  return fetch(requestUrl, {
1387
2091
  method: "POST",
1388
2092
  headers: {
1389
- ...this.additionalHeaders ?? {},
2093
+ ...this._additionalHeaders ?? {},
1390
2094
  "Content-Type": "application/json;charset=UTF-8",
1391
2095
  "X-Schematic-Api-Key": this.apiKey
1392
2096
  },
@@ -1589,12 +2293,12 @@ var Schematic = class {
1589
2293
  this.debug(`checkFlags offline result: returning empty object`);
1590
2294
  return {};
1591
2295
  }
1592
- const requestUrl = `${this.apiUrl}/flags/check`;
2296
+ const requestUrl = `${this._apiUrl}/flags/check`;
1593
2297
  const requestBody = JSON.stringify(context);
1594
2298
  return fetch(requestUrl, {
1595
2299
  method: "POST",
1596
2300
  headers: {
1597
- ...this.additionalHeaders ?? {},
2301
+ ...this._additionalHeaders ?? {},
1598
2302
  "Content-Type": "application/json;charset=UTF-8",
1599
2303
  "X-Schematic-Api-Key": this.apiKey
1600
2304
  },
@@ -2141,7 +2845,7 @@ var Schematic = class {
2141
2845
  const response = await fetch(captureUrl, {
2142
2846
  method: "POST",
2143
2847
  headers: {
2144
- ...this.additionalHeaders ?? {},
2848
+ ...this._additionalHeaders ?? {},
2145
2849
  "Content-Type": "application/json;charset=UTF-8"
2146
2850
  },
2147
2851
  body: payload
@@ -2637,7 +3341,7 @@ var Schematic = class {
2637
3341
  }
2638
3342
  });
2639
3343
  this.currentWebSocket = socket;
2640
- const clientVersion = this.additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
3344
+ const clientVersion = this._additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
2641
3345
  const messagePayload = {
2642
3346
  apiKey: this.apiKey,
2643
3347
  clientVersion,
@@ -2871,23 +3575,853 @@ var notifyCreditBalanceListener = (listener, value) => {
2871
3575
  };
2872
3576
 
2873
3577
  // src/context/schematic.tsx
2874
- import React, { createContext, useEffect, useMemo, useRef } from "react";
3578
+ import React4, { createContext as createContext3, useEffect as useEffect2, useMemo as useMemo5, useRef as useRef3 } from "react";
3579
+
3580
+ // src/billing/contract/index.ts
3581
+ function normalizeInvoiceQuery2(query) {
3582
+ return normalizeInvoiceQuery(query).includePending === true ? { includePending: true } : {};
3583
+ }
3584
+
3585
+ // src/billing/store.ts
3586
+ var Resource = class {
3587
+ constructor(_fetcher, initial, _readiness = () => "ready") {
3588
+ this._fetcher = _fetcher;
3589
+ this._readiness = _readiness;
3590
+ this._loaded = initial !== void 0;
3591
+ this._snapshot = {
3592
+ data: initial,
3593
+ error: void 0,
3594
+ isPending: initial === void 0
3595
+ };
3596
+ }
3597
+ _fetcher;
3598
+ _readiness;
3599
+ _snapshot;
3600
+ _listeners = /* @__PURE__ */ new Set();
3601
+ _inflight;
3602
+ _extending;
3603
+ /** A refetch asked for mid-load; runs once that load lands. */
3604
+ _queued;
3605
+ _generation = 0;
3606
+ _loaded = false;
3607
+ get snapshot() {
3608
+ return this._snapshot;
3609
+ }
3610
+ get subscriberCount() {
3611
+ return this._listeners.size;
3612
+ }
3613
+ getSnapshot = () => this._snapshot;
3614
+ subscribe = (listener) => {
3615
+ this._listeners.add(listener);
3616
+ if (!this._loaded && this._inflight === void 0 && this._snapshot.error === void 0) {
3617
+ void this.load();
3618
+ }
3619
+ return () => {
3620
+ this._listeners.delete(listener);
3621
+ };
3622
+ };
3623
+ load() {
3624
+ if (this._inflight !== void 0) {
3625
+ return this._inflight;
3626
+ }
3627
+ const readiness = this._readiness();
3628
+ if (readiness !== "ready") {
3629
+ if (readiness === "never" && this._snapshot.isPending) {
3630
+ this._set({ ...this._snapshot, isPending: false });
3631
+ }
3632
+ return Promise.resolve();
3633
+ }
3634
+ const generation = ++this._generation;
3635
+ this._set({ ...this._snapshot, error: void 0, isPending: true });
3636
+ const run = Promise.resolve().then(() => this._fetcher()).then(
3637
+ (data) => {
3638
+ if (generation !== this._generation) return;
3639
+ this._loaded = true;
3640
+ this._set({ data, error: void 0, isPending: false });
3641
+ },
3642
+ (cause) => {
3643
+ if (generation !== this._generation) return;
3644
+ const error = cause instanceof Error ? cause : new Error(String(cause));
3645
+ this._set({ ...this._snapshot, error, isPending: false });
3646
+ }
3647
+ ).finally(() => {
3648
+ if (generation === this._generation) {
3649
+ this._inflight = void 0;
3650
+ }
3651
+ });
3652
+ this._inflight = run;
3653
+ return run;
3654
+ }
3655
+ /**
3656
+ * Reloads; `data` holds its current value until the response lands. Asked
3657
+ * for mid-load, it runs again after: that request was built before
3658
+ * whatever prompted this one. Refetches queued on one load share the
3659
+ * re-run; a reset, seed, or clear in the meantime supersedes it.
3660
+ */
3661
+ refetch() {
3662
+ if (this._inflight === void 0) {
3663
+ return this.load();
3664
+ }
3665
+ if (this._queued === void 0) {
3666
+ const generation = this._generation;
3667
+ const queued = this._inflight.then(() => {
3668
+ if (this._queued === queued) {
3669
+ this._queued = void 0;
3670
+ }
3671
+ if (generation !== this._generation) {
3672
+ return;
3673
+ }
3674
+ return this.load();
3675
+ });
3676
+ this._queued = queued;
3677
+ }
3678
+ return this._queued;
3679
+ }
3680
+ /**
3681
+ * Pages: `fetcher` receives the current data and returns what replaces it.
3682
+ * Never rejects — a caller that wants the failure reads `snapshot.error`,
3683
+ * and `data` keeps what was already fetched.
3684
+ *
3685
+ * A load already in flight wins: it is about to refresh the window this
3686
+ * would have appended to.
3687
+ */
3688
+ extend(fetcher) {
3689
+ const current = this._snapshot.data;
3690
+ if (current === void 0) {
3691
+ return Promise.resolve();
3692
+ }
3693
+ if (this._readiness() !== "ready") {
3694
+ return Promise.resolve();
3695
+ }
3696
+ if (this._extending !== void 0) {
3697
+ return this._extending;
3698
+ }
3699
+ if (this._inflight !== void 0) {
3700
+ return this._inflight;
3701
+ }
3702
+ const generation = ++this._generation;
3703
+ this._set({ ...this._snapshot, error: void 0, isPending: true });
3704
+ const run = Promise.resolve().then(() => fetcher(current)).then(
3705
+ (data) => {
3706
+ if (generation !== this._generation) return;
3707
+ this._set({ data, error: void 0, isPending: false });
3708
+ },
3709
+ (cause) => {
3710
+ if (generation !== this._generation) return;
3711
+ const error = cause instanceof Error ? cause : new Error(String(cause));
3712
+ this._set({ ...this._snapshot, error, isPending: false });
3713
+ }
3714
+ ).finally(() => {
3715
+ if (this._extending === run) {
3716
+ this._extending = void 0;
3717
+ }
3718
+ });
3719
+ this._extending = run;
3720
+ return run;
3721
+ }
3722
+ seed(data) {
3723
+ this._generation++;
3724
+ this._inflight = void 0;
3725
+ this._extending = void 0;
3726
+ this._queued = void 0;
3727
+ this._loaded = true;
3728
+ this._set({ data, error: void 0, isPending: false });
3729
+ }
3730
+ update(fn) {
3731
+ if (this._snapshot.data === void 0) return;
3732
+ this._generation++;
3733
+ this._inflight = void 0;
3734
+ this._extending = void 0;
3735
+ this._queued = void 0;
3736
+ this._set({ ...this._snapshot, data: fn(this._snapshot.data) });
3737
+ }
3738
+ /**
3739
+ * Forgets everything and stays empty — no data, no error, not pending.
3740
+ * What a resource holds when there is no session to hold it for: a session
3741
+ * ending is not a failure and must not surface as one.
3742
+ */
3743
+ clear() {
3744
+ this._generation++;
3745
+ this._inflight = void 0;
3746
+ this._extending = void 0;
3747
+ this._queued = void 0;
3748
+ this._loaded = false;
3749
+ this._set({ data: void 0, error: void 0, isPending: false });
3750
+ }
3751
+ /** Forgets everything; reloads immediately if anyone is subscribed. */
3752
+ reset() {
3753
+ this._generation++;
3754
+ this._inflight = void 0;
3755
+ this._extending = void 0;
3756
+ this._queued = void 0;
3757
+ this._loaded = false;
3758
+ const readiness = this._readiness();
3759
+ const willLoad = this._listeners.size > 0 && readiness === "ready";
3760
+ this._set({
3761
+ data: void 0,
3762
+ error: void 0,
3763
+ isPending: willLoad || readiness === "waiting"
3764
+ });
3765
+ if (willLoad) {
3766
+ void this.load();
3767
+ }
3768
+ }
3769
+ _set(next) {
3770
+ this._snapshot = next;
3771
+ for (const listener of this._listeners) {
3772
+ listener();
3773
+ }
3774
+ }
3775
+ };
3776
+ function hashKey(params) {
3777
+ return JSON.stringify(canonical(params));
3778
+ }
3779
+ function canonical(value) {
3780
+ if (Array.isArray(value)) {
3781
+ return value.map(canonical);
3782
+ }
3783
+ if (value instanceof Date) {
3784
+ const time = value.getTime();
3785
+ return Number.isNaN(time) ? "Invalid Date" : value.toISOString();
3786
+ }
3787
+ if (value !== null && typeof value === "object") {
3788
+ const out = {};
3789
+ for (const key of Object.keys(value).sort()) {
3790
+ const v = value[key];
3791
+ if (v !== void 0) {
3792
+ out[key] = canonical(v);
3793
+ }
3794
+ }
3795
+ return out;
3796
+ }
3797
+ return value ?? null;
3798
+ }
3799
+ var DEFAULT_EVICTION = { maxIdle: 4 };
3800
+ var KeyedResource = class {
3801
+ constructor(_fetcher, options = {}) {
3802
+ this._fetcher = _fetcher;
3803
+ this._readiness = options.readiness ?? (() => "ready");
3804
+ this._hash = options.hash ?? hashKey;
3805
+ this._eviction = {
3806
+ maxIdle: options.eviction?.maxIdle ?? DEFAULT_EVICTION.maxIdle
3807
+ };
3808
+ }
3809
+ _fetcher;
3810
+ _entries = /* @__PURE__ */ new Map();
3811
+ _hash;
3812
+ _eviction;
3813
+ _readiness;
3814
+ hash(params) {
3815
+ return this._hash(params);
3816
+ }
3817
+ get size() {
3818
+ return this._entries.size;
3819
+ }
3820
+ entries() {
3821
+ return Array.from(this._entries, ([key, e]) => ({ key, ...e }));
3822
+ }
3823
+ get(params) {
3824
+ const key = this._hash(params);
3825
+ const existing = this._entries.get(key);
3826
+ if (existing !== void 0) {
3827
+ this._entries.delete(key);
3828
+ this._entries.set(key, existing);
3829
+ return existing.resource;
3830
+ }
3831
+ const resource = new Resource(
3832
+ () => this._fetcher(params, resource.snapshot.data),
3833
+ void 0,
3834
+ this._readiness
3835
+ );
3836
+ this._entries.set(key, { params, resource });
3837
+ return resource;
3838
+ }
3839
+ has(params) {
3840
+ return this._entries.has(this._hash(params));
3841
+ }
3842
+ subscribe(params, listener) {
3843
+ const resource = this.get(params);
3844
+ const unsubscribe = resource.subscribe(listener);
3845
+ return () => {
3846
+ unsubscribe();
3847
+ this._evict();
3848
+ };
3849
+ }
3850
+ seed(params, data) {
3851
+ this.get(params).seed(data);
3852
+ }
3853
+ evict(params) {
3854
+ return this._entries.delete(this._hash(params));
3855
+ }
3856
+ resetAll() {
3857
+ for (const [key, { resource }] of Array.from(this._entries)) {
3858
+ if (resource.subscriberCount === 0) {
3859
+ this._entries.delete(key);
3860
+ } else {
3861
+ resource.reset();
3862
+ }
3863
+ }
3864
+ }
3865
+ resumeAll() {
3866
+ for (const { resource } of this._entries.values()) {
3867
+ if (resource.subscriberCount === 0) {
3868
+ continue;
3869
+ }
3870
+ const { data, error } = resource.snapshot;
3871
+ if (data === void 0 || error !== void 0) {
3872
+ void resource.load();
3873
+ }
3874
+ }
3875
+ }
3876
+ clearAll() {
3877
+ for (const [key, { resource }] of Array.from(this._entries)) {
3878
+ if (resource.subscriberCount === 0) {
3879
+ this._entries.delete(key);
3880
+ } else {
3881
+ resource.clear();
3882
+ }
3883
+ }
3884
+ }
3885
+ invalidateAll() {
3886
+ for (const { resource } of this._entries.values()) {
3887
+ if (resource.snapshot.data !== void 0) {
3888
+ void resource.refetch();
3889
+ }
3890
+ }
3891
+ }
3892
+ _evict() {
3893
+ const idle = Array.from(this._entries).filter(
3894
+ ([, e]) => e.resource.subscriberCount === 0
3895
+ );
3896
+ let excess = idle.length - this._eviction.maxIdle;
3897
+ for (const [key] of idle) {
3898
+ if (excess <= 0) break;
3899
+ this._entries.delete(key);
3900
+ excess -= 1;
3901
+ }
3902
+ }
3903
+ };
3904
+
3905
+ // src/billing/client.ts
3906
+ function claimOf(client) {
3907
+ return { status: client.sessionStatus, key: client.sessionKey };
3908
+ }
3909
+ function claimFrom(session) {
3910
+ if (session === void 0) {
3911
+ return void 0;
3912
+ }
3913
+ return session === null ? { status: "ended", key: void 0 } : { status: "active", key: sessionKey(session) };
3914
+ }
3915
+ function judgeSeed(seedKey, claim) {
3916
+ if (claim.status === "ended") {
3917
+ return "drop";
3918
+ }
3919
+ if (seedKey === void 0) {
3920
+ return "adopt";
3921
+ }
3922
+ if (claim.status === "pending") {
3923
+ return "hold";
3924
+ }
3925
+ return seedKey === claim.key ? "adopt" : "drop";
3926
+ }
3927
+ var READINESS = {
3928
+ pending: "waiting",
3929
+ active: "ready",
3930
+ ended: "never"
3931
+ };
3932
+ var BillingStore = class {
3933
+ constructor(_client, initialData = {}, options = {}) {
3934
+ this._client = _client;
3935
+ this._pageSize = options.pageSize ?? INVOICE_PAGE_SIZE;
3936
+ this.invoices = new KeyedResource(
3937
+ (query, current) => this._reloadWindow(
3938
+ query,
3939
+ Math.max(this._pageSize, current?.invoices.length ?? 0)
3940
+ ),
3941
+ // Waiting until connected; then a session still pending stays
3942
+ // pending, and one that has ended settles empty rather than recording
3943
+ // the client's refusal as an error.
3944
+ {
3945
+ readiness: () => this._connected ? READINESS[this._client.sessionStatus] : "waiting"
3946
+ }
3947
+ );
3948
+ if (initialData.invoices !== void 0) {
3949
+ this._held = {
3950
+ // Normalized the way the hook normalizes, or the caller asking for
3951
+ // it fetches the same page again.
3952
+ params: normalizeInvoiceQuery2(
3953
+ initialData.params?.invoices ?? DEFAULT_INVOICE_QUERY
3954
+ ),
3955
+ data: initialData.invoices,
3956
+ key: initialData.sessionKey
3957
+ };
3958
+ this._settleSeed(claimFrom(options.session) ?? claimOf(this._client));
3959
+ }
3960
+ }
3961
+ _client;
3962
+ invoices;
3963
+ _pageSize;
3964
+ _unsubscribe;
3965
+ _connected = false;
3966
+ _seeded = false;
3967
+ /** The session that prefetch was for, where it said. */
3968
+ _seedKey;
3969
+ /** A stamped prefetch waiting for a session to check it against. */
3970
+ _held;
3971
+ /**
3972
+ * Not done in the constructor: the provider arms it from an effect, and
3973
+ * React runs an effect, its cleanup, then the effect again under
3974
+ * StrictMode. A subscription made once at construction is torn down by
3975
+ * that cleanup and never comes back, leaving the store deaf to every
3976
+ * session change for the rest of the page.
3977
+ *
3978
+ * Also what opens the store: subscribers who arrived first have been
3979
+ * waiting, and this is the moment the session is known to be installed.
3980
+ */
3981
+ connect() {
3982
+ this._unsubscribe?.();
3983
+ const unsubscribe = this._client.onSessionChange?.((event) => {
3984
+ if (event.type === "ended") {
3985
+ this._held = void 0;
3986
+ this._seeded = false;
3987
+ this.clearAll();
3988
+ } else if (event.type === "changed") {
3989
+ this._held = void 0;
3990
+ this._seeded = false;
3991
+ this.resetAll();
3992
+ } else {
3993
+ this._onStarted();
3994
+ }
3995
+ });
3996
+ this._unsubscribe = unsubscribe;
3997
+ if (!this._connected) {
3998
+ this._connected = true;
3999
+ this._settleSeed(claimOf(this._client));
4000
+ this.resumeAll();
4001
+ }
4002
+ return () => {
4003
+ unsubscribe?.();
4004
+ if (this._unsubscribe === unsubscribe) {
4005
+ this._unsubscribe = void 0;
4006
+ }
4007
+ };
4008
+ }
4009
+ _onStarted() {
4010
+ const claim = claimOf(this._client);
4011
+ this._settleSeed(claim);
4012
+ if (this._seeded && judgeSeed(this._seedKey, claim) !== "adopt") {
4013
+ this._seeded = false;
4014
+ this.resetAll();
4015
+ return;
4016
+ }
4017
+ this._seeded = false;
4018
+ this.resumeAll();
4019
+ }
4020
+ /** Adopts, keeps holding, or drops the prefetch, by what `claim` says. */
4021
+ _settleSeed(claim) {
4022
+ const held = this._held;
4023
+ if (held === void 0) {
4024
+ return;
4025
+ }
4026
+ const verdict = judgeSeed(held.key, claim);
4027
+ if (verdict === "hold") {
4028
+ return;
4029
+ }
4030
+ this._held = void 0;
4031
+ if (verdict === "adopt") {
4032
+ this.invoices.seed(held.params, held.data);
4033
+ this._seedKey = held.key;
4034
+ this._seeded = true;
4035
+ }
4036
+ }
4037
+ resource(name) {
4038
+ return this[name];
4039
+ }
4040
+ /** Forgets every resource; subscribed ones reload, idle ones are dropped. */
4041
+ resetAll() {
4042
+ for (const name of RESOURCE_NAMES) {
4043
+ this[name].resetAll();
4044
+ }
4045
+ }
4046
+ /** Forgets every resource and leaves them empty; nothing reloads. */
4047
+ clearAll() {
4048
+ for (const name of RESOURCE_NAMES) {
4049
+ this[name].clearAll();
4050
+ }
4051
+ }
4052
+ /** Loads every resource that is subscribed and has nothing yet. */
4053
+ resumeAll() {
4054
+ for (const name of RESOURCE_NAMES) {
4055
+ this[name].resumeAll();
4056
+ }
4057
+ }
4058
+ /** Reloads every resource that has been loaded, keeping its current data. */
4059
+ invalidateAll() {
4060
+ for (const name of RESOURCE_NAMES) {
4061
+ this[name].invalidateAll();
4062
+ }
4063
+ }
4064
+ /**
4065
+ * Appends the next page to the invoices list for `query`, when there is
4066
+ * one. A failure records the error on the resource and keeps the rows
4067
+ * already fetched; the returned promise never rejects.
4068
+ */
4069
+ loadMoreInvoices(query = DEFAULT_INVOICE_QUERY) {
4070
+ const resource = this.invoices.get(normalizeInvoiceQuery2(query));
4071
+ if (resource.snapshot.data?.hasMore !== true) {
4072
+ return Promise.resolve();
4073
+ }
4074
+ return resource.extend(async (current) => {
4075
+ const page = await this._fetchInvoices(
4076
+ normalizeInvoiceQuery2(query),
4077
+ current.invoices.length,
4078
+ this._pageSize
4079
+ );
4080
+ const invoices = [...current.invoices, ...page.invoices];
4081
+ return {
4082
+ invoices,
4083
+ count: page.count,
4084
+ // From the count the page came back with, not the one the list was
4085
+ // built on: an invoice finalized between the two requests changes
4086
+ // what is left to load. An empty page ends the list whatever the
4087
+ // count says — the rows and the count are two queries, and a count
4088
+ // that outruns the rows would otherwise leave `hasMore` true for
4089
+ // good, with every further page fetching nothing.
4090
+ hasMore: page.invoices.length > 0 && invoices.length < page.count
4091
+ };
4092
+ });
4093
+ }
4094
+ dispose() {
4095
+ this._unsubscribe?.();
4096
+ }
4097
+ /**
4098
+ * Re-reads the window already loaded, in as many requests as the API's
4099
+ * page cap needs. A window paged past that cap still comes back whole:
4100
+ * asking for it in one request would be a 400, and asking for only the
4101
+ * first page would drop the rest.
4102
+ */
4103
+ async _reloadWindow(query, window2) {
4104
+ const invoices = [];
4105
+ let count = 0;
4106
+ while (invoices.length < window2) {
4107
+ const page = await this._fetchInvoices(
4108
+ query,
4109
+ invoices.length,
4110
+ Math.min(INVOICE_MAX_PAGE_SIZE, window2 - invoices.length)
4111
+ );
4112
+ count = page.count;
4113
+ invoices.push(...page.invoices);
4114
+ if (page.invoices.length === 0 || invoices.length >= count) {
4115
+ break;
4116
+ }
4117
+ }
4118
+ return {
4119
+ invoices,
4120
+ count,
4121
+ hasMore: invoices.length > 0 && invoices.length < count
4122
+ };
4123
+ }
4124
+ /**
4125
+ * Returns what the server said and nothing more: whether there is more to
4126
+ * load depends on the whole window, which only the caller assembling it
4127
+ * knows — `_reloadWindow` across its requests, and `loadMoreInvoices`
4128
+ * across the rows already loaded.
4129
+ */
4130
+ _fetchInvoices(query, offset, limit) {
4131
+ return this._client.fetchInvoices({ ...query, limit, offset });
4132
+ }
4133
+ };
4134
+ var RESOURCE_NAMES = ["invoices"];
4135
+
4136
+ // src/billing/context.tsx
4137
+ import { createContext as createContext2, useContext as useContext2, useMemo as useMemo2 } from "react";
4138
+
4139
+ // src/i18n/context.tsx
4140
+ import { createContext, useContext, useMemo } from "react";
4141
+ import { jsx } from "react/jsx-runtime";
4142
+ var EMPTY = Object.freeze({});
4143
+ var SchematicI18nContext = createContext(EMPTY);
4144
+ function SchematicI18nProvider({
4145
+ children,
4146
+ locale,
4147
+ onMissingString,
4148
+ strings,
4149
+ translate
4150
+ }) {
4151
+ const parent = useContext(SchematicI18nContext);
4152
+ const value = useMemo(
4153
+ () => ({
4154
+ locale: locale ?? parent.locale,
4155
+ translate: translate ?? parent.translate,
4156
+ strings: strings === void 0 ? parent.strings : { ...parent.strings, ...strings },
4157
+ onMissingString: onMissingString ?? parent.onMissingString
4158
+ }),
4159
+ [locale, onMissingString, parent, strings, translate]
4160
+ );
4161
+ return /* @__PURE__ */ jsx(SchematicI18nContext.Provider, { value, children });
4162
+ }
4163
+ function useSchematicI18n() {
4164
+ return useContext(SchematicI18nContext);
4165
+ }
4166
+ function useSchematicLocale() {
4167
+ return useContext(SchematicI18nContext).locale;
4168
+ }
4169
+ function useSchematicTranslate() {
4170
+ return useContext(SchematicI18nContext).translate;
4171
+ }
4172
+ function useSchematicStrings() {
4173
+ return useContext(SchematicI18nContext).strings;
4174
+ }
4175
+
4176
+ // src/billing/context.tsx
4177
+ import { jsx as jsx2 } from "react/jsx-runtime";
4178
+ var BillingDataContext = createContext2(
4179
+ void 0
4180
+ );
4181
+ var MISSING_BILLING_SOURCE_MESSAGE = "Schematic billing hooks need a SchematicProvider with a session, billingClient, or initialData, or a BillingDataProvider.";
4182
+ var missingSourceError = new Error(MISSING_BILLING_SOURCE_MESSAGE);
4183
+ var missingHandle = {
4184
+ data: void 0,
4185
+ error: missingSourceError,
4186
+ isPending: false,
4187
+ refetch: () => {
4188
+ }
4189
+ };
4190
+ var missingBillingSource = {
4191
+ subscribe: () => () => {
4192
+ },
4193
+ handle: () => missingHandle,
4194
+ loadMoreInvoices: () => Promise.resolve(),
4195
+ invalidateAll: () => {
4196
+ }
4197
+ };
4198
+ function useBillingDataSource() {
4199
+ return useContext2(BillingDataContext) ?? missingBillingSource;
4200
+ }
4201
+ function BillingDataProvider({
4202
+ children,
4203
+ data,
4204
+ locale,
4205
+ onLoadMoreInvoices,
4206
+ onMissingString,
4207
+ onRefetch,
4208
+ status,
4209
+ strings,
4210
+ translate
4211
+ }) {
4212
+ const source = useMemo2(() => {
4213
+ const handles = /* @__PURE__ */ new Map();
4214
+ return {
4215
+ subscribe: () => () => {
4216
+ },
4217
+ handle: (name) => {
4218
+ const cached = handles.get(name);
4219
+ if (cached !== void 0) {
4220
+ return cached;
4221
+ }
4222
+ const value = data[name];
4223
+ const override = status?.[name];
4224
+ const handle = {
4225
+ data: value,
4226
+ error: override?.error,
4227
+ isPending: override?.isPending ?? value === void 0,
4228
+ refetch: () => onRefetch?.(name)
4229
+ };
4230
+ handles.set(name, handle);
4231
+ return handle;
4232
+ },
4233
+ loadMoreInvoices: (query) => {
4234
+ onLoadMoreInvoices?.(query);
4235
+ return Promise.resolve();
4236
+ },
4237
+ invalidateAll: () => {
4238
+ }
4239
+ };
4240
+ }, [data, onLoadMoreInvoices, onRefetch, status]);
4241
+ return /* @__PURE__ */ jsx2(BillingDataContext.Provider, { value: source, children: /* @__PURE__ */ jsx2(
4242
+ SchematicI18nProvider,
4243
+ {
4244
+ locale,
4245
+ strings,
4246
+ translate,
4247
+ onMissingString,
4248
+ children
4249
+ }
4250
+ ) });
4251
+ }
4252
+
4253
+ // src/billing/hooks.ts
4254
+ import { useCallback, useMemo as useMemo3, useRef, useSyncExternalStore } from "react";
4255
+ function useStableParams(params) {
4256
+ const key = hashKey(params);
4257
+ const ref = useRef({ key, params });
4258
+ if (ref.current.key !== key) {
4259
+ ref.current = { key, params };
4260
+ }
4261
+ return ref.current.params;
4262
+ }
4263
+ function useBillingResource(name, params) {
4264
+ const source = useBillingDataSource();
4265
+ const subscribe = useCallback(
4266
+ (listener) => source.subscribe(name, params, listener),
4267
+ [name, params, source]
4268
+ );
4269
+ const getSnapshot = useCallback(
4270
+ () => source.handle(name, params),
4271
+ [name, params, source]
4272
+ );
4273
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
4274
+ }
4275
+ function useInvoices(query = DEFAULT_INVOICE_QUERY) {
4276
+ const source = useBillingDataSource();
4277
+ const params = useStableParams(normalizeInvoiceQuery2(query));
4278
+ const handle = useBillingResource("invoices", params);
4279
+ const loadMore = useCallback(
4280
+ () => source.loadMoreInvoices(params),
4281
+ [params, source]
4282
+ );
4283
+ return useMemo3(() => ({ ...handle, loadMore }), [handle, loadMore]);
4284
+ }
4285
+ function useInvalidateBillingData() {
4286
+ return useBillingDataSource().invalidateAll;
4287
+ }
4288
+
4289
+ // src/billing/provider.tsx
4290
+ import { useEffect, useMemo as useMemo4, useRef as useRef2 } from "react";
4291
+ import { jsx as jsx3 } from "react/jsx-runtime";
4292
+ var SESSION_REPLACED_MESSAGE = "BillingProvider is moving its billingClient from one session to another. A client holds one session: if another provider shares this client, each will keep installing its own and show the other's data. Give each provider its own client.";
4293
+ function BillingProvider({
4294
+ billingClient,
4295
+ children,
4296
+ initialData,
4297
+ locale,
4298
+ onMissingString,
4299
+ session,
4300
+ strings,
4301
+ translate
4302
+ }) {
4303
+ const initialRef = useRef2(initialData);
4304
+ const install = () => {
4305
+ billingClient?.setSession?.(session);
4306
+ };
4307
+ useEffect(() => {
4308
+ const claim = billingClient?.sessionKey;
4309
+ if (claim !== void 0 && session !== null && session !== void 0 && claim !== sessionKey(session)) {
4310
+ console.warn(SESSION_REPLACED_MESSAGE);
4311
+ }
4312
+ }, []);
4313
+ useEffect(install);
4314
+ const seedSpent = useRef2(false);
4315
+ const store = useMemo4(
4316
+ () => billingClient === void 0 ? void 0 : new BillingStore(
4317
+ billingClient,
4318
+ seedSpent.current ? void 0 : initialRef.current,
4319
+ {
4320
+ // What `install` is about to say, so a stamped prefetch is
4321
+ // judged now rather than after the effect.
4322
+ session
4323
+ }
4324
+ ),
4325
+ // `session` is read only when the store is built: the client learns
4326
+ // later sessions through `install`, and the store through the client.
4327
+ [billingClient]
4328
+ );
4329
+ useEffect(() => {
4330
+ if (store !== void 0) {
4331
+ seedSpent.current = true;
4332
+ }
4333
+ }, [store]);
4334
+ useEffect(() => store?.connect(), [store]);
4335
+ const source = useMemo4(() => {
4336
+ if (store === void 0) {
4337
+ return initialRef.current === void 0 ? void 0 : staticSource(initialRef.current);
4338
+ }
4339
+ const handles = /* @__PURE__ */ new WeakMap();
4340
+ const handle = (name, params) => {
4341
+ const resource = store.resource(name).get(params);
4342
+ const snapshot = resource.getSnapshot();
4343
+ const cached = handles.get(resource);
4344
+ if (cached !== void 0 && cached.snapshot === snapshot) {
4345
+ return cached.handle;
4346
+ }
4347
+ const next = {
4348
+ ...snapshot,
4349
+ refetch: () => void resource.refetch()
4350
+ };
4351
+ handles.set(resource, { snapshot, handle: next });
4352
+ return next;
4353
+ };
4354
+ return {
4355
+ subscribe: (name, params, listener) => store.resource(name).subscribe(params, listener),
4356
+ handle,
4357
+ loadMoreInvoices: (query) => store.loadMoreInvoices(query),
4358
+ invalidateAll: () => store.invalidateAll()
4359
+ };
4360
+ }, [store]);
4361
+ const localized = /* @__PURE__ */ jsx3(
4362
+ SchematicI18nProvider,
4363
+ {
4364
+ locale,
4365
+ strings,
4366
+ translate,
4367
+ onMissingString,
4368
+ children
4369
+ }
4370
+ );
4371
+ if (source === void 0) {
4372
+ return localized;
4373
+ }
4374
+ return /* @__PURE__ */ jsx3(BillingDataContext.Provider, { value: source, children: localized });
4375
+ }
4376
+ function staticSource(data) {
4377
+ const handles = /* @__PURE__ */ new Map();
4378
+ return {
4379
+ subscribe: () => () => {
4380
+ },
4381
+ handle: (name) => {
4382
+ const cached = handles.get(name);
4383
+ if (cached !== void 0) {
4384
+ return cached;
4385
+ }
4386
+ const value = data[name];
4387
+ const next = {
4388
+ data: value,
4389
+ error: void 0,
4390
+ isPending: value === void 0,
4391
+ refetch: () => {
4392
+ }
4393
+ };
4394
+ handles.set(name, next);
4395
+ return next;
4396
+ },
4397
+ loadMoreInvoices: () => Promise.resolve(),
4398
+ invalidateAll: () => {
4399
+ }
4400
+ };
4401
+ }
2875
4402
 
2876
4403
  // src/version.ts
2877
- var version2 = "1.5.0";
4404
+ var version2 = "1.7.0";
2878
4405
 
2879
4406
  // src/context/schematic.tsx
2880
- import { jsx } from "react/jsx-runtime";
2881
- var SchematicContext = createContext(
4407
+ import { jsx as jsx4 } from "react/jsx-runtime";
4408
+ var SchematicContext = createContext3(
2882
4409
  null
2883
4410
  );
2884
4411
  var SchematicProvider = ({
4412
+ session,
4413
+ billingClient,
2885
4414
  children,
2886
4415
  client: providedClient,
4416
+ initialData,
4417
+ locale,
4418
+ onMissingString,
2887
4419
  publishableKey,
4420
+ strings,
4421
+ translate,
2888
4422
  ...clientOpts
2889
4423
  }) => {
2890
- const initialOptsRef = useRef({
4424
+ const initialOptsRef = useRef3({
2891
4425
  publishableKey,
2892
4426
  useWebSocket: true,
2893
4427
  additionalHeaders: {
@@ -2895,7 +4429,7 @@ var SchematicProvider = ({
2895
4429
  },
2896
4430
  ...clientOpts
2897
4431
  });
2898
- const client = useMemo(() => {
4432
+ const client = useMemo5(() => {
2899
4433
  if (providedClient) {
2900
4434
  return providedClient;
2901
4435
  }
@@ -2903,7 +4437,7 @@ var SchematicProvider = ({
2903
4437
  ...initialOptsRef.current
2904
4438
  });
2905
4439
  }, [providedClient]);
2906
- useEffect(() => {
4440
+ useEffect2(() => {
2907
4441
  return () => {
2908
4442
  if (!providedClient) {
2909
4443
  client.cleanup().catch((error) => {
@@ -2912,16 +4446,46 @@ var SchematicProvider = ({
2912
4446
  }
2913
4447
  };
2914
4448
  }, [client, providedClient]);
2915
- const contextValue = useMemo(
4449
+ const contextValue = useMemo5(
2916
4450
  () => ({
2917
4451
  client
2918
4452
  }),
2919
4453
  [client]
2920
4454
  );
2921
- return /* @__PURE__ */ jsx(SchematicContext.Provider, { value: contextValue, children });
4455
+ const { apiUrl, additionalHeaders } = initialOptsRef.current;
4456
+ const providedApiUrl = providedClient?.apiUrl;
4457
+ const resolvedBillingClient = useMemo5(
4458
+ () => billingClient ?? new SchematicBillingClient({
4459
+ session,
4460
+ apiUrl: apiUrl ?? providedApiUrl,
4461
+ // Read as they stand when a client is built: headers do not change
4462
+ // where the token goes, so they are no reason to build one.
4463
+ additionalHeaders: {
4464
+ ...providedClient?.additionalHeaders,
4465
+ ...additionalHeaders
4466
+ }
4467
+ }),
4468
+ // `session` is deliberately absent: `BillingProvider` forwards it through
4469
+ // `setSession`, so a token change resets the billing resources without
4470
+ // rebuilding the client.
4471
+ [additionalHeaders, apiUrl, billingClient, providedApiUrl]
4472
+ );
4473
+ return /* @__PURE__ */ jsx4(SchematicContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx4(
4474
+ BillingProvider,
4475
+ {
4476
+ billingClient: resolvedBillingClient,
4477
+ initialData,
4478
+ locale,
4479
+ session,
4480
+ strings,
4481
+ translate,
4482
+ onMissingString,
4483
+ children
4484
+ }
4485
+ ) });
2922
4486
  };
2923
4487
  var useSchematic = () => {
2924
- const context = React.useContext(SchematicContext);
4488
+ const context = React4.useContext(SchematicContext);
2925
4489
  if (context === null) {
2926
4490
  throw new Error("useSchematic must be used within a SchematicProvider");
2927
4491
  }
@@ -2929,11 +4493,11 @@ var useSchematic = () => {
2929
4493
  };
2930
4494
 
2931
4495
  // src/hooks/schematic.ts
2932
- import { useMemo as useMemo2, useSyncExternalStore, useCallback } from "react";
4496
+ import { useMemo as useMemo6, useSyncExternalStore as useSyncExternalStore2, useCallback as useCallback2 } from "react";
2933
4497
  var useSchematicClient = (opts) => {
2934
4498
  const schematic = useSchematic();
2935
4499
  const { client } = opts ?? {};
2936
- return useMemo2(() => {
4500
+ return useMemo6(() => {
2937
4501
  if (client) {
2938
4502
  return client;
2939
4503
  }
@@ -2942,7 +4506,7 @@ var useSchematicClient = (opts) => {
2942
4506
  };
2943
4507
  var useSchematicContext = (opts) => {
2944
4508
  const client = useSchematicClient(opts);
2945
- return useMemo2(
4509
+ return useMemo6(
2946
4510
  () => ({
2947
4511
  setContext: client.setContext.bind(client)
2948
4512
  }),
@@ -2951,33 +4515,33 @@ var useSchematicContext = (opts) => {
2951
4515
  };
2952
4516
  var useSchematicEvents = (opts) => {
2953
4517
  const client = useSchematicClient(opts);
2954
- const track = useCallback(
4518
+ const track = useCallback2(
2955
4519
  (...args) => client.track(...args),
2956
4520
  [client]
2957
4521
  );
2958
- const identify = useCallback(
4522
+ const identify = useCallback2(
2959
4523
  (...args) => client.identify(...args),
2960
4524
  [client]
2961
4525
  );
2962
- return useMemo2(() => ({ track, identify }), [track, identify]);
4526
+ return useMemo6(() => ({ track, identify }), [track, identify]);
2963
4527
  };
2964
4528
  var useSchematicFlag = (key, opts) => {
2965
4529
  const client = useSchematicClient(opts);
2966
4530
  const fallback = opts?.fallback ?? false;
2967
- const subscribe = useCallback(
4531
+ const subscribe = useCallback2(
2968
4532
  (callback) => client.addFlagValueListener(key, callback),
2969
4533
  [client, key]
2970
4534
  );
2971
- const getSnapshot = useCallback(() => {
4535
+ const getSnapshot = useCallback2(() => {
2972
4536
  const value = client.getFlagValue(key);
2973
4537
  return typeof value === "undefined" ? fallback : value;
2974
4538
  }, [client, key, fallback]);
2975
- return useSyncExternalStore(subscribe, getSnapshot, () => fallback);
4539
+ return useSyncExternalStore2(subscribe, getSnapshot, () => fallback);
2976
4540
  };
2977
4541
  var useSchematicEntitlement = (key, opts) => {
2978
4542
  const client = useSchematicClient(opts);
2979
4543
  const fallback = opts?.fallback ?? false;
2980
- const fallbackCheck = useMemo2(
4544
+ const fallbackCheck = useMemo6(
2981
4545
  () => ({
2982
4546
  flag: key,
2983
4547
  reason: "Fallback",
@@ -2985,20 +4549,20 @@ var useSchematicEntitlement = (key, opts) => {
2985
4549
  }),
2986
4550
  [key, fallback]
2987
4551
  );
2988
- const subscribe = useCallback(
4552
+ const subscribe = useCallback2(
2989
4553
  (callback) => client.addFlagCheckListener(key, callback),
2990
4554
  [client, key]
2991
4555
  );
2992
- const getSnapshot = useCallback(() => {
4556
+ const getSnapshot = useCallback2(() => {
2993
4557
  const check = client.getFlagCheck(key);
2994
4558
  return check ?? fallbackCheck;
2995
4559
  }, [client, key, fallbackCheck]);
2996
- return useSyncExternalStore(subscribe, getSnapshot, () => fallbackCheck);
4560
+ return useSyncExternalStore2(subscribe, getSnapshot, () => fallbackCheck);
2997
4561
  };
2998
4562
  var useSchematicPlan = (opts) => {
2999
4563
  const client = useSchematicClient(opts);
3000
4564
  const fallback = opts?.fallback;
3001
- const fallbackPlan = useMemo2(
4565
+ const fallbackPlan = useMemo6(
3002
4566
  () => fallback,
3003
4567
  [
3004
4568
  fallback?.id,
@@ -3007,37 +4571,37 @@ var useSchematicPlan = (opts) => {
3007
4571
  fallback?.trialStatus
3008
4572
  ]
3009
4573
  );
3010
- const subscribe = useCallback(
4574
+ const subscribe = useCallback2(
3011
4575
  (callback) => client.addPlanListener(callback),
3012
4576
  [client]
3013
4577
  );
3014
- const getSnapshot = useCallback(() => {
4578
+ const getSnapshot = useCallback2(() => {
3015
4579
  const plan = client.getPlan();
3016
4580
  return plan ?? fallbackPlan;
3017
4581
  }, [client, fallbackPlan]);
3018
- return useSyncExternalStore(subscribe, getSnapshot, () => fallbackPlan);
4582
+ return useSyncExternalStore2(subscribe, getSnapshot, () => fallbackPlan);
3019
4583
  };
3020
4584
  var useSchematicCreditBalance = (creditId, opts) => {
3021
4585
  const client = useSchematicClient(opts);
3022
- const subscribe = useCallback(
4586
+ const subscribe = useCallback2(
3023
4587
  (callback) => client.addCreditBalanceListener(callback),
3024
4588
  [client]
3025
4589
  );
3026
- const getSnapshot = useCallback(
3027
- () => client.getCreditBalance(creditId),
4590
+ const getSnapshot = useCallback2(
4591
+ () => creditId === void 0 ? void 0 : client.getCreditBalance(creditId),
3028
4592
  [client, creditId]
3029
4593
  );
3030
- const balance = useSyncExternalStore(subscribe, getSnapshot, () => void 0);
3031
- const isPendingSubscribe = useCallback(
4594
+ const balance = useSyncExternalStore2(subscribe, getSnapshot, () => void 0);
4595
+ const isPendingSubscribe = useCallback2(
3032
4596
  (callback) => client.addIsPendingListener(callback),
3033
4597
  [client]
3034
4598
  );
3035
- const isPending = useSyncExternalStore(
4599
+ const isPending = useSyncExternalStore2(
3036
4600
  isPendingSubscribe,
3037
4601
  () => client.getIsPending(),
3038
4602
  () => true
3039
4603
  );
3040
- return useMemo2(
4604
+ return useMemo6(
3041
4605
  () => ({
3042
4606
  balance: balance?.settled ?? 0,
3043
4607
  isLoading: balance === void 0 && isPending
@@ -3047,27 +4611,42 @@ var useSchematicCreditBalance = (creditId, opts) => {
3047
4611
  };
3048
4612
  var useSchematicIsPending = (opts) => {
3049
4613
  const client = useSchematicClient(opts);
3050
- const subscribe = useCallback(
4614
+ const subscribe = useCallback2(
3051
4615
  (callback) => client.addIsPendingListener(callback),
3052
4616
  [client]
3053
4617
  );
3054
- const getSnapshot = useCallback(() => client.getIsPending(), [client]);
3055
- return useSyncExternalStore(subscribe, getSnapshot, () => true);
4618
+ const getSnapshot = useCallback2(() => client.getIsPending(), [client]);
4619
+ return useSyncExternalStore2(subscribe, getSnapshot, () => true);
3056
4620
  };
3057
4621
  export {
4622
+ BillingDataProvider,
4623
+ BillingProvider,
4624
+ DEFAULT_INVOICE_QUERY,
4625
+ INVOICE_PAGE_SIZE,
4626
+ InvoiceStatus,
3058
4627
  RuleType,
3059
4628
  Schematic,
4629
+ SchematicI18nContext,
4630
+ SchematicI18nProvider,
3060
4631
  SchematicProvider,
3061
4632
  TrialStatus,
3062
4633
  UsagePeriod,
4634
+ normalizeInvoiceQuery2 as normalizeInvoiceQuery,
4635
+ useBillingDataSource,
4636
+ useInvalidateBillingData,
4637
+ useInvoices,
3063
4638
  useSchematic,
3064
4639
  useSchematicContext,
3065
4640
  useSchematicCreditBalance,
3066
4641
  useSchematicEntitlement,
3067
4642
  useSchematicEvents,
3068
4643
  useSchematicFlag,
4644
+ useSchematicI18n,
3069
4645
  useSchematicIsPending,
3070
- useSchematicPlan
4646
+ useSchematicLocale,
4647
+ useSchematicPlan,
4648
+ useSchematicStrings,
4649
+ useSchematicTranslate
3071
4650
  };
3072
4651
  /*! Bundled license information:
3073
4652