@schematichq/schematic-js 1.4.0 → 1.5.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 +17 -0
- package/dist/schematic.browser.js +2 -2
- package/dist/schematic.cjs.js +649 -29
- package/dist/schematic.d.ts +160 -22
- package/dist/schematic.esm.js +649 -29
- package/package.json +15 -16
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)
|
|
@@ -573,6 +577,7 @@ __export(index_exports, {
|
|
|
573
577
|
CheckFlagReturnFromJSON: () => CheckFlagReturnFromJSON,
|
|
574
578
|
CheckFlagsResponseFromJSON: () => CheckFlagsResponseFromJSON,
|
|
575
579
|
CheckPlanReturnFromJSON: () => CheckPlanReturnFromJSON,
|
|
580
|
+
CreditBalancesFromJSON: () => CreditBalancesFromJSON,
|
|
576
581
|
DatastreamCompanyPlanFromJSON: () => DatastreamCompanyPlanFromJSON,
|
|
577
582
|
EventBodyFlagCheckToJSON: () => EventBodyFlagCheckToJSON,
|
|
578
583
|
RuleType: () => RuleType,
|
|
@@ -592,23 +597,18 @@ function unsafeStringify(arr, offset = 0) {
|
|
|
592
597
|
}
|
|
593
598
|
|
|
594
599
|
// node_modules/uuid/dist/rng.js
|
|
595
|
-
var getRandomValues;
|
|
596
600
|
var rnds8 = new Uint8Array(16);
|
|
597
601
|
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);
|
|
602
|
+
return crypto.getRandomValues(rnds8);
|
|
605
603
|
}
|
|
606
604
|
|
|
607
|
-
// node_modules/uuid/dist/native.js
|
|
608
|
-
var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
609
|
-
var native_default = { randomUUID };
|
|
610
|
-
|
|
611
605
|
// node_modules/uuid/dist/v4.js
|
|
606
|
+
function v4(options, buf, offset) {
|
|
607
|
+
if (!buf && !options && crypto.randomUUID) {
|
|
608
|
+
return crypto.randomUUID();
|
|
609
|
+
}
|
|
610
|
+
return _v4(options, buf, offset);
|
|
611
|
+
}
|
|
612
612
|
function _v4(options, buf, offset) {
|
|
613
613
|
options = options || {};
|
|
614
614
|
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
@@ -629,12 +629,6 @@ function _v4(options, buf, offset) {
|
|
|
629
629
|
}
|
|
630
630
|
return unsafeStringify(rnds);
|
|
631
631
|
}
|
|
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
632
|
var v4_default = v4;
|
|
639
633
|
|
|
640
634
|
// src/index.ts
|
|
@@ -648,6 +642,22 @@ function EntitlementValueTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
648
642
|
return json;
|
|
649
643
|
}
|
|
650
644
|
|
|
645
|
+
// src/types/api/models/MetricPeriodMonthReset.ts
|
|
646
|
+
function MetricPeriodMonthResetFromJSON(json) {
|
|
647
|
+
return MetricPeriodMonthResetFromJSONTyped(json, false);
|
|
648
|
+
}
|
|
649
|
+
function MetricPeriodMonthResetFromJSONTyped(json, ignoreDiscriminator) {
|
|
650
|
+
return json;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// src/types/api/models/MetricPeriod.ts
|
|
654
|
+
function MetricPeriodFromJSON(json) {
|
|
655
|
+
return MetricPeriodFromJSONTyped(json, false);
|
|
656
|
+
}
|
|
657
|
+
function MetricPeriodFromJSONTyped(json, ignoreDiscriminator) {
|
|
658
|
+
return json;
|
|
659
|
+
}
|
|
660
|
+
|
|
651
661
|
// src/types/api/models/FeatureEntitlement.ts
|
|
652
662
|
function FeatureEntitlementFromJSON(json) {
|
|
653
663
|
return FeatureEntitlementFromJSONTyped(json, false);
|
|
@@ -658,22 +668,34 @@ function FeatureEntitlementFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
658
668
|
}
|
|
659
669
|
return {
|
|
660
670
|
allocation: json["allocation"] == null ? void 0 : json["allocation"],
|
|
671
|
+
consumptionRate: json["consumption_rate"] == null ? void 0 : json["consumption_rate"],
|
|
661
672
|
creditId: json["credit_id"] == null ? void 0 : json["credit_id"],
|
|
662
673
|
creditRemaining: json["credit_remaining"] == null ? void 0 : json["credit_remaining"],
|
|
674
|
+
creditReserved: json["credit_reserved"] == null ? void 0 : json["credit_reserved"],
|
|
675
|
+
creditSettled: json["credit_settled"] == null ? void 0 : json["credit_settled"],
|
|
663
676
|
creditTotal: json["credit_total"] == null ? void 0 : json["credit_total"],
|
|
664
677
|
creditUsed: json["credit_used"] == null ? void 0 : json["credit_used"],
|
|
665
678
|
eventName: json["event_name"] == null ? void 0 : json["event_name"],
|
|
679
|
+
eventSubtype: json["event_subtype"] == null ? void 0 : json["event_subtype"],
|
|
666
680
|
featureId: json["feature_id"],
|
|
667
681
|
featureKey: json["feature_key"],
|
|
668
|
-
metricPeriod: json["metric_period"] == null ? void 0 : json["metric_period"],
|
|
682
|
+
metricPeriod: json["metric_period"] == null ? void 0 : MetricPeriodFromJSON(json["metric_period"]),
|
|
669
683
|
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"],
|
|
684
|
+
monthReset: json["month_reset"] == null ? void 0 : MetricPeriodMonthResetFromJSON(json["month_reset"]),
|
|
671
685
|
softLimit: json["soft_limit"] == null ? void 0 : json["soft_limit"],
|
|
672
686
|
usage: json["usage"] == null ? void 0 : json["usage"],
|
|
673
687
|
valueType: EntitlementValueTypeFromJSON(json["value_type"])
|
|
674
688
|
};
|
|
675
689
|
}
|
|
676
690
|
|
|
691
|
+
// src/types/api/models/RuleType.ts
|
|
692
|
+
function RuleTypeFromJSON(json) {
|
|
693
|
+
return RuleTypeFromJSONTyped(json, false);
|
|
694
|
+
}
|
|
695
|
+
function RuleTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
696
|
+
return json;
|
|
697
|
+
}
|
|
698
|
+
|
|
677
699
|
// src/types/api/models/CheckFlagResponseData.ts
|
|
678
700
|
function CheckFlagResponseDataFromJSON(json) {
|
|
679
701
|
return CheckFlagResponseDataFromJSONTyped(json, false);
|
|
@@ -689,13 +711,13 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
689
711
|
featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
|
|
690
712
|
featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
|
|
691
713
|
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"],
|
|
714
|
+
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : MetricPeriodFromJSON(json["feature_usage_period"]),
|
|
693
715
|
featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
|
|
694
716
|
flag: json["flag"],
|
|
695
717
|
flagId: json["flag_id"] == null ? void 0 : json["flag_id"],
|
|
696
718
|
reason: json["reason"],
|
|
697
719
|
ruleId: json["rule_id"] == null ? void 0 : json["rule_id"],
|
|
698
|
-
ruleType: json["rule_type"] == null ? void 0 : json["rule_type"],
|
|
720
|
+
ruleType: json["rule_type"] == null ? void 0 : RuleTypeFromJSON(json["rule_type"]),
|
|
699
721
|
userId: json["user_id"] == null ? void 0 : json["user_id"],
|
|
700
722
|
value: json["value"]
|
|
701
723
|
};
|
|
@@ -715,6 +737,272 @@ function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
715
737
|
};
|
|
716
738
|
}
|
|
717
739
|
|
|
740
|
+
// src/types/api/runtime.ts
|
|
741
|
+
var BASE_PATH = "https://api.schematichq.com".replace(/\/+$/, "");
|
|
742
|
+
var Configuration = class {
|
|
743
|
+
constructor(configuration = {}) {
|
|
744
|
+
this.configuration = configuration;
|
|
745
|
+
}
|
|
746
|
+
configuration;
|
|
747
|
+
set config(configuration) {
|
|
748
|
+
this.configuration = configuration;
|
|
749
|
+
}
|
|
750
|
+
get basePath() {
|
|
751
|
+
return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH;
|
|
752
|
+
}
|
|
753
|
+
get fetchApi() {
|
|
754
|
+
return this.configuration.fetchApi;
|
|
755
|
+
}
|
|
756
|
+
get middleware() {
|
|
757
|
+
return this.configuration.middleware || [];
|
|
758
|
+
}
|
|
759
|
+
get queryParamsStringify() {
|
|
760
|
+
return this.configuration.queryParamsStringify || querystring;
|
|
761
|
+
}
|
|
762
|
+
get username() {
|
|
763
|
+
return this.configuration.username;
|
|
764
|
+
}
|
|
765
|
+
get password() {
|
|
766
|
+
return this.configuration.password;
|
|
767
|
+
}
|
|
768
|
+
get apiKey() {
|
|
769
|
+
const apiKey = this.configuration.apiKey;
|
|
770
|
+
if (apiKey) {
|
|
771
|
+
return typeof apiKey === "function" ? apiKey : () => apiKey;
|
|
772
|
+
}
|
|
773
|
+
return void 0;
|
|
774
|
+
}
|
|
775
|
+
get accessToken() {
|
|
776
|
+
const accessToken = this.configuration.accessToken;
|
|
777
|
+
if (accessToken) {
|
|
778
|
+
return typeof accessToken === "function" ? accessToken : async () => accessToken;
|
|
779
|
+
}
|
|
780
|
+
return void 0;
|
|
781
|
+
}
|
|
782
|
+
get headers() {
|
|
783
|
+
return this.configuration.headers;
|
|
784
|
+
}
|
|
785
|
+
get credentials() {
|
|
786
|
+
return this.configuration.credentials;
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
var DefaultConfig = new Configuration();
|
|
790
|
+
var BaseAPI = class _BaseAPI {
|
|
791
|
+
constructor(configuration = DefaultConfig) {
|
|
792
|
+
this.configuration = configuration;
|
|
793
|
+
this.middleware = configuration.middleware;
|
|
794
|
+
}
|
|
795
|
+
configuration;
|
|
796
|
+
static jsonRegex = new RegExp(
|
|
797
|
+
"^(:?application/json|[^;/ ]+/[^;/ ]+[+]json)[ ]*(:?;.*)?$",
|
|
798
|
+
"i"
|
|
799
|
+
);
|
|
800
|
+
middleware;
|
|
801
|
+
withMiddleware(...middlewares) {
|
|
802
|
+
const next = this.clone();
|
|
803
|
+
next.middleware = next.middleware.concat(...middlewares);
|
|
804
|
+
return next;
|
|
805
|
+
}
|
|
806
|
+
withPreMiddleware(...preMiddlewares) {
|
|
807
|
+
const middlewares = preMiddlewares.map((pre) => ({ pre }));
|
|
808
|
+
return this.withMiddleware(...middlewares);
|
|
809
|
+
}
|
|
810
|
+
withPostMiddleware(...postMiddlewares) {
|
|
811
|
+
const middlewares = postMiddlewares.map((post) => ({ post }));
|
|
812
|
+
return this.withMiddleware(...middlewares);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Check if the given MIME is a JSON MIME.
|
|
816
|
+
* JSON MIME examples:
|
|
817
|
+
* application/json
|
|
818
|
+
* application/json; charset=UTF8
|
|
819
|
+
* APPLICATION/JSON
|
|
820
|
+
* application/vnd.company+json
|
|
821
|
+
* @param mime - MIME (Multipurpose Internet Mail Extensions)
|
|
822
|
+
* @return True if the given MIME is JSON, false otherwise.
|
|
823
|
+
*/
|
|
824
|
+
isJsonMime(mime) {
|
|
825
|
+
if (!mime) {
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
return _BaseAPI.jsonRegex.test(mime);
|
|
829
|
+
}
|
|
830
|
+
async request(context, initOverrides) {
|
|
831
|
+
const { url, init } = await this.createFetchParams(context, initOverrides);
|
|
832
|
+
const response = await this.fetchApi(url, init);
|
|
833
|
+
if (response && response.status >= 200 && response.status < 300) {
|
|
834
|
+
return response;
|
|
835
|
+
}
|
|
836
|
+
throw new ResponseError(response, "Response returned an error code");
|
|
837
|
+
}
|
|
838
|
+
async createFetchParams(context, initOverrides) {
|
|
839
|
+
let url = this.configuration.basePath + context.path;
|
|
840
|
+
if (context.query !== void 0 && Object.keys(context.query).length !== 0) {
|
|
841
|
+
url += "?" + this.configuration.queryParamsStringify(context.query);
|
|
842
|
+
}
|
|
843
|
+
const headers = Object.assign(
|
|
844
|
+
{},
|
|
845
|
+
this.configuration.headers,
|
|
846
|
+
context.headers
|
|
847
|
+
);
|
|
848
|
+
Object.keys(headers).forEach(
|
|
849
|
+
(key) => headers[key] === void 0 ? delete headers[key] : {}
|
|
850
|
+
);
|
|
851
|
+
const initOverrideFn = typeof initOverrides === "function" ? initOverrides : async () => initOverrides;
|
|
852
|
+
const initParams = {
|
|
853
|
+
method: context.method,
|
|
854
|
+
headers,
|
|
855
|
+
body: context.body,
|
|
856
|
+
credentials: this.configuration.credentials
|
|
857
|
+
};
|
|
858
|
+
const overriddenInit = {
|
|
859
|
+
...initParams,
|
|
860
|
+
...await initOverrideFn({
|
|
861
|
+
init: initParams,
|
|
862
|
+
context
|
|
863
|
+
})
|
|
864
|
+
};
|
|
865
|
+
let body;
|
|
866
|
+
if (isFormData(overriddenInit.body) || overriddenInit.body instanceof URLSearchParams || isBlob(overriddenInit.body)) {
|
|
867
|
+
body = overriddenInit.body;
|
|
868
|
+
} else if (this.isJsonMime(headers["Content-Type"])) {
|
|
869
|
+
body = JSON.stringify(overriddenInit.body);
|
|
870
|
+
} else {
|
|
871
|
+
body = overriddenInit.body;
|
|
872
|
+
}
|
|
873
|
+
const init = {
|
|
874
|
+
...overriddenInit,
|
|
875
|
+
body
|
|
876
|
+
};
|
|
877
|
+
return { url, init };
|
|
878
|
+
}
|
|
879
|
+
fetchApi = async (url, init) => {
|
|
880
|
+
let fetchParams = { url, init };
|
|
881
|
+
for (const middleware of this.middleware) {
|
|
882
|
+
if (middleware.pre) {
|
|
883
|
+
fetchParams = await middleware.pre({
|
|
884
|
+
fetch: this.fetchApi,
|
|
885
|
+
...fetchParams
|
|
886
|
+
}) || fetchParams;
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
let response = void 0;
|
|
890
|
+
try {
|
|
891
|
+
response = await (this.configuration.fetchApi || fetch)(
|
|
892
|
+
fetchParams.url,
|
|
893
|
+
fetchParams.init
|
|
894
|
+
);
|
|
895
|
+
} catch (e) {
|
|
896
|
+
for (const middleware of this.middleware) {
|
|
897
|
+
if (middleware.onError) {
|
|
898
|
+
response = await middleware.onError({
|
|
899
|
+
fetch: this.fetchApi,
|
|
900
|
+
url: fetchParams.url,
|
|
901
|
+
init: fetchParams.init,
|
|
902
|
+
error: e,
|
|
903
|
+
response: response ? response.clone() : void 0
|
|
904
|
+
}) || response;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
if (response === void 0) {
|
|
908
|
+
if (e instanceof Error) {
|
|
909
|
+
throw new FetchError(
|
|
910
|
+
e,
|
|
911
|
+
"The request failed and the interceptors did not return an alternative response"
|
|
912
|
+
);
|
|
913
|
+
} else {
|
|
914
|
+
throw e;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
for (const middleware of this.middleware) {
|
|
919
|
+
if (middleware.post) {
|
|
920
|
+
response = await middleware.post({
|
|
921
|
+
fetch: this.fetchApi,
|
|
922
|
+
url: fetchParams.url,
|
|
923
|
+
init: fetchParams.init,
|
|
924
|
+
response: response.clone()
|
|
925
|
+
}) || response;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
return response;
|
|
929
|
+
};
|
|
930
|
+
/**
|
|
931
|
+
* Create a shallow clone of `this` by constructing a new instance
|
|
932
|
+
* and then shallow cloning data members.
|
|
933
|
+
*/
|
|
934
|
+
clone() {
|
|
935
|
+
const constructor = this.constructor;
|
|
936
|
+
const next = new constructor(this.configuration);
|
|
937
|
+
next.middleware = this.middleware.slice();
|
|
938
|
+
return next;
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
function isBlob(value) {
|
|
942
|
+
return typeof Blob !== "undefined" && value instanceof Blob;
|
|
943
|
+
}
|
|
944
|
+
function isFormData(value) {
|
|
945
|
+
return typeof FormData !== "undefined" && value instanceof FormData;
|
|
946
|
+
}
|
|
947
|
+
var ResponseError = class extends Error {
|
|
948
|
+
constructor(response, msg) {
|
|
949
|
+
super(msg);
|
|
950
|
+
this.response = response;
|
|
951
|
+
}
|
|
952
|
+
response;
|
|
953
|
+
name = "ResponseError";
|
|
954
|
+
};
|
|
955
|
+
var FetchError = class extends Error {
|
|
956
|
+
constructor(cause, msg) {
|
|
957
|
+
super(msg);
|
|
958
|
+
this.cause = cause;
|
|
959
|
+
}
|
|
960
|
+
cause;
|
|
961
|
+
name = "FetchError";
|
|
962
|
+
};
|
|
963
|
+
function querystring(params, prefix = "") {
|
|
964
|
+
return Object.keys(params).map((key) => querystringSingleKey(key, params[key], prefix)).filter((part) => part.length > 0).join("&");
|
|
965
|
+
}
|
|
966
|
+
function querystringSingleKey(key, value, keyPrefix = "") {
|
|
967
|
+
const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key);
|
|
968
|
+
if (value instanceof Array) {
|
|
969
|
+
const multiValue = value.map((singleValue) => encodeURIComponent(String(singleValue))).join(`&${encodeURIComponent(fullKey)}=`);
|
|
970
|
+
return `${encodeURIComponent(fullKey)}=${multiValue}`;
|
|
971
|
+
}
|
|
972
|
+
if (value instanceof Set) {
|
|
973
|
+
const valueAsArray = Array.from(value);
|
|
974
|
+
return querystringSingleKey(key, valueAsArray, keyPrefix);
|
|
975
|
+
}
|
|
976
|
+
if (value instanceof Date) {
|
|
977
|
+
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`;
|
|
978
|
+
}
|
|
979
|
+
if (value instanceof Object) {
|
|
980
|
+
return querystring(value, fullKey);
|
|
981
|
+
}
|
|
982
|
+
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
|
|
983
|
+
}
|
|
984
|
+
function mapValues(data, fn) {
|
|
985
|
+
return Object.keys(data).reduce(
|
|
986
|
+
(acc, key) => ({ ...acc, [key]: fn(data[key]) }),
|
|
987
|
+
{}
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
// src/types/api/models/CompanyCreditBalance.ts
|
|
992
|
+
function CompanyCreditBalanceFromJSON(json) {
|
|
993
|
+
return CompanyCreditBalanceFromJSONTyped(json, false);
|
|
994
|
+
}
|
|
995
|
+
function CompanyCreditBalanceFromJSONTyped(json, ignoreDiscriminator) {
|
|
996
|
+
if (json == null) {
|
|
997
|
+
return json;
|
|
998
|
+
}
|
|
999
|
+
return {
|
|
1000
|
+
remaining: json["remaining"],
|
|
1001
|
+
reserved: json["reserved"],
|
|
1002
|
+
settled: json["settled"]
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
|
|
718
1006
|
// src/types/api/models/TrialStatus.ts
|
|
719
1007
|
var TrialStatus = {
|
|
720
1008
|
Active: "active",
|
|
@@ -753,6 +1041,7 @@ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
753
1041
|
return json;
|
|
754
1042
|
}
|
|
755
1043
|
return {
|
|
1044
|
+
creditBalances: json["credit_balances"] == null ? void 0 : mapValues(json["credit_balances"], CompanyCreditBalanceFromJSON),
|
|
756
1045
|
flags: json["flags"].map(CheckFlagResponseDataFromJSON),
|
|
757
1046
|
plan: json["plan"] == null ? void 0 : DatastreamCompanyPlanFromJSON(json["plan"])
|
|
758
1047
|
};
|
|
@@ -841,7 +1130,10 @@ var CheckFlagReturnFromJSON = (json) => {
|
|
|
841
1130
|
return {
|
|
842
1131
|
featureUsageExceeded,
|
|
843
1132
|
companyId: companyId == null ? void 0 : companyId,
|
|
1133
|
+
creditId: entitlement?.creditId == null ? void 0 : entitlement.creditId,
|
|
844
1134
|
creditRemaining: entitlement?.creditRemaining == null ? void 0 : entitlement.creditRemaining,
|
|
1135
|
+
creditReserved: entitlement?.creditReserved == null ? void 0 : entitlement.creditReserved,
|
|
1136
|
+
creditSettled: entitlement?.creditSettled == null ? void 0 : entitlement.creditSettled,
|
|
845
1137
|
error: error == null ? void 0 : error,
|
|
846
1138
|
featureAllocation: resolvedAllocation == null ? void 0 : resolvedAllocation,
|
|
847
1139
|
featureUsage: resolvedUsage == null ? void 0 : resolvedUsage,
|
|
@@ -867,6 +1159,24 @@ var CheckPlanReturnFromJSON = (json) => {
|
|
|
867
1159
|
trialStatus: trialStatus == null ? void 0 : trialStatus
|
|
868
1160
|
};
|
|
869
1161
|
};
|
|
1162
|
+
var CreditBalancesFromJSON = (json) => {
|
|
1163
|
+
if (json == null || typeof json !== "object") {
|
|
1164
|
+
return {};
|
|
1165
|
+
}
|
|
1166
|
+
const balances = {};
|
|
1167
|
+
for (const [creditId, raw] of Object.entries(json)) {
|
|
1168
|
+
if (raw == null || typeof raw !== "object") continue;
|
|
1169
|
+
const { remaining, reserved, settled } = CompanyCreditBalanceFromJSON(raw);
|
|
1170
|
+
if (typeof remaining !== "number" || typeof reserved !== "number" || typeof settled !== "number") {
|
|
1171
|
+
continue;
|
|
1172
|
+
}
|
|
1173
|
+
balances[creditId] = { remaining, reserved, settled };
|
|
1174
|
+
}
|
|
1175
|
+
return balances;
|
|
1176
|
+
};
|
|
1177
|
+
|
|
1178
|
+
// src/cacheVersion.ts
|
|
1179
|
+
var cacheVersion = "bb56e75d";
|
|
870
1180
|
|
|
871
1181
|
// src/utils.ts
|
|
872
1182
|
function contextString(context) {
|
|
@@ -885,10 +1195,14 @@ function contextString(context) {
|
|
|
885
1195
|
}
|
|
886
1196
|
|
|
887
1197
|
// src/version.ts
|
|
888
|
-
var version = "1.
|
|
1198
|
+
var version = "1.5.0";
|
|
889
1199
|
|
|
890
1200
|
// src/index.ts
|
|
891
1201
|
var anonymousIdKey = "schematicId";
|
|
1202
|
+
var flagStateCachePrefix = "schematicCache";
|
|
1203
|
+
var flagStateCacheMaxContexts = 10;
|
|
1204
|
+
var flagStateCacheDefaultMaxAgeMs = 7 * 24 * 60 * 60 * 1e3;
|
|
1205
|
+
var emptyCreditBalances = Object.freeze({});
|
|
892
1206
|
var Schematic = class {
|
|
893
1207
|
additionalHeaders = {};
|
|
894
1208
|
apiKey;
|
|
@@ -905,11 +1219,17 @@ var Schematic = class {
|
|
|
905
1219
|
isPending = true;
|
|
906
1220
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
907
1221
|
planListeners = /* @__PURE__ */ new Set();
|
|
1222
|
+
creditBalanceListeners = /* @__PURE__ */ new Set();
|
|
908
1223
|
storage;
|
|
1224
|
+
persistFlagState = true;
|
|
1225
|
+
flagStateCacheKey;
|
|
1226
|
+
flagStateCacheMaxAgeMs = flagStateCacheDefaultMaxAgeMs;
|
|
1227
|
+
cachedFlagState = null;
|
|
909
1228
|
useWebSocket = false;
|
|
910
1229
|
checks = {};
|
|
911
1230
|
featureUsageEventMap = {};
|
|
912
1231
|
planChecks = {};
|
|
1232
|
+
creditBalances = {};
|
|
913
1233
|
webSocketUrl = "wss://api.schematichq.com";
|
|
914
1234
|
webSocketConnectionTimeout = 1e4;
|
|
915
1235
|
webSocketReconnect = true;
|
|
@@ -938,11 +1258,16 @@ var Schematic = class {
|
|
|
938
1258
|
fallbackCheckCache = {};
|
|
939
1259
|
constructor(apiKey, options) {
|
|
940
1260
|
this.apiKey = apiKey;
|
|
1261
|
+
this.flagStateCacheKey = `${flagStateCachePrefix}:${apiKey}`;
|
|
941
1262
|
this.eventQueue = [];
|
|
942
1263
|
this.contextDependentEventQueue = [];
|
|
943
1264
|
this.useWebSocket = options?.useWebSocket ?? false;
|
|
944
1265
|
this.debugEnabled = options?.debug ?? false;
|
|
945
1266
|
this.offlineEnabled = options?.offline ?? false;
|
|
1267
|
+
this.persistFlagState = options?.persistFlagState ?? true;
|
|
1268
|
+
if (typeof options?.flagStateCacheMaxAgeMs === "number" && options.flagStateCacheMaxAgeMs > 0) {
|
|
1269
|
+
this.flagStateCacheMaxAgeMs = options.flagStateCacheMaxAgeMs;
|
|
1270
|
+
}
|
|
946
1271
|
if (typeof window !== "undefined" && typeof window.location !== "undefined") {
|
|
947
1272
|
const params = new URLSearchParams(window.location.search);
|
|
948
1273
|
const debugParam = params.get("schematic_debug");
|
|
@@ -975,6 +1300,7 @@ var Schematic = class {
|
|
|
975
1300
|
} catch {
|
|
976
1301
|
}
|
|
977
1302
|
}
|
|
1303
|
+
this.hydrateFlagStateFromCache();
|
|
978
1304
|
if (options?.apiUrl !== void 0) {
|
|
979
1305
|
this.apiUrl = options.apiUrl;
|
|
980
1306
|
}
|
|
@@ -1268,6 +1594,29 @@ var Schematic = class {
|
|
|
1268
1594
|
});
|
|
1269
1595
|
this.notifyPlanListeners(plan);
|
|
1270
1596
|
}
|
|
1597
|
+
if (message.credit_balances !== void 0 && message.credit_balances !== null) {
|
|
1598
|
+
const contextStr = contextString(context);
|
|
1599
|
+
const updates = CreditBalancesFromJSON(message.credit_balances);
|
|
1600
|
+
const previous = this.creditBalances[contextStr] ?? {};
|
|
1601
|
+
let changed = false;
|
|
1602
|
+
const merged = { ...previous };
|
|
1603
|
+
for (const [creditId, next] of Object.entries(updates)) {
|
|
1604
|
+
const current = previous[creditId];
|
|
1605
|
+
if (current === void 0 || current.remaining !== next.remaining || current.reserved !== next.reserved || current.settled !== next.settled) {
|
|
1606
|
+
merged[creditId] = next;
|
|
1607
|
+
changed = true;
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
if (changed) {
|
|
1611
|
+
this.creditBalances[contextStr] = merged;
|
|
1612
|
+
this.debug(
|
|
1613
|
+
`WebSocket credit balance update received. Notifying listeners`,
|
|
1614
|
+
{ creditBalances: merged }
|
|
1615
|
+
);
|
|
1616
|
+
this.notifyCreditBalanceListeners(merged);
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
this.persistContextToCache(contextString(context));
|
|
1271
1620
|
this.flushContextDependentEventQueue();
|
|
1272
1621
|
this.setIsPending(false);
|
|
1273
1622
|
};
|
|
@@ -1375,7 +1724,32 @@ var Schematic = class {
|
|
|
1375
1724
|
return;
|
|
1376
1725
|
}
|
|
1377
1726
|
try {
|
|
1378
|
-
|
|
1727
|
+
const newContextStr = contextString(context);
|
|
1728
|
+
const cacheHit = this.hasCachedValuesForContext(newContextStr);
|
|
1729
|
+
if (cacheHit) {
|
|
1730
|
+
this.debug(
|
|
1731
|
+
`setContext: cache hit for context, pre-resolving from cached values`
|
|
1732
|
+
);
|
|
1733
|
+
this.context = context;
|
|
1734
|
+
this.flushContextDependentEventQueue();
|
|
1735
|
+
this.setIsPending(false);
|
|
1736
|
+
const cachedChecks = this.checks[newContextStr] ?? {};
|
|
1737
|
+
for (const [flagKey, check] of Object.entries(cachedChecks)) {
|
|
1738
|
+
if (check === void 0) continue;
|
|
1739
|
+
this.notifyFlagCheckListeners(flagKey, check);
|
|
1740
|
+
this.notifyFlagValueListeners(flagKey, check.value);
|
|
1741
|
+
}
|
|
1742
|
+
const cachedPlan = this.planChecks[newContextStr];
|
|
1743
|
+
if (cachedPlan !== void 0) {
|
|
1744
|
+
this.notifyPlanListeners(cachedPlan);
|
|
1745
|
+
}
|
|
1746
|
+
const cachedCreditBalances = this.creditBalances[newContextStr];
|
|
1747
|
+
if (cachedCreditBalances !== void 0) {
|
|
1748
|
+
this.notifyCreditBalanceListeners(cachedCreditBalances);
|
|
1749
|
+
}
|
|
1750
|
+
} else {
|
|
1751
|
+
this.setIsPending(true);
|
|
1752
|
+
}
|
|
1379
1753
|
if (!this.conn) {
|
|
1380
1754
|
if (this.isConnecting) {
|
|
1381
1755
|
this.debug(
|
|
@@ -1386,7 +1760,7 @@ var Schematic = class {
|
|
|
1386
1760
|
}
|
|
1387
1761
|
if (this.conn !== null) {
|
|
1388
1762
|
const socket2 = await this.conn;
|
|
1389
|
-
await this.wsSendMessage(socket2, context);
|
|
1763
|
+
await this.wsSendMessage(socket2, context, cacheHit);
|
|
1390
1764
|
return;
|
|
1391
1765
|
}
|
|
1392
1766
|
}
|
|
@@ -1402,7 +1776,7 @@ var Schematic = class {
|
|
|
1402
1776
|
this.conn = this.wsConnect();
|
|
1403
1777
|
const socket2 = await this.conn;
|
|
1404
1778
|
this.isConnecting = false;
|
|
1405
|
-
await this.wsSendMessage(socket2, context);
|
|
1779
|
+
await this.wsSendMessage(socket2, context, cacheHit);
|
|
1406
1780
|
return;
|
|
1407
1781
|
} catch (error) {
|
|
1408
1782
|
this.isConnecting = false;
|
|
@@ -1410,7 +1784,7 @@ var Schematic = class {
|
|
|
1410
1784
|
}
|
|
1411
1785
|
}
|
|
1412
1786
|
const socket = await this.conn;
|
|
1413
|
-
await this.wsSendMessage(socket, context);
|
|
1787
|
+
await this.wsSendMessage(socket, context, cacheHit);
|
|
1414
1788
|
} catch (error) {
|
|
1415
1789
|
console.warn("Failed to establish WebSocket connection:", error);
|
|
1416
1790
|
this.context = context;
|
|
@@ -1470,10 +1844,12 @@ var Schematic = class {
|
|
|
1470
1844
|
`Optimistically updating feature usage for event: ${eventName}`,
|
|
1471
1845
|
{ quantity }
|
|
1472
1846
|
);
|
|
1847
|
+
let dirty = false;
|
|
1473
1848
|
Object.entries(flagsForEvent).forEach(([flagKey, check]) => {
|
|
1474
1849
|
if (check === void 0) return;
|
|
1475
1850
|
const updatedCheck = { ...check };
|
|
1476
1851
|
if (typeof updatedCheck.featureUsage === "number") {
|
|
1852
|
+
dirty = true;
|
|
1477
1853
|
updatedCheck.featureUsage += quantity;
|
|
1478
1854
|
if (typeof updatedCheck.featureAllocation === "number") {
|
|
1479
1855
|
const wasExceeded = updatedCheck.featureUsageExceeded === true;
|
|
@@ -1503,6 +1879,9 @@ var Schematic = class {
|
|
|
1503
1879
|
this.notifyFlagValueListeners(flagKey, updatedCheck.value);
|
|
1504
1880
|
}
|
|
1505
1881
|
});
|
|
1882
|
+
if (dirty) {
|
|
1883
|
+
this.persistContextToCache(contextString(this.context));
|
|
1884
|
+
}
|
|
1506
1885
|
};
|
|
1507
1886
|
/**
|
|
1508
1887
|
* Event processing
|
|
@@ -1605,6 +1984,206 @@ var Schematic = class {
|
|
|
1605
1984
|
this.storage.setItem(anonymousIdKey, generatedAnonymousId);
|
|
1606
1985
|
return generatedAnonymousId;
|
|
1607
1986
|
};
|
|
1987
|
+
hasCachedValuesForContext = (contextStr) => {
|
|
1988
|
+
const cachedChecks = this.checks[contextStr];
|
|
1989
|
+
if (cachedChecks !== void 0 && Object.keys(cachedChecks).length > 0) {
|
|
1990
|
+
return true;
|
|
1991
|
+
}
|
|
1992
|
+
if (this.planChecks[contextStr] !== void 0) {
|
|
1993
|
+
return true;
|
|
1994
|
+
}
|
|
1995
|
+
const cachedCreditBalances = this.creditBalances[contextStr];
|
|
1996
|
+
return cachedCreditBalances !== void 0 && Object.keys(cachedCreditBalances).length > 0;
|
|
1997
|
+
};
|
|
1998
|
+
readFlagStateCache = () => {
|
|
1999
|
+
if (!this.persistFlagState || this.storage === void 0) {
|
|
2000
|
+
return null;
|
|
2001
|
+
}
|
|
2002
|
+
let raw;
|
|
2003
|
+
try {
|
|
2004
|
+
raw = this.storage.getItem(this.flagStateCacheKey);
|
|
2005
|
+
} catch (error) {
|
|
2006
|
+
this.debug("Failed to read flag state cache:", error);
|
|
2007
|
+
return null;
|
|
2008
|
+
}
|
|
2009
|
+
if (raw === null || raw === void 0) {
|
|
2010
|
+
return null;
|
|
2011
|
+
}
|
|
2012
|
+
let parsed;
|
|
2013
|
+
try {
|
|
2014
|
+
parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
2015
|
+
} catch (error) {
|
|
2016
|
+
this.debug("Flag state cache is not valid JSON, ignoring:", error);
|
|
2017
|
+
return null;
|
|
2018
|
+
}
|
|
2019
|
+
if (parsed === null || typeof parsed !== "object" || parsed.version !== cacheVersion || typeof parsed.contexts !== "object" || parsed.contexts === null) {
|
|
2020
|
+
this.debug(
|
|
2021
|
+
`Flag state cache invalid or version mismatch (expected ${cacheVersion}), ignoring`,
|
|
2022
|
+
{
|
|
2023
|
+
parsedType: typeof parsed,
|
|
2024
|
+
version: parsed?.version
|
|
2025
|
+
}
|
|
2026
|
+
);
|
|
2027
|
+
return null;
|
|
2028
|
+
}
|
|
2029
|
+
return parsed;
|
|
2030
|
+
};
|
|
2031
|
+
reviveCachedCheck = (raw) => {
|
|
2032
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
2033
|
+
const obj = raw;
|
|
2034
|
+
if (typeof obj.flag !== "string" || typeof obj.value !== "boolean" || typeof obj.reason !== "string") {
|
|
2035
|
+
return null;
|
|
2036
|
+
}
|
|
2037
|
+
const revived = { ...obj };
|
|
2038
|
+
if (typeof revived.featureUsageResetAt === "string") {
|
|
2039
|
+
const d = new Date(revived.featureUsageResetAt);
|
|
2040
|
+
revived.featureUsageResetAt = isNaN(d.getTime()) ? void 0 : d;
|
|
2041
|
+
}
|
|
2042
|
+
return revived;
|
|
2043
|
+
};
|
|
2044
|
+
reviveCachedPlan = (raw) => {
|
|
2045
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
2046
|
+
const obj = raw;
|
|
2047
|
+
if (typeof obj.id !== "string" || typeof obj.name !== "string") {
|
|
2048
|
+
return null;
|
|
2049
|
+
}
|
|
2050
|
+
const revived = { ...obj };
|
|
2051
|
+
if (typeof revived.trialEndDate === "string") {
|
|
2052
|
+
const d = new Date(revived.trialEndDate);
|
|
2053
|
+
revived.trialEndDate = isNaN(d.getTime()) ? void 0 : d;
|
|
2054
|
+
}
|
|
2055
|
+
return revived;
|
|
2056
|
+
};
|
|
2057
|
+
reviveCachedCreditBalances = (raw) => {
|
|
2058
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
2059
|
+
const revived = {};
|
|
2060
|
+
for (const [creditId, value] of Object.entries(
|
|
2061
|
+
raw
|
|
2062
|
+
)) {
|
|
2063
|
+
if (value === null || typeof value !== "object") continue;
|
|
2064
|
+
const obj = value;
|
|
2065
|
+
if (typeof obj.remaining !== "number" || typeof obj.reserved !== "number" || typeof obj.settled !== "number") {
|
|
2066
|
+
continue;
|
|
2067
|
+
}
|
|
2068
|
+
revived[creditId] = {
|
|
2069
|
+
remaining: obj.remaining,
|
|
2070
|
+
reserved: obj.reserved,
|
|
2071
|
+
settled: obj.settled
|
|
2072
|
+
};
|
|
2073
|
+
}
|
|
2074
|
+
return Object.keys(revived).length > 0 ? revived : null;
|
|
2075
|
+
};
|
|
2076
|
+
hydrateFlagStateFromCache = () => {
|
|
2077
|
+
const parsed = this.readFlagStateCache();
|
|
2078
|
+
if (parsed === null) return;
|
|
2079
|
+
const cutoff = Date.now() - this.flagStateCacheMaxAgeMs;
|
|
2080
|
+
const fresh = {};
|
|
2081
|
+
let contextsLoaded = 0;
|
|
2082
|
+
let contextsExpired = 0;
|
|
2083
|
+
for (const [contextStr, entry] of Object.entries(parsed.contexts)) {
|
|
2084
|
+
if (entry === null || typeof entry !== "object") continue;
|
|
2085
|
+
if (typeof entry.updatedAt !== "number") continue;
|
|
2086
|
+
if (entry.updatedAt < cutoff) {
|
|
2087
|
+
contextsExpired += 1;
|
|
2088
|
+
continue;
|
|
2089
|
+
}
|
|
2090
|
+
const revivedChecks = {};
|
|
2091
|
+
if (entry.checks !== null && typeof entry.checks === "object") {
|
|
2092
|
+
for (const [flagKey, rawCheck] of Object.entries(entry.checks)) {
|
|
2093
|
+
const revived = this.reviveCachedCheck(rawCheck);
|
|
2094
|
+
if (revived === null || revived.flag !== flagKey) continue;
|
|
2095
|
+
revivedChecks[flagKey] = revived;
|
|
2096
|
+
if (typeof revived.featureUsageEvent === "string") {
|
|
2097
|
+
this.updateFeatureUsageEventMap(revived);
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
if (Object.keys(revivedChecks).length > 0) {
|
|
2101
|
+
this.checks[contextStr] = revivedChecks;
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
let revivedPlan;
|
|
2105
|
+
if (entry.plan !== void 0 && entry.plan !== null) {
|
|
2106
|
+
const p = this.reviveCachedPlan(entry.plan);
|
|
2107
|
+
if (p !== null) {
|
|
2108
|
+
revivedPlan = p;
|
|
2109
|
+
this.planChecks[contextStr] = p;
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
let revivedCreditBalances;
|
|
2113
|
+
if (entry.creditBalances !== void 0 && entry.creditBalances !== null) {
|
|
2114
|
+
const balances = this.reviveCachedCreditBalances(entry.creditBalances);
|
|
2115
|
+
if (balances !== null) {
|
|
2116
|
+
revivedCreditBalances = balances;
|
|
2117
|
+
this.creditBalances[contextStr] = balances;
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
fresh[contextStr] = {
|
|
2121
|
+
checks: revivedChecks,
|
|
2122
|
+
plan: revivedPlan,
|
|
2123
|
+
creditBalances: revivedCreditBalances,
|
|
2124
|
+
updatedAt: entry.updatedAt
|
|
2125
|
+
};
|
|
2126
|
+
contextsLoaded += 1;
|
|
2127
|
+
}
|
|
2128
|
+
this.cachedFlagState = { version: cacheVersion, contexts: fresh };
|
|
2129
|
+
this.debug(
|
|
2130
|
+
`Hydrated flag state cache: ${contextsLoaded} loaded, ${contextsExpired} expired`
|
|
2131
|
+
);
|
|
2132
|
+
};
|
|
2133
|
+
persistContextToCache = (contextStr) => {
|
|
2134
|
+
const checksForContext = this.checks[contextStr];
|
|
2135
|
+
const planForContext = this.planChecks[contextStr];
|
|
2136
|
+
const creditBalancesForContext = this.creditBalances[contextStr];
|
|
2137
|
+
if (checksForContext === void 0 && planForContext === void 0 && creditBalancesForContext === void 0) {
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
if (this.cachedFlagState === null) {
|
|
2141
|
+
this.cachedFlagState = (this.persistFlagState ? this.readFlagStateCache() : null) ?? {
|
|
2142
|
+
version: cacheVersion,
|
|
2143
|
+
contexts: {}
|
|
2144
|
+
};
|
|
2145
|
+
}
|
|
2146
|
+
const cleanChecks = {};
|
|
2147
|
+
if (checksForContext !== void 0) {
|
|
2148
|
+
for (const [flagKey, check] of Object.entries(checksForContext)) {
|
|
2149
|
+
if (check !== void 0) cleanChecks[flagKey] = check;
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
this.cachedFlagState.contexts[contextStr] = {
|
|
2153
|
+
checks: cleanChecks,
|
|
2154
|
+
plan: planForContext,
|
|
2155
|
+
creditBalances: creditBalancesForContext,
|
|
2156
|
+
updatedAt: Date.now()
|
|
2157
|
+
};
|
|
2158
|
+
const entries = Object.entries(this.cachedFlagState.contexts);
|
|
2159
|
+
if (entries.length > flagStateCacheMaxContexts) {
|
|
2160
|
+
entries.sort((a, b) => b[1].updatedAt - a[1].updatedAt);
|
|
2161
|
+
const survivors = entries.slice(0, flagStateCacheMaxContexts);
|
|
2162
|
+
const survivorKeys = new Set(survivors.map(([k]) => k));
|
|
2163
|
+
for (const key of Object.keys(this.checks)) {
|
|
2164
|
+
if (!survivorKeys.has(key)) delete this.checks[key];
|
|
2165
|
+
}
|
|
2166
|
+
for (const key of Object.keys(this.planChecks)) {
|
|
2167
|
+
if (!survivorKeys.has(key)) delete this.planChecks[key];
|
|
2168
|
+
}
|
|
2169
|
+
for (const key of Object.keys(this.creditBalances)) {
|
|
2170
|
+
if (!survivorKeys.has(key)) delete this.creditBalances[key];
|
|
2171
|
+
}
|
|
2172
|
+
this.cachedFlagState = {
|
|
2173
|
+
version: cacheVersion,
|
|
2174
|
+
contexts: Object.fromEntries(survivors)
|
|
2175
|
+
};
|
|
2176
|
+
}
|
|
2177
|
+
if (!this.persistFlagState || this.storage === void 0) return;
|
|
2178
|
+
try {
|
|
2179
|
+
this.storage.setItem(
|
|
2180
|
+
this.flagStateCacheKey,
|
|
2181
|
+
JSON.stringify(this.cachedFlagState)
|
|
2182
|
+
);
|
|
2183
|
+
} catch (error) {
|
|
2184
|
+
this.debug("Failed to write flag state cache:", error);
|
|
2185
|
+
}
|
|
2186
|
+
};
|
|
1608
2187
|
handleEvent = (eventType, eventBody) => {
|
|
1609
2188
|
const event = {
|
|
1610
2189
|
api_key: this.apiKey,
|
|
@@ -1865,6 +2444,9 @@ var Schematic = class {
|
|
|
1865
2444
|
if (this.conn !== null) {
|
|
1866
2445
|
try {
|
|
1867
2446
|
const socket = await this.conn;
|
|
2447
|
+
if (this.currentWebSocket === socket) {
|
|
2448
|
+
this.currentWebSocket = null;
|
|
2449
|
+
}
|
|
1868
2450
|
if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
|
|
1869
2451
|
socket.close();
|
|
1870
2452
|
}
|
|
@@ -2030,6 +2612,7 @@ var Schematic = class {
|
|
|
2030
2612
|
this.debug(`Creating WebSocket connection ${connectionId} to ${wsUrl}`);
|
|
2031
2613
|
let timeoutId = null;
|
|
2032
2614
|
let isResolved = false;
|
|
2615
|
+
let didOpen = false;
|
|
2033
2616
|
timeoutId = setTimeout(() => {
|
|
2034
2617
|
if (!isResolved) {
|
|
2035
2618
|
isResolved = true;
|
|
@@ -2043,6 +2626,7 @@ var Schematic = class {
|
|
|
2043
2626
|
webSocket.onopen = () => {
|
|
2044
2627
|
if (isResolved) return;
|
|
2045
2628
|
isResolved = true;
|
|
2629
|
+
didOpen = true;
|
|
2046
2630
|
if (timeoutId !== null) {
|
|
2047
2631
|
clearTimeout(timeoutId);
|
|
2048
2632
|
}
|
|
@@ -2068,11 +2652,12 @@ var Schematic = class {
|
|
|
2068
2652
|
}
|
|
2069
2653
|
this.debug(`WebSocket connection ${connectionId} closed`);
|
|
2070
2654
|
this.conn = null;
|
|
2655
|
+
const wasCurrent = this.currentWebSocket === webSocket;
|
|
2071
2656
|
if (this.currentWebSocket === webSocket) {
|
|
2072
2657
|
this.currentWebSocket = null;
|
|
2073
2658
|
this.isConnecting = false;
|
|
2074
2659
|
}
|
|
2075
|
-
if (
|
|
2660
|
+
if (wasCurrent && didOpen && !this.wsIntentionalDisconnect && this.webSocketReconnect) {
|
|
2076
2661
|
this.attemptReconnect();
|
|
2077
2662
|
}
|
|
2078
2663
|
};
|
|
@@ -2168,6 +2753,16 @@ var Schematic = class {
|
|
|
2168
2753
|
const plan = this.planChecks[contextStr];
|
|
2169
2754
|
return plan;
|
|
2170
2755
|
};
|
|
2756
|
+
/** Get the company's lease-aware credit balances for the current context, keyed by credit ID */
|
|
2757
|
+
getCreditBalances = () => {
|
|
2758
|
+
const contextStr = contextString(this.context);
|
|
2759
|
+
return this.creditBalances[contextStr] ?? emptyCreditBalances;
|
|
2760
|
+
};
|
|
2761
|
+
/** Get the company's lease-aware balance for a single credit type in the current context */
|
|
2762
|
+
getCreditBalance = (creditId) => {
|
|
2763
|
+
const contextStr = contextString(this.context);
|
|
2764
|
+
return this.creditBalances[contextStr]?.[creditId];
|
|
2765
|
+
};
|
|
2171
2766
|
// flag checks state
|
|
2172
2767
|
getFlagCheck = (flagKey) => {
|
|
2173
2768
|
const contextStr = contextString(this.context);
|
|
@@ -2227,6 +2822,13 @@ var Schematic = class {
|
|
|
2227
2822
|
this.planListeners.delete(listener);
|
|
2228
2823
|
};
|
|
2229
2824
|
};
|
|
2825
|
+
/** Register an event listener that will be notified with the company's credit balances (keyed by credit ID) whenever they change */
|
|
2826
|
+
addCreditBalanceListener = (listener) => {
|
|
2827
|
+
this.creditBalanceListeners.add(listener);
|
|
2828
|
+
return () => {
|
|
2829
|
+
this.creditBalanceListeners.delete(listener);
|
|
2830
|
+
};
|
|
2831
|
+
};
|
|
2230
2832
|
notifyFlagCheckListeners = (flagKey, check) => {
|
|
2231
2833
|
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
2232
2834
|
if (listeners.size > 0) {
|
|
@@ -2290,6 +2892,17 @@ var Schematic = class {
|
|
|
2290
2892
|
});
|
|
2291
2893
|
});
|
|
2292
2894
|
};
|
|
2895
|
+
notifyCreditBalanceListeners = (value) => {
|
|
2896
|
+
const listeners = this.creditBalanceListeners ?? [];
|
|
2897
|
+
if (listeners.size > 0) {
|
|
2898
|
+
this.debug(`Notifying ${listeners.size} credit balance listeners`, {
|
|
2899
|
+
value
|
|
2900
|
+
});
|
|
2901
|
+
}
|
|
2902
|
+
listeners.forEach(
|
|
2903
|
+
(listener) => notifyCreditBalanceListener(listener, value)
|
|
2904
|
+
);
|
|
2905
|
+
};
|
|
2293
2906
|
};
|
|
2294
2907
|
var notifyPendingListener = (listener, value) => {
|
|
2295
2908
|
if (listener.length > 0) {
|
|
@@ -2319,4 +2932,11 @@ var notifyPlanListener = (listener, value) => {
|
|
|
2319
2932
|
listener();
|
|
2320
2933
|
}
|
|
2321
2934
|
};
|
|
2935
|
+
var notifyCreditBalanceListener = (listener, value) => {
|
|
2936
|
+
if (listener.length > 0) {
|
|
2937
|
+
listener(value);
|
|
2938
|
+
} else {
|
|
2939
|
+
listener();
|
|
2940
|
+
}
|
|
2941
|
+
};
|
|
2322
2942
|
/* @preserve */
|