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