@schematichq/schematic-vue 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 +26 -0
- package/dist/schematic-vue.cjs.js +666 -27
- package/dist/schematic-vue.d.ts +1060 -30
- package/dist/schematic-vue.esm.js +666 -27
- package/package.json +3 -2
|
@@ -27,6 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
useSchematic: () => useSchematic,
|
|
28
28
|
useSchematicClient: () => useSchematicClient,
|
|
29
29
|
useSchematicContext: () => useSchematicContext,
|
|
30
|
+
useSchematicCreditBalance: () => useSchematicCreditBalance,
|
|
30
31
|
useSchematicEntitlement: () => useSchematicEntitlement,
|
|
31
32
|
useSchematicEvents: () => useSchematicEvents,
|
|
32
33
|
useSchematicFlag: () => useSchematicFlag,
|
|
@@ -43,7 +44,11 @@ var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
|
43
44
|
var __getProtoOf = Object.getPrototypeOf;
|
|
44
45
|
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
45
46
|
var __commonJS = (cb, mod) => function __require() {
|
|
46
|
-
|
|
47
|
+
try {
|
|
48
|
+
return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
49
|
+
} catch (e) {
|
|
50
|
+
throw mod = 0, e;
|
|
51
|
+
}
|
|
47
52
|
};
|
|
48
53
|
var __copyProps2 = (to, from, except, desc) => {
|
|
49
54
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -602,19 +607,16 @@ for (let i = 0; i < 256; ++i) {
|
|
|
602
607
|
function unsafeStringify(arr, offset = 0) {
|
|
603
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();
|
|
604
609
|
}
|
|
605
|
-
var getRandomValues;
|
|
606
610
|
var rnds8 = new Uint8Array(16);
|
|
607
611
|
function rng() {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
612
|
+
return crypto.getRandomValues(rnds8);
|
|
613
|
+
}
|
|
614
|
+
function v4(options, buf, offset) {
|
|
615
|
+
if (!buf && !options && crypto.randomUUID) {
|
|
616
|
+
return crypto.randomUUID();
|
|
613
617
|
}
|
|
614
|
-
return
|
|
618
|
+
return _v4(options, buf, offset);
|
|
615
619
|
}
|
|
616
|
-
var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
617
|
-
var native_default = { randomUUID };
|
|
618
620
|
function _v4(options, buf, offset) {
|
|
619
621
|
options = options || {};
|
|
620
622
|
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
@@ -635,12 +637,6 @@ function _v4(options, buf, offset) {
|
|
|
635
637
|
}
|
|
636
638
|
return unsafeStringify(rnds);
|
|
637
639
|
}
|
|
638
|
-
function v4(options, buf, offset) {
|
|
639
|
-
if (native_default.randomUUID && !buf && !options) {
|
|
640
|
-
return native_default.randomUUID();
|
|
641
|
-
}
|
|
642
|
-
return _v4(options, buf, offset);
|
|
643
|
-
}
|
|
644
640
|
var v4_default = v4;
|
|
645
641
|
var import_polyfill = __toESM(require_browser_polyfill());
|
|
646
642
|
function EntitlementValueTypeFromJSON(json) {
|
|
@@ -649,6 +645,18 @@ function EntitlementValueTypeFromJSON(json) {
|
|
|
649
645
|
function EntitlementValueTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
650
646
|
return json;
|
|
651
647
|
}
|
|
648
|
+
function MetricPeriodMonthResetFromJSON(json) {
|
|
649
|
+
return MetricPeriodMonthResetFromJSONTyped(json, false);
|
|
650
|
+
}
|
|
651
|
+
function MetricPeriodMonthResetFromJSONTyped(json, ignoreDiscriminator) {
|
|
652
|
+
return json;
|
|
653
|
+
}
|
|
654
|
+
function MetricPeriodFromJSON(json) {
|
|
655
|
+
return MetricPeriodFromJSONTyped(json, false);
|
|
656
|
+
}
|
|
657
|
+
function MetricPeriodFromJSONTyped(json, ignoreDiscriminator) {
|
|
658
|
+
return json;
|
|
659
|
+
}
|
|
652
660
|
function FeatureEntitlementFromJSON(json) {
|
|
653
661
|
return FeatureEntitlementFromJSONTyped(json, false);
|
|
654
662
|
}
|
|
@@ -658,21 +666,31 @@ function FeatureEntitlementFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
658
666
|
}
|
|
659
667
|
return {
|
|
660
668
|
allocation: json["allocation"] == null ? void 0 : json["allocation"],
|
|
669
|
+
consumptionRate: json["consumption_rate"] == null ? void 0 : json["consumption_rate"],
|
|
661
670
|
creditId: json["credit_id"] == null ? void 0 : json["credit_id"],
|
|
662
671
|
creditRemaining: json["credit_remaining"] == null ? void 0 : json["credit_remaining"],
|
|
672
|
+
creditReserved: json["credit_reserved"] == null ? void 0 : json["credit_reserved"],
|
|
673
|
+
creditSettled: json["credit_settled"] == null ? void 0 : json["credit_settled"],
|
|
663
674
|
creditTotal: json["credit_total"] == null ? void 0 : json["credit_total"],
|
|
664
675
|
creditUsed: json["credit_used"] == null ? void 0 : json["credit_used"],
|
|
665
676
|
eventName: json["event_name"] == null ? void 0 : json["event_name"],
|
|
677
|
+
eventSubtype: json["event_subtype"] == null ? void 0 : json["event_subtype"],
|
|
666
678
|
featureId: json["feature_id"],
|
|
667
679
|
featureKey: json["feature_key"],
|
|
668
|
-
metricPeriod: json["metric_period"] == null ? void 0 : json["metric_period"],
|
|
680
|
+
metricPeriod: json["metric_period"] == null ? void 0 : MetricPeriodFromJSON(json["metric_period"]),
|
|
669
681
|
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"],
|
|
682
|
+
monthReset: json["month_reset"] == null ? void 0 : MetricPeriodMonthResetFromJSON(json["month_reset"]),
|
|
671
683
|
softLimit: json["soft_limit"] == null ? void 0 : json["soft_limit"],
|
|
672
684
|
usage: json["usage"] == null ? void 0 : json["usage"],
|
|
673
685
|
valueType: EntitlementValueTypeFromJSON(json["value_type"])
|
|
674
686
|
};
|
|
675
687
|
}
|
|
688
|
+
function RuleTypeFromJSON(json) {
|
|
689
|
+
return RuleTypeFromJSONTyped(json, false);
|
|
690
|
+
}
|
|
691
|
+
function RuleTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
692
|
+
return json;
|
|
693
|
+
}
|
|
676
694
|
function CheckFlagResponseDataFromJSON(json) {
|
|
677
695
|
return CheckFlagResponseDataFromJSONTyped(json, false);
|
|
678
696
|
}
|
|
@@ -687,13 +705,13 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
687
705
|
featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
|
|
688
706
|
featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
|
|
689
707
|
featureUsageEvent: json["feature_usage_event"] == null ? void 0 : json["feature_usage_event"],
|
|
690
|
-
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
|
|
708
|
+
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : MetricPeriodFromJSON(json["feature_usage_period"]),
|
|
691
709
|
featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
|
|
692
710
|
flag: json["flag"],
|
|
693
711
|
flagId: json["flag_id"] == null ? void 0 : json["flag_id"],
|
|
694
712
|
reason: json["reason"],
|
|
695
713
|
ruleId: json["rule_id"] == null ? void 0 : json["rule_id"],
|
|
696
|
-
ruleType: json["rule_type"] == null ? void 0 : json["rule_type"],
|
|
714
|
+
ruleType: json["rule_type"] == null ? void 0 : RuleTypeFromJSON(json["rule_type"]),
|
|
697
715
|
userId: json["user_id"] == null ? void 0 : json["user_id"],
|
|
698
716
|
value: json["value"]
|
|
699
717
|
};
|
|
@@ -710,6 +728,268 @@ function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
710
728
|
params: json["params"]
|
|
711
729
|
};
|
|
712
730
|
}
|
|
731
|
+
var BASE_PATH = "https://api.schematichq.com".replace(/\/+$/, "");
|
|
732
|
+
var Configuration = class {
|
|
733
|
+
constructor(configuration = {}) {
|
|
734
|
+
this.configuration = configuration;
|
|
735
|
+
}
|
|
736
|
+
configuration;
|
|
737
|
+
set config(configuration) {
|
|
738
|
+
this.configuration = configuration;
|
|
739
|
+
}
|
|
740
|
+
get basePath() {
|
|
741
|
+
return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH;
|
|
742
|
+
}
|
|
743
|
+
get fetchApi() {
|
|
744
|
+
return this.configuration.fetchApi;
|
|
745
|
+
}
|
|
746
|
+
get middleware() {
|
|
747
|
+
return this.configuration.middleware || [];
|
|
748
|
+
}
|
|
749
|
+
get queryParamsStringify() {
|
|
750
|
+
return this.configuration.queryParamsStringify || querystring;
|
|
751
|
+
}
|
|
752
|
+
get username() {
|
|
753
|
+
return this.configuration.username;
|
|
754
|
+
}
|
|
755
|
+
get password() {
|
|
756
|
+
return this.configuration.password;
|
|
757
|
+
}
|
|
758
|
+
get apiKey() {
|
|
759
|
+
const apiKey = this.configuration.apiKey;
|
|
760
|
+
if (apiKey) {
|
|
761
|
+
return typeof apiKey === "function" ? apiKey : () => apiKey;
|
|
762
|
+
}
|
|
763
|
+
return void 0;
|
|
764
|
+
}
|
|
765
|
+
get accessToken() {
|
|
766
|
+
const accessToken = this.configuration.accessToken;
|
|
767
|
+
if (accessToken) {
|
|
768
|
+
return typeof accessToken === "function" ? accessToken : async () => accessToken;
|
|
769
|
+
}
|
|
770
|
+
return void 0;
|
|
771
|
+
}
|
|
772
|
+
get headers() {
|
|
773
|
+
return this.configuration.headers;
|
|
774
|
+
}
|
|
775
|
+
get credentials() {
|
|
776
|
+
return this.configuration.credentials;
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
var DefaultConfig = new Configuration();
|
|
780
|
+
var BaseAPI = class _BaseAPI {
|
|
781
|
+
constructor(configuration = DefaultConfig) {
|
|
782
|
+
this.configuration = configuration;
|
|
783
|
+
this.middleware = configuration.middleware;
|
|
784
|
+
}
|
|
785
|
+
configuration;
|
|
786
|
+
static jsonRegex = new RegExp(
|
|
787
|
+
"^(:?application/json|[^;/ ]+/[^;/ ]+[+]json)[ ]*(:?;.*)?$",
|
|
788
|
+
"i"
|
|
789
|
+
);
|
|
790
|
+
middleware;
|
|
791
|
+
withMiddleware(...middlewares) {
|
|
792
|
+
const next = this.clone();
|
|
793
|
+
next.middleware = next.middleware.concat(...middlewares);
|
|
794
|
+
return next;
|
|
795
|
+
}
|
|
796
|
+
withPreMiddleware(...preMiddlewares) {
|
|
797
|
+
const middlewares = preMiddlewares.map((pre) => ({ pre }));
|
|
798
|
+
return this.withMiddleware(...middlewares);
|
|
799
|
+
}
|
|
800
|
+
withPostMiddleware(...postMiddlewares) {
|
|
801
|
+
const middlewares = postMiddlewares.map((post) => ({ post }));
|
|
802
|
+
return this.withMiddleware(...middlewares);
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Check if the given MIME is a JSON MIME.
|
|
806
|
+
* JSON MIME examples:
|
|
807
|
+
* application/json
|
|
808
|
+
* application/json; charset=UTF8
|
|
809
|
+
* APPLICATION/JSON
|
|
810
|
+
* application/vnd.company+json
|
|
811
|
+
* @param mime - MIME (Multipurpose Internet Mail Extensions)
|
|
812
|
+
* @return True if the given MIME is JSON, false otherwise.
|
|
813
|
+
*/
|
|
814
|
+
isJsonMime(mime) {
|
|
815
|
+
if (!mime) {
|
|
816
|
+
return false;
|
|
817
|
+
}
|
|
818
|
+
return _BaseAPI.jsonRegex.test(mime);
|
|
819
|
+
}
|
|
820
|
+
async request(context, initOverrides) {
|
|
821
|
+
const { url, init } = await this.createFetchParams(context, initOverrides);
|
|
822
|
+
const response = await this.fetchApi(url, init);
|
|
823
|
+
if (response && response.status >= 200 && response.status < 300) {
|
|
824
|
+
return response;
|
|
825
|
+
}
|
|
826
|
+
throw new ResponseError(response, "Response returned an error code");
|
|
827
|
+
}
|
|
828
|
+
async createFetchParams(context, initOverrides) {
|
|
829
|
+
let url = this.configuration.basePath + context.path;
|
|
830
|
+
if (context.query !== void 0 && Object.keys(context.query).length !== 0) {
|
|
831
|
+
url += "?" + this.configuration.queryParamsStringify(context.query);
|
|
832
|
+
}
|
|
833
|
+
const headers = Object.assign(
|
|
834
|
+
{},
|
|
835
|
+
this.configuration.headers,
|
|
836
|
+
context.headers
|
|
837
|
+
);
|
|
838
|
+
Object.keys(headers).forEach(
|
|
839
|
+
(key) => headers[key] === void 0 ? delete headers[key] : {}
|
|
840
|
+
);
|
|
841
|
+
const initOverrideFn = typeof initOverrides === "function" ? initOverrides : async () => initOverrides;
|
|
842
|
+
const initParams = {
|
|
843
|
+
method: context.method,
|
|
844
|
+
headers,
|
|
845
|
+
body: context.body,
|
|
846
|
+
credentials: this.configuration.credentials
|
|
847
|
+
};
|
|
848
|
+
const overriddenInit = {
|
|
849
|
+
...initParams,
|
|
850
|
+
...await initOverrideFn({
|
|
851
|
+
init: initParams,
|
|
852
|
+
context
|
|
853
|
+
})
|
|
854
|
+
};
|
|
855
|
+
let body;
|
|
856
|
+
if (isFormData(overriddenInit.body) || overriddenInit.body instanceof URLSearchParams || isBlob(overriddenInit.body)) {
|
|
857
|
+
body = overriddenInit.body;
|
|
858
|
+
} else if (this.isJsonMime(headers["Content-Type"])) {
|
|
859
|
+
body = JSON.stringify(overriddenInit.body);
|
|
860
|
+
} else {
|
|
861
|
+
body = overriddenInit.body;
|
|
862
|
+
}
|
|
863
|
+
const init = {
|
|
864
|
+
...overriddenInit,
|
|
865
|
+
body
|
|
866
|
+
};
|
|
867
|
+
return { url, init };
|
|
868
|
+
}
|
|
869
|
+
fetchApi = async (url, init) => {
|
|
870
|
+
let fetchParams = { url, init };
|
|
871
|
+
for (const middleware of this.middleware) {
|
|
872
|
+
if (middleware.pre) {
|
|
873
|
+
fetchParams = await middleware.pre({
|
|
874
|
+
fetch: this.fetchApi,
|
|
875
|
+
...fetchParams
|
|
876
|
+
}) || fetchParams;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
let response = void 0;
|
|
880
|
+
try {
|
|
881
|
+
response = await (this.configuration.fetchApi || fetch)(
|
|
882
|
+
fetchParams.url,
|
|
883
|
+
fetchParams.init
|
|
884
|
+
);
|
|
885
|
+
} catch (e) {
|
|
886
|
+
for (const middleware of this.middleware) {
|
|
887
|
+
if (middleware.onError) {
|
|
888
|
+
response = await middleware.onError({
|
|
889
|
+
fetch: this.fetchApi,
|
|
890
|
+
url: fetchParams.url,
|
|
891
|
+
init: fetchParams.init,
|
|
892
|
+
error: e,
|
|
893
|
+
response: response ? response.clone() : void 0
|
|
894
|
+
}) || response;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
if (response === void 0) {
|
|
898
|
+
if (e instanceof Error) {
|
|
899
|
+
throw new FetchError(
|
|
900
|
+
e,
|
|
901
|
+
"The request failed and the interceptors did not return an alternative response"
|
|
902
|
+
);
|
|
903
|
+
} else {
|
|
904
|
+
throw e;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
for (const middleware of this.middleware) {
|
|
909
|
+
if (middleware.post) {
|
|
910
|
+
response = await middleware.post({
|
|
911
|
+
fetch: this.fetchApi,
|
|
912
|
+
url: fetchParams.url,
|
|
913
|
+
init: fetchParams.init,
|
|
914
|
+
response: response.clone()
|
|
915
|
+
}) || response;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
return response;
|
|
919
|
+
};
|
|
920
|
+
/**
|
|
921
|
+
* Create a shallow clone of `this` by constructing a new instance
|
|
922
|
+
* and then shallow cloning data members.
|
|
923
|
+
*/
|
|
924
|
+
clone() {
|
|
925
|
+
const constructor = this.constructor;
|
|
926
|
+
const next = new constructor(this.configuration);
|
|
927
|
+
next.middleware = this.middleware.slice();
|
|
928
|
+
return next;
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
function isBlob(value) {
|
|
932
|
+
return typeof Blob !== "undefined" && value instanceof Blob;
|
|
933
|
+
}
|
|
934
|
+
function isFormData(value) {
|
|
935
|
+
return typeof FormData !== "undefined" && value instanceof FormData;
|
|
936
|
+
}
|
|
937
|
+
var ResponseError = class extends Error {
|
|
938
|
+
constructor(response, msg) {
|
|
939
|
+
super(msg);
|
|
940
|
+
this.response = response;
|
|
941
|
+
}
|
|
942
|
+
response;
|
|
943
|
+
name = "ResponseError";
|
|
944
|
+
};
|
|
945
|
+
var FetchError = class extends Error {
|
|
946
|
+
constructor(cause, msg) {
|
|
947
|
+
super(msg);
|
|
948
|
+
this.cause = cause;
|
|
949
|
+
}
|
|
950
|
+
cause;
|
|
951
|
+
name = "FetchError";
|
|
952
|
+
};
|
|
953
|
+
function querystring(params, prefix = "") {
|
|
954
|
+
return Object.keys(params).map((key) => querystringSingleKey(key, params[key], prefix)).filter((part) => part.length > 0).join("&");
|
|
955
|
+
}
|
|
956
|
+
function querystringSingleKey(key, value, keyPrefix = "") {
|
|
957
|
+
const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key);
|
|
958
|
+
if (value instanceof Array) {
|
|
959
|
+
const multiValue = value.map((singleValue) => encodeURIComponent(String(singleValue))).join(`&${encodeURIComponent(fullKey)}=`);
|
|
960
|
+
return `${encodeURIComponent(fullKey)}=${multiValue}`;
|
|
961
|
+
}
|
|
962
|
+
if (value instanceof Set) {
|
|
963
|
+
const valueAsArray = Array.from(value);
|
|
964
|
+
return querystringSingleKey(key, valueAsArray, keyPrefix);
|
|
965
|
+
}
|
|
966
|
+
if (value instanceof Date) {
|
|
967
|
+
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`;
|
|
968
|
+
}
|
|
969
|
+
if (value instanceof Object) {
|
|
970
|
+
return querystring(value, fullKey);
|
|
971
|
+
}
|
|
972
|
+
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
|
|
973
|
+
}
|
|
974
|
+
function mapValues(data, fn) {
|
|
975
|
+
return Object.keys(data).reduce(
|
|
976
|
+
(acc, key) => ({ ...acc, [key]: fn(data[key]) }),
|
|
977
|
+
{}
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
function CompanyCreditBalanceFromJSON(json) {
|
|
981
|
+
return CompanyCreditBalanceFromJSONTyped(json, false);
|
|
982
|
+
}
|
|
983
|
+
function CompanyCreditBalanceFromJSONTyped(json, ignoreDiscriminator) {
|
|
984
|
+
if (json == null) {
|
|
985
|
+
return json;
|
|
986
|
+
}
|
|
987
|
+
return {
|
|
988
|
+
remaining: json["remaining"],
|
|
989
|
+
reserved: json["reserved"],
|
|
990
|
+
settled: json["settled"]
|
|
991
|
+
};
|
|
992
|
+
}
|
|
713
993
|
function TrialStatusFromJSON(json) {
|
|
714
994
|
return TrialStatusFromJSONTyped(json, false);
|
|
715
995
|
}
|
|
@@ -738,6 +1018,7 @@ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
738
1018
|
return json;
|
|
739
1019
|
}
|
|
740
1020
|
return {
|
|
1021
|
+
creditBalances: json["credit_balances"] == null ? void 0 : mapValues(json["credit_balances"], CompanyCreditBalanceFromJSON),
|
|
741
1022
|
flags: json["flags"].map(CheckFlagResponseDataFromJSON),
|
|
742
1023
|
plan: json["plan"] == null ? void 0 : DatastreamCompanyPlanFromJSON(json["plan"])
|
|
743
1024
|
};
|
|
@@ -820,7 +1101,10 @@ var CheckFlagReturnFromJSON = (json) => {
|
|
|
820
1101
|
return {
|
|
821
1102
|
featureUsageExceeded,
|
|
822
1103
|
companyId: companyId == null ? void 0 : companyId,
|
|
1104
|
+
creditId: entitlement?.creditId == null ? void 0 : entitlement.creditId,
|
|
823
1105
|
creditRemaining: entitlement?.creditRemaining == null ? void 0 : entitlement.creditRemaining,
|
|
1106
|
+
creditReserved: entitlement?.creditReserved == null ? void 0 : entitlement.creditReserved,
|
|
1107
|
+
creditSettled: entitlement?.creditSettled == null ? void 0 : entitlement.creditSettled,
|
|
824
1108
|
error: error == null ? void 0 : error,
|
|
825
1109
|
featureAllocation: resolvedAllocation == null ? void 0 : resolvedAllocation,
|
|
826
1110
|
featureUsage: resolvedUsage == null ? void 0 : resolvedUsage,
|
|
@@ -846,6 +1130,22 @@ var CheckPlanReturnFromJSON = (json) => {
|
|
|
846
1130
|
trialStatus: trialStatus == null ? void 0 : trialStatus
|
|
847
1131
|
};
|
|
848
1132
|
};
|
|
1133
|
+
var CreditBalancesFromJSON = (json) => {
|
|
1134
|
+
if (json == null || typeof json !== "object") {
|
|
1135
|
+
return {};
|
|
1136
|
+
}
|
|
1137
|
+
const balances = {};
|
|
1138
|
+
for (const [creditId, raw] of Object.entries(json)) {
|
|
1139
|
+
if (raw == null || typeof raw !== "object") continue;
|
|
1140
|
+
const { remaining, reserved, settled } = CompanyCreditBalanceFromJSON(raw);
|
|
1141
|
+
if (typeof remaining !== "number" || typeof reserved !== "number" || typeof settled !== "number") {
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
balances[creditId] = { remaining, reserved, settled };
|
|
1145
|
+
}
|
|
1146
|
+
return balances;
|
|
1147
|
+
};
|
|
1148
|
+
var cacheVersion = "bb56e75d";
|
|
849
1149
|
function contextString(context) {
|
|
850
1150
|
const sortedContext = Object.keys(context).reduce((acc, key) => {
|
|
851
1151
|
const sortedKeys = Object.keys(
|
|
@@ -860,8 +1160,12 @@ function contextString(context) {
|
|
|
860
1160
|
}, {});
|
|
861
1161
|
return JSON.stringify(sortedContext);
|
|
862
1162
|
}
|
|
863
|
-
var version = "1.
|
|
1163
|
+
var version = "1.5.0";
|
|
864
1164
|
var anonymousIdKey = "schematicId";
|
|
1165
|
+
var flagStateCachePrefix = "schematicCache";
|
|
1166
|
+
var flagStateCacheMaxContexts = 10;
|
|
1167
|
+
var flagStateCacheDefaultMaxAgeMs = 7 * 24 * 60 * 60 * 1e3;
|
|
1168
|
+
var emptyCreditBalances = Object.freeze({});
|
|
865
1169
|
var Schematic = class {
|
|
866
1170
|
additionalHeaders = {};
|
|
867
1171
|
apiKey;
|
|
@@ -878,11 +1182,17 @@ var Schematic = class {
|
|
|
878
1182
|
isPending = true;
|
|
879
1183
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
880
1184
|
planListeners = /* @__PURE__ */ new Set();
|
|
1185
|
+
creditBalanceListeners = /* @__PURE__ */ new Set();
|
|
881
1186
|
storage;
|
|
1187
|
+
persistFlagState = true;
|
|
1188
|
+
flagStateCacheKey;
|
|
1189
|
+
flagStateCacheMaxAgeMs = flagStateCacheDefaultMaxAgeMs;
|
|
1190
|
+
cachedFlagState = null;
|
|
882
1191
|
useWebSocket = false;
|
|
883
1192
|
checks = {};
|
|
884
1193
|
featureUsageEventMap = {};
|
|
885
1194
|
planChecks = {};
|
|
1195
|
+
creditBalances = {};
|
|
886
1196
|
webSocketUrl = "wss://api.schematichq.com";
|
|
887
1197
|
webSocketConnectionTimeout = 1e4;
|
|
888
1198
|
webSocketReconnect = true;
|
|
@@ -911,11 +1221,16 @@ var Schematic = class {
|
|
|
911
1221
|
fallbackCheckCache = {};
|
|
912
1222
|
constructor(apiKey, options) {
|
|
913
1223
|
this.apiKey = apiKey;
|
|
1224
|
+
this.flagStateCacheKey = `${flagStateCachePrefix}:${apiKey}`;
|
|
914
1225
|
this.eventQueue = [];
|
|
915
1226
|
this.contextDependentEventQueue = [];
|
|
916
1227
|
this.useWebSocket = options?.useWebSocket ?? false;
|
|
917
1228
|
this.debugEnabled = options?.debug ?? false;
|
|
918
1229
|
this.offlineEnabled = options?.offline ?? false;
|
|
1230
|
+
this.persistFlagState = options?.persistFlagState ?? true;
|
|
1231
|
+
if (typeof options?.flagStateCacheMaxAgeMs === "number" && options.flagStateCacheMaxAgeMs > 0) {
|
|
1232
|
+
this.flagStateCacheMaxAgeMs = options.flagStateCacheMaxAgeMs;
|
|
1233
|
+
}
|
|
919
1234
|
if (typeof window !== "undefined" && typeof window.location !== "undefined") {
|
|
920
1235
|
const params = new URLSearchParams(window.location.search);
|
|
921
1236
|
const debugParam = params.get("schematic_debug");
|
|
@@ -948,6 +1263,7 @@ var Schematic = class {
|
|
|
948
1263
|
} catch {
|
|
949
1264
|
}
|
|
950
1265
|
}
|
|
1266
|
+
this.hydrateFlagStateFromCache();
|
|
951
1267
|
if (options?.apiUrl !== void 0) {
|
|
952
1268
|
this.apiUrl = options.apiUrl;
|
|
953
1269
|
}
|
|
@@ -1241,6 +1557,29 @@ var Schematic = class {
|
|
|
1241
1557
|
});
|
|
1242
1558
|
this.notifyPlanListeners(plan);
|
|
1243
1559
|
}
|
|
1560
|
+
if (message.credit_balances !== void 0 && message.credit_balances !== null) {
|
|
1561
|
+
const contextStr = contextString(context);
|
|
1562
|
+
const updates = CreditBalancesFromJSON(message.credit_balances);
|
|
1563
|
+
const previous = this.creditBalances[contextStr] ?? {};
|
|
1564
|
+
let changed = false;
|
|
1565
|
+
const merged = { ...previous };
|
|
1566
|
+
for (const [creditId, next] of Object.entries(updates)) {
|
|
1567
|
+
const current = previous[creditId];
|
|
1568
|
+
if (current === void 0 || current.remaining !== next.remaining || current.reserved !== next.reserved || current.settled !== next.settled) {
|
|
1569
|
+
merged[creditId] = next;
|
|
1570
|
+
changed = true;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
if (changed) {
|
|
1574
|
+
this.creditBalances[contextStr] = merged;
|
|
1575
|
+
this.debug(
|
|
1576
|
+
`WebSocket credit balance update received. Notifying listeners`,
|
|
1577
|
+
{ creditBalances: merged }
|
|
1578
|
+
);
|
|
1579
|
+
this.notifyCreditBalanceListeners(merged);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
this.persistContextToCache(contextString(context));
|
|
1244
1583
|
this.flushContextDependentEventQueue();
|
|
1245
1584
|
this.setIsPending(false);
|
|
1246
1585
|
};
|
|
@@ -1348,7 +1687,32 @@ var Schematic = class {
|
|
|
1348
1687
|
return;
|
|
1349
1688
|
}
|
|
1350
1689
|
try {
|
|
1351
|
-
|
|
1690
|
+
const newContextStr = contextString(context);
|
|
1691
|
+
const cacheHit = this.hasCachedValuesForContext(newContextStr);
|
|
1692
|
+
if (cacheHit) {
|
|
1693
|
+
this.debug(
|
|
1694
|
+
`setContext: cache hit for context, pre-resolving from cached values`
|
|
1695
|
+
);
|
|
1696
|
+
this.context = context;
|
|
1697
|
+
this.flushContextDependentEventQueue();
|
|
1698
|
+
this.setIsPending(false);
|
|
1699
|
+
const cachedChecks = this.checks[newContextStr] ?? {};
|
|
1700
|
+
for (const [flagKey, check] of Object.entries(cachedChecks)) {
|
|
1701
|
+
if (check === void 0) continue;
|
|
1702
|
+
this.notifyFlagCheckListeners(flagKey, check);
|
|
1703
|
+
this.notifyFlagValueListeners(flagKey, check.value);
|
|
1704
|
+
}
|
|
1705
|
+
const cachedPlan = this.planChecks[newContextStr];
|
|
1706
|
+
if (cachedPlan !== void 0) {
|
|
1707
|
+
this.notifyPlanListeners(cachedPlan);
|
|
1708
|
+
}
|
|
1709
|
+
const cachedCreditBalances = this.creditBalances[newContextStr];
|
|
1710
|
+
if (cachedCreditBalances !== void 0) {
|
|
1711
|
+
this.notifyCreditBalanceListeners(cachedCreditBalances);
|
|
1712
|
+
}
|
|
1713
|
+
} else {
|
|
1714
|
+
this.setIsPending(true);
|
|
1715
|
+
}
|
|
1352
1716
|
if (!this.conn) {
|
|
1353
1717
|
if (this.isConnecting) {
|
|
1354
1718
|
this.debug(
|
|
@@ -1359,7 +1723,7 @@ var Schematic = class {
|
|
|
1359
1723
|
}
|
|
1360
1724
|
if (this.conn !== null) {
|
|
1361
1725
|
const socket2 = await this.conn;
|
|
1362
|
-
await this.wsSendMessage(socket2, context);
|
|
1726
|
+
await this.wsSendMessage(socket2, context, cacheHit);
|
|
1363
1727
|
return;
|
|
1364
1728
|
}
|
|
1365
1729
|
}
|
|
@@ -1375,7 +1739,7 @@ var Schematic = class {
|
|
|
1375
1739
|
this.conn = this.wsConnect();
|
|
1376
1740
|
const socket2 = await this.conn;
|
|
1377
1741
|
this.isConnecting = false;
|
|
1378
|
-
await this.wsSendMessage(socket2, context);
|
|
1742
|
+
await this.wsSendMessage(socket2, context, cacheHit);
|
|
1379
1743
|
return;
|
|
1380
1744
|
} catch (error) {
|
|
1381
1745
|
this.isConnecting = false;
|
|
@@ -1383,7 +1747,7 @@ var Schematic = class {
|
|
|
1383
1747
|
}
|
|
1384
1748
|
}
|
|
1385
1749
|
const socket = await this.conn;
|
|
1386
|
-
await this.wsSendMessage(socket, context);
|
|
1750
|
+
await this.wsSendMessage(socket, context, cacheHit);
|
|
1387
1751
|
} catch (error) {
|
|
1388
1752
|
console.warn("Failed to establish WebSocket connection:", error);
|
|
1389
1753
|
this.context = context;
|
|
@@ -1443,10 +1807,12 @@ var Schematic = class {
|
|
|
1443
1807
|
`Optimistically updating feature usage for event: ${eventName}`,
|
|
1444
1808
|
{ quantity }
|
|
1445
1809
|
);
|
|
1810
|
+
let dirty = false;
|
|
1446
1811
|
Object.entries(flagsForEvent).forEach(([flagKey, check]) => {
|
|
1447
1812
|
if (check === void 0) return;
|
|
1448
1813
|
const updatedCheck = { ...check };
|
|
1449
1814
|
if (typeof updatedCheck.featureUsage === "number") {
|
|
1815
|
+
dirty = true;
|
|
1450
1816
|
updatedCheck.featureUsage += quantity;
|
|
1451
1817
|
if (typeof updatedCheck.featureAllocation === "number") {
|
|
1452
1818
|
const wasExceeded = updatedCheck.featureUsageExceeded === true;
|
|
@@ -1476,6 +1842,9 @@ var Schematic = class {
|
|
|
1476
1842
|
this.notifyFlagValueListeners(flagKey, updatedCheck.value);
|
|
1477
1843
|
}
|
|
1478
1844
|
});
|
|
1845
|
+
if (dirty) {
|
|
1846
|
+
this.persistContextToCache(contextString(this.context));
|
|
1847
|
+
}
|
|
1479
1848
|
};
|
|
1480
1849
|
/**
|
|
1481
1850
|
* Event processing
|
|
@@ -1578,6 +1947,206 @@ var Schematic = class {
|
|
|
1578
1947
|
this.storage.setItem(anonymousIdKey, generatedAnonymousId);
|
|
1579
1948
|
return generatedAnonymousId;
|
|
1580
1949
|
};
|
|
1950
|
+
hasCachedValuesForContext = (contextStr) => {
|
|
1951
|
+
const cachedChecks = this.checks[contextStr];
|
|
1952
|
+
if (cachedChecks !== void 0 && Object.keys(cachedChecks).length > 0) {
|
|
1953
|
+
return true;
|
|
1954
|
+
}
|
|
1955
|
+
if (this.planChecks[contextStr] !== void 0) {
|
|
1956
|
+
return true;
|
|
1957
|
+
}
|
|
1958
|
+
const cachedCreditBalances = this.creditBalances[contextStr];
|
|
1959
|
+
return cachedCreditBalances !== void 0 && Object.keys(cachedCreditBalances).length > 0;
|
|
1960
|
+
};
|
|
1961
|
+
readFlagStateCache = () => {
|
|
1962
|
+
if (!this.persistFlagState || this.storage === void 0) {
|
|
1963
|
+
return null;
|
|
1964
|
+
}
|
|
1965
|
+
let raw;
|
|
1966
|
+
try {
|
|
1967
|
+
raw = this.storage.getItem(this.flagStateCacheKey);
|
|
1968
|
+
} catch (error) {
|
|
1969
|
+
this.debug("Failed to read flag state cache:", error);
|
|
1970
|
+
return null;
|
|
1971
|
+
}
|
|
1972
|
+
if (raw === null || raw === void 0) {
|
|
1973
|
+
return null;
|
|
1974
|
+
}
|
|
1975
|
+
let parsed;
|
|
1976
|
+
try {
|
|
1977
|
+
parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
1978
|
+
} catch (error) {
|
|
1979
|
+
this.debug("Flag state cache is not valid JSON, ignoring:", error);
|
|
1980
|
+
return null;
|
|
1981
|
+
}
|
|
1982
|
+
if (parsed === null || typeof parsed !== "object" || parsed.version !== cacheVersion || typeof parsed.contexts !== "object" || parsed.contexts === null) {
|
|
1983
|
+
this.debug(
|
|
1984
|
+
`Flag state cache invalid or version mismatch (expected ${cacheVersion}), ignoring`,
|
|
1985
|
+
{
|
|
1986
|
+
parsedType: typeof parsed,
|
|
1987
|
+
version: parsed?.version
|
|
1988
|
+
}
|
|
1989
|
+
);
|
|
1990
|
+
return null;
|
|
1991
|
+
}
|
|
1992
|
+
return parsed;
|
|
1993
|
+
};
|
|
1994
|
+
reviveCachedCheck = (raw) => {
|
|
1995
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
1996
|
+
const obj = raw;
|
|
1997
|
+
if (typeof obj.flag !== "string" || typeof obj.value !== "boolean" || typeof obj.reason !== "string") {
|
|
1998
|
+
return null;
|
|
1999
|
+
}
|
|
2000
|
+
const revived = { ...obj };
|
|
2001
|
+
if (typeof revived.featureUsageResetAt === "string") {
|
|
2002
|
+
const d = new Date(revived.featureUsageResetAt);
|
|
2003
|
+
revived.featureUsageResetAt = isNaN(d.getTime()) ? void 0 : d;
|
|
2004
|
+
}
|
|
2005
|
+
return revived;
|
|
2006
|
+
};
|
|
2007
|
+
reviveCachedPlan = (raw) => {
|
|
2008
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
2009
|
+
const obj = raw;
|
|
2010
|
+
if (typeof obj.id !== "string" || typeof obj.name !== "string") {
|
|
2011
|
+
return null;
|
|
2012
|
+
}
|
|
2013
|
+
const revived = { ...obj };
|
|
2014
|
+
if (typeof revived.trialEndDate === "string") {
|
|
2015
|
+
const d = new Date(revived.trialEndDate);
|
|
2016
|
+
revived.trialEndDate = isNaN(d.getTime()) ? void 0 : d;
|
|
2017
|
+
}
|
|
2018
|
+
return revived;
|
|
2019
|
+
};
|
|
2020
|
+
reviveCachedCreditBalances = (raw) => {
|
|
2021
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
2022
|
+
const revived = {};
|
|
2023
|
+
for (const [creditId, value] of Object.entries(
|
|
2024
|
+
raw
|
|
2025
|
+
)) {
|
|
2026
|
+
if (value === null || typeof value !== "object") continue;
|
|
2027
|
+
const obj = value;
|
|
2028
|
+
if (typeof obj.remaining !== "number" || typeof obj.reserved !== "number" || typeof obj.settled !== "number") {
|
|
2029
|
+
continue;
|
|
2030
|
+
}
|
|
2031
|
+
revived[creditId] = {
|
|
2032
|
+
remaining: obj.remaining,
|
|
2033
|
+
reserved: obj.reserved,
|
|
2034
|
+
settled: obj.settled
|
|
2035
|
+
};
|
|
2036
|
+
}
|
|
2037
|
+
return Object.keys(revived).length > 0 ? revived : null;
|
|
2038
|
+
};
|
|
2039
|
+
hydrateFlagStateFromCache = () => {
|
|
2040
|
+
const parsed = this.readFlagStateCache();
|
|
2041
|
+
if (parsed === null) return;
|
|
2042
|
+
const cutoff = Date.now() - this.flagStateCacheMaxAgeMs;
|
|
2043
|
+
const fresh = {};
|
|
2044
|
+
let contextsLoaded = 0;
|
|
2045
|
+
let contextsExpired = 0;
|
|
2046
|
+
for (const [contextStr, entry] of Object.entries(parsed.contexts)) {
|
|
2047
|
+
if (entry === null || typeof entry !== "object") continue;
|
|
2048
|
+
if (typeof entry.updatedAt !== "number") continue;
|
|
2049
|
+
if (entry.updatedAt < cutoff) {
|
|
2050
|
+
contextsExpired += 1;
|
|
2051
|
+
continue;
|
|
2052
|
+
}
|
|
2053
|
+
const revivedChecks = {};
|
|
2054
|
+
if (entry.checks !== null && typeof entry.checks === "object") {
|
|
2055
|
+
for (const [flagKey, rawCheck] of Object.entries(entry.checks)) {
|
|
2056
|
+
const revived = this.reviveCachedCheck(rawCheck);
|
|
2057
|
+
if (revived === null || revived.flag !== flagKey) continue;
|
|
2058
|
+
revivedChecks[flagKey] = revived;
|
|
2059
|
+
if (typeof revived.featureUsageEvent === "string") {
|
|
2060
|
+
this.updateFeatureUsageEventMap(revived);
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
if (Object.keys(revivedChecks).length > 0) {
|
|
2064
|
+
this.checks[contextStr] = revivedChecks;
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
let revivedPlan;
|
|
2068
|
+
if (entry.plan !== void 0 && entry.plan !== null) {
|
|
2069
|
+
const p = this.reviveCachedPlan(entry.plan);
|
|
2070
|
+
if (p !== null) {
|
|
2071
|
+
revivedPlan = p;
|
|
2072
|
+
this.planChecks[contextStr] = p;
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
let revivedCreditBalances;
|
|
2076
|
+
if (entry.creditBalances !== void 0 && entry.creditBalances !== null) {
|
|
2077
|
+
const balances = this.reviveCachedCreditBalances(entry.creditBalances);
|
|
2078
|
+
if (balances !== null) {
|
|
2079
|
+
revivedCreditBalances = balances;
|
|
2080
|
+
this.creditBalances[contextStr] = balances;
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
fresh[contextStr] = {
|
|
2084
|
+
checks: revivedChecks,
|
|
2085
|
+
plan: revivedPlan,
|
|
2086
|
+
creditBalances: revivedCreditBalances,
|
|
2087
|
+
updatedAt: entry.updatedAt
|
|
2088
|
+
};
|
|
2089
|
+
contextsLoaded += 1;
|
|
2090
|
+
}
|
|
2091
|
+
this.cachedFlagState = { version: cacheVersion, contexts: fresh };
|
|
2092
|
+
this.debug(
|
|
2093
|
+
`Hydrated flag state cache: ${contextsLoaded} loaded, ${contextsExpired} expired`
|
|
2094
|
+
);
|
|
2095
|
+
};
|
|
2096
|
+
persistContextToCache = (contextStr) => {
|
|
2097
|
+
const checksForContext = this.checks[contextStr];
|
|
2098
|
+
const planForContext = this.planChecks[contextStr];
|
|
2099
|
+
const creditBalancesForContext = this.creditBalances[contextStr];
|
|
2100
|
+
if (checksForContext === void 0 && planForContext === void 0 && creditBalancesForContext === void 0) {
|
|
2101
|
+
return;
|
|
2102
|
+
}
|
|
2103
|
+
if (this.cachedFlagState === null) {
|
|
2104
|
+
this.cachedFlagState = (this.persistFlagState ? this.readFlagStateCache() : null) ?? {
|
|
2105
|
+
version: cacheVersion,
|
|
2106
|
+
contexts: {}
|
|
2107
|
+
};
|
|
2108
|
+
}
|
|
2109
|
+
const cleanChecks = {};
|
|
2110
|
+
if (checksForContext !== void 0) {
|
|
2111
|
+
for (const [flagKey, check] of Object.entries(checksForContext)) {
|
|
2112
|
+
if (check !== void 0) cleanChecks[flagKey] = check;
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
this.cachedFlagState.contexts[contextStr] = {
|
|
2116
|
+
checks: cleanChecks,
|
|
2117
|
+
plan: planForContext,
|
|
2118
|
+
creditBalances: creditBalancesForContext,
|
|
2119
|
+
updatedAt: Date.now()
|
|
2120
|
+
};
|
|
2121
|
+
const entries = Object.entries(this.cachedFlagState.contexts);
|
|
2122
|
+
if (entries.length > flagStateCacheMaxContexts) {
|
|
2123
|
+
entries.sort((a, b) => b[1].updatedAt - a[1].updatedAt);
|
|
2124
|
+
const survivors = entries.slice(0, flagStateCacheMaxContexts);
|
|
2125
|
+
const survivorKeys = new Set(survivors.map(([k]) => k));
|
|
2126
|
+
for (const key of Object.keys(this.checks)) {
|
|
2127
|
+
if (!survivorKeys.has(key)) delete this.checks[key];
|
|
2128
|
+
}
|
|
2129
|
+
for (const key of Object.keys(this.planChecks)) {
|
|
2130
|
+
if (!survivorKeys.has(key)) delete this.planChecks[key];
|
|
2131
|
+
}
|
|
2132
|
+
for (const key of Object.keys(this.creditBalances)) {
|
|
2133
|
+
if (!survivorKeys.has(key)) delete this.creditBalances[key];
|
|
2134
|
+
}
|
|
2135
|
+
this.cachedFlagState = {
|
|
2136
|
+
version: cacheVersion,
|
|
2137
|
+
contexts: Object.fromEntries(survivors)
|
|
2138
|
+
};
|
|
2139
|
+
}
|
|
2140
|
+
if (!this.persistFlagState || this.storage === void 0) return;
|
|
2141
|
+
try {
|
|
2142
|
+
this.storage.setItem(
|
|
2143
|
+
this.flagStateCacheKey,
|
|
2144
|
+
JSON.stringify(this.cachedFlagState)
|
|
2145
|
+
);
|
|
2146
|
+
} catch (error) {
|
|
2147
|
+
this.debug("Failed to write flag state cache:", error);
|
|
2148
|
+
}
|
|
2149
|
+
};
|
|
1581
2150
|
handleEvent = (eventType, eventBody) => {
|
|
1582
2151
|
const event = {
|
|
1583
2152
|
api_key: this.apiKey,
|
|
@@ -1838,6 +2407,9 @@ var Schematic = class {
|
|
|
1838
2407
|
if (this.conn !== null) {
|
|
1839
2408
|
try {
|
|
1840
2409
|
const socket = await this.conn;
|
|
2410
|
+
if (this.currentWebSocket === socket) {
|
|
2411
|
+
this.currentWebSocket = null;
|
|
2412
|
+
}
|
|
1841
2413
|
if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
|
|
1842
2414
|
socket.close();
|
|
1843
2415
|
}
|
|
@@ -2003,6 +2575,7 @@ var Schematic = class {
|
|
|
2003
2575
|
this.debug(`Creating WebSocket connection ${connectionId} to ${wsUrl}`);
|
|
2004
2576
|
let timeoutId = null;
|
|
2005
2577
|
let isResolved = false;
|
|
2578
|
+
let didOpen = false;
|
|
2006
2579
|
timeoutId = setTimeout(() => {
|
|
2007
2580
|
if (!isResolved) {
|
|
2008
2581
|
isResolved = true;
|
|
@@ -2016,6 +2589,7 @@ var Schematic = class {
|
|
|
2016
2589
|
webSocket.onopen = () => {
|
|
2017
2590
|
if (isResolved) return;
|
|
2018
2591
|
isResolved = true;
|
|
2592
|
+
didOpen = true;
|
|
2019
2593
|
if (timeoutId !== null) {
|
|
2020
2594
|
clearTimeout(timeoutId);
|
|
2021
2595
|
}
|
|
@@ -2041,11 +2615,12 @@ var Schematic = class {
|
|
|
2041
2615
|
}
|
|
2042
2616
|
this.debug(`WebSocket connection ${connectionId} closed`);
|
|
2043
2617
|
this.conn = null;
|
|
2618
|
+
const wasCurrent = this.currentWebSocket === webSocket;
|
|
2044
2619
|
if (this.currentWebSocket === webSocket) {
|
|
2045
2620
|
this.currentWebSocket = null;
|
|
2046
2621
|
this.isConnecting = false;
|
|
2047
2622
|
}
|
|
2048
|
-
if (
|
|
2623
|
+
if (wasCurrent && didOpen && !this.wsIntentionalDisconnect && this.webSocketReconnect) {
|
|
2049
2624
|
this.attemptReconnect();
|
|
2050
2625
|
}
|
|
2051
2626
|
};
|
|
@@ -2141,6 +2716,16 @@ var Schematic = class {
|
|
|
2141
2716
|
const plan = this.planChecks[contextStr];
|
|
2142
2717
|
return plan;
|
|
2143
2718
|
};
|
|
2719
|
+
/** Get the company's lease-aware credit balances for the current context, keyed by credit ID */
|
|
2720
|
+
getCreditBalances = () => {
|
|
2721
|
+
const contextStr = contextString(this.context);
|
|
2722
|
+
return this.creditBalances[contextStr] ?? emptyCreditBalances;
|
|
2723
|
+
};
|
|
2724
|
+
/** Get the company's lease-aware balance for a single credit type in the current context */
|
|
2725
|
+
getCreditBalance = (creditId) => {
|
|
2726
|
+
const contextStr = contextString(this.context);
|
|
2727
|
+
return this.creditBalances[contextStr]?.[creditId];
|
|
2728
|
+
};
|
|
2144
2729
|
// flag checks state
|
|
2145
2730
|
getFlagCheck = (flagKey) => {
|
|
2146
2731
|
const contextStr = contextString(this.context);
|
|
@@ -2200,6 +2785,13 @@ var Schematic = class {
|
|
|
2200
2785
|
this.planListeners.delete(listener);
|
|
2201
2786
|
};
|
|
2202
2787
|
};
|
|
2788
|
+
/** Register an event listener that will be notified with the company's credit balances (keyed by credit ID) whenever they change */
|
|
2789
|
+
addCreditBalanceListener = (listener) => {
|
|
2790
|
+
this.creditBalanceListeners.add(listener);
|
|
2791
|
+
return () => {
|
|
2792
|
+
this.creditBalanceListeners.delete(listener);
|
|
2793
|
+
};
|
|
2794
|
+
};
|
|
2203
2795
|
notifyFlagCheckListeners = (flagKey, check) => {
|
|
2204
2796
|
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
2205
2797
|
if (listeners.size > 0) {
|
|
@@ -2263,6 +2855,17 @@ var Schematic = class {
|
|
|
2263
2855
|
});
|
|
2264
2856
|
});
|
|
2265
2857
|
};
|
|
2858
|
+
notifyCreditBalanceListeners = (value) => {
|
|
2859
|
+
const listeners = this.creditBalanceListeners ?? [];
|
|
2860
|
+
if (listeners.size > 0) {
|
|
2861
|
+
this.debug(`Notifying ${listeners.size} credit balance listeners`, {
|
|
2862
|
+
value
|
|
2863
|
+
});
|
|
2864
|
+
}
|
|
2865
|
+
listeners.forEach(
|
|
2866
|
+
(listener) => notifyCreditBalanceListener(listener, value)
|
|
2867
|
+
);
|
|
2868
|
+
};
|
|
2266
2869
|
};
|
|
2267
2870
|
var notifyPendingListener = (listener, value) => {
|
|
2268
2871
|
if (listener.length > 0) {
|
|
@@ -2292,12 +2895,19 @@ var notifyPlanListener = (listener, value) => {
|
|
|
2292
2895
|
listener();
|
|
2293
2896
|
}
|
|
2294
2897
|
};
|
|
2898
|
+
var notifyCreditBalanceListener = (listener, value) => {
|
|
2899
|
+
if (listener.length > 0) {
|
|
2900
|
+
listener(value);
|
|
2901
|
+
} else {
|
|
2902
|
+
listener();
|
|
2903
|
+
}
|
|
2904
|
+
};
|
|
2295
2905
|
|
|
2296
2906
|
// src/context/schematic.ts
|
|
2297
2907
|
var import_vue = require("vue");
|
|
2298
2908
|
|
|
2299
2909
|
// src/version.ts
|
|
2300
|
-
var version2 = "1.
|
|
2910
|
+
var version2 = "1.5.0";
|
|
2301
2911
|
|
|
2302
2912
|
// src/context/schematic.ts
|
|
2303
2913
|
var SchematicSymbol = Symbol("schematic");
|
|
@@ -2430,6 +3040,35 @@ var useSchematicPlan = (opts) => {
|
|
|
2430
3040
|
});
|
|
2431
3041
|
return plan;
|
|
2432
3042
|
};
|
|
3043
|
+
var useSchematicCreditBalance = (creditId, opts) => {
|
|
3044
|
+
const client = useSchematicClient(opts);
|
|
3045
|
+
const creditBalance = (0, import_vue2.ref)(
|
|
3046
|
+
client.getCreditBalance(creditId)
|
|
3047
|
+
);
|
|
3048
|
+
const isPending = (0, import_vue2.ref)(client.getIsPending());
|
|
3049
|
+
let unsubscribeBalance = null;
|
|
3050
|
+
let unsubscribePending = null;
|
|
3051
|
+
(0, import_vue2.onMounted)(() => {
|
|
3052
|
+
unsubscribeBalance = client.addCreditBalanceListener(() => {
|
|
3053
|
+
creditBalance.value = client.getCreditBalance(creditId);
|
|
3054
|
+
});
|
|
3055
|
+
unsubscribePending = client.addIsPendingListener(() => {
|
|
3056
|
+
isPending.value = client.getIsPending();
|
|
3057
|
+
});
|
|
3058
|
+
});
|
|
3059
|
+
(0, import_vue2.onScopeDispose)(() => {
|
|
3060
|
+
unsubscribeBalance?.();
|
|
3061
|
+
unsubscribePending?.();
|
|
3062
|
+
});
|
|
3063
|
+
return {
|
|
3064
|
+
/** The spendable balance; 0 while loading or when the company holds no balance in this credit */
|
|
3065
|
+
balance: (0, import_vue2.computed)(() => creditBalance.value?.settled ?? 0),
|
|
3066
|
+
/** True while the balance is still loading and no value has arrived yet */
|
|
3067
|
+
isLoading: (0, import_vue2.computed)(
|
|
3068
|
+
() => creditBalance.value === void 0 && isPending.value
|
|
3069
|
+
)
|
|
3070
|
+
};
|
|
3071
|
+
};
|
|
2433
3072
|
var useSchematicIsPending = (opts) => {
|
|
2434
3073
|
const client = useSchematicClient(opts);
|
|
2435
3074
|
const isPending = (0, import_vue2.ref)(client.getIsPending());
|