@schematichq/schematic-react 1.5.0 → 1.6.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.7.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"],
@@ -1127,16 +1145,545 @@ function contextString(context) {
1127
1145
  }, {});
1128
1146
  return JSON.stringify(sortedContext);
1129
1147
  }
1130
- var version = "1.5.0";
1148
+ var version = "1.7.0";
1149
+ var models_exports = {};
1150
+ __export(models_exports, {
1151
+ ApiErrorFromJSON: () => ApiErrorFromJSON,
1152
+ ApiErrorFromJSONTyped: () => ApiErrorFromJSONTyped,
1153
+ ApiErrorToJSON: () => ApiErrorToJSON,
1154
+ ApiErrorToJSONTyped: () => ApiErrorToJSONTyped,
1155
+ CompanyInvoiceResponseDataFromJSON: () => CompanyInvoiceResponseDataFromJSON,
1156
+ CompanyInvoiceResponseDataFromJSONTyped: () => CompanyInvoiceResponseDataFromJSONTyped,
1157
+ CompanyInvoiceResponseDataToJSON: () => CompanyInvoiceResponseDataToJSON,
1158
+ CompanyInvoiceResponseDataToJSONTyped: () => CompanyInvoiceResponseDataToJSONTyped,
1159
+ CompanyInvoicesResponseDataFromJSON: () => CompanyInvoicesResponseDataFromJSON,
1160
+ CompanyInvoicesResponseDataFromJSONTyped: () => CompanyInvoicesResponseDataFromJSONTyped,
1161
+ CompanyInvoicesResponseDataToJSON: () => CompanyInvoicesResponseDataToJSON,
1162
+ CompanyInvoicesResponseDataToJSONTyped: () => CompanyInvoicesResponseDataToJSONTyped,
1163
+ GetCompanyInvoicesParamsFromJSON: () => GetCompanyInvoicesParamsFromJSON,
1164
+ GetCompanyInvoicesParamsFromJSONTyped: () => GetCompanyInvoicesParamsFromJSONTyped,
1165
+ GetCompanyInvoicesParamsToJSON: () => GetCompanyInvoicesParamsToJSON,
1166
+ GetCompanyInvoicesParamsToJSONTyped: () => GetCompanyInvoicesParamsToJSONTyped,
1167
+ GetCompanyInvoicesResponseFromJSON: () => GetCompanyInvoicesResponseFromJSON,
1168
+ GetCompanyInvoicesResponseFromJSONTyped: () => GetCompanyInvoicesResponseFromJSONTyped,
1169
+ GetCompanyInvoicesResponseToJSON: () => GetCompanyInvoicesResponseToJSON,
1170
+ GetCompanyInvoicesResponseToJSONTyped: () => GetCompanyInvoicesResponseToJSONTyped,
1171
+ InvoiceStatus: () => InvoiceStatus,
1172
+ InvoiceStatusFromJSON: () => InvoiceStatusFromJSON,
1173
+ InvoiceStatusFromJSONTyped: () => InvoiceStatusFromJSONTyped,
1174
+ InvoiceStatusToJSON: () => InvoiceStatusToJSON,
1175
+ InvoiceStatusToJSONTyped: () => InvoiceStatusToJSONTyped,
1176
+ instanceOfApiError: () => instanceOfApiError,
1177
+ instanceOfCompanyInvoiceResponseData: () => instanceOfCompanyInvoiceResponseData,
1178
+ instanceOfCompanyInvoicesResponseData: () => instanceOfCompanyInvoicesResponseData,
1179
+ instanceOfGetCompanyInvoicesParams: () => instanceOfGetCompanyInvoicesParams,
1180
+ instanceOfGetCompanyInvoicesResponse: () => instanceOfGetCompanyInvoicesResponse,
1181
+ instanceOfInvoiceStatus: () => instanceOfInvoiceStatus
1182
+ });
1183
+ function instanceOfApiError(value) {
1184
+ if (!("error" in value) || value["error"] === void 0) return false;
1185
+ return true;
1186
+ }
1187
+ function ApiErrorFromJSON(json) {
1188
+ return ApiErrorFromJSONTyped(json, false);
1189
+ }
1190
+ function ApiErrorFromJSONTyped(json, ignoreDiscriminator) {
1191
+ if (json == null) {
1192
+ return json;
1193
+ }
1194
+ return {
1195
+ error: json["error"]
1196
+ };
1197
+ }
1198
+ function ApiErrorToJSON(json) {
1199
+ return ApiErrorToJSONTyped(json, false);
1200
+ }
1201
+ function ApiErrorToJSONTyped(value, ignoreDiscriminator = false) {
1202
+ if (value == null) {
1203
+ return value;
1204
+ }
1205
+ return {
1206
+ error: value["error"]
1207
+ };
1208
+ }
1209
+ var InvoiceStatus = {
1210
+ Draft: "draft",
1211
+ Open: "open",
1212
+ Paid: "paid",
1213
+ Uncollectible: "uncollectible",
1214
+ Void: "void"
1215
+ };
1216
+ function instanceOfInvoiceStatus(value) {
1217
+ for (const key in InvoiceStatus) {
1218
+ if (Object.prototype.hasOwnProperty.call(InvoiceStatus, key)) {
1219
+ if (InvoiceStatus[key] === value) {
1220
+ return true;
1221
+ }
1222
+ }
1223
+ }
1224
+ return false;
1225
+ }
1226
+ function InvoiceStatusFromJSON(json) {
1227
+ return InvoiceStatusFromJSONTyped(json, false);
1228
+ }
1229
+ function InvoiceStatusFromJSONTyped(json, ignoreDiscriminator) {
1230
+ return json;
1231
+ }
1232
+ function InvoiceStatusToJSON(value) {
1233
+ return value;
1234
+ }
1235
+ function InvoiceStatusToJSONTyped(value, ignoreDiscriminator) {
1236
+ return value;
1237
+ }
1238
+ function instanceOfCompanyInvoiceResponseData(value) {
1239
+ if (!("amountDue" in value) || value["amountDue"] === void 0) return false;
1240
+ if (!("createdAt" in value) || value["createdAt"] === void 0) return false;
1241
+ if (!("currency" in value) || value["currency"] === void 0) return false;
1242
+ if (!("id" in value) || value["id"] === void 0) return false;
1243
+ return true;
1244
+ }
1245
+ function CompanyInvoiceResponseDataFromJSON(json) {
1246
+ return CompanyInvoiceResponseDataFromJSONTyped(json, false);
1247
+ }
1248
+ function CompanyInvoiceResponseDataFromJSONTyped(json, ignoreDiscriminator) {
1249
+ if (json == null) {
1250
+ return json;
1251
+ }
1252
+ return {
1253
+ amountDue: json["amount_due"],
1254
+ createdAt: new Date(json["created_at"]),
1255
+ currency: json["currency"],
1256
+ dueDate: json["due_date"] == null ? void 0 : new Date(json["due_date"]),
1257
+ id: json["id"],
1258
+ status: json["status"] == null ? void 0 : InvoiceStatusFromJSON(json["status"]),
1259
+ url: json["url"] == null ? void 0 : json["url"]
1260
+ };
1261
+ }
1262
+ function CompanyInvoiceResponseDataToJSON(json) {
1263
+ return CompanyInvoiceResponseDataToJSONTyped(json, false);
1264
+ }
1265
+ function CompanyInvoiceResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
1266
+ if (value == null) {
1267
+ return value;
1268
+ }
1269
+ return {
1270
+ amount_due: value["amountDue"],
1271
+ created_at: value["createdAt"].toISOString(),
1272
+ currency: value["currency"],
1273
+ due_date: value["dueDate"] == null ? void 0 : value["dueDate"].toISOString(),
1274
+ id: value["id"],
1275
+ status: InvoiceStatusToJSON(value["status"]),
1276
+ url: value["url"]
1277
+ };
1278
+ }
1279
+ function instanceOfCompanyInvoicesResponseData(value) {
1280
+ if (!("count" in value) || value["count"] === void 0) return false;
1281
+ if (!("invoices" in value) || value["invoices"] === void 0) return false;
1282
+ return true;
1283
+ }
1284
+ function CompanyInvoicesResponseDataFromJSON(json) {
1285
+ return CompanyInvoicesResponseDataFromJSONTyped(json, false);
1286
+ }
1287
+ function CompanyInvoicesResponseDataFromJSONTyped(json, ignoreDiscriminator) {
1288
+ if (json == null) {
1289
+ return json;
1290
+ }
1291
+ return {
1292
+ count: json["count"],
1293
+ invoices: json["invoices"].map(
1294
+ CompanyInvoiceResponseDataFromJSON
1295
+ )
1296
+ };
1297
+ }
1298
+ function CompanyInvoicesResponseDataToJSON(json) {
1299
+ return CompanyInvoicesResponseDataToJSONTyped(json, false);
1300
+ }
1301
+ function CompanyInvoicesResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
1302
+ if (value == null) {
1303
+ return value;
1304
+ }
1305
+ return {
1306
+ count: value["count"],
1307
+ invoices: value["invoices"].map(
1308
+ CompanyInvoiceResponseDataToJSON
1309
+ )
1310
+ };
1311
+ }
1312
+ function instanceOfGetCompanyInvoicesParams(value) {
1313
+ return true;
1314
+ }
1315
+ function GetCompanyInvoicesParamsFromJSON(json) {
1316
+ return GetCompanyInvoicesParamsFromJSONTyped(json, false);
1317
+ }
1318
+ function GetCompanyInvoicesParamsFromJSONTyped(json, ignoreDiscriminator) {
1319
+ if (json == null) {
1320
+ return json;
1321
+ }
1322
+ return {
1323
+ includePending: json["include_pending"] == null ? void 0 : json["include_pending"],
1324
+ limit: json["limit"] == null ? void 0 : json["limit"],
1325
+ offset: json["offset"] == null ? void 0 : json["offset"]
1326
+ };
1327
+ }
1328
+ function GetCompanyInvoicesParamsToJSON(json) {
1329
+ return GetCompanyInvoicesParamsToJSONTyped(json, false);
1330
+ }
1331
+ function GetCompanyInvoicesParamsToJSONTyped(value, ignoreDiscriminator = false) {
1332
+ if (value == null) {
1333
+ return value;
1334
+ }
1335
+ return {
1336
+ include_pending: value["includePending"],
1337
+ limit: value["limit"],
1338
+ offset: value["offset"]
1339
+ };
1340
+ }
1341
+ function instanceOfGetCompanyInvoicesResponse(value) {
1342
+ if (!("data" in value) || value["data"] === void 0) return false;
1343
+ if (!("params" in value) || value["params"] === void 0) return false;
1344
+ return true;
1345
+ }
1346
+ function GetCompanyInvoicesResponseFromJSON(json) {
1347
+ return GetCompanyInvoicesResponseFromJSONTyped(json, false);
1348
+ }
1349
+ function GetCompanyInvoicesResponseFromJSONTyped(json, ignoreDiscriminator) {
1350
+ if (json == null) {
1351
+ return json;
1352
+ }
1353
+ return {
1354
+ data: CompanyInvoicesResponseDataFromJSON(json["data"]),
1355
+ params: GetCompanyInvoicesParamsFromJSON(json["params"])
1356
+ };
1357
+ }
1358
+ function GetCompanyInvoicesResponseToJSON(json) {
1359
+ return GetCompanyInvoicesResponseToJSONTyped(json, false);
1360
+ }
1361
+ function GetCompanyInvoicesResponseToJSONTyped(value, ignoreDiscriminator = false) {
1362
+ if (value == null) {
1363
+ return value;
1364
+ }
1365
+ return {
1366
+ data: CompanyInvoicesResponseDataToJSON(value["data"]),
1367
+ params: GetCompanyInvoicesParamsToJSON(value["params"])
1368
+ };
1369
+ }
1370
+ var DEFAULT_INVOICE_QUERY = {};
1371
+ function normalizeInvoiceQuery(query) {
1372
+ const { includePending, ...rest } = query;
1373
+ return includePending === true ? { ...rest, includePending: true } : rest;
1374
+ }
1375
+ var SchematicApiError = class extends Error {
1376
+ constructor(status, path, body) {
1377
+ super(
1378
+ typeof body === "object" && body !== null && "error" in body ? String(body.error) : `Request to ${path} failed with status ${status}`
1379
+ );
1380
+ this.status = status;
1381
+ this.path = path;
1382
+ this.body = body;
1383
+ this.name = "SchematicApiError";
1384
+ }
1385
+ status;
1386
+ path;
1387
+ body;
1388
+ };
1389
+ var DEFAULT_API_URL = "https://api.schematichq.com";
1390
+ var TOKEN_CACHE_SIZE = 10;
1391
+ function sessionKey(session) {
1392
+ return JSON.stringify([session.company, session.user ?? null]);
1393
+ }
1394
+ var SchematicSession = class {
1395
+ _apiUrl;
1396
+ _headers;
1397
+ _fetch;
1398
+ _session;
1399
+ _tokens = /* @__PURE__ */ new Map();
1400
+ _resolving = /* @__PURE__ */ new Map();
1401
+ /**
1402
+ * Bumped when the session's identity changes, and only then — the object
1403
+ * itself is replaced on every render. Anything asking "is this still the
1404
+ * session I started under?" counts generations rather than comparing.
1405
+ */
1406
+ _generation = 0;
1407
+ _listeners = /* @__PURE__ */ new Set();
1408
+ constructor(options = {}) {
1409
+ this._session = options.session;
1410
+ this._apiUrl = (options.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, "");
1411
+ this._headers = options.additionalHeaders ?? {};
1412
+ this._fetch = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
1413
+ }
1414
+ get key() {
1415
+ return this._session === null || this._session === void 0 ? void 0 : sessionKey(this._session);
1416
+ }
1417
+ get status() {
1418
+ if (this._session === void 0) {
1419
+ return "pending";
1420
+ }
1421
+ return this._session === null ? "ended" : "active";
1422
+ }
1423
+ /** Only a statement that changes which pair is read counts as a change. */
1424
+ set(session) {
1425
+ if (session === void 0) {
1426
+ return;
1427
+ }
1428
+ const previous = this._session;
1429
+ this._session = session;
1430
+ if (session === null) {
1431
+ if (previous === null) {
1432
+ return;
1433
+ }
1434
+ this._tokens.clear();
1435
+ this._resolving.clear();
1436
+ this._generation += 1;
1437
+ this._emit({ type: "ended" });
1438
+ return;
1439
+ }
1440
+ if (previous !== null && previous !== void 0) {
1441
+ if (previous.company === session.company && (previous.user ?? null) === (session.user ?? null)) {
1442
+ return;
1443
+ }
1444
+ this._generation += 1;
1445
+ this._emit({ type: "changed" });
1446
+ return;
1447
+ }
1448
+ this._generation += 1;
1449
+ this._emit({ type: "started" });
1450
+ }
1451
+ onChange(listener) {
1452
+ this._listeners.add(listener);
1453
+ return () => {
1454
+ this._listeners.delete(listener);
1455
+ };
1456
+ }
1457
+ _emit(event) {
1458
+ for (const listener of this._listeners) {
1459
+ listener(event);
1460
+ }
1461
+ }
1462
+ _cached(key) {
1463
+ const cached = this._tokens.get(key);
1464
+ if (cached === void 0) {
1465
+ return void 0;
1466
+ }
1467
+ if (cached.expiresAt !== void 0 && cached.expiresAt.getTime() <= Date.now()) {
1468
+ this._tokens.delete(key);
1469
+ return void 0;
1470
+ }
1471
+ this._tokens.delete(key);
1472
+ this._tokens.set(key, cached);
1473
+ return cached;
1474
+ }
1475
+ _cache(key, resolved) {
1476
+ this._tokens.delete(key);
1477
+ this._tokens.set(key, resolved);
1478
+ while (this._tokens.size > TOKEN_CACHE_SIZE) {
1479
+ const oldest = this._tokens.keys().next();
1480
+ if (oldest.done === true) {
1481
+ break;
1482
+ }
1483
+ this._tokens.delete(oldest.value);
1484
+ }
1485
+ }
1486
+ /**
1487
+ * The credential for a session, minted if this one is not held. `force`
1488
+ * retires what is held first: the caller is a request the API has just
1489
+ * rejected.
1490
+ */
1491
+ resolveToken(session, force) {
1492
+ const { token } = session;
1493
+ if (typeof token === "string") {
1494
+ return Promise.resolve(token);
1495
+ }
1496
+ const key = sessionKey(session);
1497
+ if (!force) {
1498
+ const cached = this._cached(key);
1499
+ if (cached !== void 0) {
1500
+ return Promise.resolve(cached.token);
1501
+ }
1502
+ } else {
1503
+ this._tokens.delete(key);
1504
+ }
1505
+ const inflight = this._resolving.get(key);
1506
+ if (inflight !== void 0 && inflight.sessionGeneration === this._generation && (!force || inflight.forced)) {
1507
+ return inflight.promise;
1508
+ }
1509
+ const provider = token;
1510
+ const sessionGeneration = this._generation;
1511
+ const owns = () => this._resolving.get(key)?.promise === promise;
1512
+ const promise = Promise.resolve().then(() => provider()).then((result) => {
1513
+ const { resolved, stamped } = asResolvedToken(result, session);
1514
+ if (owns() && (this._generation === sessionGeneration || stamped)) {
1515
+ this._cache(key, resolved);
1516
+ }
1517
+ return resolved.token;
1518
+ }).finally(() => {
1519
+ if (owns()) {
1520
+ this._resolving.delete(key);
1521
+ }
1522
+ });
1523
+ this._resolving.set(key, { promise, forced: force, sessionGeneration });
1524
+ return promise;
1525
+ }
1526
+ /**
1527
+ * Sends a request under the active session's credential, refreshing once
1528
+ * and retrying if the API rejects it. Rejects rather than answering when
1529
+ * the session changes while the request is in flight: the rows would
1530
+ * otherwise come back as the answer to a question asked for another pair.
1531
+ */
1532
+ async request(path, options = {}) {
1533
+ const { method = "GET", body } = options;
1534
+ const send = async (credential2) => this._fetch(`${this._apiUrl}${path}`, {
1535
+ method,
1536
+ headers: {
1537
+ "Accept": "application/json",
1538
+ ...body === void 0 ? {} : { "Content-Type": "application/json" },
1539
+ ...this._headers,
1540
+ "X-Schematic-Api-Key": credential2
1541
+ },
1542
+ ...body === void 0 ? {} : { body: JSON.stringify(body) }
1543
+ });
1544
+ const session = this._session;
1545
+ if (session === null) {
1546
+ throw new Error("There is no session to read data for.");
1547
+ }
1548
+ if (session === void 0) {
1549
+ throw new Error("A session is required to read data.");
1550
+ }
1551
+ const provider = session.token;
1552
+ const generation = this._generation;
1553
+ const stillOurs = async (response2) => {
1554
+ if (this._generation === generation) {
1555
+ return;
1556
+ }
1557
+ if (response2 !== void 0) {
1558
+ await discardBody(response2);
1559
+ }
1560
+ throw new Error("The session changed while this request was in flight.");
1561
+ };
1562
+ const credential = await this.resolveToken(session, false);
1563
+ if (this._generation !== generation) {
1564
+ throw new Error("The session changed before this request was sent.");
1565
+ }
1566
+ let response = await send(credential);
1567
+ await stillOurs(response);
1568
+ if (response.status === 401 && typeof provider === "function" && this._generation === generation) {
1569
+ const status = response.status;
1570
+ const rejected = await readBody(response);
1571
+ let retried = false;
1572
+ const current = this._session;
1573
+ if (this._generation === generation && current !== null && current !== void 0) {
1574
+ const refreshed = await this.resolveToken(current, true);
1575
+ if (this._generation === generation) {
1576
+ response = await send(refreshed);
1577
+ await stillOurs(response);
1578
+ retried = true;
1579
+ }
1580
+ }
1581
+ if (!retried) {
1582
+ throw new SchematicApiError(status, path, rejected);
1583
+ }
1584
+ }
1585
+ const parsed = await readBody(response);
1586
+ await stillOurs();
1587
+ if (!response.ok) {
1588
+ throw new SchematicApiError(response.status, path, parsed);
1589
+ }
1590
+ return parsed;
1591
+ }
1592
+ };
1593
+ function asResolvedToken(result, session) {
1594
+ if (typeof result === "string") {
1595
+ return { resolved: { token: result }, stamped: false };
1596
+ }
1597
+ const token = result?.token;
1598
+ if (typeof token !== "string" || token === "") {
1599
+ throw new Error("The access token provider did not return a token.");
1600
+ }
1601
+ if (result.company !== void 0 && result.company !== session.company || result.user !== void 0 && session.user !== void 0 && result.user !== session.user) {
1602
+ throw new Error(
1603
+ "The access token provider returned a token for a different session."
1604
+ );
1605
+ }
1606
+ const stamped = result.company !== void 0 && (session.user === void 0 || result.user !== void 0);
1607
+ return { resolved: { token, expiresAt: asDate(result.expiresAt) }, stamped };
1608
+ }
1609
+ function asDate(value) {
1610
+ if (value === void 0 || value === null) {
1611
+ return void 0;
1612
+ }
1613
+ const date = value instanceof Date ? value : new Date(value);
1614
+ return Number.isNaN(date.getTime()) ? void 0 : date;
1615
+ }
1616
+ async function discardBody(response) {
1617
+ try {
1618
+ await response.body?.cancel();
1619
+ } catch {
1620
+ }
1621
+ }
1622
+ async function readBody(response) {
1623
+ const text = await response.text();
1624
+ if (text === "") {
1625
+ return null;
1626
+ }
1627
+ try {
1628
+ return JSON.parse(text);
1629
+ } catch {
1630
+ return text;
1631
+ }
1632
+ }
1633
+ var INVOICE_PAGE_SIZE = 12;
1634
+ var INVOICE_MAX_PAGE_SIZE = 250;
1635
+ var SchematicBillingClient = class {
1636
+ /**
1637
+ * Public so a second client over the same surface can be constructed on
1638
+ * this one rather than minting tokens of its own.
1639
+ */
1640
+ session;
1641
+ constructor(options = {}) {
1642
+ this.session = options instanceof SchematicSession ? options : new SchematicSession(options);
1643
+ }
1644
+ get sessionKey() {
1645
+ return this.session.key;
1646
+ }
1647
+ get sessionStatus() {
1648
+ return this.session.status;
1649
+ }
1650
+ setSession(session) {
1651
+ this.session.set(session);
1652
+ }
1653
+ onSessionChange(listener) {
1654
+ return this.session.onChange(listener);
1655
+ }
1656
+ fetchInvoices(params) {
1657
+ const query = new URLSearchParams({
1658
+ limit: String(Math.min(params.limit, INVOICE_MAX_PAGE_SIZE)),
1659
+ offset: String(params.offset)
1660
+ });
1661
+ if (params.includePending !== void 0) {
1662
+ query.set("include_pending", String(params.includePending));
1663
+ }
1664
+ const path = `/company/invoices?${query}`;
1665
+ return this.session.request(path).then((body) => {
1666
+ if (body === null || typeof body !== "object" || !("data" in body)) {
1667
+ throw new Error(`Malformed response from ${path}`);
1668
+ }
1669
+ const data = body.data;
1670
+ if (data == null || data.invoices == null) {
1671
+ return { invoices: [], count: 0 };
1672
+ }
1673
+ const decoded = GetCompanyInvoicesResponseFromJSON(body).data;
1674
+ return { invoices: decoded.invoices, count: decoded.count };
1675
+ });
1676
+ }
1677
+ };
1131
1678
  var anonymousIdKey = "schematicId";
