@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
|
@@ -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.
|
|
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
|
-
|
|
1684
|
+
_additionalHeaders = {};
|
|
1138
1685
|
apiKey;
|
|
1139
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
1938
|
+
const requestUrl = `${this._apiUrl}/flags/${key}/check`;
|
|
1386
1939
|
return fetch(requestUrl, {
|
|
1387
1940
|
method: "POST",
|
|
1388
1941
|
headers: {
|
|
1389
|
-
...this.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
4253
|
+
var version2 = "1.6.0";
|
|
2878
4254
|
|
|
2879
4255
|
// src/context/schematic.tsx
|
|
2880
|
-
import { jsx } from "react/jsx-runtime";
|
|
2881
|
-
var SchematicContext =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
4298
|
+
const contextValue = useMemo5(
|
|
2916
4299
|
() => ({
|
|
2917
4300
|
client
|
|
2918
4301
|
}),
|
|
2919
4302
|
[client]
|
|
2920
4303
|
);
|
|
2921
|
-
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
4367
|
+
const track = useCallback2(
|
|
2955
4368
|
(...args) => client.track(...args),
|
|
2956
4369
|
[client]
|
|
2957
4370
|
);
|
|
2958
|
-
const identify =
|
|
4371
|
+
const identify = useCallback2(
|
|
2959
4372
|
(...args) => client.identify(...args),
|
|
2960
4373
|
[client]
|
|
2961
4374
|
);
|
|
2962
|
-
return
|
|
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 =
|
|
4380
|
+
const subscribe = useCallback2(
|
|
2968
4381
|
(callback) => client.addFlagValueListener(key, callback),
|
|
2969
4382
|
[client, key]
|
|
2970
4383
|
);
|
|
2971
|
-
const getSnapshot =
|
|
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
|
|
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 =
|
|
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 =
|
|
4401
|
+
const subscribe = useCallback2(
|
|
2989
4402
|
(callback) => client.addFlagCheckListener(key, callback),
|
|
2990
4403
|
[client, key]
|
|
2991
4404
|
);
|
|
2992
|
-
const getSnapshot =
|
|
4405
|
+
const getSnapshot = useCallback2(() => {
|
|
2993
4406
|
const check = client.getFlagCheck(key);
|
|
2994
4407
|
return check ?? fallbackCheck;
|
|
2995
4408
|
}, [client, key, fallbackCheck]);
|
|
2996
|
-
return
|
|
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 =
|
|
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 =
|
|
4423
|
+
const subscribe = useCallback2(
|
|
3011
4424
|
(callback) => client.addPlanListener(callback),
|
|
3012
4425
|
[client]
|
|
3013
4426
|
);
|
|
3014
|
-
const getSnapshot =
|
|
4427
|
+
const getSnapshot = useCallback2(() => {
|
|
3015
4428
|
const plan = client.getPlan();
|
|
3016
4429
|
return plan ?? fallbackPlan;
|
|
3017
4430
|
}, [client, fallbackPlan]);
|
|
3018
|
-
return
|
|
4431
|
+
return useSyncExternalStore2(subscribe, getSnapshot, () => fallbackPlan);
|
|
3019
4432
|
};
|
|
3020
4433
|
var useSchematicCreditBalance = (creditId, opts) => {
|
|
3021
4434
|
const client = useSchematicClient(opts);
|
|
3022
|
-
const subscribe =
|
|
4435
|
+
const subscribe = useCallback2(
|
|
3023
4436
|
(callback) => client.addCreditBalanceListener(callback),
|
|
3024
4437
|
[client]
|
|
3025
4438
|
);
|
|
3026
|
-
const getSnapshot =
|
|
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 =
|
|
3031
|
-
const isPendingSubscribe =
|
|
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 =
|
|
4448
|
+
const isPending = useSyncExternalStore2(
|
|
3036
4449
|
isPendingSubscribe,
|
|
3037
4450
|
() => client.getIsPending(),
|
|
3038
4451
|
() => true
|
|
3039
4452
|
);
|
|
3040
|
-
return
|
|
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 =
|
|
4463
|
+
const subscribe = useCallback2(
|
|
3051
4464
|
(callback) => client.addIsPendingListener(callback),
|
|
3052
4465
|
[client]
|
|
3053
4466
|
);
|
|
3054
|
-
const getSnapshot =
|
|
3055
|
-
return
|
|
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
|
-
|
|
4495
|
+
useSchematicLocale,
|
|
4496
|
+
useSchematicPlan,
|
|
4497
|
+
useSchematicStrings,
|
|
4498
|
+
useSchematicTranslate
|
|
3071
4499
|
};
|
|
3072
4500
|
/*! Bundled license information:
|
|
3073
4501
|
|