@schematichq/schematic-js 1.4.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 +18 -1
- package/dist/schematic.browser.js +2 -2
- package/dist/schematic.cjs.js +1267 -36
- package/dist/schematic.d.ts +760 -21
- package/dist/schematic.esm.js +1271 -36
- package/package.json +26 -28
package/dist/schematic.cjs.js
CHANGED
|
@@ -6,7 +6,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
8
|
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
-
|
|
9
|
+
try {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
throw mod = 0, e;
|
|
13
|
+
}
|
|
10
14
|
};
|
|
11
15
|
var __export = (target, all) => {
|
|
12
16
|
for (var name in all)
|
|
@@ -30,9 +34,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
34
|
));
|
|
31
35
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
36
|
|
|
33
|
-
// node_modules/cross-fetch/dist/browser-polyfill.js
|
|
37
|
+
// node_modules/.pnpm/cross-fetch@4.1.0/node_modules/cross-fetch/dist/browser-polyfill.js
|
|
34
38
|
var require_browser_polyfill = __commonJS({
|
|
35
|
-
"node_modules/cross-fetch/dist/browser-polyfill.js"(exports) {
|
|
39
|
+
"node_modules/.pnpm/cross-fetch@4.1.0/node_modules/cross-fetch/dist/browser-polyfill.js"(exports) {
|
|
36
40
|
(function(self2) {
|
|
37
41
|
var irrelevant = (function(exports2) {
|
|
38
42
|
var g = typeof globalThis !== "undefined" && globalThis || typeof self2 !== "undefined" && self2 || // eslint-disable-next-line no-undef
|
|
@@ -573,16 +577,29 @@ __export(index_exports, {
|
|
|
573
577
|
CheckFlagReturnFromJSON: () => CheckFlagReturnFromJSON,
|
|
574
578
|
CheckFlagsResponseFromJSON: () => CheckFlagsResponseFromJSON,
|
|
575
579
|
CheckPlanReturnFromJSON: () => CheckPlanReturnFromJSON,
|
|
580
|
+
CreditBalancesFromJSON: () => CreditBalancesFromJSON,
|
|
581
|
+
DEFAULT_INVOICE_QUERY: () => DEFAULT_INVOICE_QUERY,
|
|
576
582
|
DatastreamCompanyPlanFromJSON: () => DatastreamCompanyPlanFromJSON,
|
|
577
583
|
EventBodyFlagCheckToJSON: () => EventBodyFlagCheckToJSON,
|
|
584
|
+
INVOICE_MAX_PAGE_SIZE: () => INVOICE_MAX_PAGE_SIZE,
|
|
585
|
+
INVOICE_PAGE_SIZE: () => INVOICE_PAGE_SIZE,
|
|
586
|
+
InvoiceStatus: () => InvoiceStatus,
|
|
578
587
|
RuleType: () => RuleType,
|
|
579
588
|
Schematic: () => Schematic,
|
|
589
|
+
SchematicApiError: () => SchematicApiError,
|
|
590
|
+
SchematicBillingClient: () => SchematicBillingClient,
|
|
591
|
+
SchematicSession: () => SchematicSession,
|
|
592
|
+
TOKEN_CACHE_SIZE: () => TOKEN_CACHE_SIZE,
|
|
580
593
|
TrialStatus: () => TrialStatus,
|
|
581
|
-
UsagePeriod: () => UsagePeriod
|
|
594
|
+
UsagePeriod: () => UsagePeriod,
|
|
595
|
+
billingApi: () => models_exports,
|
|
596
|
+
fetchBillingData: () => fetchBillingData,
|
|
597
|
+
normalizeInvoiceQuery: () => normalizeInvoiceQuery,
|
|
598
|
+
sessionKey: () => sessionKey
|
|
582
599
|
});
|
|
583
600
|
module.exports = __toCommonJS(index_exports);
|
|
584
601
|
|
|
585
|
-
// node_modules/uuid/dist/stringify.js
|
|
602
|
+
// node_modules/.pnpm/uuid@14.0.2/node_modules/uuid/dist/stringify.js
|
|
586
603
|
var byteToHex = [];
|
|
587
604
|
for (let i = 0; i < 256; ++i) {
|
|
588
605
|
byteToHex.push((i + 256).toString(16).slice(1));
|
|
@@ -591,24 +608,19 @@ function unsafeStringify(arr, offset = 0) {
|
|
|
591
608
|
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
592
609
|
}
|
|
593
610
|
|
|
594
|
-
// node_modules/uuid/dist/rng.js
|
|
595
|
-
var getRandomValues;
|
|
611
|
+
// node_modules/.pnpm/uuid@14.0.2/node_modules/uuid/dist/rng.js
|
|
596
612
|
var rnds8 = new Uint8Array(16);
|
|
597
613
|
function rng() {
|
|
598
|
-
|
|
599
|
-
if (typeof crypto === "undefined" || !crypto.getRandomValues) {
|
|
600
|
-
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
|
601
|
-
}
|
|
602
|
-
getRandomValues = crypto.getRandomValues.bind(crypto);
|
|
603
|
-
}
|
|
604
|
-
return getRandomValues(rnds8);
|
|
614
|
+
return crypto.getRandomValues(rnds8);
|
|
605
615
|
}
|
|
606
616
|
|
|
607
|
-
// node_modules/uuid/dist/
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
617
|
+
// node_modules/.pnpm/uuid@14.0.2/node_modules/uuid/dist/v4.js
|
|
618
|
+
function v4(options, buf, offset) {
|
|
619
|
+
if (!buf && !options && crypto.randomUUID) {
|
|
620
|
+
return crypto.randomUUID();
|
|
621
|
+
}
|
|
622
|
+
return _v4(options, buf, offset);
|
|
623
|
+
}
|
|
612
624
|
function _v4(options, buf, offset) {
|
|
613
625
|
options = options || {};
|
|
614
626
|
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
@@ -629,12 +641,6 @@ function _v4(options, buf, offset) {
|
|
|
629
641
|
}
|
|
630
642
|
return unsafeStringify(rnds);
|
|
631
643
|
}
|
|
632
|
-
function v4(options, buf, offset) {
|
|
633
|
-
if (native_default.randomUUID && !buf && !options) {
|
|
634
|
-
return native_default.randomUUID();
|
|
635
|
-
}
|
|
636
|
-
return _v4(options, buf, offset);
|
|
637
|
-
}
|
|
638
644
|
var v4_default = v4;
|
|
639
645
|
|
|
640
646
|
// src/index.ts
|
|
@@ -648,6 +654,36 @@ function EntitlementValueTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
648
654
|
return json;
|
|
649
655
|
}
|
|
650
656
|
|
|
657
|
+
// src/types/api/models/MetricPeriodMonthReset.ts
|
|
658
|
+
function MetricPeriodMonthResetFromJSON(json) {
|
|
659
|
+
return MetricPeriodMonthResetFromJSONTyped(json, false);
|
|
660
|
+
}
|
|
661
|
+
function MetricPeriodMonthResetFromJSONTyped(json, ignoreDiscriminator) {
|
|
662
|
+
return json;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// src/types/api/models/WarningTier.ts
|
|
666
|
+
function WarningTierFromJSON(json) {
|
|
667
|
+
return WarningTierFromJSONTyped(json, false);
|
|
668
|
+
}
|
|
669
|
+
function WarningTierFromJSONTyped(json, ignoreDiscriminator) {
|
|
670
|
+
if (json == null) {
|
|
671
|
+
return json;
|
|
672
|
+
}
|
|
673
|
+
return {
|
|
674
|
+
key: json["key"],
|
|
675
|
+
value: json["value"]
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// src/types/api/models/MetricPeriod.ts
|
|
680
|
+
function MetricPeriodFromJSON(json) {
|
|
681
|
+
return MetricPeriodFromJSONTyped(json, false);
|
|
682
|
+
}
|
|
683
|
+
function MetricPeriodFromJSONTyped(json, ignoreDiscriminator) {
|
|
684
|
+
return json;
|
|
685
|
+
}
|
|
686
|
+
|
|
651
687
|
// src/types/api/models/FeatureEntitlement.ts
|
|
652
688
|
function FeatureEntitlementFromJSON(json) {
|
|
653
689
|
return FeatureEntitlementFromJSONTyped(json, false);
|
|
@@ -658,22 +694,35 @@ function FeatureEntitlementFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
658
694
|
}
|
|
659
695
|
return {
|
|
660
696
|
allocation: json["allocation"] == null ? void 0 : json["allocation"],
|
|
697
|
+
consumptionRate: json["consumption_rate"] == null ? void 0 : json["consumption_rate"],
|
|
661
698
|
creditId: json["credit_id"] == null ? void 0 : json["credit_id"],
|
|
662
699
|
creditRemaining: json["credit_remaining"] == null ? void 0 : json["credit_remaining"],
|
|
700
|
+
creditReserved: json["credit_reserved"] == null ? void 0 : json["credit_reserved"],
|
|
701
|
+
creditSettled: json["credit_settled"] == null ? void 0 : json["credit_settled"],
|
|
663
702
|
creditTotal: json["credit_total"] == null ? void 0 : json["credit_total"],
|
|
664
703
|
creditUsed: json["credit_used"] == null ? void 0 : json["credit_used"],
|
|
665
704
|
eventName: json["event_name"] == null ? void 0 : json["event_name"],
|
|
705
|
+
eventSubtype: json["event_subtype"] == null ? void 0 : json["event_subtype"],
|
|
666
706
|
featureId: json["feature_id"],
|
|
667
707
|
featureKey: json["feature_key"],
|
|
668
|
-
metricPeriod: json["metric_period"] == null ? void 0 : json["metric_period"],
|
|
708
|
+
metricPeriod: json["metric_period"] == null ? void 0 : MetricPeriodFromJSON(json["metric_period"]),
|
|
669
709
|
metricResetAt: json["metric_reset_at"] == null ? void 0 : new Date(json["metric_reset_at"]),
|
|
670
|
-
monthReset: json["month_reset"] == null ? void 0 : json["month_reset"],
|
|
710
|
+
monthReset: json["month_reset"] == null ? void 0 : MetricPeriodMonthResetFromJSON(json["month_reset"]),
|
|
671
711
|
softLimit: json["soft_limit"] == null ? void 0 : json["soft_limit"],
|
|
672
712
|
usage: json["usage"] == null ? void 0 : json["usage"],
|
|
673
|
-
valueType: EntitlementValueTypeFromJSON(json["value_type"])
|
|
713
|
+
valueType: EntitlementValueTypeFromJSON(json["value_type"]),
|
|
714
|
+
warningTiers: json["warning_tiers"] == null ? void 0 : json["warning_tiers"].map(WarningTierFromJSON)
|
|
674
715
|
};
|
|
675
716
|
}
|
|
676
717
|
|
|
718
|
+
// src/types/api/models/RuleType.ts
|
|
719
|
+
function RuleTypeFromJSON(json) {
|
|
720
|
+
return RuleTypeFromJSONTyped(json, false);
|
|
721
|
+
}
|
|
722
|
+
function RuleTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
723
|
+
return json;
|
|
724
|
+
}
|
|
725
|
+
|
|
677
726
|
// src/types/api/models/CheckFlagResponseData.ts
|
|
678
727
|
function CheckFlagResponseDataFromJSON(json) {
|
|
679
728
|
return CheckFlagResponseDataFromJSONTyped(json, false);
|
|
@@ -689,13 +738,13 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
689
738
|
featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
|
|
690
739
|
featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
|
|
691
740
|
featureUsageEvent: json["feature_usage_event"] == null ? void 0 : json["feature_usage_event"],
|
|
692
|
-
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
|
|
741
|
+
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : MetricPeriodFromJSON(json["feature_usage_period"]),
|
|
693
742
|
featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
|
|
694
743
|
flag: json["flag"],
|
|
695
744
|
flagId: json["flag_id"] == null ? void 0 : json["flag_id"],
|
|
696
745
|
reason: json["reason"],
|
|
697
746
|
ruleId: json["rule_id"] == null ? void 0 : json["rule_id"],
|
|
698
|
-
ruleType: json["rule_type"] == null ? void 0 : json["rule_type"],
|
|
747
|
+
ruleType: json["rule_type"] == null ? void 0 : RuleTypeFromJSON(json["rule_type"]),
|
|
699
748
|
userId: json["user_id"] == null ? void 0 : json["user_id"],
|
|
700
749
|
value: json["value"]
|
|
701
750
|
};
|
|
@@ -715,6 +764,272 @@ function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
715
764
|
};
|
|
716
765
|
}
|
|
717
766
|
|
|
767
|
+
// src/types/api/runtime.ts
|
|
768
|
+
var BASE_PATH = "https://api.schematichq.com".replace(/\/+$/, "");
|
|
769
|
+
var Configuration = class {
|
|
770
|
+
constructor(configuration = {}) {
|
|
771
|
+
this.configuration = configuration;
|
|
772
|
+
}
|
|
773
|
+
configuration;
|
|
774
|
+
set config(configuration) {
|
|
775
|
+
this.configuration = configuration;
|
|
776
|
+
}
|
|
777
|
+
get basePath() {
|
|
778
|
+
return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH;
|
|
779
|
+
}
|
|
780
|
+
get fetchApi() {
|
|
781
|
+
return this.configuration.fetchApi;
|
|
782
|
+
}
|
|
783
|
+
get middleware() {
|
|
784
|
+
return this.configuration.middleware || [];
|
|
785
|
+
}
|
|
786
|
+
get queryParamsStringify() {
|
|
787
|
+
return this.configuration.queryParamsStringify || querystring;
|
|
788
|
+
}
|
|
789
|
+
get username() {
|
|
790
|
+
return this.configuration.username;
|
|
791
|
+
}
|
|
792
|
+
get password() {
|
|
793
|
+
return this.configuration.password;
|
|
794
|
+
}
|
|
795
|
+
get apiKey() {
|
|
796
|
+
const apiKey = this.configuration.apiKey;
|
|
797
|
+
if (apiKey) {
|
|
798
|
+
return typeof apiKey === "function" ? apiKey : () => apiKey;
|
|
799
|
+
}
|
|
800
|
+
return void 0;
|
|
801
|
+
}
|
|
802
|
+
get accessToken() {
|
|
803
|
+
const accessToken = this.configuration.accessToken;
|
|
804
|
+
if (accessToken) {
|
|
805
|
+
return typeof accessToken === "function" ? accessToken : async () => accessToken;
|
|
806
|
+
}
|
|
807
|
+
return void 0;
|
|
808
|
+
}
|
|
809
|
+
get headers() {
|
|
810
|
+
return this.configuration.headers;
|
|
811
|
+
}
|
|
812
|
+
get credentials() {
|
|
813
|
+
return this.configuration.credentials;
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
var DefaultConfig = new Configuration();
|
|
817
|
+
var BaseAPI = class _BaseAPI {
|
|
818
|
+
constructor(configuration = DefaultConfig) {
|
|
819
|
+
this.configuration = configuration;
|
|
820
|
+
this.middleware = configuration.middleware;
|
|
821
|
+
}
|
|
822
|
+
configuration;
|
|
823
|
+
static jsonRegex = new RegExp(
|
|
824
|
+
"^(:?application/json|[^;/ ]+/[^;/ ]+[+]json)[ ]*(:?;.*)?$",
|
|
825
|
+
"i"
|
|
826
|
+
);
|
|
827
|
+
middleware;
|
|
828
|
+
withMiddleware(...middlewares) {
|
|
829
|
+
const next = this.clone();
|
|
830
|
+
next.middleware = next.middleware.concat(...middlewares);
|
|
831
|
+
return next;
|
|
832
|
+
}
|
|
833
|
+
withPreMiddleware(...preMiddlewares) {
|
|
834
|
+
const middlewares = preMiddlewares.map((pre) => ({ pre }));
|
|
835
|
+
return this.withMiddleware(...middlewares);
|
|
836
|
+
}
|
|
837
|
+
withPostMiddleware(...postMiddlewares) {
|
|
838
|
+
const middlewares = postMiddlewares.map((post) => ({ post }));
|
|
839
|
+
return this.withMiddleware(...middlewares);
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Check if the given MIME is a JSON MIME.
|
|
843
|
+
* JSON MIME examples:
|
|
844
|
+
* application/json
|
|
845
|
+
* application/json; charset=UTF8
|
|
846
|
+
* APPLICATION/JSON
|
|
847
|
+
* application/vnd.company+json
|
|
848
|
+
* @param mime - MIME (Multipurpose Internet Mail Extensions)
|
|
849
|
+
* @return True if the given MIME is JSON, false otherwise.
|
|
850
|
+
*/
|
|
851
|
+
isJsonMime(mime) {
|
|
852
|
+
if (!mime) {
|
|
853
|
+
return false;
|
|
854
|
+
}
|
|
855
|
+
return _BaseAPI.jsonRegex.test(mime);
|
|
856
|
+
}
|
|
857
|
+
async request(context, initOverrides) {
|
|
858
|
+
const { url, init } = await this.createFetchParams(context, initOverrides);
|
|
859
|
+
const response = await this.fetchApi(url, init);
|
|
860
|
+
if (response && response.status >= 200 && response.status < 300) {
|
|
861
|
+
return response;
|
|
862
|
+
}
|
|
863
|
+
throw new ResponseError(response, "Response returned an error code");
|
|
864
|
+
}
|
|
865
|
+
async createFetchParams(context, initOverrides) {
|
|
866
|
+
let url = this.configuration.basePath + context.path;
|
|
867
|
+
if (context.query !== void 0 && Object.keys(context.query).length !== 0) {
|
|
868
|
+
url += "?" + this.configuration.queryParamsStringify(context.query);
|
|
869
|
+
}
|
|
870
|
+
const headers = Object.assign(
|
|
871
|
+
{},
|
|
872
|
+
this.configuration.headers,
|
|
873
|
+
context.headers
|
|
874
|
+
);
|
|
875
|
+
Object.keys(headers).forEach(
|
|
876
|
+
(key) => headers[key] === void 0 ? delete headers[key] : {}
|
|
877
|
+
);
|
|
878
|
+
const initOverrideFn = typeof initOverrides === "function" ? initOverrides : async () => initOverrides;
|
|
879
|
+
const initParams = {
|
|
880
|
+
method: context.method,
|
|
881
|
+
headers,
|
|
882
|
+
body: context.body,
|
|
883
|
+
credentials: this.configuration.credentials
|
|
884
|
+
};
|
|
885
|
+
const overriddenInit = {
|
|
886
|
+
...initParams,
|
|
887
|
+
...await initOverrideFn({
|
|
888
|
+
init: initParams,
|
|
889
|
+
context
|
|
890
|
+
})
|
|
891
|
+
};
|
|
892
|
+
let body;
|
|
893
|
+
if (isFormData(overriddenInit.body) || overriddenInit.body instanceof URLSearchParams || isBlob(overriddenInit.body)) {
|
|
894
|
+
body = overriddenInit.body;
|
|
895
|
+
} else if (this.isJsonMime(headers["Content-Type"])) {
|
|
896
|
+
body = JSON.stringify(overriddenInit.body);
|
|
897
|
+
} else {
|
|
898
|
+
body = overriddenInit.body;
|
|
899
|
+
}
|
|
900
|
+
const init = {
|
|
901
|
+
...overriddenInit,
|
|
902
|
+
body
|
|
903
|
+
};
|
|
904
|
+
return { url, init };
|
|
905
|
+
}
|
|
906
|
+
fetchApi = async (url, init) => {
|
|
907
|
+
let fetchParams = { url, init };
|
|
908
|
+
for (const middleware of this.middleware) {
|
|
909
|
+
if (middleware.pre) {
|
|
910
|
+
fetchParams = await middleware.pre({
|
|
911
|
+
fetch: this.fetchApi,
|
|
912
|
+
...fetchParams
|
|
913
|
+
}) || fetchParams;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
let response = void 0;
|
|
917
|
+
try {
|
|
918
|
+
response = await (this.configuration.fetchApi || fetch)(
|
|
919
|
+
fetchParams.url,
|
|
920
|
+
fetchParams.init
|
|
921
|
+
);
|
|
922
|
+
} catch (e) {
|
|
923
|
+
for (const middleware of this.middleware) {
|
|
924
|
+
if (middleware.onError) {
|
|
925
|
+
response = await middleware.onError({
|
|
926
|
+
fetch: this.fetchApi,
|
|
927
|
+
url: fetchParams.url,
|
|
928
|
+
init: fetchParams.init,
|
|
929
|
+
error: e,
|
|
930
|
+
response: response ? response.clone() : void 0
|
|
931
|
+
}) || response;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
if (response === void 0) {
|
|
935
|
+
if (e instanceof Error) {
|
|
936
|
+
throw new FetchError(
|
|
937
|
+
e,
|
|
938
|
+
"The request failed and the interceptors did not return an alternative response"
|
|
939
|
+
);
|
|
940
|
+
} else {
|
|
941
|
+
throw e;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
for (const middleware of this.middleware) {
|
|
946
|
+
if (middleware.post) {
|
|
947
|
+
response = await middleware.post({
|
|
948
|
+
fetch: this.fetchApi,
|
|
949
|
+
url: fetchParams.url,
|
|
950
|
+
init: fetchParams.init,
|
|
951
|
+
response: response.clone()
|
|
952
|
+
}) || response;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
return response;
|
|
956
|
+
};
|
|
957
|
+
/**
|
|
958
|
+
* Create a shallow clone of `this` by constructing a new instance
|
|
959
|
+
* and then shallow cloning data members.
|
|
960
|
+
*/
|
|
961
|
+
clone() {
|
|
962
|
+
const constructor = this.constructor;
|
|
963
|
+
const next = new constructor(this.configuration);
|
|
964
|
+
next.middleware = this.middleware.slice();
|
|
965
|
+
return next;
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
function isBlob(value) {
|
|
969
|
+
return typeof Blob !== "undefined" && value instanceof Blob;
|
|
970
|
+
}
|
|
971
|
+
function isFormData(value) {
|
|
972
|
+
return typeof FormData !== "undefined" && value instanceof FormData;
|
|
973
|
+
}
|
|
974
|
+
var ResponseError = class extends Error {
|
|
975
|
+
constructor(response, msg) {
|
|
976
|
+
super(msg);
|
|
977
|
+
this.response = response;
|
|
978
|
+
}
|
|
979
|
+
response;
|
|
980
|
+
name = "ResponseError";
|
|
981
|
+
};
|
|
982
|
+
var FetchError = class extends Error {
|
|
983
|
+
constructor(cause, msg) {
|
|
984
|
+
super(msg);
|
|
985
|
+
this.cause = cause;
|
|
986
|
+
}
|
|
987
|
+
cause;
|
|
988
|
+
name = "FetchError";
|
|
989
|
+
};
|
|
990
|
+
function querystring(params, prefix = "") {
|
|
991
|
+
return Object.keys(params).map((key) => querystringSingleKey(key, params[key], prefix)).filter((part) => part.length > 0).join("&");
|
|
992
|
+
}
|
|
993
|
+
function querystringSingleKey(key, value, keyPrefix = "") {
|
|
994
|
+
const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key);
|
|
995
|
+
if (value instanceof Array) {
|
|
996
|
+
const multiValue = value.map((singleValue) => encodeURIComponent(String(singleValue))).join(`&${encodeURIComponent(fullKey)}=`);
|
|
997
|
+
return `${encodeURIComponent(fullKey)}=${multiValue}`;
|
|
998
|
+
}
|
|
999
|
+
if (value instanceof Set) {
|
|
1000
|
+
const valueAsArray = Array.from(value);
|
|
1001
|
+
return querystringSingleKey(key, valueAsArray, keyPrefix);
|
|
1002
|
+
}
|
|
1003
|
+
if (value instanceof Date) {
|
|
1004
|
+
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`;
|
|
1005
|
+
}
|
|
1006
|
+
if (value instanceof Object) {
|
|
1007
|
+
return querystring(value, fullKey);
|
|
1008
|
+
}
|
|
1009
|
+
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
|
|
1010
|
+
}
|
|
1011
|
+
function mapValues(data, fn) {
|
|
1012
|
+
return Object.keys(data).reduce(
|
|
1013
|
+
(acc, key) => ({ ...acc, [key]: fn(data[key]) }),
|
|
1014
|
+
{}
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// src/types/api/models/CompanyCreditBalance.ts
|
|
1019
|
+
function CompanyCreditBalanceFromJSON(json) {
|
|
1020
|
+
return CompanyCreditBalanceFromJSONTyped(json, false);
|
|
1021
|
+
}
|
|
1022
|
+
function CompanyCreditBalanceFromJSONTyped(json, ignoreDiscriminator) {
|
|
1023
|
+
if (json == null) {
|
|
1024
|
+
return json;
|
|
1025
|
+
}
|
|
1026
|
+
return {
|
|
1027
|
+
remaining: json["remaining"],
|
|
1028
|
+
reserved: json["reserved"],
|
|
1029
|
+
settled: json["settled"]
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1032
|
+
|
|
718
1033
|
// src/types/api/models/TrialStatus.ts
|
|
719
1034
|
var TrialStatus = {
|
|
720
1035
|
Active: "active",
|
|
@@ -753,6 +1068,7 @@ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
753
1068
|
return json;
|
|
754
1069
|
}
|
|
755
1070
|
return {
|
|
1071
|
+
creditBalances: json["credit_balances"] == null ? void 0 : mapValues(json["credit_balances"], CompanyCreditBalanceFromJSON),
|
|
756
1072
|
flags: json["flags"].map(CheckFlagResponseDataFromJSON),
|
|
757
1073
|
plan: json["plan"] == null ? void 0 : DatastreamCompanyPlanFromJSON(json["plan"])
|
|
758
1074
|
};
|
|
@@ -785,6 +1101,7 @@ function EventBodyFlagCheckToJSONTyped(value, ignoreDiscriminator = false) {
|
|
|
785
1101
|
error: value["error"],
|
|
786
1102
|
flag_id: value["flagId"],
|
|
787
1103
|
flag_key: value["flagKey"],
|
|
1104
|
+
preflight: value["preflight"],
|
|
788
1105
|
reason: value["reason"],
|
|
789
1106
|
req_company: value["reqCompany"],
|
|
790
1107
|
req_user: value["reqUser"],
|
|
@@ -841,7 +1158,10 @@ var CheckFlagReturnFromJSON = (json) => {
|
|
|
841
1158
|
return {
|
|
842
1159
|
featureUsageExceeded,
|
|
843
1160
|
companyId: companyId == null ? void 0 : companyId,
|
|
1161
|
+
creditId: entitlement?.creditId == null ? void 0 : entitlement.creditId,
|
|
844
1162
|
creditRemaining: entitlement?.creditRemaining == null ? void 0 : entitlement.creditRemaining,
|
|
1163
|
+
creditReserved: entitlement?.creditReserved == null ? void 0 : entitlement.creditReserved,
|
|
1164
|
+
creditSettled: entitlement?.creditSettled == null ? void 0 : entitlement.creditSettled,
|
|
845
1165
|
error: error == null ? void 0 : error,
|
|
846
1166
|
featureAllocation: resolvedAllocation == null ? void 0 : resolvedAllocation,
|
|
847
1167
|
featureUsage: resolvedUsage == null ? void 0 : resolvedUsage,
|
|
@@ -867,6 +1187,24 @@ var CheckPlanReturnFromJSON = (json) => {
|
|
|
867
1187
|
trialStatus: trialStatus == null ? void 0 : trialStatus
|
|
868
1188
|
};
|
|
869
1189
|
};
|
|
1190
|
+
var CreditBalancesFromJSON = (json) => {
|
|
1191
|
+
if (json == null || typeof json !== "object") {
|
|
1192
|
+
return {};
|
|
1193
|
+
}
|
|
1194
|
+
const balances = {};
|
|
1195
|
+
for (const [creditId, raw] of Object.entries(json)) {
|
|
1196
|
+
if (raw == null || typeof raw !== "object") continue;
|
|
1197
|
+
const { remaining, reserved, settled } = CompanyCreditBalanceFromJSON(raw);
|
|
1198
|
+
if (typeof remaining !== "number" || typeof reserved !== "number" || typeof settled !== "number") {
|
|
1199
|
+
continue;
|
|
1200
|
+
}
|
|
1201
|
+
balances[creditId] = { remaining, reserved, settled };
|
|
1202
|
+
}
|
|
1203
|
+
return balances;
|
|
1204
|
+
};
|
|
1205
|
+
|
|
1206
|
+
// src/cacheVersion.ts
|
|
1207
|
+
var cacheVersion = "bb56e75d";
|
|
870
1208
|
|
|
871
1209
|
// src/utils.ts
|
|
872
1210
|
function contextString(context) {
|
|
@@ -885,10 +1223,597 @@ function contextString(context) {
|
|
|
885
1223
|
}
|
|
886
1224
|
|
|
887
1225
|
// src/version.ts
|
|
888
|
-
var version = "1.
|
|
1226
|
+
var version = "1.6.0";
|
|
1227
|
+
|
|
1228
|
+
// src/billing/api/generated/models/index.ts
|
|
1229
|
+
var models_exports = {};
|
|
1230
|
+
__export(models_exports, {
|
|
1231
|
+
ApiErrorFromJSON: () => ApiErrorFromJSON,
|
|
1232
|
+
ApiErrorFromJSONTyped: () => ApiErrorFromJSONTyped,
|
|
1233
|
+
ApiErrorToJSON: () => ApiErrorToJSON,
|
|
1234
|
+
ApiErrorToJSONTyped: () => ApiErrorToJSONTyped,
|
|
1235
|
+
CompanyInvoiceResponseDataFromJSON: () => CompanyInvoiceResponseDataFromJSON,
|
|
1236
|
+
CompanyInvoiceResponseDataFromJSONTyped: () => CompanyInvoiceResponseDataFromJSONTyped,
|
|
1237
|
+
CompanyInvoiceResponseDataToJSON: () => CompanyInvoiceResponseDataToJSON,
|
|
1238
|
+
CompanyInvoiceResponseDataToJSONTyped: () => CompanyInvoiceResponseDataToJSONTyped,
|
|
1239
|
+
CompanyInvoicesResponseDataFromJSON: () => CompanyInvoicesResponseDataFromJSON,
|
|
1240
|
+
CompanyInvoicesResponseDataFromJSONTyped: () => CompanyInvoicesResponseDataFromJSONTyped,
|
|
1241
|
+
CompanyInvoicesResponseDataToJSON: () => CompanyInvoicesResponseDataToJSON,
|
|
1242
|
+
CompanyInvoicesResponseDataToJSONTyped: () => CompanyInvoicesResponseDataToJSONTyped,
|
|
1243
|
+
GetCompanyInvoicesParamsFromJSON: () => GetCompanyInvoicesParamsFromJSON,
|
|
1244
|
+
GetCompanyInvoicesParamsFromJSONTyped: () => GetCompanyInvoicesParamsFromJSONTyped,
|
|
1245
|
+
GetCompanyInvoicesParamsToJSON: () => GetCompanyInvoicesParamsToJSON,
|
|
1246
|
+
GetCompanyInvoicesParamsToJSONTyped: () => GetCompanyInvoicesParamsToJSONTyped,
|
|
1247
|
+
GetCompanyInvoicesResponseFromJSON: () => GetCompanyInvoicesResponseFromJSON,
|
|
1248
|
+
GetCompanyInvoicesResponseFromJSONTyped: () => GetCompanyInvoicesResponseFromJSONTyped,
|
|
1249
|
+
GetCompanyInvoicesResponseToJSON: () => GetCompanyInvoicesResponseToJSON,
|
|
1250
|
+
GetCompanyInvoicesResponseToJSONTyped: () => GetCompanyInvoicesResponseToJSONTyped,
|
|
1251
|
+
InvoiceStatus: () => InvoiceStatus,
|
|
1252
|
+
InvoiceStatusFromJSON: () => InvoiceStatusFromJSON,
|
|
1253
|
+
InvoiceStatusFromJSONTyped: () => InvoiceStatusFromJSONTyped,
|
|
1254
|
+
InvoiceStatusToJSON: () => InvoiceStatusToJSON,
|
|
1255
|
+
InvoiceStatusToJSONTyped: () => InvoiceStatusToJSONTyped,
|
|
1256
|
+
instanceOfApiError: () => instanceOfApiError,
|
|
1257
|
+
instanceOfCompanyInvoiceResponseData: () => instanceOfCompanyInvoiceResponseData,
|
|
1258
|
+
instanceOfCompanyInvoicesResponseData: () => instanceOfCompanyInvoicesResponseData,
|
|
1259
|
+
instanceOfGetCompanyInvoicesParams: () => instanceOfGetCompanyInvoicesParams,
|
|
1260
|
+
instanceOfGetCompanyInvoicesResponse: () => instanceOfGetCompanyInvoicesResponse,
|
|
1261
|
+
instanceOfInvoiceStatus: () => instanceOfInvoiceStatus
|
|
1262
|
+
});
|
|
1263
|
+
|
|
1264
|
+
// src/billing/api/generated/models/ApiError.ts
|
|
1265
|
+
function instanceOfApiError(value) {
|
|
1266
|
+
if (!("error" in value) || value["error"] === void 0) return false;
|
|
1267
|
+
return true;
|
|
1268
|
+
}
|
|
1269
|
+
function ApiErrorFromJSON(json) {
|
|
1270
|
+
return ApiErrorFromJSONTyped(json, false);
|
|
1271
|
+
}
|
|
1272
|
+
function ApiErrorFromJSONTyped(json, ignoreDiscriminator) {
|
|
1273
|
+
if (json == null) {
|
|
1274
|
+
return json;
|
|
1275
|
+
}
|
|
1276
|
+
return {
|
|
1277
|
+
error: json["error"]
|
|
1278
|
+
};
|
|
1279
|
+
}
|
|
1280
|
+
function ApiErrorToJSON(json) {
|
|
1281
|
+
return ApiErrorToJSONTyped(json, false);
|
|
1282
|
+
}
|
|
1283
|
+
function ApiErrorToJSONTyped(value, ignoreDiscriminator = false) {
|
|
1284
|
+
if (value == null) {
|
|
1285
|
+
return value;
|
|
1286
|
+
}
|
|
1287
|
+
return {
|
|
1288
|
+
error: value["error"]
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
// src/billing/api/generated/models/InvoiceStatus.ts
|
|
1293
|
+
var InvoiceStatus = {
|
|
1294
|
+
Draft: "draft",
|
|
1295
|
+
Open: "open",
|
|
1296
|
+
Paid: "paid",
|
|
1297
|
+
Uncollectible: "uncollectible",
|
|
1298
|
+
Void: "void"
|
|
1299
|
+
};
|
|
1300
|
+
function instanceOfInvoiceStatus(value) {
|
|
1301
|
+
for (const key in InvoiceStatus) {
|
|
1302
|
+
if (Object.prototype.hasOwnProperty.call(InvoiceStatus, key)) {
|
|
1303
|
+
if (InvoiceStatus[key] === value) {
|
|
1304
|
+
return true;
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
return false;
|
|
1309
|
+
}
|
|
1310
|
+
function InvoiceStatusFromJSON(json) {
|
|
1311
|
+
return InvoiceStatusFromJSONTyped(json, false);
|
|
1312
|
+
}
|
|
1313
|
+
function InvoiceStatusFromJSONTyped(json, ignoreDiscriminator) {
|
|
1314
|
+
return json;
|
|
1315
|
+
}
|
|
1316
|
+
function InvoiceStatusToJSON(value) {
|
|
1317
|
+
return value;
|
|
1318
|
+
}
|
|
1319
|
+
function InvoiceStatusToJSONTyped(value, ignoreDiscriminator) {
|
|
1320
|
+
return value;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
// src/billing/api/generated/models/CompanyInvoiceResponseData.ts
|
|
1324
|
+
function instanceOfCompanyInvoiceResponseData(value) {
|
|
1325
|
+
if (!("amountDue" in value) || value["amountDue"] === void 0) return false;
|
|
1326
|
+
if (!("createdAt" in value) || value["createdAt"] === void 0) return false;
|
|
1327
|
+
if (!("currency" in value) || value["currency"] === void 0) return false;
|
|
1328
|
+
if (!("id" in value) || value["id"] === void 0) return false;
|
|
1329
|
+
return true;
|
|
1330
|
+
}
|
|
1331
|
+
function CompanyInvoiceResponseDataFromJSON(json) {
|
|
1332
|
+
return CompanyInvoiceResponseDataFromJSONTyped(json, false);
|
|
1333
|
+
}
|
|
1334
|
+
function CompanyInvoiceResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
1335
|
+
if (json == null) {
|
|
1336
|
+
return json;
|
|
1337
|
+
}
|
|
1338
|
+
return {
|
|
1339
|
+
amountDue: json["amount_due"],
|
|
1340
|
+
createdAt: new Date(json["created_at"]),
|
|
1341
|
+
currency: json["currency"],
|
|
1342
|
+
dueDate: json["due_date"] == null ? void 0 : new Date(json["due_date"]),
|
|
1343
|
+
id: json["id"],
|
|
1344
|
+
status: json["status"] == null ? void 0 : InvoiceStatusFromJSON(json["status"]),
|
|
1345
|
+
url: json["url"] == null ? void 0 : json["url"]
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
function CompanyInvoiceResponseDataToJSON(json) {
|
|
1349
|
+
return CompanyInvoiceResponseDataToJSONTyped(json, false);
|
|
1350
|
+
}
|
|
1351
|
+
function CompanyInvoiceResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
|
|
1352
|
+
if (value == null) {
|
|
1353
|
+
return value;
|
|
1354
|
+
}
|
|
1355
|
+
return {
|
|
1356
|
+
amount_due: value["amountDue"],
|
|
1357
|
+
created_at: value["createdAt"].toISOString(),
|
|
1358
|
+
currency: value["currency"],
|
|
1359
|
+
due_date: value["dueDate"] == null ? void 0 : value["dueDate"].toISOString(),
|
|
1360
|
+
id: value["id"],
|
|
1361
|
+
status: InvoiceStatusToJSON(value["status"]),
|
|
1362
|
+
url: value["url"]
|
|
1363
|
+
};
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// src/billing/api/generated/models/CompanyInvoicesResponseData.ts
|
|
1367
|
+
function instanceOfCompanyInvoicesResponseData(value) {
|
|
1368
|
+
if (!("count" in value) || value["count"] === void 0) return false;
|
|
1369
|
+
if (!("invoices" in value) || value["invoices"] === void 0) return false;
|
|
1370
|
+
return true;
|
|
1371
|
+
}
|
|
1372
|
+
function CompanyInvoicesResponseDataFromJSON(json) {
|
|
1373
|
+
return CompanyInvoicesResponseDataFromJSONTyped(json, false);
|
|
1374
|
+
}
|
|
1375
|
+
function CompanyInvoicesResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
1376
|
+
if (json == null) {
|
|
1377
|
+
return json;
|
|
1378
|
+
}
|
|
1379
|
+
return {
|
|
1380
|
+
count: json["count"],
|
|
1381
|
+
invoices: json["invoices"].map(
|
|
1382
|
+
CompanyInvoiceResponseDataFromJSON
|
|
1383
|
+
)
|
|
1384
|
+
};
|
|
1385
|
+
}
|
|
1386
|
+
function CompanyInvoicesResponseDataToJSON(json) {
|
|
1387
|
+
return CompanyInvoicesResponseDataToJSONTyped(json, false);
|
|
1388
|
+
}
|
|
1389
|
+
function CompanyInvoicesResponseDataToJSONTyped(value, ignoreDiscriminator = false) {
|
|
1390
|
+
if (value == null) {
|
|
1391
|
+
return value;
|
|
1392
|
+
}
|
|
1393
|
+
return {
|
|
1394
|
+
count: value["count"],
|
|
1395
|
+
invoices: value["invoices"].map(
|
|
1396
|
+
CompanyInvoiceResponseDataToJSON
|
|
1397
|
+
)
|
|
1398
|
+
};
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
// src/billing/api/generated/models/GetCompanyInvoicesParams.ts
|
|
1402
|
+
function instanceOfGetCompanyInvoicesParams(value) {
|
|
1403
|
+
return true;
|
|
1404
|
+
}
|
|
1405
|
+
function GetCompanyInvoicesParamsFromJSON(json) {
|
|
1406
|
+
return GetCompanyInvoicesParamsFromJSONTyped(json, false);
|
|
1407
|
+
}
|
|
1408
|
+
function GetCompanyInvoicesParamsFromJSONTyped(json, ignoreDiscriminator) {
|
|
1409
|
+
if (json == null) {
|
|
1410
|
+
return json;
|
|
1411
|
+
}
|
|
1412
|
+
return {
|
|
1413
|
+
includePending: json["include_pending"] == null ? void 0 : json["include_pending"],
|
|
1414
|
+
limit: json["limit"] == null ? void 0 : json["limit"],
|
|
1415
|
+
offset: json["offset"] == null ? void 0 : json["offset"]
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
function GetCompanyInvoicesParamsToJSON(json) {
|
|
1419
|
+
return GetCompanyInvoicesParamsToJSONTyped(json, false);
|
|
1420
|
+
}
|
|
1421
|
+
function GetCompanyInvoicesParamsToJSONTyped(value, ignoreDiscriminator = false) {
|
|
1422
|
+
if (value == null) {
|
|
1423
|
+
return value;
|
|
1424
|
+
}
|
|
1425
|
+
return {
|
|
1426
|
+
include_pending: value["includePending"],
|
|
1427
|
+
limit: value["limit"],
|
|
1428
|
+
offset: value["offset"]
|
|
1429
|
+
};
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
// src/billing/api/generated/models/GetCompanyInvoicesResponse.ts
|
|
1433
|
+
function instanceOfGetCompanyInvoicesResponse(value) {
|
|
1434
|
+
if (!("data" in value) || value["data"] === void 0) return false;
|
|
1435
|
+
if (!("params" in value) || value["params"] === void 0) return false;
|
|
1436
|
+
return true;
|
|
1437
|
+
}
|
|
1438
|
+
function GetCompanyInvoicesResponseFromJSON(json) {
|
|
1439
|
+
return GetCompanyInvoicesResponseFromJSONTyped(json, false);
|
|
1440
|
+
}
|
|
1441
|
+
function GetCompanyInvoicesResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
1442
|
+
if (json == null) {
|
|
1443
|
+
return json;
|
|
1444
|
+
}
|
|
1445
|
+
return {
|
|
1446
|
+
data: CompanyInvoicesResponseDataFromJSON(json["data"]),
|
|
1447
|
+
params: GetCompanyInvoicesParamsFromJSON(json["params"])
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
function GetCompanyInvoicesResponseToJSON(json) {
|
|
1451
|
+
return GetCompanyInvoicesResponseToJSONTyped(json, false);
|
|
1452
|
+
}
|
|
1453
|
+
function GetCompanyInvoicesResponseToJSONTyped(value, ignoreDiscriminator = false) {
|
|
1454
|
+
if (value == null) {
|
|
1455
|
+
return value;
|
|
1456
|
+
}
|
|
1457
|
+
return {
|
|
1458
|
+
data: CompanyInvoicesResponseDataToJSON(value["data"]),
|
|
1459
|
+
params: GetCompanyInvoicesParamsToJSON(value["params"])
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
// src/billing/contract/invoices.ts
|
|
1464
|
+
var DEFAULT_INVOICE_QUERY = {};
|
|
1465
|
+
function normalizeInvoiceQuery(query) {
|
|
1466
|
+
const { includePending, ...rest } = query;
|
|
1467
|
+
return includePending === true ? { ...rest, includePending: true } : rest;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
// src/billing/session.ts
|
|
1471
|
+
var SchematicApiError = class extends Error {
|
|
1472
|
+
constructor(status, path, body) {
|
|
1473
|
+
super(
|
|
1474
|
+
typeof body === "object" && body !== null && "error" in body ? String(body.error) : `Request to ${path} failed with status ${status}`
|
|
1475
|
+
);
|
|
1476
|
+
this.status = status;
|
|
1477
|
+
this.path = path;
|
|
1478
|
+
this.body = body;
|
|
1479
|
+
this.name = "SchematicApiError";
|
|
1480
|
+
}
|
|
1481
|
+
status;
|
|
1482
|
+
path;
|
|
1483
|
+
body;
|
|
1484
|
+
};
|
|
1485
|
+
var DEFAULT_API_URL = "https://api.schematichq.com";
|
|
1486
|
+
var TOKEN_CACHE_SIZE = 10;
|
|
1487
|
+
function sessionKey(session) {
|
|
1488
|
+
return JSON.stringify([session.company, session.user ?? null]);
|
|
1489
|
+
}
|
|
1490
|
+
var SchematicSession = class {
|
|
1491
|
+
_apiUrl;
|
|
1492
|
+
_headers;
|
|
1493
|
+
_fetch;
|
|
1494
|
+
_session;
|
|
1495
|
+
_tokens = /* @__PURE__ */ new Map();
|
|
1496
|
+
_resolving = /* @__PURE__ */ new Map();
|
|
1497
|
+
/**
|
|
1498
|
+
* Bumped when the session's identity changes, and only then — the object
|
|
1499
|
+
* itself is replaced on every render. Anything asking "is this still the
|
|
1500
|
+
* session I started under?" counts generations rather than comparing.
|
|
1501
|
+
*/
|
|
1502
|
+
_generation = 0;
|
|
1503
|
+
_listeners = /* @__PURE__ */ new Set();
|
|
1504
|
+
constructor(options = {}) {
|
|
1505
|
+
this._session = options.session;
|
|
1506
|
+
this._apiUrl = (options.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, "");
|
|
1507
|
+
this._headers = options.additionalHeaders ?? {};
|
|
1508
|
+
this._fetch = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
|
|
1509
|
+
}
|
|
1510
|
+
get key() {
|
|
1511
|
+
return this._session === null || this._session === void 0 ? void 0 : sessionKey(this._session);
|
|
1512
|
+
}
|
|
1513
|
+
get status() {
|
|
1514
|
+
if (this._session === void 0) {
|
|
1515
|
+
return "pending";
|
|
1516
|
+
}
|
|
1517
|
+
return this._session === null ? "ended" : "active";
|
|
1518
|
+
}
|
|
1519
|
+
/** Only a statement that changes which pair is read counts as a change. */
|
|
1520
|
+
set(session) {
|
|
1521
|
+
if (session === void 0) {
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
const previous = this._session;
|
|
1525
|
+
this._session = session;
|
|
1526
|
+
if (session === null) {
|
|
1527
|
+
if (previous === null) {
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
this._tokens.clear();
|
|
1531
|
+
this._resolving.clear();
|
|
1532
|
+
this._generation += 1;
|
|
1533
|
+
this._emit({ type: "ended" });
|
|
1534
|
+
return;
|
|
1535
|
+
}
|
|
1536
|
+
if (previous !== null && previous !== void 0) {
|
|
1537
|
+
if (previous.company === session.company && (previous.user ?? null) === (session.user ?? null)) {
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
1540
|
+
this._generation += 1;
|
|
1541
|
+
this._emit({ type: "changed" });
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1544
|
+
this._generation += 1;
|
|
1545
|
+
this._emit({ type: "started" });
|
|
1546
|
+
}
|
|
1547
|
+
onChange(listener) {
|
|
1548
|
+
this._listeners.add(listener);
|
|
1549
|
+
return () => {
|
|
1550
|
+
this._listeners.delete(listener);
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
_emit(event) {
|
|
1554
|
+
for (const listener of this._listeners) {
|
|
1555
|
+
listener(event);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
_cached(key) {
|
|
1559
|
+
const cached = this._tokens.get(key);
|
|
1560
|
+
if (cached === void 0) {
|
|
1561
|
+
return void 0;
|
|
1562
|
+
}
|
|
1563
|
+
if (cached.expiresAt !== void 0 && cached.expiresAt.getTime() <= Date.now()) {
|
|
1564
|
+
this._tokens.delete(key);
|
|
1565
|
+
return void 0;
|
|
1566
|
+
}
|
|
1567
|
+
this._tokens.delete(key);
|
|
1568
|
+
this._tokens.set(key, cached);
|
|
1569
|
+
return cached;
|
|
1570
|
+
}
|
|
1571
|
+
_cache(key, resolved) {
|
|
1572
|
+
this._tokens.delete(key);
|
|
1573
|
+
this._tokens.set(key, resolved);
|
|
1574
|
+
while (this._tokens.size > TOKEN_CACHE_SIZE) {
|
|
1575
|
+
const oldest = this._tokens.keys().next();
|
|
1576
|
+
if (oldest.done === true) {
|
|
1577
|
+
break;
|
|
1578
|
+
}
|
|
1579
|
+
this._tokens.delete(oldest.value);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* The credential for a session, minted if this one is not held. `force`
|
|
1584
|
+
* retires what is held first: the caller is a request the API has just
|
|
1585
|
+
* rejected.
|
|
1586
|
+
*/
|
|
1587
|
+
resolveToken(session, force) {
|
|
1588
|
+
const { token } = session;
|
|
1589
|
+
if (typeof token === "string") {
|
|
1590
|
+
return Promise.resolve(token);
|
|
1591
|
+
}
|
|
1592
|
+
const key = sessionKey(session);
|
|
1593
|
+
if (!force) {
|
|
1594
|
+
const cached = this._cached(key);
|
|
1595
|
+
if (cached !== void 0) {
|
|
1596
|
+
return Promise.resolve(cached.token);
|
|
1597
|
+
}
|
|
1598
|
+
} else {
|
|
1599
|
+
this._tokens.delete(key);
|
|
1600
|
+
}
|
|
1601
|
+
const inflight = this._resolving.get(key);
|
|
1602
|
+
if (inflight !== void 0 && inflight.sessionGeneration === this._generation && (!force || inflight.forced)) {
|
|
1603
|
+
return inflight.promise;
|
|
1604
|
+
}
|
|
1605
|
+
const provider = token;
|
|
1606
|
+
const sessionGeneration = this._generation;
|
|
1607
|
+
const owns = () => this._resolving.get(key)?.promise === promise;
|
|
1608
|
+
const promise = Promise.resolve().then(() => provider()).then((result) => {
|
|
1609
|
+
const { resolved, stamped } = asResolvedToken(result, session);
|
|
1610
|
+
if (owns() && (this._generation === sessionGeneration || stamped)) {
|
|
1611
|
+
this._cache(key, resolved);
|
|
1612
|
+
}
|
|
1613
|
+
return resolved.token;
|
|
1614
|
+
}).finally(() => {
|
|
1615
|
+
if (owns()) {
|
|
1616
|
+
this._resolving.delete(key);
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1619
|
+
this._resolving.set(key, { promise, forced: force, sessionGeneration });
|
|
1620
|
+
return promise;
|
|
1621
|
+
}
|
|
1622
|
+
/**
|
|
1623
|
+
* Sends a request under the active session's credential, refreshing once
|
|
1624
|
+
* and retrying if the API rejects it. Rejects rather than answering when
|
|
1625
|
+
* the session changes while the request is in flight: the rows would
|
|
1626
|
+
* otherwise come back as the answer to a question asked for another pair.
|
|
1627
|
+
*/
|
|
1628
|
+
async request(path, options = {}) {
|
|
1629
|
+
const { method = "GET", body } = options;
|
|
1630
|
+
const send = async (credential2) => this._fetch(`${this._apiUrl}${path}`, {
|
|
1631
|
+
method,
|
|
1632
|
+
headers: {
|
|
1633
|
+
"Accept": "application/json",
|
|
1634
|
+
...body === void 0 ? {} : { "Content-Type": "application/json" },
|
|
1635
|
+
...this._headers,
|
|
1636
|
+
"X-Schematic-Api-Key": credential2
|
|
1637
|
+
},
|
|
1638
|
+
...body === void 0 ? {} : { body: JSON.stringify(body) }
|
|
1639
|
+
});
|
|
1640
|
+
const session = this._session;
|
|
1641
|
+
if (session === null) {
|
|
1642
|
+
throw new Error("There is no session to read data for.");
|
|
1643
|
+
}
|
|
1644
|
+
if (session === void 0) {
|
|
1645
|
+
throw new Error("A session is required to read data.");
|
|
1646
|
+
}
|
|
1647
|
+
const provider = session.token;
|
|
1648
|
+
const generation = this._generation;
|
|
1649
|
+
const stillOurs = async (response2) => {
|
|
1650
|
+
if (this._generation === generation) {
|
|
1651
|
+
return;
|
|
1652
|
+
}
|
|
1653
|
+
if (response2 !== void 0) {
|
|
1654
|
+
await discardBody(response2);
|
|
1655
|
+
}
|
|
1656
|
+
throw new Error("The session changed while this request was in flight.");
|
|
1657
|
+
};
|
|
1658
|
+
const credential = await this.resolveToken(session, false);
|
|
1659
|
+
if (this._generation !== generation) {
|
|
1660
|
+
throw new Error("The session changed before this request was sent.");
|
|
1661
|
+
}
|
|
1662
|
+
let response = await send(credential);
|
|
1663
|
+
await stillOurs(response);
|
|
1664
|
+
if (response.status === 401 && typeof provider === "function" && this._generation === generation) {
|
|
1665
|
+
const status = response.status;
|
|
1666
|
+
const rejected = await readBody(response);
|
|
1667
|
+
let retried = false;
|
|
1668
|
+
const current = this._session;
|
|
1669
|
+
if (this._generation === generation && current !== null && current !== void 0) {
|
|
1670
|
+
const refreshed = await this.resolveToken(current, true);
|
|
1671
|
+
if (this._generation === generation) {
|
|
1672
|
+
response = await send(refreshed);
|
|
1673
|
+
await stillOurs(response);
|
|
1674
|
+
retried = true;
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
if (!retried) {
|
|
1678
|
+
throw new SchematicApiError(status, path, rejected);
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
const parsed = await readBody(response);
|
|
1682
|
+
await stillOurs();
|
|
1683
|
+
if (!response.ok) {
|
|
1684
|
+
throw new SchematicApiError(response.status, path, parsed);
|
|
1685
|
+
}
|
|
1686
|
+
return parsed;
|
|
1687
|
+
}
|
|
1688
|
+
};
|
|
1689
|
+
function asResolvedToken(result, session) {
|
|
1690
|
+
if (typeof result === "string") {
|
|
1691
|
+
return { resolved: { token: result }, stamped: false };
|
|
1692
|
+
}
|
|
1693
|
+
const token = result?.token;
|
|
1694
|
+
if (typeof token !== "string" || token === "") {
|
|
1695
|
+
throw new Error("The access token provider did not return a token.");
|
|
1696
|
+
}
|
|
1697
|
+
if (result.company !== void 0 && result.company !== session.company || result.user !== void 0 && session.user !== void 0 && result.user !== session.user) {
|
|
1698
|
+
throw new Error(
|
|
1699
|
+
"The access token provider returned a token for a different session."
|
|
1700
|
+
);
|
|
1701
|
+
}
|
|
1702
|
+
const stamped = result.company !== void 0 && (session.user === void 0 || result.user !== void 0);
|
|
1703
|
+
return { resolved: { token, expiresAt: asDate(result.expiresAt) }, stamped };
|
|
1704
|
+
}
|
|
1705
|
+
function asDate(value) {
|
|
1706
|
+
if (value === void 0 || value === null) {
|
|
1707
|
+
return void 0;
|
|
1708
|
+
}
|
|
1709
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
1710
|
+
return Number.isNaN(date.getTime()) ? void 0 : date;
|
|
1711
|
+
}
|
|
1712
|
+
async function discardBody(response) {
|
|
1713
|
+
try {
|
|
1714
|
+
await response.body?.cancel();
|
|
1715
|
+
} catch {
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
async function readBody(response) {
|
|
1719
|
+
const text = await response.text();
|
|
1720
|
+
if (text === "") {
|
|
1721
|
+
return null;
|
|
1722
|
+
}
|
|
1723
|
+
try {
|
|
1724
|
+
return JSON.parse(text);
|
|
1725
|
+
} catch {
|
|
1726
|
+
return text;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
// src/billing/client.ts
|
|
1731
|
+
var INVOICE_PAGE_SIZE = 12;
|
|
1732
|
+
var INVOICE_MAX_PAGE_SIZE = 250;
|
|
1733
|
+
var SchematicBillingClient = class {
|
|
1734
|
+
/**
|
|
1735
|
+
* Public so a second client over the same surface can be constructed on
|
|
1736
|
+
* this one rather than minting tokens of its own.
|
|
1737
|
+
*/
|
|
1738
|
+
session;
|
|
1739
|
+
constructor(options = {}) {
|
|
1740
|
+
this.session = options instanceof SchematicSession ? options : new SchematicSession(options);
|
|
1741
|
+
}
|
|
1742
|
+
get sessionKey() {
|
|
1743
|
+
return this.session.key;
|
|
1744
|
+
}
|
|
1745
|
+
get sessionStatus() {
|
|
1746
|
+
return this.session.status;
|
|
1747
|
+
}
|
|
1748
|
+
setSession(session) {
|
|
1749
|
+
this.session.set(session);
|
|
1750
|
+
}
|
|
1751
|
+
onSessionChange(listener) {
|
|
1752
|
+
return this.session.onChange(listener);
|
|
1753
|
+
}
|
|
1754
|
+
fetchInvoices(params) {
|
|
1755
|
+
const query = new URLSearchParams({
|
|
1756
|
+
limit: String(Math.min(params.limit, INVOICE_MAX_PAGE_SIZE)),
|
|
1757
|
+
offset: String(params.offset)
|
|
1758
|
+
});
|
|
1759
|
+
if (params.includePending !== void 0) {
|
|
1760
|
+
query.set("include_pending", String(params.includePending));
|
|
1761
|
+
}
|
|
1762
|
+
const path = `/company/invoices?${query}`;
|
|
1763
|
+
return this.session.request(path).then((body) => {
|
|
1764
|
+
if (body === null || typeof body !== "object" || !("data" in body)) {
|
|
1765
|
+
throw new Error(`Malformed response from ${path}`);
|
|
1766
|
+
}
|
|
1767
|
+
const data = body.data;
|
|
1768
|
+
if (data == null || data.invoices == null) {
|
|
1769
|
+
return { invoices: [], count: 0 };
|
|
1770
|
+
}
|
|
1771
|
+
const decoded = GetCompanyInvoicesResponseFromJSON(body).data;
|
|
1772
|
+
return { invoices: decoded.invoices, count: decoded.count };
|
|
1773
|
+
});
|
|
1774
|
+
}
|
|
1775
|
+
};
|
|
1776
|
+
async function fetchBillingData(client, options = {}) {
|
|
1777
|
+
const wanted = options.names ?? ["invoices"];
|
|
1778
|
+
const data = {};
|
|
1779
|
+
const invoices = options.invoices === void 0 ? void 0 : normalizeInvoiceQuery(options.invoices);
|
|
1780
|
+
if (invoices !== void 0) {
|
|
1781
|
+
data.params = { invoices };
|
|
1782
|
+
}
|
|
1783
|
+
data.sessionKey = client.sessionKey;
|
|
1784
|
+
await Promise.all(
|
|
1785
|
+
wanted.map(async (name) => {
|
|
1786
|
+
try {
|
|
1787
|
+
switch (name) {
|
|
1788
|
+
case "invoices": {
|
|
1789
|
+
const page = await client.fetchInvoices({
|
|
1790
|
+
...invoices ?? {},
|
|
1791
|
+
limit: INVOICE_PAGE_SIZE,
|
|
1792
|
+
offset: 0
|
|
1793
|
+
});
|
|
1794
|
+
data.invoices = {
|
|
1795
|
+
invoices: page.invoices,
|
|
1796
|
+
count: page.count,
|
|
1797
|
+
// Two queries on the server: a count that outran the rows
|
|
1798
|
+
// would seed a page that pages nothing.
|
|
1799
|
+
hasMore: page.invoices.length > 0 && page.invoices.length < page.count
|
|
1800
|
+
};
|
|
1801
|
+
break;
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
} catch {
|
|
1805
|
+
}
|
|
1806
|
+
})
|
|
1807
|
+
);
|
|
1808
|
+
return data;
|
|
1809
|
+
}
|
|
889
1810
|
|
|
890
1811
|
// src/index.ts
|
|
891
1812
|
var anonymousIdKey = "schematicId";
|
|
1813
|
+
var flagStateCachePrefix = "schematicCache";
|
|
1814
|
+
var flagStateCacheMaxContexts = 10;
|
|
1815
|
+
var flagStateCacheDefaultMaxAgeMs = 7 * 24 * 60 * 60 * 1e3;
|
|
1816
|
+
var emptyCreditBalances = Object.freeze({});
|
|
892
1817
|
var Schematic = class {
|
|
893
1818
|
additionalHeaders = {};
|
|
894
1819
|
apiKey;
|
|
@@ -905,11 +1830,17 @@ var Schematic = class {
|
|
|
905
1830
|
isPending = true;
|
|
906
1831
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
907
1832
|
planListeners = /* @__PURE__ */ new Set();
|
|
1833
|
+
creditBalanceListeners = /* @__PURE__ */ new Set();
|
|
908
1834
|
storage;
|
|
1835
|
+
persistFlagState = true;
|
|
1836
|
+
flagStateCacheKey;
|
|
1837
|
+
flagStateCacheMaxAgeMs = flagStateCacheDefaultMaxAgeMs;
|
|
1838
|
+
cachedFlagState = null;
|
|
909
1839
|
useWebSocket = false;
|
|
910
1840
|
checks = {};
|
|
911
1841
|
featureUsageEventMap = {};
|
|
912
1842
|
planChecks = {};
|
|
1843
|
+
creditBalances = {};
|
|
913
1844
|
webSocketUrl = "wss://api.schematichq.com";
|
|
914
1845
|
webSocketConnectionTimeout = 1e4;
|
|
915
1846
|
webSocketReconnect = true;
|
|
@@ -938,11 +1869,16 @@ var Schematic = class {
|
|
|
938
1869
|
fallbackCheckCache = {};
|
|
939
1870
|
constructor(apiKey, options) {
|
|
940
1871
|
this.apiKey = apiKey;
|
|
1872
|
+
this.flagStateCacheKey = `${flagStateCachePrefix}:${apiKey}`;
|
|
941
1873
|
this.eventQueue = [];
|
|
942
1874
|
this.contextDependentEventQueue = [];
|
|
943
1875
|
this.useWebSocket = options?.useWebSocket ?? false;
|
|
944
1876
|
this.debugEnabled = options?.debug ?? false;
|
|
945
1877
|
this.offlineEnabled = options?.offline ?? false;
|
|
1878
|
+
this.persistFlagState = options?.persistFlagState ?? true;
|
|
1879
|
+
if (typeof options?.flagStateCacheMaxAgeMs === "number" && options.flagStateCacheMaxAgeMs > 0) {
|
|
1880
|
+
this.flagStateCacheMaxAgeMs = options.flagStateCacheMaxAgeMs;
|
|
1881
|
+
}
|
|
946
1882
|
if (typeof window !== "undefined" && typeof window.location !== "undefined") {
|
|
947
1883
|
const params = new URLSearchParams(window.location.search);
|
|
948
1884
|
const debugParam = params.get("schematic_debug");
|
|
@@ -975,6 +1911,7 @@ var Schematic = class {
|
|
|
975
1911
|
} catch {
|
|
976
1912
|
}
|
|
977
1913
|
}
|
|
1914
|
+
this.hydrateFlagStateFromCache();
|
|
978
1915
|
if (options?.apiUrl !== void 0) {
|
|
979
1916
|
this.apiUrl = options.apiUrl;
|
|
980
1917
|
}
|
|
@@ -1268,6 +2205,29 @@ var Schematic = class {
|
|
|
1268
2205
|
});
|
|
1269
2206
|
this.notifyPlanListeners(plan);
|
|
1270
2207
|
}
|
|
2208
|
+
if (message.credit_balances !== void 0 && message.credit_balances !== null) {
|
|
2209
|
+
const contextStr = contextString(context);
|
|
2210
|
+
const updates = CreditBalancesFromJSON(message.credit_balances);
|
|
2211
|
+
const previous = this.creditBalances[contextStr] ?? {};
|
|
2212
|
+
let changed = false;
|
|
2213
|
+
const merged = { ...previous };
|
|
2214
|
+
for (const [creditId, next] of Object.entries(updates)) {
|
|
2215
|
+
const current = previous[creditId];
|
|
2216
|
+
if (current === void 0 || current.remaining !== next.remaining || current.reserved !== next.reserved || current.settled !== next.settled) {
|
|
2217
|
+
merged[creditId] = next;
|
|
2218
|
+
changed = true;
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
if (changed) {
|
|
2222
|
+
this.creditBalances[contextStr] = merged;
|
|
2223
|
+
this.debug(
|
|
2224
|
+
`WebSocket credit balance update received. Notifying listeners`,
|
|
2225
|
+
{ creditBalances: merged }
|
|
2226
|
+
);
|
|
2227
|
+
this.notifyCreditBalanceListeners(merged);
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
this.persistContextToCache(contextString(context));
|
|
1271
2231
|
this.flushContextDependentEventQueue();
|
|
1272
2232
|
this.setIsPending(false);
|
|
1273
2233
|
};
|
|
@@ -1375,7 +2335,32 @@ var Schematic = class {
|
|
|
1375
2335
|
return;
|
|
1376
2336
|
}
|
|
1377
2337
|
try {
|
|
1378
|
-
|
|
2338
|
+
const newContextStr = contextString(context);
|
|
2339
|
+
const cacheHit = this.hasCachedValuesForContext(newContextStr);
|
|
2340
|
+
if (cacheHit) {
|
|
2341
|
+
this.debug(
|
|
2342
|
+
`setContext: cache hit for context, pre-resolving from cached values`
|
|
2343
|
+
);
|
|
2344
|
+
this.context = context;
|
|
2345
|
+
this.flushContextDependentEventQueue();
|
|
2346
|
+
this.setIsPending(false);
|
|
2347
|
+
const cachedChecks = this.checks[newContextStr] ?? {};
|
|
2348
|
+
for (const [flagKey, check] of Object.entries(cachedChecks)) {
|
|
2349
|
+
if (check === void 0) continue;
|
|
2350
|
+
this.notifyFlagCheckListeners(flagKey, check);
|
|
2351
|
+
this.notifyFlagValueListeners(flagKey, check.value);
|
|
2352
|
+
}
|
|
2353
|
+
const cachedPlan = this.planChecks[newContextStr];
|
|
2354
|
+
if (cachedPlan !== void 0) {
|
|
2355
|
+
this.notifyPlanListeners(cachedPlan);
|
|
2356
|
+
}
|
|
2357
|
+
const cachedCreditBalances = this.creditBalances[newContextStr];
|
|
2358
|
+
if (cachedCreditBalances !== void 0) {
|
|
2359
|
+
this.notifyCreditBalanceListeners(cachedCreditBalances);
|
|
2360
|
+
}
|
|
2361
|
+
} else {
|
|
2362
|
+
this.setIsPending(true);
|
|
2363
|
+
}
|
|
1379
2364
|
if (!this.conn) {
|
|
1380
2365
|
if (this.isConnecting) {
|
|
1381
2366
|
this.debug(
|
|
@@ -1386,7 +2371,7 @@ var Schematic = class {
|
|
|
1386
2371
|
}
|
|
1387
2372
|
if (this.conn !== null) {
|
|
1388
2373
|
const socket2 = await this.conn;
|
|
1389
|
-
await this.wsSendMessage(socket2, context);
|
|
2374
|
+
await this.wsSendMessage(socket2, context, cacheHit);
|
|
1390
2375
|
return;
|
|
1391
2376
|
}
|
|
1392
2377
|
}
|
|
@@ -1402,7 +2387,7 @@ var Schematic = class {
|
|
|
1402
2387
|
this.conn = this.wsConnect();
|
|
1403
2388
|
const socket2 = await this.conn;
|
|
1404
2389
|
this.isConnecting = false;
|
|
1405
|
-
await this.wsSendMessage(socket2, context);
|
|
2390
|
+
await this.wsSendMessage(socket2, context, cacheHit);
|
|
1406
2391
|
return;
|
|
1407
2392
|
} catch (error) {
|
|
1408
2393
|
this.isConnecting = false;
|
|
@@ -1410,7 +2395,7 @@ var Schematic = class {
|
|
|
1410
2395
|
}
|
|
1411
2396
|
}
|
|
1412
2397
|
const socket = await this.conn;
|
|
1413
|
-
await this.wsSendMessage(socket, context);
|
|
2398
|
+
await this.wsSendMessage(socket, context, cacheHit);
|
|
1414
2399
|
} catch (error) {
|
|
1415
2400
|
console.warn("Failed to establish WebSocket connection:", error);
|
|
1416
2401
|
this.context = context;
|
|
@@ -1470,10 +2455,12 @@ var Schematic = class {
|
|
|
1470
2455
|
`Optimistically updating feature usage for event: ${eventName}`,
|
|
1471
2456
|
{ quantity }
|
|
1472
2457
|
);
|
|
2458
|
+
let dirty = false;
|
|
1473
2459
|
Object.entries(flagsForEvent).forEach(([flagKey, check]) => {
|
|
1474
2460
|
if (check === void 0) return;
|
|
1475
2461
|
const updatedCheck = { ...check };
|
|
1476
2462
|
if (typeof updatedCheck.featureUsage === "number") {
|
|
2463
|
+
dirty = true;
|
|
1477
2464
|
updatedCheck.featureUsage += quantity;
|
|
1478
2465
|
if (typeof updatedCheck.featureAllocation === "number") {
|
|
1479
2466
|
const wasExceeded = updatedCheck.featureUsageExceeded === true;
|
|
@@ -1503,6 +2490,9 @@ var Schematic = class {
|
|
|
1503
2490
|
this.notifyFlagValueListeners(flagKey, updatedCheck.value);
|
|
1504
2491
|
}
|
|
1505
2492
|
});
|
|
2493
|
+
if (dirty) {
|
|
2494
|
+
this.persistContextToCache(contextString(this.context));
|
|
2495
|
+
}
|
|
1506
2496
|
};
|
|
1507
2497
|
/**
|
|
1508
2498
|
* Event processing
|
|
@@ -1605,6 +2595,206 @@ var Schematic = class {
|
|
|
1605
2595
|
this.storage.setItem(anonymousIdKey, generatedAnonymousId);
|
|
1606
2596
|
return generatedAnonymousId;
|
|
1607
2597
|
};
|
|
2598
|
+
hasCachedValuesForContext = (contextStr) => {
|
|
2599
|
+
const cachedChecks = this.checks[contextStr];
|
|
2600
|
+
if (cachedChecks !== void 0 && Object.keys(cachedChecks).length > 0) {
|
|
2601
|
+
return true;
|
|
2602
|
+
}
|
|
2603
|
+
if (this.planChecks[contextStr] !== void 0) {
|
|
2604
|
+
return true;
|
|
2605
|
+
}
|
|
2606
|
+
const cachedCreditBalances = this.creditBalances[contextStr];
|
|
2607
|
+
return cachedCreditBalances !== void 0 && Object.keys(cachedCreditBalances).length > 0;
|
|
2608
|
+
};
|
|
2609
|
+
readFlagStateCache = () => {
|
|
2610
|
+
if (!this.persistFlagState || this.storage === void 0) {
|
|
2611
|
+
return null;
|
|
2612
|
+
}
|
|
2613
|
+
let raw;
|
|
2614
|
+
try {
|
|
2615
|
+
raw = this.storage.getItem(this.flagStateCacheKey);
|
|
2616
|
+
} catch (error) {
|
|
2617
|
+
this.debug("Failed to read flag state cache:", error);
|
|
2618
|
+
return null;
|
|
2619
|
+
}
|
|
2620
|
+
if (raw === null || raw === void 0) {
|
|
2621
|
+
return null;
|
|
2622
|
+
}
|
|
2623
|
+
let parsed;
|
|
2624
|
+
try {
|
|
2625
|
+
parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
2626
|
+
} catch (error) {
|
|
2627
|
+
this.debug("Flag state cache is not valid JSON, ignoring:", error);
|
|
2628
|
+
return null;
|
|
2629
|
+
}
|
|
2630
|
+
if (parsed === null || typeof parsed !== "object" || parsed.version !== cacheVersion || typeof parsed.contexts !== "object" || parsed.contexts === null) {
|
|
2631
|
+
this.debug(
|
|
2632
|
+
`Flag state cache invalid or version mismatch (expected ${cacheVersion}), ignoring`,
|
|
2633
|
+
{
|
|
2634
|
+
parsedType: typeof parsed,
|
|
2635
|
+
version: parsed?.version
|
|
2636
|
+
}
|
|
2637
|
+
);
|
|
2638
|
+
return null;
|
|
2639
|
+
}
|
|
2640
|
+
return parsed;
|
|
2641
|
+
};
|
|
2642
|
+
reviveCachedCheck = (raw) => {
|
|
2643
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
2644
|
+
const obj = raw;
|
|
2645
|
+
if (typeof obj.flag !== "string" || typeof obj.value !== "boolean" || typeof obj.reason !== "string") {
|
|
2646
|
+
return null;
|
|
2647
|
+
}
|
|
2648
|
+
const revived = { ...obj };
|
|
2649
|
+
if (typeof revived.featureUsageResetAt === "string") {
|
|
2650
|
+
const d = new Date(revived.featureUsageResetAt);
|
|
2651
|
+
revived.featureUsageResetAt = isNaN(d.getTime()) ? void 0 : d;
|
|
2652
|
+
}
|
|
2653
|
+
return revived;
|
|
2654
|
+
};
|
|
2655
|
+
reviveCachedPlan = (raw) => {
|
|
2656
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
2657
|
+
const obj = raw;
|
|
2658
|
+
if (typeof obj.id !== "string" || typeof obj.name !== "string") {
|
|
2659
|
+
return null;
|
|
2660
|
+
}
|
|
2661
|
+
const revived = { ...obj };
|
|
2662
|
+
if (typeof revived.trialEndDate === "string") {
|
|
2663
|
+
const d = new Date(revived.trialEndDate);
|
|
2664
|
+
revived.trialEndDate = isNaN(d.getTime()) ? void 0 : d;
|
|
2665
|
+
}
|
|
2666
|
+
return revived;
|
|
2667
|
+
};
|
|
2668
|
+
reviveCachedCreditBalances = (raw) => {
|
|
2669
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
2670
|
+
const revived = {};
|
|
2671
|
+
for (const [creditId, value] of Object.entries(
|
|
2672
|
+
raw
|
|
2673
|
+
)) {
|
|
2674
|
+
if (value === null || typeof value !== "object") continue;
|
|
2675
|
+
const obj = value;
|
|
2676
|
+
if (typeof obj.remaining !== "number" || typeof obj.reserved !== "number" || typeof obj.settled !== "number") {
|
|
2677
|
+
continue;
|
|
2678
|
+
}
|
|
2679
|
+
revived[creditId] = {
|
|
2680
|
+
remaining: obj.remaining,
|
|
2681
|
+
reserved: obj.reserved,
|
|
2682
|
+
settled: obj.settled
|
|
2683
|
+
};
|
|
2684
|
+
}
|
|
2685
|
+
return Object.keys(revived).length > 0 ? revived : null;
|
|
2686
|
+
};
|
|
2687
|
+
hydrateFlagStateFromCache = () => {
|
|
2688
|
+
const parsed = this.readFlagStateCache();
|
|
2689
|
+
if (parsed === null) return;
|
|
2690
|
+
const cutoff = Date.now() - this.flagStateCacheMaxAgeMs;
|
|
2691
|
+
const fresh = {};
|
|
2692
|
+
let contextsLoaded = 0;
|
|
2693
|
+
let contextsExpired = 0;
|
|
2694
|
+
for (const [contextStr, entry] of Object.entries(parsed.contexts)) {
|
|
2695
|
+
if (entry === null || typeof entry !== "object") continue;
|
|
2696
|
+
if (typeof entry.updatedAt !== "number") continue;
|
|
2697
|
+
if (entry.updatedAt < cutoff) {
|
|
2698
|
+
contextsExpired += 1;
|
|
2699
|
+
continue;
|
|
2700
|
+
}
|
|
2701
|
+
const revivedChecks = {};
|
|
2702
|
+
if (entry.checks !== null && typeof entry.checks === "object") {
|
|
2703
|
+
for (const [flagKey, rawCheck] of Object.entries(entry.checks)) {
|
|
2704
|
+
const revived = this.reviveCachedCheck(rawCheck);
|
|
2705
|
+
if (revived === null || revived.flag !== flagKey) continue;
|
|
2706
|
+
revivedChecks[flagKey] = revived;
|
|
2707
|
+
if (typeof revived.featureUsageEvent === "string") {
|
|
2708
|
+
this.updateFeatureUsageEventMap(revived);
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2711
|
+
if (Object.keys(revivedChecks).length > 0) {
|
|
2712
|
+
this.checks[contextStr] = revivedChecks;
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
let revivedPlan;
|
|
2716
|
+
if (entry.plan !== void 0 && entry.plan !== null) {
|
|
2717
|
+
const p = this.reviveCachedPlan(entry.plan);
|
|
2718
|
+
if (p !== null) {
|
|
2719
|
+
revivedPlan = p;
|
|
2720
|
+
this.planChecks[contextStr] = p;
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
let revivedCreditBalances;
|
|
2724
|
+
if (entry.creditBalances !== void 0 && entry.creditBalances !== null) {
|
|
2725
|
+
const balances = this.reviveCachedCreditBalances(entry.creditBalances);
|
|
2726
|
+
if (balances !== null) {
|
|
2727
|
+
revivedCreditBalances = balances;
|
|
2728
|
+
this.creditBalances[contextStr] = balances;
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
fresh[contextStr] = {
|
|
2732
|
+
checks: revivedChecks,
|
|
2733
|
+
plan: revivedPlan,
|
|
2734
|
+
creditBalances: revivedCreditBalances,
|
|
2735
|
+
updatedAt: entry.updatedAt
|
|
2736
|
+
};
|
|
2737
|
+
contextsLoaded += 1;
|
|
2738
|
+
}
|
|
2739
|
+
this.cachedFlagState = { version: cacheVersion, contexts: fresh };
|
|
2740
|
+
this.debug(
|
|
2741
|
+
`Hydrated flag state cache: ${contextsLoaded} loaded, ${contextsExpired} expired`
|
|
2742
|
+
);
|
|
2743
|
+
};
|
|
2744
|
+
persistContextToCache = (contextStr) => {
|
|
2745
|
+
const checksForContext = this.checks[contextStr];
|
|
2746
|
+
const planForContext = this.planChecks[contextStr];
|
|
2747
|
+
const creditBalancesForContext = this.creditBalances[contextStr];
|
|
2748
|
+
if (checksForContext === void 0 && planForContext === void 0 && creditBalancesForContext === void 0) {
|
|
2749
|
+
return;
|
|
2750
|
+
}
|
|
2751
|
+
if (this.cachedFlagState === null) {
|
|
2752
|
+
this.cachedFlagState = (this.persistFlagState ? this.readFlagStateCache() : null) ?? {
|
|
2753
|
+
version: cacheVersion,
|
|
2754
|
+
contexts: {}
|
|
2755
|
+
};
|
|
2756
|
+
}
|
|
2757
|
+
const cleanChecks = {};
|
|
2758
|
+
if (checksForContext !== void 0) {
|
|
2759
|
+
for (const [flagKey, check] of Object.entries(checksForContext)) {
|
|
2760
|
+
if (check !== void 0) cleanChecks[flagKey] = check;
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
this.cachedFlagState.contexts[contextStr] = {
|
|
2764
|
+
checks: cleanChecks,
|
|
2765
|
+
plan: planForContext,
|
|
2766
|
+
creditBalances: creditBalancesForContext,
|
|
2767
|
+
updatedAt: Date.now()
|
|
2768
|
+
};
|
|
2769
|
+
const entries = Object.entries(this.cachedFlagState.contexts);
|
|
2770
|
+
if (entries.length > flagStateCacheMaxContexts) {
|
|
2771
|
+
entries.sort((a, b) => b[1].updatedAt - a[1].updatedAt);
|
|
2772
|
+
const survivors = entries.slice(0, flagStateCacheMaxContexts);
|
|
2773
|
+
const survivorKeys = new Set(survivors.map(([k]) => k));
|
|
2774
|
+
for (const key of Object.keys(this.checks)) {
|
|
2775
|
+
if (!survivorKeys.has(key)) delete this.checks[key];
|
|
2776
|
+
}
|
|
2777
|
+
for (const key of Object.keys(this.planChecks)) {
|
|
2778
|
+
if (!survivorKeys.has(key)) delete this.planChecks[key];
|
|
2779
|
+
}
|
|
2780
|
+
for (const key of Object.keys(this.creditBalances)) {
|
|
2781
|
+
if (!survivorKeys.has(key)) delete this.creditBalances[key];
|
|
2782
|
+
}
|
|
2783
|
+
this.cachedFlagState = {
|
|
2784
|
+
version: cacheVersion,
|
|
2785
|
+
contexts: Object.fromEntries(survivors)
|
|
2786
|
+
};
|
|
2787
|
+
}
|
|
2788
|
+
if (!this.persistFlagState || this.storage === void 0) return;
|
|
2789
|
+
try {
|
|
2790
|
+
this.storage.setItem(
|
|
2791
|
+
this.flagStateCacheKey,
|
|
2792
|
+
JSON.stringify(this.cachedFlagState)
|
|
2793
|
+
);
|
|
2794
|
+
} catch (error) {
|
|
2795
|
+
this.debug("Failed to write flag state cache:", error);
|
|
2796
|
+
}
|
|
2797
|
+
};
|
|
1608
2798
|
handleEvent = (eventType, eventBody) => {
|
|
1609
2799
|
const event = {
|
|
1610
2800
|
api_key: this.apiKey,
|
|
@@ -1865,6 +3055,9 @@ var Schematic = class {
|
|
|
1865
3055
|
if (this.conn !== null) {
|
|
1866
3056
|
try {
|
|
1867
3057
|
const socket = await this.conn;
|
|
3058
|
+
if (this.currentWebSocket === socket) {
|
|
3059
|
+
this.currentWebSocket = null;
|
|
3060
|
+
}
|
|
1868
3061
|
if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
|
|
1869
3062
|
socket.close();
|
|
1870
3063
|
}
|
|
@@ -2030,6 +3223,7 @@ var Schematic = class {
|
|
|
2030
3223
|
this.debug(`Creating WebSocket connection ${connectionId} to ${wsUrl}`);
|
|
2031
3224
|
let timeoutId = null;
|
|
2032
3225
|
let isResolved = false;
|
|
3226
|
+
let didOpen = false;
|
|
2033
3227
|
timeoutId = setTimeout(() => {
|
|
2034
3228
|
if (!isResolved) {
|
|
2035
3229
|
isResolved = true;
|
|
@@ -2043,6 +3237,7 @@ var Schematic = class {
|
|
|
2043
3237
|
webSocket.onopen = () => {
|
|
2044
3238
|
if (isResolved) return;
|
|
2045
3239
|
isResolved = true;
|
|
3240
|
+
didOpen = true;
|
|
2046
3241
|
if (timeoutId !== null) {
|
|
2047
3242
|
clearTimeout(timeoutId);
|
|
2048
3243
|
}
|
|
@@ -2068,11 +3263,12 @@ var Schematic = class {
|
|
|
2068
3263
|
}
|
|
2069
3264
|
this.debug(`WebSocket connection ${connectionId} closed`);
|
|
2070
3265
|
this.conn = null;
|
|
3266
|
+
const wasCurrent = this.currentWebSocket === webSocket;
|
|
2071
3267
|
if (this.currentWebSocket === webSocket) {
|
|
2072
3268
|
this.currentWebSocket = null;
|
|
2073
3269
|
this.isConnecting = false;
|
|
2074
3270
|
}
|
|
2075
|
-
if (
|
|
3271
|
+
if (wasCurrent && didOpen && !this.wsIntentionalDisconnect && this.webSocketReconnect) {
|
|
2076
3272
|
this.attemptReconnect();
|
|
2077
3273
|
}
|
|
2078
3274
|
};
|
|
@@ -2168,6 +3364,16 @@ var Schematic = class {
|
|
|
2168
3364
|
const plan = this.planChecks[contextStr];
|
|
2169
3365
|
return plan;
|
|
2170
3366
|
};
|
|
3367
|
+
/** Get the company's lease-aware credit balances for the current context, keyed by credit ID */
|
|
3368
|
+
getCreditBalances = () => {
|
|
3369
|
+
const contextStr = contextString(this.context);
|
|
3370
|
+
return this.creditBalances[contextStr] ?? emptyCreditBalances;
|
|
3371
|
+
};
|
|
3372
|
+
/** Get the company's lease-aware balance for a single credit type in the current context */
|
|
3373
|
+
getCreditBalance = (creditId) => {
|
|
3374
|
+
const contextStr = contextString(this.context);
|
|
3375
|
+
return this.creditBalances[contextStr]?.[creditId];
|
|
3376
|
+
};
|
|
2171
3377
|
// flag checks state
|
|
2172
3378
|
getFlagCheck = (flagKey) => {
|
|
2173
3379
|
const contextStr = contextString(this.context);
|
|
@@ -2227,6 +3433,13 @@ var Schematic = class {
|
|
|
2227
3433
|
this.planListeners.delete(listener);
|
|
2228
3434
|
};
|
|
2229
3435
|
};
|
|
3436
|
+
/** Register an event listener that will be notified with the company's credit balances (keyed by credit ID) whenever they change */
|
|
3437
|
+
addCreditBalanceListener = (listener) => {
|
|
3438
|
+
this.creditBalanceListeners.add(listener);
|
|
3439
|
+
return () => {
|
|
3440
|
+
this.creditBalanceListeners.delete(listener);
|
|
3441
|
+
};
|
|
3442
|
+
};
|
|
2230
3443
|
notifyFlagCheckListeners = (flagKey, check) => {
|
|
2231
3444
|
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
2232
3445
|
if (listeners.size > 0) {
|
|
@@ -2290,6 +3503,17 @@ var Schematic = class {
|
|
|
2290
3503
|
});
|
|
2291
3504
|
});
|
|
2292
3505
|
};
|
|
3506
|
+
notifyCreditBalanceListeners = (value) => {
|
|
3507
|
+
const listeners = this.creditBalanceListeners ?? [];
|
|
3508
|
+
if (listeners.size > 0) {
|
|
3509
|
+
this.debug(`Notifying ${listeners.size} credit balance listeners`, {
|
|
3510
|
+
value
|
|
3511
|
+
});
|
|
3512
|
+
}
|
|
3513
|
+
listeners.forEach(
|
|
3514
|
+
(listener) => notifyCreditBalanceListener(listener, value)
|
|
3515
|
+
);
|
|
3516
|
+
};
|
|
2293
3517
|
};
|
|
2294
3518
|
var notifyPendingListener = (listener, value) => {
|
|
2295
3519
|
if (listener.length > 0) {
|
|
@@ -2319,4 +3543,11 @@ var notifyPlanListener = (listener, value) => {
|
|
|
2319
3543
|
listener();
|
|
2320
3544
|
}
|
|
2321
3545
|
};
|
|
3546
|
+
var notifyCreditBalanceListener = (listener, value) => {
|
|
3547
|
+
if (listener.length > 0) {
|
|
3548
|
+
listener(value);
|
|
3549
|
+
} else {
|
|
3550
|
+
listener();
|
|
3551
|
+
}
|
|
3552
|
+
};
|
|
2322
3553
|
/* @preserve */
|