1132
1679
  var flagStateCachePrefix = "schematicCache";
1133
1680
  var flagStateCacheMaxContexts = 10;
1134
1681
  var flagStateCacheDefaultMaxAgeMs = 7 * 24 * 60 * 60 * 1e3;
1135
1682
  var emptyCreditBalances = Object.freeze({});
1136
1683
  var Schematic = class {
1137
- additionalHeaders = {};
1684
+ _additionalHeaders = {};
1138
1685
  apiKey;
1139
- apiUrl = "https://api.schematichq.com";
1686
+ _apiUrl = "https://api.schematichq.com";
1140
1687
  conn = null;
1141
1688
  context = {};
1142
1689
  debugEnabled = false;
@@ -1216,7 +1763,7 @@ var Schematic = class {
1216
1763
  if (this.offlineEnabled) {
1217
1764
  this.setIsPending(false);
1218
1765
  }
1219
- this.additionalHeaders = {
1766
+ this._additionalHeaders = {
1220
1767
  "X-Schematic-Client-Version": `schematic-js@${version}`,
1221
1768
  ...options?.additionalHeaders ?? {}
1222
1769
  };
@@ -1232,7 +1779,7 @@ var Schematic = class {
1232
1779
  }
1233
1780
  this.hydrateFlagStateFromCache();
1234
1781
  if (options?.apiUrl !== void 0) {
1235
- this.apiUrl = options.apiUrl;
1782
+ this._apiUrl = options.apiUrl;
1236
1783
  }
1237
1784
  if (options?.eventUrl !== void 0) {
1238
1785
  this.eventUrl = options.eventUrl;
@@ -1297,6 +1844,12 @@ var Schematic = class {
1297
1844
  this.debug("Initialized with debug mode enabled");
1298
1845
  }
1299
1846
  }
1847
+ get apiUrl() {
1848
+ return this._apiUrl;
1849
+ }
1850
+ get additionalHeaders() {
1851
+ return { ...this._additionalHeaders };
1852
+ }
1300
1853
  /**
1301
1854
  * Resolve fallback value according to priority order:
1302
1855
  * 1. Callsite fallback value (if provided)
@@ -1382,11 +1935,11 @@ var Schematic = class {
1382
1935
  return resolvedFallbackResult.value;
1383
1936
  }
1384
1937
  if (!this.useWebSocket) {
1385
- const requestUrl = `${this.apiUrl}/flags/${key}/check`;
1938
+ const requestUrl = `${this._apiUrl}/flags/${key}/check`;
1386
1939
  return fetch(requestUrl, {
1387
1940
  method: "POST",
1388
1941
  headers: {
1389
- ...this.additionalHeaders ?? {},
1942
+ ...this._additionalHeaders ?? {},
1390
1943
  "Content-Type": "application/json;charset=UTF-8",
1391
1944
  "X-Schematic-Api-Key": this.apiKey
1392
1945
  },
@@ -1589,12 +2142,12 @@ var Schematic = class {
1589
2142
  this.debug(`checkFlags offline result: returning empty object`);
1590
2143
  return {};
1591
2144
  }
1592
- const requestUrl = `${this.apiUrl}/flags/check`;
2145
+ const requestUrl = `${this._apiUrl}/flags/check`;
1593
2146
  const requestBody = JSON.stringify(context);
1594
2147
  return fetch(requestUrl, {
1595
2148
  method: "POST",
1596
2149
  headers: {
1597
- ...this.additionalHeaders ?? {},
2150
+ ...this._additionalHeaders ?? {},
1598
2151
  "Content-Type": "application/json;charset=UTF-8",
1599
2152
  "X-Schematic-Api-Key": this.apiKey
1600
2153
  },
@@ -2141,7 +2694,7 @@ var Schematic = class {
2141
2694
  const response = await fetch(captureUrl, {
2142
2695
  method: "POST",
2143
2696
  headers: {
2144
- ...this.additionalHeaders ?? {},
2697
+ ...this._additionalHeaders ?? {},
2145
2698
  "Content-Type": "application/json;charset=UTF-8"
2146
2699
  },
2147
2700
  body: payload
@@ -2637,7 +3190,7 @@ var Schematic = class {
2637
3190
  }
2638
3191
  });
2639
3192
  this.currentWebSocket = socket;
2640
- const clientVersion = this.additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
3193
+ const clientVersion = this._additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
2641
3194
  const messagePayload = {
2642
3195
  apiKey: this.apiKey,
2643
3196
  clientVersion,
@@ -2871,23 +3424,853 @@ var notifyCreditBalanceListener = (listener, value) => {
2871
3424
  };
2872
3425
 
2873
3426
  // src/context/schematic.tsx
2874
- import React, { createContext, useEffect, useMemo, useRef } from "react";
3427
+ import React4, { createContext as createContext3, useEffect as useEffect2, useMemo as useMemo5, useRef as useRef3 } from "react";
3428
+
3429
+ // src/billing/contract/index.ts
3430
+ function normalizeInvoiceQuery2(query) {
3431
+ return normalizeInvoiceQuery(query).includePending === true ? { includePending: true } : {};
3432
+ }
3433
+
3434
+ // src/billing/store.ts
3435
+ var Resource = class {
3436
+ constructor(_fetcher, initial, _readiness = () => "ready") {
3437
+ this._fetcher = _fetcher;
3438
+ this._readiness = _readiness;
3439
+ this._loaded = initial !== void 0;
3440
+ this._snapshot = {
3441
+ data: initial,
3442
+ error: void 0,
3443
+ isPending: initial === void 0
3444
+ };
3445
+ }
3446
+ _fetcher;
3447
+ _readiness;
3448
+ _snapshot;
3449
+ _listeners = /* @__PURE__ */ new Set();
3450
+ _inflight;
3451
+ _extending;
3452
+ /** A refetch asked for mid-load; runs once that load lands. */
3453
+ _queued;
3454
+ _generation = 0;
3455
+ _loaded = false;
3456
+ get snapshot() {
3457
+ return this._snapshot;
3458
+ }
3459
+ get subscriberCount() {
3460
+ return this._listeners.size;
3461
+ }
3462
+ getSnapshot = () => this._snapshot;
3463
+ subscribe = (listener) => {
3464
+ this._listeners.add(listener);
3465
+ if (!this._loaded && this._inflight === void 0 && this._snapshot.error === void 0) {
3466
+ void this.load();
3467
+ }
3468
+ return () => {
3469
+ this._listeners.delete(listener);
3470
+ };
3471
+ };
3472
+ load() {
3473
+ if (this._inflight !== void 0) {
3474
+ return this._inflight;
3475
+ }
3476
+ const readiness = this._readiness();
3477
+ if (readiness !== "ready") {
3478
+ if (readiness === "never" && this._snapshot.isPending) {
3479
+ this._set({ ...this._snapshot, isPending: false });
3480
+ }
3481
+ return Promise.resolve();
3482
+ }
3483
+ const generation = ++this._generation;
3484
+ this._set({ ...this._snapshot, error: void 0, isPending: true });
3485
+ const run = Promise.resolve().then(() => this._fetcher()).then(
3486
+ (data) => {
3487
+ if (generation !== this._generation) return;
3488
+ this._loaded = true;
3489
+ this._set({ data, error: void 0, isPending: false });
3490
+ },
3491
+ (cause) => {
3492
+ if (generation !== this._generation) return;
3493
+ const error = cause instanceof Error ? cause : new Error(String(cause));
3494
+ this._set({ ...this._snapshot, error, isPending: false });
3495
+ }
3496
+ ).finally(() => {
3497
+ if (generation === this._generation) {
3498
+ this._inflight = void 0;
3499
+ }
3500
+ });
3501
+ this._inflight = run;
3502
+ return run;
3503
+ }
3504
+ /**
3505
+ * Reloads; `data` holds its current value until the response lands. Asked
3506
+ * for mid-load, it runs again after: that request was built before
3507
+ * whatever prompted this one. Refetches queued on one load share the
3508
+ * re-run; a reset, seed, or clear in the meantime supersedes it.
3509
+ */
3510
+ refetch() {
3511
+ if (this._inflight === void 0) {
3512
+ return this.load();
3513
+ }
3514
+ if (this._queued === void 0) {
3515
+ const generation = this._generation;
3516
+ const queued = this._inflight.then(() => {
3517
+ if (this._queued === queued) {
3518
+ this._queued = void 0;
3519
+ }
3520
+ if (generation !== this._generation) {
3521
+ return;
3522
+ }
3523
+ return this.load();
3524
+ });
3525
+ this._queued = queued;
3526
+ }
3527
+ return this._queued;
3528
+ }
3529
+ /**
3530
+ * Pages: `fetcher` receives the current data and returns what replaces it.
3531
+ * Never rejects — a caller that wants the failure reads `snapshot.error`,
3532
+ * and `data` keeps what was already fetched.
3533
+ *
3534
+ * A load already in flight wins: it is about to refresh the window this
3535
+ * would have appended to.
3536
+ */
3537
+ extend(fetcher) {
3538
+ const current = this._snapshot.data;
3539
+ if (current === void 0) {
3540
+ return Promise.resolve();
3541
+ }
3542
+ if (this._readiness() !== "ready") {
3543
+ return Promise.resolve();
3544
+ }
3545
+ if (this._extending !== void 0) {
3546
+ return this._extending;
3547
+ }
3548
+ if (this._inflight !== void 0) {
3549
+ return this._inflight;
3550
+ }
3551
+ const generation = ++this._generation;
3552
+ this._set({ ...this._snapshot, error: void 0, isPending: true });
3553
+ const run = Promise.resolve().then(() => fetcher(current)).then(
3554
+ (data) => {
3555
+ if (generation !== this._generation) return;
3556
+ this._set({ data, error: void 0, isPending: false });
3557
+ },
3558
+ (cause) => {
3559
+ if (generation !== this._generation) return;
3560
+ const error = cause instanceof Error ? cause : new Error(String(cause));
3561
+ this._set({ ...this._snapshot, error, isPending: false });
3562
+ }
3563
+ ).finally(() => {
3564
+ if (this._extending === run) {
3565
+ this._extending = void 0;
3566
+ }
3567
+ });
3568
+ this._extending = run;
3569
+ return run;
3570
+ }
3571
+ seed(data) {
3572
+ this._generation++;
3573
+ this._inflight = void 0;
3574
+ this._extending = void 0;
3575
+ this._queued = void 0;
3576
+ this._loaded = true;
3577
+ this._set({ data, error: void 0, isPending: false });
3578
+ }
3579
+ update(fn) {
3580
+ if (this._snapshot.data === void 0) return;
3581
+ this._generation++;
3582
+ this._inflight = void 0;
3583
+ this._extending = void 0;
3584
+ this._queued = void 0;
3585
+ this._set({ ...this._snapshot, data: fn(this._snapshot.data) });
3586
+ }
3587
+ /**
3588
+ * Forgets everything and stays empty — no data, no error, not pending.
3589
+ * What a resource holds when there is no session to hold it for: a session
3590
+ * ending is not a failure and must not surface as one.
3591
+ */
3592
+ clear() {
3593
+ this._generation++;
3594
+ this._inflight = void 0;
3595
+ this._extending = void 0;
3596
+ this._queued = void 0;
3597
+ this._loaded = false;
3598
+ this._set({ data: void 0, error: void 0, isPending: false });
3599
+ }
3600
+ /** Forgets everything; reloads immediately if anyone is subscribed. */
3601
+ reset() {
3602
+ this._generation++;
3603
+ this._inflight = void 0;
3604
+ this._extending = void 0;
3605
+ this._queued = void 0;
3606
+ this._loaded = false;
3607
+ const readiness = this._readiness();
3608
+ const willLoad = this._listeners.size > 0 && readiness === "ready";
3609
+ this._set({
3610
+ data: void 0,
3611
+ error: void 0,
3612
+ isPending: willLoad || readiness === "waiting"
3613
+ });
3614
+ if (willLoad) {
3615
+ void this.load();
3616
+ }
3617
+ }
3618
+ _set(next) {
3619
+ this._snapshot = next;
3620
+ for (const listener of this._listeners) {
3621
+ listener();
3622
+ }
3623
+ }
3624
+ };
3625
+ function hashKey(params) {
3626
+ return JSON.stringify(canonical(params));
3627
+ }
3628
+ function canonical(value) {
3629
+ if (Array.isArray(value)) {
3630
+ return value.map(canonical);
3631
+ }
3632
+ if (value instanceof Date) {
3633
+ const time = value.getTime();
3634
+ return Number.isNaN(time) ? "Invalid Date" : value.toISOString();
3635
+ }
3636
+ if (value !== null && typeof value === "object") {
3637
+ const out = {};
3638
+ for (const key of Object.keys(value).sort()) {
3639
+ const v = value[key];
3640
+ if (v !== void 0) {
3641
+ out[key] = canonical(v);
3642
+ }
3643
+ }
3644
+ return out;
3645
+ }
3646
+ return value ?? null;
3647
+ }
3648
+ var DEFAULT_EVICTION = { maxIdle: 4 };
3649
+ var KeyedResource = class {
3650
+ constructor(_fetcher, options = {}) {
3651
+ this._fetcher = _fetcher;
3652
+ this._readiness = options.readiness ?? (() => "ready");
3653
+ this._hash = options.hash ?? hashKey;
3654
+ this._eviction = {
3655
+ maxIdle: options.eviction?.maxIdle ?? DEFAULT_EVICTION.maxIdle
3656
+ };
3657
+ }
3658
+ _fetcher;
3659
+ _entries = /* @__PURE__ */ new Map();
3660
+ _hash;
3661
+ _eviction;
3662
+ _readiness;
3663
+ hash(params) {
3664
+ return this._hash(params);
3665
+ }
3666
+ get size() {
3667
+ return this._entries.size;
3668
+ }
3669
+ entries() {
3670
+ return Array.from(this._entries, ([key, e]) => ({ key, ...e }));
3671
+ }
3672
+ get(params) {
3673
+ const key = this._hash(params);
3674
+ const existing = this._entries.get(key);
3675
+ if (existing !== void 0) {
3676
+ this._entries.delete(key);
3677
+ this._entries.set(key, existing);
3678
+ return existing.resource;
3679
+ }
3680
+ const resource = new Resource(
3681
+ () => this._fetcher(params, resource.snapshot.data),
3682
+ void 0,
3683
+ this._readiness
3684
+ );
3685
+ this._entries.set(key, { params, resource });
3686
+ return resource;
3687
+ }
3688
+ has(params) {
3689
+ return this._entries.has(this._hash(params));
3690
+ }
3691
+ subscribe(params, listener) {
3692
+ const resource = this.get(params);
3693
+ const unsubscribe = resource.subscribe(listener);
3694
+ return () => {
3695
+ unsubscribe();
3696
+ this._evict();
3697
+ };
3698
+ }
3699
+ seed(params, data) {
3700
+ this.get(params).seed(data);
3701
+ }
3702
+ evict(params) {
3703
+ return this._entries.delete(this._hash(params));
3704
+ }
3705
+ resetAll() {
3706
+ for (const [key, { resource }] of Array.from(this._entries)) {
3707
+ if (resource.subscriberCount === 0) {
3708
+ this._entries.delete(key);
3709
+ } else {
3710
+ resource.reset();
3711
+ }
3712
+ }
3713
+ }
3714
+ resumeAll() {
3715
+ for (const { resource } of this._entries.values()) {
3716
+ if (resource.subscriberCount === 0) {
3717
+ continue;
3718
+ }
3719
+ const { data, error } = resource.snapshot;
3720
+ if (data === void 0 || error !== void 0) {
3721
+ void resource.load();
3722
+ }
3723
+ }
3724
+ }
3725
+ clearAll() {
3726
+ for (const [key, { resource }] of Array.from(this._entries)) {
3727
+ if (resource.subscriberCount === 0) {
3728
+ this._entries.delete(key);
3729
+ } else {
3730
+ resource.clear();
3731
+ }
3732
+ }
3733
+ }
3734
+ invalidateAll() {
3735
+ for (const { resource } of this._entries.values()) {
3736
+ if (resource.snapshot.data !== void 0) {
3737
+ void resource.refetch();
3738
+ }
3739
+ }
3740
+ }
3741
+ _evict() {
3742
+ const idle = Array.from(this._entries).filter(
3743
+ ([, e]) => e.resource.subscriberCount === 0
3744
+ );
3745
+ let excess = idle.length - this._eviction.maxIdle;
3746
+ for (const [key] of idle) {
3747
+ if (excess <= 0) break;
3748
+ this._entries.delete(key);
3749
+ excess -= 1;
3750
+ }
3751
+ }
3752
+ };
3753
+
3754
+ // src/billing/client.ts
3755
+ function claimOf(client) {
3756
+ return { status: client.sessionStatus, key: client.sessionKey };
3757
+ }
3758
+ function claimFrom(session) {
3759
+ if (session === void 0) {
3760
+ return void 0;
3761
+ }
3762
+ return session === null ? { status: "ended", key: void 0 } : { status: "active", key: sessionKey(session) };
3763
+ }
3764
+ function judgeSeed(seedKey, claim) {
3765
+ if (claim.status === "ended") {
3766
+ return "drop";
3767
+ }
3768
+ if (seedKey === void 0) {
3769
+ return "adopt";
3770
+ }
3771
+ if (claim.status === "pending") {
3772
+ return "hold";
3773
+ }
3774
+ return seedKey === claim.key ? "adopt" : "drop";
3775
+ }
3776
+ var READINESS = {
3777
+ pending: "waiting",
3778
+ active: "ready",
3779
+ ended: "never"
3780
+ };
3781
+ var BillingStore = class {
3782
+ constructor(_client, initialData = {}, options = {}) {
3783
+ this._client = _client;
3784
+ this._pageSize = options.pageSize ?? INVOICE_PAGE_SIZE;
3785
+ this.invoices = new KeyedResource(
3786
+ (query, current) => this._reloadWindow(
3787
+ query,
3788
+ Math.max(this._pageSize, current?.invoices.length ?? 0)
3789
+ ),
3790
+ // Waiting until connected; then a session still pending stays
3791
+ // pending, and one that has ended settles empty rather than recording
3792
+ // the client's refusal as an error.
3793
+ {
3794
+ readiness: () => this._connected ? READINESS[this._client.sessionStatus] : "waiting"
3795
+ }
3796
+ );
3797
+ if (initialData.invoices !== void 0) {
3798
+ this._held = {
3799
+ // Normalized the way the hook normalizes, or the caller asking for
3800
+ // it fetches the same page again.
3801
+ params: normalizeInvoiceQuery2(
3802
+ initialData.params?.invoices ?? DEFAULT_INVOICE_QUERY
3803
+ ),
3804
+ data: initialData.invoices,
3805
+ key: initialData.sessionKey
3806
+ };
3807
+ this._settleSeed(claimFrom(options.session) ?? claimOf(this._client));
3808
+ }
3809
+ }
3810
+ _client;
3811
+ invoices;
3812
+ _pageSize;
3813
+ _unsubscribe;
3814
+ _connected = false;
3815
+ _seeded = false;
3816
+ /** The session that prefetch was for, where it said. */
3817
+ _seedKey;
3818
+ /** A stamped prefetch waiting for a session to check it against. */
3819
+ _held;
3820
+ /**
3821
+ * Not done in the constructor: the provider arms it from an effect, and
3822
+ * React runs an effect, its cleanup, then the effect again under
3823
+ * StrictMode. A subscription made once at construction is torn down by
3824
+ * that cleanup and never comes back, leaving the store deaf to every
3825
+ * session change for the rest of the page.
3826
+ *
3827
+ * Also what opens the store: subscribers who arrived first have been
3828
+ * waiting, and this is the moment the session is known to be installed.
3829
+ */
3830
+ connect() {
3831
+ this._unsubscribe?.();
3832
+ const unsubscribe = this._client.onSessionChange?.((event) => {
3833
+ if (event.type === "ended") {
3834
+ this._held = void 0;
3835
+ this._seeded = false;
3836
+ this.clearAll();
3837
+ } else if (event.type === "changed") {
3838
+ this._held = void 0;
3839
+ this._seeded = false;
3840
+ this.resetAll();
3841
+ } else {
3842
+ this._onStarted();
3843
+ }
3844
+ });
3845
+ this._unsubscribe = unsubscribe;
3846
+ if (!this._connected) {
3847
+ this._connected = true;
3848
+ this._settleSeed(claimOf(this._client));
3849
+ this.resumeAll();
3850
+ }
3851
+ return () => {
3852
+ unsubscribe?.();
3853
+ if (this._unsubscribe === unsubscribe) {
3854
+ this._unsubscribe = void 0;
3855
+ }
3856
+ };
3857
+ }
3858
+ _onStarted() {
3859
+ const claim = claimOf(this._client);
3860
+ this._settleSeed(claim);
3861
+ if (this._seeded && judgeSeed(this._seedKey, claim) !== "adopt") {
3862
+ this._seeded = false;
3863
+ this.resetAll();
3864
+ return;
3865
+ }
3866
+ this._seeded = false;
3867
+ this.resumeAll();
3868
+ }
3869
+ /** Adopts, keeps holding, or drops the prefetch, by what `claim` says. */
3870
+ _settleSeed(claim) {
3871
+ const held = this._held;
3872
+ if (held === void 0) {
3873
+ return;
3874
+ }
3875
+ const verdict = judgeSeed(held.key, claim);
3876
+ if (verdict === "hold") {
3877
+ return;
3878
+ }
3879
+ this._held = void 0;
3880
+ if (verdict === "adopt") {
3881
+ this.invoices.seed(held.params, held.data);
3882
+ this._seedKey = held.key;
3883
+ this._seeded = true;
3884
+ }
3885
+ }
3886
+ resource(name) {
3887
+ return this[name];
3888
+ }
3889
+ /** Forgets every resource; subscribed ones reload, idle ones are dropped. */
3890
+ resetAll() {
3891
+ for (const name of RESOURCE_NAMES) {
3892
+ this[name].resetAll();
3893
+ }
3894
+ }
3895
+ /** Forgets every resource and leaves them empty; nothing reloads. */
3896
+ clearAll() {
3897
+ for (const name of RESOURCE_NAMES) {
3898
+ this[name].clearAll();
3899
+ }
3900
+ }
3901
+ /** Loads every resource that is subscribed and has nothing yet. */
3902
+ resumeAll() {
3903
+ for (const name of RESOURCE_NAMES) {
3904
+ this[name].resumeAll();
3905
+ }
3906
+ }
3907
+ /** Reloads every resource that has been loaded, keeping its current data. */
3908
+ invalidateAll() {
3909
+ for (const name of RESOURCE_NAMES) {
3910
+ this[name].invalidateAll();
3911
+ }
3912
+ }
3913
+ /**
3914
+ * Appends the next page to the invoices list for `query`, when there is
3915
+ * one. A failure records the error on the resource and keeps the rows
3916
+ * already fetched; the returned promise never rejects.
3917
+ */
3918
+ loadMoreInvoices(query = DEFAULT_INVOICE_QUERY) {
3919
+ const resource = this.invoices.get(normalizeInvoiceQuery2(query));
3920
+ if (resource.snapshot.data?.hasMore !== true) {
3921
+ return Promise.resolve();
3922
+ }
3923
+ return resource.extend(async (current) => {
3924
+ const page = await this._fetchInvoices(
3925
+ normalizeInvoiceQuery2(query),
3926
+ current.invoices.length,
3927
+ this._pageSize
3928
+ );
3929
+ const invoices = [...current.invoices, ...page.invoices];
3930
+ return {
3931
+ invoices,
3932
+ count: page.count,
3933
+ // From the count the page came back with, not the one the list was
3934
+ // built on: an invoice finalized between the two requests changes
3935
+ // what is left to load. An empty page ends the list whatever the
3936
+ // count says — the rows and the count are two queries, and a count
3937
+ // that outruns the rows would otherwise leave `hasMore` true for
3938
+ // good, with every further page fetching nothing.
3939
+ hasMore: page.invoices.length > 0 && invoices.length < page.count
3940
+ };
3941
+ });
3942
+ }
3943
+ dispose() {
3944
+ this._unsubscribe?.();
3945
+ }
3946
+ /**
3947
+ * Re-reads the window already loaded, in as many requests as the API's
3948
+ * page cap needs. A window paged past that cap still comes back whole:
3949
+ * asking for it in one request would be a 400, and asking for only the
3950
+ * first page would drop the rest.
3951
+ */
3952
+ async _reloadWindow(query, window2) {
3953
+ const invoices = [];
3954
+ let count = 0;
3955
+ while (invoices.length < window2) {
3956
+ const page = await this._fetchInvoices(
3957
+ query,
3958
+ invoices.length,
3959
+ Math.min(INVOICE_MAX_PAGE_SIZE, window2 - invoices.length)
3960
+ );
3961
+ count = page.count;
3962
+ invoices.push(...page.invoices);
3963
+ if (page.invoices.length === 0 || invoices.length >= count) {
3964
+ break;
3965
+ }
3966
+ }
3967
+ return {
3968
+ invoices,
3969
+ count,
3970
+ hasMore: invoices.length > 0 && invoices.length < count
3971
+ };
3972
+ }
3973
+ /**
3974
+ * Returns what the server said and nothing more: whether there is more to
3975
+ * load depends on the whole window, which only the caller assembling it
3976
+ * knows — `_reloadWindow` across its requests, and `loadMoreInvoices`
3977
+ * across the rows already loaded.
3978
+ */
3979
+ _fetchInvoices(query, offset, limit) {
3980
+ return this._client.fetchInvoices({ ...query, limit, offset });
3981
+ }
3982
+ };
3983
+ var RESOURCE_NAMES = ["invoices"];
3984
+
3985
+ // src/billing/context.tsx
3986
+ import { createContext as createContext2, useContext as useContext2, useMemo as useMemo2 } from "react";
3987
+
3988
+ // src/i18n/context.tsx
3989
+ import { createContext, useContext, useMemo } from "react";
3990
+ import { jsx } from "react/jsx-runtime";
3991
+ var EMPTY = Object.freeze({});
3992
+ var SchematicI18nContext = createContext(EMPTY);
3993
+ function SchematicI18nProvider({
3994
+ children,
3995
+ locale,
3996
+ onMissingString,
3997
+ strings,
3998
+ translate
3999
+ }) {
4000
+ const parent = useContext(SchematicI18nContext);
4001
+ const value = useMemo(
4002
+ () => ({
4003
+ locale: locale ?? parent.locale,
4004
+ translate: translate ?? parent.translate,
4005
+ strings: strings === void 0 ? parent.strings : { ...parent.strings, ...strings },
4006
+ onMissingString: onMissingString ?? parent.onMissingString
4007
+ }),
4008
+ [locale, onMissingString, parent, strings, translate]
4009
+ );
4010
+ return /* @__PURE__ */ jsx(SchematicI18nContext.Provider, { value, children });
4011
+ }
4012
+ function useSchematicI18n() {
4013
+ return useContext(SchematicI18nContext);
4014
+ }
4015
+ function useSchematicLocale() {
4016
+ return useContext(SchematicI18nContext).locale;
4017
+ }
4018
+ function useSchematicTranslate() {
4019
+ return useContext(SchematicI18nContext).translate;
4020
+ }
4021
+ function useSchematicStrings() {
4022
+ return useContext(SchematicI18nContext).strings;
4023
+ }
4024
+
4025
+ // src/billing/context.tsx
4026
+ import { jsx as jsx2 } from "react/jsx-runtime";
4027
+ var BillingDataContext = createContext2(
4028
+ void 0
4029
+ );
4030
+ var MISSING_BILLING_SOURCE_MESSAGE = "Schematic billing hooks need a SchematicProvider with a session, billingClient, or initialData, or a BillingDataProvider.";
4031
+ var missingSourceError = new Error(MISSING_BILLING_SOURCE_MESSAGE);
4032
+ var missingHandle = {
4033
+ data: void 0,
4034
+ error: missingSourceError,
4035
+ isPending: false,
4036
+ refetch: () => {
4037
+ }
4038
+ };
4039
+ var missingBillingSource = {
4040
+ subscribe: () => () => {
4041
+ },
4042
+ handle: () => missingHandle,
4043
+ loadMoreInvoices: () => Promise.resolve(),
4044
+ invalidateAll: () => {
4045
+ }
4046
+ };
4047
+ function useBillingDataSource() {
4048
+ return useContext2(BillingDataContext) ?? missingBillingSource;
4049
+ }
4050
+ function BillingDataProvider({
4051
+ children,
4052
+ data,
4053
+ locale,
4054
+ onLoadMoreInvoices,
4055
+ onMissingString,
4056
+ onRefetch,
4057
+ status,
4058
+ strings,
4059
+ translate
4060
+ }) {
4061
+ const source = useMemo2(() => {
4062
+ const handles = /* @__PURE__ */ new Map();
4063
+ return {
4064
+ subscribe: () => () => {
4065
+ },
4066
+ handle: (name) => {
4067
+ const cached = handles.get(name);
4068
+ if (cached !== void 0) {
4069
+ return cached;
4070
+ }
4071
+ const value = data[name];
4072
+ const override = status?.[name];
4073
+ const handle = {
4074
+ data: value,
4075
+ error: override?.error,
4076
+ isPending: override?.isPending ?? value === void 0,
4077
+ refetch: () => onRefetch?.(name)
4078
+ };
4079
+ handles.set(name, handle);
4080
+ return handle;
4081
+ },
4082
+ loadMoreInvoices: (query) => {
4083
+ onLoadMoreInvoices?.(query);
4084
+ return Promise.resolve();
4085
+ },
4086
+ invalidateAll: () => {
4087
+ }
4088
+ };
4089
+ }, [data, onLoadMoreInvoices, onRefetch, status]);
4090
+ return /* @__PURE__ */ jsx2(BillingDataContext.Provider, { value: source, children: /* @__PURE__ */ jsx2(
4091
+ SchematicI18nProvider,
4092
+ {
4093
+ locale,
4094
+ strings,
4095
+ translate,
4096
+ onMissingString,
4097
+ children
4098
+ }
4099
+ ) });
4100
+ }
4101
+
4102
+ // src/billing/hooks.ts
4103
+ import { useCallback, useMemo as useMemo3, useRef, useSyncExternalStore } from "react";
4104
+ function useStableParams(params) {
4105
+ const key = hashKey(params);
4106
+ const ref = useRef({ key, params });
4107
+ if (ref.current.key !== key) {
4108
+ ref.current = { key, params };
4109
+ }
4110
+ return ref.current.params;
4111
+ }
4112
+ function useBillingResource(name, params) {
4113
+ const source = useBillingDataSource();
4114
+ const subscribe = useCallback(
4115
+ (listener) => source.subscribe(name, params, listener),
4116
+ [name, params, source]
4117
+ );
4118
+ const getSnapshot = useCallback(
4119
+ () => source.handle(name, params),
4120
+ [name, params, source]
4121
+ );
4122
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
4123
+ }
4124
+ function useInvoices(query = DEFAULT_INVOICE_QUERY) {
4125
+ const source = useBillingDataSource();
4126
+ const params = useStableParams(normalizeInvoiceQuery2(query));
4127
+ const handle = useBillingResource("invoices", params);
4128
+ const loadMore = useCallback(
4129
+ () => source.loadMoreInvoices(params),
4130
+ [params, source]
4131
+ );
4132
+ return useMemo3(() => ({ ...handle, loadMore }), [handle, loadMore]);
4133
+ }
4134
+ function useInvalidateBillingData() {
4135
+ return useBillingDataSource().invalidateAll;
4136
+ }
4137
+
4138
+ // src/billing/provider.tsx
4139
+ import { useEffect, useMemo as useMemo4, useRef as useRef2 } from "react";
4140
+ import { jsx as jsx3 } from "react/jsx-runtime";
4141
+ 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.";
4142
+ function BillingProvider({
4143
+ billingClient,
4144
+ children,
4145
+ initialData,
4146
+ locale,
4147
+ onMissingString,
4148
+ session,
4149
+ strings,
4150
+ translate
4151
+ }) {
4152
+ const initialRef = useRef2(initialData);
4153
+ const install = () => {
4154
+ billingClient?.setSession?.(session);
4155
+ };
4156
+ useEffect(() => {
4157
+ const claim = billingClient?.sessionKey;
4158
+ if (claim !== void 0 && session !== null && session !== void 0 && claim !== sessionKey(session)) {
4159
+ console.warn(SESSION_REPLACED_MESSAGE);
4160
+ }
4161
+ }, []);
4162
+ useEffect(install);
4163
+ const seedSpent = useRef2(false);
4164
+ const store = useMemo4(
4165
+ () => billingClient === void 0 ? void 0 : new BillingStore(
4166
+ billingClient,
4167
+ seedSpent.current ? void 0 : initialRef.current,
4168
+ {
4169
+ // What `install` is about to say, so a stamped prefetch is
4170
+ // judged now rather than after the effect.
4171
+ session
4172
+ }
4173
+ ),
4174
+ // `session` is read only when the store is built: the client learns
4175
+ // later sessions through `install`, and the store through the client.
4176
+ [billingClient]
4177
+ );
4178
+ useEffect(() => {
4179
+ if (store !== void 0) {
4180
+ seedSpent.current = true;
4181
+ }
4182
+ }, [store]);
4183
+ useEffect(() => store?.connect(), [store]);
4184
+ const source = useMemo4(() => {
4185
+ if (store === void 0) {
4186
+ return initialRef.current === void 0 ? void 0 : staticSource(initialRef.current);
4187
+ }
4188
+ const handles = /* @__PURE__ */ new WeakMap();
4189
+ const handle = (name, params) => {
4190
+ const resource = store.resource(name).get(params);
4191
+ const snapshot = resource.getSnapshot();
4192
+ const cached = handles.get(resource);
4193
+ if (cached !== void 0 && cached.snapshot === snapshot) {
4194
+ return cached.handle;
4195
+ }
4196
+ const next = {
4197
+ ...snapshot,
4198
+ refetch: () => void resource.refetch()
4199
+ };
4200
+ handles.set(resource, { snapshot, handle: next });
4201
+ return next;
4202
+ };
4203
+ return {
4204
+ subscribe: (name, params, listener) => store.resource(name).subscribe(params, listener),
4205
+ handle,
4206
+ loadMoreInvoices: (query) => store.loadMoreInvoices(query),
4207
+ invalidateAll: () => store.invalidateAll()
4208
+ };
4209
+ }, [store]);
4210
+ const localized = /* @__PURE__ */ jsx3(
4211
+ SchematicI18nProvider,
4212
+ {
4213
+ locale,
4214
+ strings,
4215
+ translate,
4216
+ onMissingString,
4217
+ children
4218
+ }
4219
+ );
4220
+ if (source === void 0) {
4221
+ return localized;
4222
+ }
4223
+ return /* @__PURE__ */ jsx3(BillingDataContext.Provider, { value: source, children: localized });
4224
+ }
4225
+ function staticSource(data) {
4226
+ const handles = /* @__PURE__ */ new Map();
4227
+ return {
4228
+ subscribe: () => () => {
4229
+ },
4230
+ handle: (name) => {
4231
+ const cached = handles.get(name);
4232
+ if (cached !== void 0) {
4233
+ return cached;
4234
+ }
4235
+ const value = data[name];
4236
+ const next = {
4237
+ data: value,
4238
+ error: void 0,
4239
+ isPending: value === void 0,
4240
+ refetch: () => {
4241
+ }
4242
+ };
4243
+ handles.set(name, next);
4244
+ return next;
4245
+ },
4246
+ loadMoreInvoices: () => Promise.resolve(),
4247
+ invalidateAll: () => {
4248
+ }
4249
+ };
4250
+ }
2875
4251
 
2876
4252
  // src/version.ts
2877
- var version2 = "1.5.0";
4253
+ var version2 = "1.6.0";
2878
4254
 
2879
4255
  // src/context/schematic.tsx
2880
- import { jsx } from "react/jsx-runtime";
2881
- var SchematicContext = createContext(
4256
+ import { jsx as jsx4 } from "react/jsx-runtime";
4257
+ var SchematicContext = createContext3(
2882
4258
  null
2883
4259
  );
2884
4260
  var SchematicProvider = ({
4261
+ session,
4262
+ billingClient,
2885
4263
  children,
2886
4264
  client: providedClient,
4265
+ initialData,
4266
+ locale,
4267
+ onMissingString,
2887
4268
  publishableKey,
4269
+ strings,
4270
+ translate,
2888
4271
  ...clientOpts
2889
4272
  }) => {
2890
- const initialOptsRef = useRef({
4273
+ const initialOptsRef = useRef3({
2891
4274
  publishableKey,
2892
4275
  useWebSocket: true,
2893
4276
  additionalHeaders: {
@@ -2895,7 +4278,7 @@ var SchematicProvider = ({
2895
4278
  },
2896
4279
  ...clientOpts
2897
4280
  });
2898
- const client = useMemo(() => {
4281
+ const client = useMemo5(() => {
2899
4282
  if (providedClient) {
2900
4283
  return providedClient;
2901
4284
  }
@@ -2903,7 +4286,7 @@ var SchematicProvider = ({
2903
4286
  ...initialOptsRef.current
2904
4287
  });
2905
4288
  }, [providedClient]);
2906
- useEffect(() => {
4289
+ useEffect2(() => {
2907
4290
  return () => {
2908
4291
  if (!providedClient) {
2909
4292
  client.cleanup().catch((error) => {
@@ -2912,16 +4295,46 @@ var SchematicProvider = ({
2912
4295
  }
2913
4296
  };
2914
4297
  }, [client, providedClient]);
2915
- const contextValue = useMemo(
4298
+ const contextValue = useMemo5(
2916
4299
  () => ({
2917
4300
  client
2918
4301
  }),
2919
4302
  [client]
2920
4303
  );
2921
- return /* @__PURE__ */ jsx(SchematicContext.Provider, { value: contextValue, children });
4304
+ const { apiUrl, additionalHeaders } = initialOptsRef.current;
4305
+ const providedApiUrl = providedClient?.apiUrl;
4306
+ const resolvedBillingClient = useMemo5(
4307
+ () => billingClient ?? new SchematicBillingClient({
4308
+ session,
4309
+ apiUrl: apiUrl ?? providedApiUrl,
4310
+ // Read as they stand when a client is built: headers do not change
4311
+ // where the token goes, so they are no reason to build one.
4312
+ additionalHeaders: {
4313
+ ...providedClient?.additionalHeaders,
4314
+ ...additionalHeaders
4315
+ }
4316
+ }),
4317
+ // `session` is deliberately absent: `BillingProvider` forwards it through
4318
+ // `setSession`, so a token change resets the billing resources without
4319
+ // rebuilding the client.
4320
+ [additionalHeaders, apiUrl, billingClient, providedApiUrl]
4321
+ );
4322
+ return /* @__PURE__ */ jsx4(SchematicContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx4(
4323
+ BillingProvider,
4324
+ {
4325
+ billingClient: resolvedBillingClient,
4326
+ initialData,
4327
+ locale,
4328
+ session,
4329
+ strings,
4330
+ translate,
4331
+ onMissingString,
4332
+ children
4333
+ }
4334
+ ) });
2922
4335
  };
2923
4336
  var useSchematic = () => {
2924
- const context = React.useContext(SchematicContext);
4337
+ const context = React4.useContext(SchematicContext);
2925
4338
  if (context === null) {
2926
4339
  throw new Error("useSchematic must be used within a SchematicProvider");
2927
4340
  }
@@ -2929,11 +4342,11 @@ var useSchematic = () => {
2929
4342
  };
2930
4343
 
2931
4344
  // src/hooks/schematic.ts
2932
- import { useMemo as useMemo2, useSyncExternalStore, useCallback } from "react";
4345
+ import { useMemo as useMemo6, useSyncExternalStore as useSyncExternalStore2, useCallback as useCallback2 } from "react";
2933
4346
  var useSchematicClient = (opts) => {
2934
4347
  const schematic = useSchematic();
2935
4348
  const { client } = opts ?? {};
2936
- return useMemo2(() => {
4349
+ return useMemo6(() => {
2937
4350
  if (client) {
2938
4351
  return client;
2939
4352
  }
@@ -2942,7 +4355,7 @@ var useSchematicClient = (opts) => {
2942
4355
  };
2943
4356
  var useSchematicContext = (opts) => {
2944
4357
  const client = useSchematicClient(opts);
2945
- return useMemo2(
4358
+ return useMemo6(
2946
4359
  () => ({
2947
4360
  setContext: client.setContext.bind(client)
2948
4361
  }),
@@ -2951,33 +4364,33 @@ var useSchematicContext = (opts) => {
2951
4364
  };
2952
4365
  var useSchematicEvents = (opts) => {
2953
4366
  const client = useSchematicClient(opts);
2954
- const track = useCallback(
4367
+ const track = useCallback2(
2955
4368
  (...args) => client.track(...args),
2956
4369
  [client]
2957
4370
  );
2958
- const identify = useCallback(
4371
+ const identify = useCallback2(
2959
4372
  (...args) => client.identify(...args),
2960
4373
  [client]
2961
4374
  );
2962
- return useMemo2(() => ({ track, identify }), [track, identify]);
4375
+ return useMemo6(() => ({ track, identify }), [track, identify]);
2963
4376
  };
2964
4377
  var useSchematicFlag = (key, opts) => {
2965
4378
  const client = useSchematicClient(opts);
2966
4379
  const fallback = opts?.fallback ?? false;
2967
- const subscribe = useCallback(
4380
+ const subscribe = useCallback2(
2968
4381
  (callback) => client.addFlagValueListener(key, callback),
2969
4382
  [client, key]
2970
4383
  );
2971
- const getSnapshot = useCallback(() => {
4384
+ const getSnapshot = useCallback2(() => {
2972
4385
  const value = client.getFlagValue(key);
2973
4386
  return typeof value === "undefined" ? fallback : value;
2974
4387
  }, [client, key, fallback]);
2975
- return useSyncExternalStore(subscribe, getSnapshot, () => fallback);
4388
+ return useSyncExternalStore2(subscribe, getSnapshot, () => fallback);
2976
4389
  };
2977
4390
  var useSchematicEntitlement = (key, opts) => {
2978
4391
  const client = useSchematicClient(opts);
2979
4392
  const fallback = opts?.fallback ?? false;
2980
- const fallbackCheck = useMemo2(
4393
+ const fallbackCheck = useMemo6(
2981
4394
  () => ({
2982
4395
  flag: key,
2983
4396
  reason: "Fallback",
@@ -2985,20 +4398,20 @@ var useSchematicEntitlement = (key, opts) => {
2985
4398
  }),
2986
4399
  [key, fallback]
2987
4400
  );
2988
- const subscribe = useCallback(
4401
+ const subscribe = useCallback2(
2989
4402
  (callback) => client.addFlagCheckListener(key, callback),
2990
4403
  [client, key]
2991
4404
  );
2992
- const getSnapshot = useCallback(() => {
4405
+ const getSnapshot = useCallback2(() => {
2993
4406
  const check = client.getFlagCheck(key);
2994
4407
  return check ?? fallbackCheck;
2995
4408
  }, [client, key, fallbackCheck]);
2996
- return useSyncExternalStore(subscribe, getSnapshot, () => fallbackCheck);
4409
+ return useSyncExternalStore2(subscribe, getSnapshot, () => fallbackCheck);
2997
4410
  };
2998
4411
  var useSchematicPlan = (opts) => {
2999
4412
  const client = useSchematicClient(opts);
3000
4413
  const fallback = opts?.fallback;
3001
- const fallbackPlan = useMemo2(
4414
+ const fallbackPlan = useMemo6(
3002
4415
  () => fallback,
3003
4416
  [
3004
4417
  fallback?.id,
@@ -3007,37 +4420,37 @@ var useSchematicPlan = (opts) => {
3007
4420
  fallback?.trialStatus
3008
4421
  ]
3009
4422
  );
3010
- const subscribe = useCallback(
4423
+ const subscribe = useCallback2(
3011
4424
  (callback) => client.addPlanListener(callback),
3012
4425
  [client]
3013
4426
  );
3014
- const getSnapshot = useCallback(() => {
4427
+ const getSnapshot = useCallback2(() => {
3015
4428
  const plan = client.getPlan();
3016
4429
  return plan ?? fallbackPlan;
3017
4430
  }, [client, fallbackPlan]);
3018
- return useSyncExternalStore(subscribe, getSnapshot, () => fallbackPlan);
4431
+ return useSyncExternalStore2(subscribe, getSnapshot, () => fallbackPlan);
3019
4432
  };
3020
4433
  var useSchematicCreditBalance = (creditId, opts) => {
3021
4434
  const client = useSchematicClient(opts);
3022
- const subscribe = useCallback(
4435
+ const subscribe = useCallback2(
3023
4436
  (callback) => client.addCreditBalanceListener(callback),
3024
4437
  [client]
3025
4438
  );
3026
- const getSnapshot = useCallback(
3027
- () => client.getCreditBalance(creditId),
4439
+ const getSnapshot = useCallback2(
4440
+ () => creditId === void 0 ? void 0 : client.getCreditBalance(creditId),
3028
4441
  [client, creditId]
3029
4442
  );
3030
- const balance = useSyncExternalStore(subscribe, getSnapshot, () => void 0);
3031
- const isPendingSubscribe = useCallback(
4443
+ const balance = useSyncExternalStore2(subscribe, getSnapshot, () => void 0);
4444
+ const isPendingSubscribe = useCallback2(
3032
4445
  (callback) => client.addIsPendingListener(callback),
3033
4446
  [client]
3034
4447
  );
3035
- const isPending = useSyncExternalStore(
4448
+ const isPending = useSyncExternalStore2(
3036
4449
  isPendingSubscribe,
3037
4450
  () => client.getIsPending(),
3038
4451
  () => true
3039
4452
  );
3040
- return useMemo2(
4453
+ return useMemo6(
3041
4454
  () => ({
3042
4455
  balance: balance?.settled ?? 0,
3043
4456
  isLoading: balance === void 0 && isPending
@@ -3047,27 +4460,42 @@ var useSchematicCreditBalance = (creditId, opts) => {
3047
4460
  };
3048
4461
  var useSchematicIsPending = (opts) => {
3049
4462
  const client = useSchematicClient(opts);
3050
- const subscribe = useCallback(
4463
+ const subscribe = useCallback2(
3051
4464
  (callback) => client.addIsPendingListener(callback),
3052
4465
  [client]
3053
4466
  );
3054
- const getSnapshot = useCallback(() => client.getIsPending(), [client]);
3055
- return useSyncExternalStore(subscribe, getSnapshot, () => true);
4467
+ const getSnapshot = useCallback2(() => client.getIsPending(), [client]);
4468
+ return useSyncExternalStore2(subscribe, getSnapshot, () => true);
3056
4469
  };
3057
4470
  export {
4471
+ BillingDataProvider,
4472
+ BillingProvider,
4473
+ DEFAULT_INVOICE_QUERY,
4474
+ INVOICE_PAGE_SIZE,
4475
+ InvoiceStatus,
3058
4476
  RuleType,
3059
4477
  Schematic,
4478
+ SchematicI18nContext,
4479
+ SchematicI18nProvider,
3060
4480
  SchematicProvider,
3061
4481
  TrialStatus,
3062
4482
  UsagePeriod,
4483
+ normalizeInvoiceQuery2 as normalizeInvoiceQuery,
4484
+ useBillingDataSource,
4485
+ useInvalidateBillingData,
4486
+ useInvoices,
3063
4487
  useSchematic,
3064
4488
  useSchematicContext,
3065
4489
  useSchematicCreditBalance,
3066
4490
  useSchematicEntitlement,
3067
4491
  useSchematicEvents,
3068
4492
  useSchematicFlag,
4493
+ useSchematicI18n,
3069
4494
  useSchematicIsPending,
3070
- useSchematicPlan
4495
+ useSchematicLocale,
4496
+ useSchematicPlan,
4497
+ useSchematicStrings,
4498
+ useSchematicTranslate
3071
4499
  };
3072
4500
  /*! Bundled license information:
3073
4501