@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.esm.js
CHANGED
|
@@ -5,7 +5,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
5
5
|
var __getProtoOf = Object.getPrototypeOf;
|
|
6
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
7
|
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
-
|
|
8
|
+
try {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
} catch (e) {
|
|
11
|
+
throw mod = 0, e;
|
|
12
|
+
}
|
|
9
13
|
};
|
|
10
14
|
var __copyProps = (to, from, except, desc) => {
|
|
11
15
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -570,23 +574,18 @@ function unsafeStringify(arr, offset = 0) {
|
|
|
570
574
|
}
|
|
571
575
|
|
|
572
576
|
// node_modules/uuid/dist/rng.js
|
|
573
|
-
var getRandomValues;
|
|
574
577
|
var rnds8 = new Uint8Array(16);
|
|
575
578
|
function rng() {
|
|
576
|
-
|
|
577
|
-
if (typeof crypto === "undefined" || !crypto.getRandomValues) {
|
|
578
|
-
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
|
579
|
-
}
|
|
580
|
-
getRandomValues = crypto.getRandomValues.bind(crypto);
|
|
581
|
-
}
|
|
582
|
-
return getRandomValues(rnds8);
|
|
579
|
+
return crypto.getRandomValues(rnds8);
|
|
583
580
|
}
|
|
584
581
|
|
|
585
|
-
// node_modules/uuid/dist/native.js
|
|
586
|
-
var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
587
|
-
var native_default = { randomUUID };
|
|
588
|
-
|
|
589
582
|
// node_modules/uuid/dist/v4.js
|
|
583
|
+
function v4(options, buf, offset) {
|
|
584
|
+
if (!buf && !options && crypto.randomUUID) {
|
|
585
|
+
return crypto.randomUUID();
|
|
586
|
+
}
|
|
587
|
+
return _v4(options, buf, offset);
|
|
588
|
+
}
|
|
590
589
|
function _v4(options, buf, offset) {
|
|
591
590
|
options = options || {};
|
|
592
591
|
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
@@ -607,12 +606,6 @@ function _v4(options, buf, offset) {
|
|
|
607
606
|
}
|
|
608
607
|
return unsafeStringify(rnds);
|
|
609
608
|
}
|
|
610
|
-
function v4(options, buf, offset) {
|
|
611
|
-
if (native_default.randomUUID && !buf && !options) {
|
|
612
|
-
return native_default.randomUUID();
|
|
613
|
-
}
|
|
614
|
-
return _v4(options, buf, offset);
|
|
615
|
-
}
|
|
616
609
|
var v4_default = v4;
|
|
617
610
|
|
|
618
611
|
// src/index.ts
|
|
@@ -626,6 +619,22 @@ function EntitlementValueTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
626
619
|
return json;
|
|
627
620
|
}
|
|
628
621
|
|
|
622
|
+
// src/types/api/models/MetricPeriodMonthReset.ts
|
|
623
|
+
function MetricPeriodMonthResetFromJSON(json) {
|
|
624
|
+
return MetricPeriodMonthResetFromJSONTyped(json, false);
|
|
625
|
+
}
|
|
626
|
+
function MetricPeriodMonthResetFromJSONTyped(json, ignoreDiscriminator) {
|
|
627
|
+
return json;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// src/types/api/models/MetricPeriod.ts
|
|
631
|
+
function MetricPeriodFromJSON(json) {
|
|
632
|
+
return MetricPeriodFromJSONTyped(json, false);
|
|
633
|
+
}
|
|
634
|
+
function MetricPeriodFromJSONTyped(json, ignoreDiscriminator) {
|
|
635
|
+
return json;
|
|
636
|
+
}
|
|
637
|
+
|
|
629
638
|
// src/types/api/models/FeatureEntitlement.ts
|
|
630
639
|
function FeatureEntitlementFromJSON(json) {
|
|
631
640
|
return FeatureEntitlementFromJSONTyped(json, false);
|
|
@@ -636,22 +645,34 @@ function FeatureEntitlementFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
636
645
|
}
|
|
637
646
|
return {
|
|
638
647
|
allocation: json["allocation"] == null ? void 0 : json["allocation"],
|
|
648
|
+
consumptionRate: json["consumption_rate"] == null ? void 0 : json["consumption_rate"],
|
|
639
649
|
creditId: json["credit_id"] == null ? void 0 : json["credit_id"],
|
|
640
650
|
creditRemaining: json["credit_remaining"] == null ? void 0 : json["credit_remaining"],
|
|
651
|
+
creditReserved: json["credit_reserved"] == null ? void 0 : json["credit_reserved"],
|
|
652
|
+
creditSettled: json["credit_settled"] == null ? void 0 : json["credit_settled"],
|
|
641
653
|
creditTotal: json["credit_total"] == null ? void 0 : json["credit_total"],
|
|
642
654
|
creditUsed: json["credit_used"] == null ? void 0 : json["credit_used"],
|
|
643
655
|
eventName: json["event_name"] == null ? void 0 : json["event_name"],
|
|
656
|
+
eventSubtype: json["event_subtype"] == null ? void 0 : json["event_subtype"],
|
|
644
657
|
featureId: json["feature_id"],
|
|
645
658
|
featureKey: json["feature_key"],
|
|
646
|
-
metricPeriod: json["metric_period"] == null ? void 0 : json["metric_period"],
|
|
659
|
+
metricPeriod: json["metric_period"] == null ? void 0 : MetricPeriodFromJSON(json["metric_period"]),
|
|
647
660
|
metricResetAt: json["metric_reset_at"] == null ? void 0 : new Date(json["metric_reset_at"]),
|
|
648
|
-
monthReset: json["month_reset"] == null ? void 0 : json["month_reset"],
|
|
661
|
+
monthReset: json["month_reset"] == null ? void 0 : MetricPeriodMonthResetFromJSON(json["month_reset"]),
|
|
649
662
|
softLimit: json["soft_limit"] == null ? void 0 : json["soft_limit"],
|
|
650
663
|
usage: json["usage"] == null ? void 0 : json["usage"],
|
|
651
664
|
valueType: EntitlementValueTypeFromJSON(json["value_type"])
|
|
652
665
|
};
|
|
653
666
|
}
|
|
654
667
|
|
|
668
|
+
// src/types/api/models/RuleType.ts
|
|
669
|
+
function RuleTypeFromJSON(json) {
|
|
670
|
+
return RuleTypeFromJSONTyped(json, false);
|
|
671
|
+
}
|
|
672
|
+
function RuleTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
673
|
+
return json;
|
|
674
|
+
}
|
|
675
|
+
|
|
655
676
|
// src/types/api/models/CheckFlagResponseData.ts
|
|
656
677
|
function CheckFlagResponseDataFromJSON(json) {
|
|
657
678
|
return CheckFlagResponseDataFromJSONTyped(json, false);
|
|
@@ -667,13 +688,13 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
667
688
|
featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
|
|
668
689
|
featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
|
|
669
690
|
featureUsageEvent: json["feature_usage_event"] == null ? void 0 : json["feature_usage_event"],
|
|
670
|
-
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
|
|
691
|
+
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : MetricPeriodFromJSON(json["feature_usage_period"]),
|
|
671
692
|
featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
|
|
672
693
|
flag: json["flag"],
|
|
673
694
|
flagId: json["flag_id"] == null ? void 0 : json["flag_id"],
|
|
674
695
|
reason: json["reason"],
|
|
675
696
|
ruleId: json["rule_id"] == null ? void 0 : json["rule_id"],
|
|
676
|
-
ruleType: json["rule_type"] == null ? void 0 : json["rule_type"],
|
|
697
|
+
ruleType: json["rule_type"] == null ? void 0 : RuleTypeFromJSON(json["rule_type"]),
|
|
677
698
|
userId: json["user_id"] == null ? void 0 : json["user_id"],
|
|
678
699
|
value: json["value"]
|
|
679
700
|
};
|
|
@@ -693,6 +714,272 @@ function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
693
714
|
};
|
|
694
715
|
}
|
|
695
716
|
|
|
717
|
+
// src/types/api/runtime.ts
|
|
718
|
+
var BASE_PATH = "https://api.schematichq.com".replace(/\/+$/, "");
|
|
719
|
+
var Configuration = class {
|
|
720
|
+
constructor(configuration = {}) {
|
|
721
|
+
this.configuration = configuration;
|
|
722
|
+
}
|
|
723
|
+
configuration;
|
|
724
|
+
set config(configuration) {
|
|
725
|
+
this.configuration = configuration;
|
|
726
|
+
}
|
|
727
|
+
get basePath() {
|
|
728
|
+
return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH;
|
|
729
|
+
}
|
|
730
|
+
get fetchApi() {
|
|
731
|
+
return this.configuration.fetchApi;
|
|
732
|
+
}
|
|
733
|
+
get middleware() {
|
|
734
|
+
return this.configuration.middleware || [];
|
|
735
|
+
}
|
|
736
|
+
get queryParamsStringify() {
|
|
737
|
+
return this.configuration.queryParamsStringify || querystring;
|
|
738
|
+
}
|
|
739
|
+
get username() {
|
|
740
|
+
return this.configuration.username;
|
|
741
|
+
}
|
|
742
|
+
get password() {
|
|
743
|
+
return this.configuration.password;
|
|
744
|
+
}
|
|
745
|
+
get apiKey() {
|
|
746
|
+
const apiKey = this.configuration.apiKey;
|
|
747
|
+
if (apiKey) {
|
|
748
|
+
return typeof apiKey === "function" ? apiKey : () => apiKey;
|
|
749
|
+
}
|
|
750
|
+
return void 0;
|
|
751
|
+
}
|
|
752
|
+
get accessToken() {
|
|
753
|
+
const accessToken = this.configuration.accessToken;
|
|
754
|
+
if (accessToken) {
|
|
755
|
+
return typeof accessToken === "function" ? accessToken : async () => accessToken;
|
|
756
|
+
}
|
|
757
|
+
return void 0;
|
|
758
|
+
}
|
|
759
|
+
get headers() {
|
|
760
|
+
return this.configuration.headers;
|
|
761
|
+
}
|
|
762
|
+
get credentials() {
|
|
763
|
+
return this.configuration.credentials;
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
var DefaultConfig = new Configuration();
|
|
767
|
+
var BaseAPI = class _BaseAPI {
|
|
768
|
+
constructor(configuration = DefaultConfig) {
|
|
769
|
+
this.configuration = configuration;
|
|
770
|
+
this.middleware = configuration.middleware;
|
|
771
|
+
}
|
|
772
|
+
configuration;
|
|
773
|
+
static jsonRegex = new RegExp(
|
|
774
|
+
"^(:?application/json|[^;/ ]+/[^;/ ]+[+]json)[ ]*(:?;.*)?$",
|
|
775
|
+
"i"
|
|
776
|
+
);
|
|
777
|
+
middleware;
|
|
778
|
+
withMiddleware(...middlewares) {
|
|
779
|
+
const next = this.clone();
|
|
780
|
+
next.middleware = next.middleware.concat(...middlewares);
|
|
781
|
+
return next;
|
|
782
|
+
}
|
|
783
|
+
withPreMiddleware(...preMiddlewares) {
|
|
784
|
+
const middlewares = preMiddlewares.map((pre) => ({ pre }));
|
|
785
|
+
return this.withMiddleware(...middlewares);
|
|
786
|
+
}
|
|
787
|
+
withPostMiddleware(...postMiddlewares) {
|
|
788
|
+
const middlewares = postMiddlewares.map((post) => ({ post }));
|
|
789
|
+
return this.withMiddleware(...middlewares);
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Check if the given MIME is a JSON MIME.
|
|
793
|
+
* JSON MIME examples:
|
|
794
|
+
* application/json
|
|
795
|
+
* application/json; charset=UTF8
|
|
796
|
+
* APPLICATION/JSON
|
|
797
|
+
* application/vnd.company+json
|
|
798
|
+
* @param mime - MIME (Multipurpose Internet Mail Extensions)
|
|
799
|
+
* @return True if the given MIME is JSON, false otherwise.
|
|
800
|
+
*/
|
|
801
|
+
isJsonMime(mime) {
|
|
802
|
+
if (!mime) {
|
|
803
|
+
return false;
|
|
804
|
+
}
|
|
805
|
+
return _BaseAPI.jsonRegex.test(mime);
|
|
806
|
+
}
|
|
807
|
+
async request(context, initOverrides) {
|
|
808
|
+
const { url, init } = await this.createFetchParams(context, initOverrides);
|
|
809
|
+
const response = await this.fetchApi(url, init);
|
|
810
|
+
if (response && response.status >= 200 && response.status < 300) {
|
|
811
|
+
return response;
|
|
812
|
+
}
|
|
813
|
+
throw new ResponseError(response, "Response returned an error code");
|
|
814
|
+
}
|
|
815
|
+
async createFetchParams(context, initOverrides) {
|
|
816
|
+
let url = this.configuration.basePath + context.path;
|
|
817
|
+
if (context.query !== void 0 && Object.keys(context.query).length !== 0) {
|
|
818
|
+
url += "?" + this.configuration.queryParamsStringify(context.query);
|
|
819
|
+
}
|
|
820
|
+
const headers = Object.assign(
|
|
821
|
+
{},
|
|
822
|
+
this.configuration.headers,
|
|
823
|
+
context.headers
|
|
824
|
+
);
|
|
825
|
+
Object.keys(headers).forEach(
|
|
826
|
+
(key) => headers[key] === void 0 ? delete headers[key] : {}
|
|
827
|
+
);
|
|
828
|
+
const initOverrideFn = typeof initOverrides === "function" ? initOverrides : async () => initOverrides;
|
|
829
|
+
const initParams = {
|
|
830
|
+
method: context.method,
|
|
831
|
+
headers,
|
|
832
|
+
body: context.body,
|
|
833
|
+
credentials: this.configuration.credentials
|
|
834
|
+
};
|
|
835
|
+
const overriddenInit = {
|
|
836
|
+
...initParams,
|
|
837
|
+
...await initOverrideFn({
|
|
838
|
+
init: initParams,
|
|
839
|
+
context
|
|
840
|
+
})
|
|
841
|
+
};
|
|
842
|
+
let body;
|
|
843
|
+
if (isFormData(overriddenInit.body) || overriddenInit.body instanceof URLSearchParams || isBlob(overriddenInit.body)) {
|
|
844
|
+
body = overriddenInit.body;
|
|
845
|
+
} else if (this.isJsonMime(headers["Content-Type"])) {
|
|
846
|
+
body = JSON.stringify(overriddenInit.body);
|
|
847
|
+
} else {
|
|
848
|
+
body = overriddenInit.body;
|
|
849
|
+
}
|
|
850
|
+
const init = {
|
|
851
|
+
...overriddenInit,
|
|
852
|
+
body
|
|
853
|
+
};
|
|
854
|
+
return { url, init };
|
|
855
|
+
}
|
|
856
|
+
fetchApi = async (url, init) => {
|
|
857
|
+
let fetchParams = { url, init };
|
|
858
|
+
for (const middleware of this.middleware) {
|
|
859
|
+
if (middleware.pre) {
|
|
860
|
+
fetchParams = await middleware.pre({
|
|
861
|
+
fetch: this.fetchApi,
|
|
862
|
+
...fetchParams
|
|
863
|
+
}) || fetchParams;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
let response = void 0;
|
|
867
|
+
try {
|
|
868
|
+
response = await (this.configuration.fetchApi || fetch)(
|
|
869
|
+
fetchParams.url,
|
|
870
|
+
fetchParams.init
|
|
871
|
+
);
|
|
872
|
+
} catch (e) {
|
|
873
|
+
for (const middleware of this.middleware) {
|
|
874
|
+
if (middleware.onError) {
|
|
875
|
+
response = await middleware.onError({
|
|
876
|
+
fetch: this.fetchApi,
|
|
877
|
+
url: fetchParams.url,
|
|
878
|
+
init: fetchParams.init,
|
|
879
|
+
error: e,
|
|
880
|
+
response: response ? response.clone() : void 0
|
|
881
|
+
}) || response;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
if (response === void 0) {
|
|
885
|
+
if (e instanceof Error) {
|
|
886
|
+
throw new FetchError(
|
|
887
|
+
e,
|
|
888
|
+
"The request failed and the interceptors did not return an alternative response"
|
|
889
|
+
);
|
|
890
|
+
} else {
|
|
891
|
+
throw e;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
for (const middleware of this.middleware) {
|
|
896
|
+
if (middleware.post) {
|
|
897
|
+
response = await middleware.post({
|
|
898
|
+
fetch: this.fetchApi,
|
|
899
|
+
url: fetchParams.url,
|
|
900
|
+
init: fetchParams.init,
|
|
901
|
+
response: response.clone()
|
|
902
|
+
}) || response;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
return response;
|
|
906
|
+
};
|
|
907
|
+
/**
|
|
908
|
+
* Create a shallow clone of `this` by constructing a new instance
|
|
909
|
+
* and then shallow cloning data members.
|
|
910
|
+
*/
|
|
911
|
+
clone() {
|
|
912
|
+
const constructor = this.constructor;
|
|
913
|
+
const next = new constructor(this.configuration);
|
|
914
|
+
next.middleware = this.middleware.slice();
|
|
915
|
+
return next;
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
function isBlob(value) {
|
|
919
|
+
return typeof Blob !== "undefined" && value instanceof Blob;
|
|
920
|
+
}
|
|
921
|
+
function isFormData(value) {
|
|
922
|
+
return typeof FormData !== "undefined" && value instanceof FormData;
|
|
923
|
+
}
|
|
924
|
+
var ResponseError = class extends Error {
|
|
925
|
+
constructor(response, msg) {
|
|
926
|
+
super(msg);
|
|
927
|
+
this.response = response;
|
|
928
|
+
}
|
|
929
|
+
response;
|
|
930
|
+
name = "ResponseError";
|
|
931
|
+
};
|
|
932
|
+
var FetchError = class extends Error {
|
|
933
|
+
constructor(cause, msg) {
|
|
934
|
+
super(msg);
|
|
935
|
+
this.cause = cause;
|
|
936
|
+
}
|
|
937
|
+
cause;
|
|
938
|
+
name = "FetchError";
|
|
939
|
+
};
|
|
940
|
+
function querystring(params, prefix = "") {
|
|
941
|
+
return Object.keys(params).map((key) => querystringSingleKey(key, params[key], prefix)).filter((part) => part.length > 0).join("&");
|
|
942
|
+
}
|
|
943
|
+
function querystringSingleKey(key, value, keyPrefix = "") {
|
|
944
|
+
const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key);
|
|
945
|
+
if (value instanceof Array) {
|
|
946
|
+
const multiValue = value.map((singleValue) => encodeURIComponent(String(singleValue))).join(`&${encodeURIComponent(fullKey)}=`);
|
|
947
|
+
return `${encodeURIComponent(fullKey)}=${multiValue}`;
|
|
948
|
+
}
|
|
949
|
+
if (value instanceof Set) {
|
|
950
|
+
const valueAsArray = Array.from(value);
|
|
951
|
+
return querystringSingleKey(key, valueAsArray, keyPrefix);
|
|
952
|
+
}
|
|
953
|
+
if (value instanceof Date) {
|
|
954
|
+
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`;
|
|
955
|
+
}
|
|
956
|
+
if (value instanceof Object) {
|
|
957
|
+
return querystring(value, fullKey);
|
|
958
|
+
}
|
|
959
|
+
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
|
|
960
|
+
}
|
|
961
|
+
function mapValues(data, fn) {
|
|
962
|
+
return Object.keys(data).reduce(
|
|
963
|
+
(acc, key) => ({ ...acc, [key]: fn(data[key]) }),
|
|
964
|
+
{}
|
|
965
|
+
);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// src/types/api/models/CompanyCreditBalance.ts
|
|
969
|
+
function CompanyCreditBalanceFromJSON(json) {
|
|
970
|
+
return CompanyCreditBalanceFromJSONTyped(json, false);
|
|
971
|
+
}
|
|
972
|
+
function CompanyCreditBalanceFromJSONTyped(json, ignoreDiscriminator) {
|
|
973
|
+
if (json == null) {
|
|
974
|
+
return json;
|
|
975
|
+
}
|
|
976
|
+
return {
|
|
977
|
+
remaining: json["remaining"],
|
|
978
|
+
reserved: json["reserved"],
|
|
979
|
+
settled: json["settled"]
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
|
|
696
983
|
// src/types/api/models/TrialStatus.ts
|
|
697
984
|
var TrialStatus = {
|
|
698
985
|
Active: "active",
|
|
@@ -731,6 +1018,7 @@ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
731
1018
|
return json;
|
|
732
1019
|
}
|
|
733
1020
|
return {
|
|
1021
|
+
creditBalances: json["credit_balances"] == null ? void 0 : mapValues(json["credit_balances"], CompanyCreditBalanceFromJSON),
|
|
734
1022
|
flags: json["flags"].map(CheckFlagResponseDataFromJSON),
|
|
735
1023
|
plan: json["plan"] == null ? void 0 : DatastreamCompanyPlanFromJSON(json["plan"])
|
|
736
1024
|
};
|
|
@@ -819,7 +1107,10 @@ var CheckFlagReturnFromJSON = (json) => {
|
|
|
819
1107
|
return {
|
|
820
1108
|
featureUsageExceeded,
|
|
821
1109
|
companyId: companyId == null ? void 0 : companyId,
|
|
1110
|
+
creditId: entitlement?.creditId == null ? void 0 : entitlement.creditId,
|
|
822
1111
|
creditRemaining: entitlement?.creditRemaining == null ? void 0 : entitlement.creditRemaining,
|
|
1112
|
+
creditReserved: entitlement?.creditReserved == null ? void 0 : entitlement.creditReserved,
|
|
1113
|
+
creditSettled: entitlement?.creditSettled == null ? void 0 : entitlement.creditSettled,
|
|
823
1114
|
error: error == null ? void 0 : error,
|
|
824
1115
|
featureAllocation: resolvedAllocation == null ? void 0 : resolvedAllocation,
|
|
825
1116
|
featureUsage: resolvedUsage == null ? void 0 : resolvedUsage,
|
|
@@ -845,6 +1136,24 @@ var CheckPlanReturnFromJSON = (json) => {
|
|
|
845
1136
|
trialStatus: trialStatus == null ? void 0 : trialStatus
|
|
846
1137
|
};
|
|
847
1138
|
};
|
|
1139
|
+
var CreditBalancesFromJSON = (json) => {
|
|
1140
|
+
if (json == null || typeof json !== "object") {
|
|
1141
|
+
return {};
|
|
1142
|
+
}
|
|
1143
|
+
const balances = {};
|
|
1144
|
+
for (const [creditId, raw] of Object.entries(json)) {
|
|
1145
|
+
if (raw == null || typeof raw !== "object") continue;
|
|
1146
|
+
const { remaining, reserved, settled } = CompanyCreditBalanceFromJSON(raw);
|
|
1147
|
+
if (typeof remaining !== "number" || typeof reserved !== "number" || typeof settled !== "number") {
|
|
1148
|
+
continue;
|
|
1149
|
+
}
|
|
1150
|
+
balances[creditId] = { remaining, reserved, settled };
|
|
1151
|
+
}
|
|
1152
|
+
return balances;
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1155
|
+
// src/cacheVersion.ts
|
|
1156
|
+
var cacheVersion = "bb56e75d";
|
|
848
1157
|
|
|
849
1158
|
// src/utils.ts
|
|
850
1159
|
function contextString(context) {
|
|
@@ -863,10 +1172,14 @@ function contextString(context) {
|
|
|
863
1172
|
}
|
|
864
1173
|
|
|
865
1174
|
// src/version.ts
|
|
866
|
-
var version = "1.
|
|
1175
|
+
var version = "1.5.0";
|
|
867
1176
|
|
|
868
1177
|
// src/index.ts
|
|
869
1178
|
var anonymousIdKey = "schematicId";
|
|
1179
|
+
var flagStateCachePrefix = "schematicCache";
|
|
1180
|
+
var flagStateCacheMaxContexts = 10;
|
|
1181
|
+
var flagStateCacheDefaultMaxAgeMs = 7 * 24 * 60 * 60 * 1e3;
|
|
1182
|
+
var emptyCreditBalances = Object.freeze({});
|
|
870
1183
|
var Schematic = class {
|
|
871
1184
|
additionalHeaders = {};
|
|
872
1185
|
apiKey;
|
|
@@ -883,11 +1196,17 @@ var Schematic = class {
|
|
|
883
1196
|
isPending = true;
|
|
884
1197
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
885
1198
|
planListeners = /* @__PURE__ */ new Set();
|
|
1199
|
+
creditBalanceListeners = /* @__PURE__ */ new Set();
|
|
886
1200
|
storage;
|
|
1201
|
+
persistFlagState = true;
|
|
1202
|
+
flagStateCacheKey;
|
|
1203
|
+
flagStateCacheMaxAgeMs = flagStateCacheDefaultMaxAgeMs;
|
|
1204
|
+
cachedFlagState = null;
|
|
887
1205
|
useWebSocket = false;
|
|
888
1206
|
checks = {};
|
|
889
1207
|
featureUsageEventMap = {};
|
|
890
1208
|
planChecks = {};
|
|
1209
|
+
creditBalances = {};
|
|
891
1210
|
webSocketUrl = "wss://api.schematichq.com";
|
|
892
1211
|
webSocketConnectionTimeout = 1e4;
|
|
893
1212
|
webSocketReconnect = true;
|
|
@@ -916,11 +1235,16 @@ var Schematic = class {
|
|
|
916
1235
|
fallbackCheckCache = {};
|
|
917
1236
|
constructor(apiKey, options) {
|
|
918
1237
|
this.apiKey = apiKey;
|
|
1238
|
+
this.flagStateCacheKey = `${flagStateCachePrefix}:${apiKey}`;
|
|
919
1239
|
this.eventQueue = [];
|
|
920
1240
|
this.contextDependentEventQueue = [];
|
|
921
1241
|
this.useWebSocket = options?.useWebSocket ?? false;
|
|
922
1242
|
this.debugEnabled = options?.debug ?? false;
|
|
923
1243
|
this.offlineEnabled = options?.offline ?? false;
|
|
1244
|
+
this.persistFlagState = options?.persistFlagState ?? true;
|
|
1245
|
+
if (typeof options?.flagStateCacheMaxAgeMs === "number" && options.flagStateCacheMaxAgeMs > 0) {
|
|
1246
|
+
this.flagStateCacheMaxAgeMs = options.flagStateCacheMaxAgeMs;
|
|
1247
|
+
}
|
|
924
1248
|
if (typeof window !== "undefined" && typeof window.location !== "undefined") {
|
|
925
1249
|
const params = new URLSearchParams(window.location.search);
|
|
926
1250
|
const debugParam = params.get("schematic_debug");
|
|
@@ -953,6 +1277,7 @@ var Schematic = class {
|
|
|
953
1277
|
} catch {
|
|
954
1278
|
}
|
|
955
1279
|
}
|
|
1280
|
+
this.hydrateFlagStateFromCache();
|
|
956
1281
|
if (options?.apiUrl !== void 0) {
|
|
957
1282
|
this.apiUrl = options.apiUrl;
|
|
958
1283
|
}
|
|
@@ -1246,6 +1571,29 @@ var Schematic = class {
|
|
|
1246
1571
|
});
|
|
1247
1572
|
this.notifyPlanListeners(plan);
|
|
1248
1573
|
}
|
|
1574
|
+
if (message.credit_balances !== void 0 && message.credit_balances !== null) {
|
|
1575
|
+
const contextStr = contextString(context);
|
|
1576
|
+
const updates = CreditBalancesFromJSON(message.credit_balances);
|
|
1577
|
+
const previous = this.creditBalances[contextStr] ?? {};
|
|
1578
|
+
let changed = false;
|
|
1579
|
+
const merged = { ...previous };
|
|
1580
|
+
for (const [creditId, next] of Object.entries(updates)) {
|
|
1581
|
+
const current = previous[creditId];
|
|
1582
|
+
if (current === void 0 || current.remaining !== next.remaining || current.reserved !== next.reserved || current.settled !== next.settled) {
|
|
1583
|
+
merged[creditId] = next;
|
|
1584
|
+
changed = true;
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
if (changed) {
|
|
1588
|
+
this.creditBalances[contextStr] = merged;
|
|
1589
|
+
this.debug(
|
|
1590
|
+
`WebSocket credit balance update received. Notifying listeners`,
|
|
1591
|
+
{ creditBalances: merged }
|
|
1592
|
+
);
|
|
1593
|
+
this.notifyCreditBalanceListeners(merged);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
this.persistContextToCache(contextString(context));
|
|
1249
1597
|
this.flushContextDependentEventQueue();
|
|
1250
1598
|
this.setIsPending(false);
|
|
1251
1599
|
};
|
|
@@ -1353,7 +1701,32 @@ var Schematic = class {
|
|
|
1353
1701
|
return;
|
|
1354
1702
|
}
|
|
1355
1703
|
try {
|
|
1356
|
-
|
|
1704
|
+
const newContextStr = contextString(context);
|
|
1705
|
+
const cacheHit = this.hasCachedValuesForContext(newContextStr);
|
|
1706
|
+
if (cacheHit) {
|
|
1707
|
+
this.debug(
|
|
1708
|
+
`setContext: cache hit for context, pre-resolving from cached values`
|
|
1709
|
+
);
|
|
1710
|
+
this.context = context;
|
|
1711
|
+
this.flushContextDependentEventQueue();
|
|
1712
|
+
this.setIsPending(false);
|
|
1713
|
+
const cachedChecks = this.checks[newContextStr] ?? {};
|
|
1714
|
+
for (const [flagKey, check] of Object.entries(cachedChecks)) {
|
|
1715
|
+
if (check === void 0) continue;
|
|
1716
|
+
this.notifyFlagCheckListeners(flagKey, check);
|
|
1717
|
+
this.notifyFlagValueListeners(flagKey, check.value);
|
|
1718
|
+
}
|
|
1719
|
+
const cachedPlan = this.planChecks[newContextStr];
|
|
1720
|
+
if (cachedPlan !== void 0) {
|
|
1721
|
+
this.notifyPlanListeners(cachedPlan);
|
|
1722
|
+
}
|
|
1723
|
+
const cachedCreditBalances = this.creditBalances[newContextStr];
|
|
1724
|
+
if (cachedCreditBalances !== void 0) {
|
|
1725
|
+
this.notifyCreditBalanceListeners(cachedCreditBalances);
|
|
1726
|
+
}
|
|
1727
|
+
} else {
|
|
1728
|
+
this.setIsPending(true);
|
|
1729
|
+
}
|
|
1357
1730
|
if (!this.conn) {
|
|
1358
1731
|
if (this.isConnecting) {
|
|
1359
1732
|
this.debug(
|
|
@@ -1364,7 +1737,7 @@ var Schematic = class {
|
|
|
1364
1737
|
}
|
|
1365
1738
|
if (this.conn !== null) {
|
|
1366
1739
|
const socket2 = await this.conn;
|
|
1367
|
-
await this.wsSendMessage(socket2, context);
|
|
1740
|
+
await this.wsSendMessage(socket2, context, cacheHit);
|
|
1368
1741
|
return;
|
|
1369
1742
|
}
|
|
1370
1743
|
}
|
|
@@ -1380,7 +1753,7 @@ var Schematic = class {
|
|
|
1380
1753
|
this.conn = this.wsConnect();
|
|
1381
1754
|
const socket2 = await this.conn;
|
|
1382
1755
|
this.isConnecting = false;
|
|
1383
|
-
await this.wsSendMessage(socket2, context);
|
|
1756
|
+
await this.wsSendMessage(socket2, context, cacheHit);
|
|
1384
1757
|
return;
|
|
1385
1758
|
} catch (error) {
|
|
1386
1759
|
this.isConnecting = false;
|
|
@@ -1388,7 +1761,7 @@ var Schematic = class {
|
|
|
1388
1761
|
}
|
|
1389
1762
|
}
|
|
1390
1763
|
const socket = await this.conn;
|
|
1391
|
-
await this.wsSendMessage(socket, context);
|
|
1764
|
+
await this.wsSendMessage(socket, context, cacheHit);
|
|
1392
1765
|
} catch (error) {
|
|
1393
1766
|
console.warn("Failed to establish WebSocket connection:", error);
|
|
1394
1767
|
this.context = context;
|
|
@@ -1448,10 +1821,12 @@ var Schematic = class {
|
|
|
1448
1821
|
`Optimistically updating feature usage for event: ${eventName}`,
|
|
1449
1822
|
{ quantity }
|
|
1450
1823
|
);
|
|
1824
|
+
let dirty = false;
|
|
1451
1825
|
Object.entries(flagsForEvent).forEach(([flagKey, check]) => {
|
|
1452
1826
|
if (check === void 0) return;
|
|
1453
1827
|
const updatedCheck = { ...check };
|
|
1454
1828
|
if (typeof updatedCheck.featureUsage === "number") {
|
|
1829
|
+
dirty = true;
|
|
1455
1830
|
updatedCheck.featureUsage += quantity;
|
|
1456
1831
|
if (typeof updatedCheck.featureAllocation === "number") {
|
|
1457
1832
|
const wasExceeded = updatedCheck.featureUsageExceeded === true;
|
|
@@ -1481,6 +1856,9 @@ var Schematic = class {
|
|
|
1481
1856
|
this.notifyFlagValueListeners(flagKey, updatedCheck.value);
|
|
1482
1857
|
}
|
|
1483
1858
|
});
|
|
1859
|
+
if (dirty) {
|
|
1860
|
+
this.persistContextToCache(contextString(this.context));
|
|
1861
|
+
}
|
|
1484
1862
|
};
|
|
1485
1863
|
/**
|
|
1486
1864
|
* Event processing
|
|
@@ -1583,6 +1961,206 @@ var Schematic = class {
|
|
|
1583
1961
|
this.storage.setItem(anonymousIdKey, generatedAnonymousId);
|
|
1584
1962
|
return generatedAnonymousId;
|
|
1585
1963
|
};
|
|
1964
|
+
hasCachedValuesForContext = (contextStr) => {
|
|
1965
|
+
const cachedChecks = this.checks[contextStr];
|
|
1966
|
+
if (cachedChecks !== void 0 && Object.keys(cachedChecks).length > 0) {
|
|
1967
|
+
return true;
|
|
1968
|
+
}
|
|
1969
|
+
if (this.planChecks[contextStr] !== void 0) {
|
|
1970
|
+
return true;
|
|
1971
|
+
}
|
|
1972
|
+
const cachedCreditBalances = this.creditBalances[contextStr];
|
|
1973
|
+
return cachedCreditBalances !== void 0 && Object.keys(cachedCreditBalances).length > 0;
|
|
1974
|
+
};
|
|
1975
|
+
readFlagStateCache = () => {
|
|
1976
|
+
if (!this.persistFlagState || this.storage === void 0) {
|
|
1977
|
+
return null;
|
|
1978
|
+
}
|
|
1979
|
+
let raw;
|
|
1980
|
+
try {
|
|
1981
|
+
raw = this.storage.getItem(this.flagStateCacheKey);
|
|
1982
|
+
} catch (error) {
|
|
1983
|
+
this.debug("Failed to read flag state cache:", error);
|
|
1984
|
+
return null;
|
|
1985
|
+
}
|
|
1986
|
+
if (raw === null || raw === void 0) {
|
|
1987
|
+
return null;
|
|
1988
|
+
}
|
|
1989
|
+
let parsed;
|
|
1990
|
+
try {
|
|
1991
|
+
parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
1992
|
+
} catch (error) {
|
|
1993
|
+
this.debug("Flag state cache is not valid JSON, ignoring:", error);
|
|
1994
|
+
return null;
|
|
1995
|
+
}
|
|
1996
|
+
if (parsed === null || typeof parsed !== "object" || parsed.version !== cacheVersion || typeof parsed.contexts !== "object" || parsed.contexts === null) {
|
|
1997
|
+
this.debug(
|
|
1998
|
+
`Flag state cache invalid or version mismatch (expected ${cacheVersion}), ignoring`,
|
|
1999
|
+
{
|
|
2000
|
+
parsedType: typeof parsed,
|
|
2001
|
+
version: parsed?.version
|
|
2002
|
+
}
|
|
2003
|
+
);
|
|
2004
|
+
return null;
|
|
2005
|
+
}
|
|
2006
|
+
return parsed;
|
|
2007
|
+
};
|
|
2008
|
+
reviveCachedCheck = (raw) => {
|
|
2009
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
2010
|
+
const obj = raw;
|
|
2011
|
+
if (typeof obj.flag !== "string" || typeof obj.value !== "boolean" || typeof obj.reason !== "string") {
|
|
2012
|
+
return null;
|
|
2013
|
+
}
|
|
2014
|
+
const revived = { ...obj };
|
|
2015
|
+
if (typeof revived.featureUsageResetAt === "string") {
|
|
2016
|
+
const d = new Date(revived.featureUsageResetAt);
|
|
2017
|
+
revived.featureUsageResetAt = isNaN(d.getTime()) ? void 0 : d;
|
|
2018
|
+
}
|
|
2019
|
+
return revived;
|
|
2020
|
+
};
|
|
2021
|
+
reviveCachedPlan = (raw) => {
|
|
2022
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
2023
|
+
const obj = raw;
|
|
2024
|
+
if (typeof obj.id !== "string" || typeof obj.name !== "string") {
|
|
2025
|
+
return null;
|
|
2026
|
+
}
|
|
2027
|
+
const revived = { ...obj };
|
|
2028
|
+
if (typeof revived.trialEndDate === "string") {
|
|
2029
|
+
const d = new Date(revived.trialEndDate);
|
|
2030
|
+
revived.trialEndDate = isNaN(d.getTime()) ? void 0 : d;
|
|
2031
|
+
}
|
|
2032
|
+
return revived;
|
|
2033
|
+
};
|
|
2034
|
+
reviveCachedCreditBalances = (raw) => {
|
|
2035
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
2036
|
+
const revived = {};
|
|
2037
|
+
for (const [creditId, value] of Object.entries(
|
|
2038
|
+
raw
|
|
2039
|
+
)) {
|
|
2040
|
+
if (value === null || typeof value !== "object") continue;
|
|
2041
|
+
const obj = value;
|
|
2042
|
+
if (typeof obj.remaining !== "number" || typeof obj.reserved !== "number" || typeof obj.settled !== "number") {
|
|
2043
|
+
continue;
|
|
2044
|
+
}
|
|
2045
|
+
revived[creditId] = {
|
|
2046
|
+
remaining: obj.remaining,
|
|
2047
|
+
reserved: obj.reserved,
|
|
2048
|
+
settled: obj.settled
|
|
2049
|
+
};
|
|
2050
|
+
}
|
|
2051
|
+
return Object.keys(revived).length > 0 ? revived : null;
|
|
2052
|
+
};
|
|
2053
|
+
hydrateFlagStateFromCache = () => {
|
|
2054
|
+
const parsed = this.readFlagStateCache();
|
|
2055
|
+
if (parsed === null) return;
|
|
2056
|
+
const cutoff = Date.now() - this.flagStateCacheMaxAgeMs;
|
|
2057
|
+
const fresh = {};
|
|
2058
|
+
let contextsLoaded = 0;
|
|
2059
|
+
let contextsExpired = 0;
|
|
2060
|
+
for (const [contextStr, entry] of Object.entries(parsed.contexts)) {
|
|
2061
|
+
if (entry === null || typeof entry !== "object") continue;
|
|
2062
|
+
if (typeof entry.updatedAt !== "number") continue;
|
|
2063
|
+
if (entry.updatedAt < cutoff) {
|
|
2064
|
+
contextsExpired += 1;
|
|
2065
|
+
continue;
|
|
2066
|
+
}
|
|
2067
|
+
const revivedChecks = {};
|
|
2068
|
+
if (entry.checks !== null && typeof entry.checks === "object") {
|
|
2069
|
+
for (const [flagKey, rawCheck] of Object.entries(entry.checks)) {
|
|
2070
|
+
const revived = this.reviveCachedCheck(rawCheck);
|
|
2071
|
+
if (revived === null || revived.flag !== flagKey) continue;
|
|
2072
|
+
revivedChecks[flagKey] = revived;
|
|
2073
|
+
if (typeof revived.featureUsageEvent === "string") {
|
|
2074
|
+
this.updateFeatureUsageEventMap(revived);
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
if (Object.keys(revivedChecks).length > 0) {
|
|
2078
|
+
this.checks[contextStr] = revivedChecks;
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
let revivedPlan;
|
|
2082
|
+
if (entry.plan !== void 0 && entry.plan !== null) {
|
|
2083
|
+
const p = this.reviveCachedPlan(entry.plan);
|
|
2084
|
+
if (p !== null) {
|
|
2085
|
+
revivedPlan = p;
|
|
2086
|
+
this.planChecks[contextStr] = p;
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
let revivedCreditBalances;
|
|
2090
|
+
if (entry.creditBalances !== void 0 && entry.creditBalances !== null) {
|
|
2091
|
+
const balances = this.reviveCachedCreditBalances(entry.creditBalances);
|
|
2092
|
+
if (balances !== null) {
|
|
2093
|
+
revivedCreditBalances = balances;
|
|
2094
|
+
this.creditBalances[contextStr] = balances;
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
fresh[contextStr] = {
|
|
2098
|
+
checks: revivedChecks,
|
|
2099
|
+
plan: revivedPlan,
|
|
2100
|
+
creditBalances: revivedCreditBalances,
|
|
2101
|
+
updatedAt: entry.updatedAt
|
|
2102
|
+
};
|
|
2103
|
+
contextsLoaded += 1;
|
|
2104
|
+
}
|
|
2105
|
+
this.cachedFlagState = { version: cacheVersion, contexts: fresh };
|
|
2106
|
+
this.debug(
|
|
2107
|
+
`Hydrated flag state cache: ${contextsLoaded} loaded, ${contextsExpired} expired`
|
|
2108
|
+
);
|
|
2109
|
+
};
|
|
2110
|
+
persistContextToCache = (contextStr) => {
|
|
2111
|
+
const checksForContext = this.checks[contextStr];
|
|
2112
|
+
const planForContext = this.planChecks[contextStr];
|
|
2113
|
+
const creditBalancesForContext = this.creditBalances[contextStr];
|
|
2114
|
+
if (checksForContext === void 0 && planForContext === void 0 && creditBalancesForContext === void 0) {
|
|
2115
|
+
return;
|
|
2116
|
+
}
|
|
2117
|
+
if (this.cachedFlagState === null) {
|
|
2118
|
+
this.cachedFlagState = (this.persistFlagState ? this.readFlagStateCache() : null) ?? {
|
|
2119
|
+
version: cacheVersion,
|
|
2120
|
+
contexts: {}
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2123
|
+
const cleanChecks = {};
|
|
2124
|
+
if (checksForContext !== void 0) {
|
|
2125
|
+
for (const [flagKey, check] of Object.entries(checksForContext)) {
|
|
2126
|
+
if (check !== void 0) cleanChecks[flagKey] = check;
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
this.cachedFlagState.contexts[contextStr] = {
|
|
2130
|
+
checks: cleanChecks,
|
|
2131
|
+
plan: planForContext,
|
|
2132
|
+
creditBalances: creditBalancesForContext,
|
|
2133
|
+
updatedAt: Date.now()
|
|
2134
|
+
};
|
|
2135
|
+
const entries = Object.entries(this.cachedFlagState.contexts);
|
|
2136
|
+
if (entries.length > flagStateCacheMaxContexts) {
|
|
2137
|
+
entries.sort((a, b) => b[1].updatedAt - a[1].updatedAt);
|
|
2138
|
+
const survivors = entries.slice(0, flagStateCacheMaxContexts);
|
|
2139
|
+
const survivorKeys = new Set(survivors.map(([k]) => k));
|
|
2140
|
+
for (const key of Object.keys(this.checks)) {
|
|
2141
|
+
if (!survivorKeys.has(key)) delete this.checks[key];
|
|
2142
|
+
}
|
|
2143
|
+
for (const key of Object.keys(this.planChecks)) {
|
|
2144
|
+
if (!survivorKeys.has(key)) delete this.planChecks[key];
|
|
2145
|
+
}
|
|
2146
|
+
for (const key of Object.keys(this.creditBalances)) {
|
|
2147
|
+
if (!survivorKeys.has(key)) delete this.creditBalances[key];
|
|
2148
|
+
}
|
|
2149
|
+
this.cachedFlagState = {
|
|
2150
|
+
version: cacheVersion,
|
|
2151
|
+
contexts: Object.fromEntries(survivors)
|
|
2152
|
+
};
|
|
2153
|
+
}
|
|
2154
|
+
if (!this.persistFlagState || this.storage === void 0) return;
|
|
2155
|
+
try {
|
|
2156
|
+
this.storage.setItem(
|
|
2157
|
+
this.flagStateCacheKey,
|
|
2158
|
+
JSON.stringify(this.cachedFlagState)
|
|
2159
|
+
);
|
|
2160
|
+
} catch (error) {
|
|
2161
|
+
this.debug("Failed to write flag state cache:", error);
|
|
2162
|
+
}
|
|
2163
|
+
};
|
|
1586
2164
|
handleEvent = (eventType, eventBody) => {
|
|
1587
2165
|
const event = {
|
|
1588
2166
|
api_key: this.apiKey,
|
|
@@ -1843,6 +2421,9 @@ var Schematic = class {
|
|
|
1843
2421
|
if (this.conn !== null) {
|
|
1844
2422
|
try {
|
|
1845
2423
|
const socket = await this.conn;
|
|
2424
|
+
if (this.currentWebSocket === socket) {
|
|
2425
|
+
this.currentWebSocket = null;
|
|
2426
|
+
}
|
|
1846
2427
|
if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
|
|
1847
2428
|
socket.close();
|
|
1848
2429
|
}
|
|
@@ -2008,6 +2589,7 @@ var Schematic = class {
|
|
|
2008
2589
|
this.debug(`Creating WebSocket connection ${connectionId} to ${wsUrl}`);
|
|
2009
2590
|
let timeoutId = null;
|
|
2010
2591
|
let isResolved = false;
|
|
2592
|
+
let didOpen = false;
|
|
2011
2593
|
timeoutId = setTimeout(() => {
|
|
2012
2594
|
if (!isResolved) {
|
|
2013
2595
|
isResolved = true;
|
|
@@ -2021,6 +2603,7 @@ var Schematic = class {
|
|
|
2021
2603
|
webSocket.onopen = () => {
|
|
2022
2604
|
if (isResolved) return;
|
|
2023
2605
|
isResolved = true;
|
|
2606
|
+
didOpen = true;
|
|
2024
2607
|
if (timeoutId !== null) {
|
|
2025
2608
|
clearTimeout(timeoutId);
|
|
2026
2609
|
}
|
|
@@ -2046,11 +2629,12 @@ var Schematic = class {
|
|
|
2046
2629
|
}
|
|
2047
2630
|
this.debug(`WebSocket connection ${connectionId} closed`);
|
|
2048
2631
|
this.conn = null;
|
|
2632
|
+
const wasCurrent = this.currentWebSocket === webSocket;
|
|
2049
2633
|
if (this.currentWebSocket === webSocket) {
|
|
2050
2634
|
this.currentWebSocket = null;
|
|
2051
2635
|
this.isConnecting = false;
|
|
2052
2636
|
}
|
|
2053
|
-
if (
|
|
2637
|
+
if (wasCurrent && didOpen && !this.wsIntentionalDisconnect && this.webSocketReconnect) {
|
|
2054
2638
|
this.attemptReconnect();
|
|
2055
2639
|
}
|
|
2056
2640
|
};
|
|
@@ -2146,6 +2730,16 @@ var Schematic = class {
|
|
|
2146
2730
|
const plan = this.planChecks[contextStr];
|
|
2147
2731
|
return plan;
|
|
2148
2732
|
};
|
|
2733
|
+
/** Get the company's lease-aware credit balances for the current context, keyed by credit ID */
|
|
2734
|
+
getCreditBalances = () => {
|
|
2735
|
+
const contextStr = contextString(this.context);
|
|
2736
|
+
return this.creditBalances[contextStr] ?? emptyCreditBalances;
|
|
2737
|
+
};
|
|
2738
|
+
/** Get the company's lease-aware balance for a single credit type in the current context */
|
|
2739
|
+
getCreditBalance = (creditId) => {
|
|
2740
|
+
const contextStr = contextString(this.context);
|
|
2741
|
+
return this.creditBalances[contextStr]?.[creditId];
|
|
2742
|
+
};
|
|
2149
2743
|
// flag checks state
|
|
2150
2744
|
getFlagCheck = (flagKey) => {
|
|
2151
2745
|
const contextStr = contextString(this.context);
|
|
@@ -2205,6 +2799,13 @@ var Schematic = class {
|
|
|
2205
2799
|
this.planListeners.delete(listener);
|
|
2206
2800
|
};
|
|
2207
2801
|
};
|
|
2802
|
+
/** Register an event listener that will be notified with the company's credit balances (keyed by credit ID) whenever they change */
|
|
2803
|
+
addCreditBalanceListener = (listener) => {
|
|
2804
|
+
this.creditBalanceListeners.add(listener);
|
|
2805
|
+
return () => {
|
|
2806
|
+
this.creditBalanceListeners.delete(listener);
|
|
2807
|
+
};
|
|
2808
|
+
};
|
|
2208
2809
|
notifyFlagCheckListeners = (flagKey, check) => {
|
|
2209
2810
|
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
2210
2811
|
if (listeners.size > 0) {
|
|
@@ -2268,6 +2869,17 @@ var Schematic = class {
|
|
|
2268
2869
|
});
|
|
2269
2870
|
});
|
|
2270
2871
|
};
|
|
2872
|
+
notifyCreditBalanceListeners = (value) => {
|
|
2873
|
+
const listeners = this.creditBalanceListeners ?? [];
|
|
2874
|
+
if (listeners.size > 0) {
|
|
2875
|
+
this.debug(`Notifying ${listeners.size} credit balance listeners`, {
|
|
2876
|
+
value
|
|
2877
|
+
});
|
|
2878
|
+
}
|
|
2879
|
+
listeners.forEach(
|
|
2880
|
+
(listener) => notifyCreditBalanceListener(listener, value)
|
|
2881
|
+
);
|
|
2882
|
+
};
|
|
2271
2883
|
};
|
|
2272
2884
|
var notifyPendingListener = (listener, value) => {
|
|
2273
2885
|
if (listener.length > 0) {
|
|
@@ -2297,11 +2909,19 @@ var notifyPlanListener = (listener, value) => {
|
|
|
2297
2909
|
listener();
|
|
2298
2910
|
}
|
|
2299
2911
|
};
|
|
2912
|
+
var notifyCreditBalanceListener = (listener, value) => {
|
|
2913
|
+
if (listener.length > 0) {
|
|
2914
|
+
listener(value);
|
|
2915
|
+
} else {
|
|
2916
|
+
listener();
|
|
2917
|
+
}
|
|
2918
|
+
};
|
|
2300
2919
|
export {
|
|
2301
2920
|
CheckFlagResponseFromJSON,
|
|
2302
2921
|
CheckFlagReturnFromJSON,
|
|
2303
2922
|
CheckFlagsResponseFromJSON,
|
|
2304
2923
|
CheckPlanReturnFromJSON,
|
|
2924
|
+
CreditBalancesFromJSON,
|
|
2305
2925
|
DatastreamCompanyPlanFromJSON,
|
|
2306
2926
|
EventBodyFlagCheckToJSON,
|
|
2307
2927
|
RuleType,
|