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