@schematichq/schematic-vue 1.4.1 → 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 +201 -22
- package/dist/schematic-vue.esm.js +666 -27
- package/package.json +3 -2
|
@@ -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 __copyProps = (to, from, except, desc) => {
|
|
12
16
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -565,19 +569,16 @@ for (let i = 0; i < 256; ++i) {
|
|
|
565
569
|
function unsafeStringify(arr, offset = 0) {
|
|
566
570
|
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();
|
|
567
571
|
}
|
|
568
|
-
var getRandomValues;
|
|
569
572
|
var rnds8 = new Uint8Array(16);
|
|
570
573
|
function rng() {
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
574
|
+
return crypto.getRandomValues(rnds8);
|
|
575
|
+
}
|
|
576
|
+
function v4(options, buf, offset) {
|
|
577
|
+
if (!buf && !options && crypto.randomUUID) {
|
|
578
|
+
return crypto.randomUUID();
|
|
576
579
|
}
|
|
577
|
-
return
|
|
580
|
+
return _v4(options, buf, offset);
|
|
578
581
|
}
|
|
579
|
-
var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
580
|
-
var native_default = { randomUUID };
|
|
581
582
|
function _v4(options, buf, offset) {
|
|
582
583
|
options = options || {};
|
|
583
584
|
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
@@ -598,12 +599,6 @@ function _v4(options, buf, offset) {
|
|
|
598
599
|
}
|
|
599
600
|
return unsafeStringify(rnds);
|
|
600
601
|
}
|
|
601
|
-
function v4(options, buf, offset) {
|
|
602
|
-
if (native_default.randomUUID && !buf && !options) {
|
|
603
|
-
return native_default.randomUUID();
|
|
604
|
-
}
|
|
605
|
-
return _v4(options, buf, offset);
|
|
606
|
-
}
|
|
607
602
|
var v4_default = v4;
|
|
608
603
|
var import_polyfill = __toESM(require_browser_polyfill());
|
|
609
604
|
function EntitlementValueTypeFromJSON(json) {
|
|
@@ -612,6 +607,18 @@ function EntitlementValueTypeFromJSON(json) {
|
|
|
612
607
|
function EntitlementValueTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
613
608
|
return json;
|
|
614
609
|
}
|
|
610
|
+
function MetricPeriodMonthResetFromJSON(json) {
|
|
611
|
+
return MetricPeriodMonthResetFromJSONTyped(json, false);
|
|
612
|
+
}
|
|
613
|
+
function MetricPeriodMonthResetFromJSONTyped(json, ignoreDiscriminator) {
|
|
614
|
+
return json;
|
|
615
|
+
}
|
|
616
|
+
function MetricPeriodFromJSON(json) {
|
|
617
|
+
return MetricPeriodFromJSONTyped(json, false);
|
|
618
|
+
}
|
|
619
|
+
function MetricPeriodFromJSONTyped(json, ignoreDiscriminator) {
|
|
620
|
+
return json;
|
|
621
|
+
}
|
|
615
622
|
function FeatureEntitlementFromJSON(json) {
|
|
616
623
|
return FeatureEntitlementFromJSONTyped(json, false);
|
|
617
624
|
}
|
|
@@ -621,21 +628,31 @@ function FeatureEntitlementFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
621
628
|
}
|
|
622
629
|
return {
|
|
623
630
|
allocation: json["allocation"] == null ? void 0 : json["allocation"],
|
|
631
|
+
consumptionRate: json["consumption_rate"] == null ? void 0 : json["consumption_rate"],
|
|
624
632
|
creditId: json["credit_id"] == null ? void 0 : json["credit_id"],
|
|
625
633
|
creditRemaining: json["credit_remaining"] == null ? void 0 : json["credit_remaining"],
|
|
634
|
+
creditReserved: json["credit_reserved"] == null ? void 0 : json["credit_reserved"],
|
|
635
|
+
creditSettled: json["credit_settled"] == null ? void 0 : json["credit_settled"],
|
|
626
636
|
creditTotal: json["credit_total"] == null ? void 0 : json["credit_total"],
|
|
627
637
|
creditUsed: json["credit_used"] == null ? void 0 : json["credit_used"],
|
|
628
638
|
eventName: json["event_name"] == null ? void 0 : json["event_name"],
|
|
639
|
+
eventSubtype: json["event_subtype"] == null ? void 0 : json["event_subtype"],
|
|
629
640
|
featureId: json["feature_id"],
|
|
630
641
|
featureKey: json["feature_key"],
|
|
631
|
-
metricPeriod: json["metric_period"] == null ? void 0 : json["metric_period"],
|
|
642
|
+
metricPeriod: json["metric_period"] == null ? void 0 : MetricPeriodFromJSON(json["metric_period"]),
|
|
632
643
|
metricResetAt: json["metric_reset_at"] == null ? void 0 : new Date(json["metric_reset_at"]),
|
|
633
|
-
monthReset: json["month_reset"] == null ? void 0 : json["month_reset"],
|
|
644
|
+
monthReset: json["month_reset"] == null ? void 0 : MetricPeriodMonthResetFromJSON(json["month_reset"]),
|
|
634
645
|
softLimit: json["soft_limit"] == null ? void 0 : json["soft_limit"],
|
|
635
646
|
usage: json["usage"] == null ? void 0 : json["usage"],
|
|
636
647
|
valueType: EntitlementValueTypeFromJSON(json["value_type"])
|
|
637
648
|
};
|
|
638
649
|
}
|
|
650
|
+
function RuleTypeFromJSON(json) {
|
|
651
|
+
return RuleTypeFromJSONTyped(json, false);
|
|
652
|
+
}
|
|
653
|
+
function RuleTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
654
|
+
return json;
|
|
655
|
+
}
|
|
639
656
|
function CheckFlagResponseDataFromJSON(json) {
|
|
640
657
|
return CheckFlagResponseDataFromJSONTyped(json, false);
|
|
641
658
|
}
|
|
@@ -650,13 +667,13 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
650
667
|
featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
|
|
651
668
|
featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
|
|
652
669
|
featureUsageEvent: json["feature_usage_event"] == null ? void 0 : json["feature_usage_event"],
|
|
653
|
-
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
|
|
670
|
+
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : MetricPeriodFromJSON(json["feature_usage_period"]),
|
|
654
671
|
featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
|
|
655
672
|
flag: json["flag"],
|
|
656
673
|
flagId: json["flag_id"] == null ? void 0 : json["flag_id"],
|
|
657
674
|
reason: json["reason"],
|
|
658
675
|
ruleId: json["rule_id"] == null ? void 0 : json["rule_id"],
|
|
659
|
-
ruleType: json["rule_type"] == null ? void 0 : json["rule_type"],
|
|
676
|
+
ruleType: json["rule_type"] == null ? void 0 : RuleTypeFromJSON(json["rule_type"]),
|
|
660
677
|
userId: json["user_id"] == null ? void 0 : json["user_id"],
|
|
661
678
|
value: json["value"]
|
|
662
679
|
};
|
|
@@ -673,6 +690,268 @@ function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
673
690
|
params: json["params"]
|
|
674
691
|
};
|
|
675
692
|
}
|
|
693
|
+
var BASE_PATH = "https://api.schematichq.com".replace(/\/+$/, "");
|
|
694
|
+
var Configuration = class {
|
|
695
|
+
constructor(configuration = {}) {
|
|
696
|
+
this.configuration = configuration;
|
|
697
|
+
}
|
|
698
|
+
configuration;
|
|
699
|
+
set config(configuration) {
|
|
700
|
+
this.configuration = configuration;
|
|
701
|
+
}
|
|
702
|
+
get basePath() {
|
|
703
|
+
return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH;
|
|
704
|
+
}
|
|
705
|
+
get fetchApi() {
|
|
706
|
+
return this.configuration.fetchApi;
|
|
707
|
+
}
|
|
708
|
+
get middleware() {
|
|
709
|
+
return this.configuration.middleware || [];
|
|
710
|
+
}
|
|
711
|
+
get queryParamsStringify() {
|
|
712
|
+
return this.configuration.queryParamsStringify || querystring;
|
|
713
|
+
}
|
|
714
|
+
get username() {
|
|
715
|
+
return this.configuration.username;
|
|
716
|
+
}
|
|
717
|
+
get password() {
|
|
718
|
+
return this.configuration.password;
|
|
719
|
+
}
|
|
720
|
+
get apiKey() {
|
|
721
|
+
const apiKey = this.configuration.apiKey;
|
|
722
|
+
if (apiKey) {
|
|
723
|
+
return typeof apiKey === "function" ? apiKey : () => apiKey;
|
|
724
|
+
}
|
|
725
|
+
return void 0;
|
|
726
|
+
}
|
|
727
|
+
get accessToken() {
|
|
728
|
+
const accessToken = this.configuration.accessToken;
|
|
729
|
+
if (accessToken) {
|
|
730
|
+
return typeof accessToken === "function" ? accessToken : async () => accessToken;
|
|
731
|
+
}
|
|
732
|
+
return void 0;
|
|
733
|
+
}
|
|
734
|
+
get headers() {
|
|
735
|
+
return this.configuration.headers;
|
|
736
|
+
}
|
|
737
|
+
get credentials() {
|
|
738
|
+
return this.configuration.credentials;
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
var DefaultConfig = new Configuration();
|
|
742
|
+
var BaseAPI = class _BaseAPI {
|
|
743
|
+
constructor(configuration = DefaultConfig) {
|
|
744
|
+
this.configuration = configuration;
|
|
745
|
+
this.middleware = configuration.middleware;
|
|
746
|
+
}
|
|
747
|
+
configuration;
|
|
748
|
+
static jsonRegex = new RegExp(
|
|
749
|
+
"^(:?application/json|[^;/ ]+/[^;/ ]+[+]json)[ ]*(:?;.*)?$",
|
|
750
|
+
"i"
|
|
751
|
+
);
|
|
752
|
+
middleware;
|
|
753
|
+
withMiddleware(...middlewares) {
|
|
754
|
+
const next = this.clone();
|
|
755
|
+
next.middleware = next.middleware.concat(...middlewares);
|
|
756
|
+
return next;
|
|
757
|
+
}
|
|
758
|
+
withPreMiddleware(...preMiddlewares) {
|
|
759
|
+
const middlewares = preMiddlewares.map((pre) => ({ pre }));
|
|
760
|
+
return this.withMiddleware(...middlewares);
|
|
761
|
+
}
|
|
762
|
+
withPostMiddleware(...postMiddlewares) {
|
|
763
|
+
const middlewares = postMiddlewares.map((post) => ({ post }));
|
|
764
|
+
return this.withMiddleware(...middlewares);
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Check if the given MIME is a JSON MIME.
|
|
768
|
+
* JSON MIME examples:
|
|
769
|
+
* application/json
|
|
770
|
+
* application/json; charset=UTF8
|
|
771
|
+
* APPLICATION/JSON
|
|
772
|
+
* application/vnd.company+json
|
|
773
|
+
* @param mime - MIME (Multipurpose Internet Mail Extensions)
|
|
774
|
+
* @return True if the given MIME is JSON, false otherwise.
|
|
775
|
+
*/
|
|
776
|
+
isJsonMime(mime) {
|
|
777
|
+
if (!mime) {
|
|
778
|
+
return false;
|
|
779
|
+
}
|
|
780
|
+
return _BaseAPI.jsonRegex.test(mime);
|
|
781
|
+
}
|
|
782
|
+
async request(context, initOverrides) {
|
|
783
|
+
const { url, init } = await this.createFetchParams(context, initOverrides);
|
|
784
|
+
const response = await this.fetchApi(url, init);
|
|
785
|
+
if (response && response.status >= 200 && response.status < 300) {
|
|
786
|
+
return response;
|
|
787
|
+
}
|
|
788
|
+
throw new ResponseError(response, "Response returned an error code");
|
|
789
|
+
}
|
|
790
|
+
async createFetchParams(context, initOverrides) {
|
|
791
|
+
let url = this.configuration.basePath + context.path;
|
|
792
|
+
if (context.query !== void 0 && Object.keys(context.query).length !== 0) {
|
|
793
|
+
url += "?" + this.configuration.queryParamsStringify(context.query);
|
|
794
|
+
}
|
|
795
|
+
const headers = Object.assign(
|
|
796
|
+
{},
|
|
797
|
+
this.configuration.headers,
|
|
798
|
+
context.headers
|
|
799
|
+
);
|
|
800
|
+
Object.keys(headers).forEach(
|
|
801
|
+
(key) => headers[key] === void 0 ? delete headers[key] : {}
|
|
802
|
+
);
|
|
803
|
+
const initOverrideFn = typeof initOverrides === "function" ? initOverrides : async () => initOverrides;
|
|
804
|
+
const initParams = {
|
|
805
|
+
method: context.method,
|
|
806
|
+
headers,
|
|
807
|
+
body: context.body,
|
|
808
|
+
credentials: this.configuration.credentials
|
|
809
|
+
};
|
|
810
|
+
const overriddenInit = {
|
|
811
|
+
...initParams,
|
|
812
|
+
...await initOverrideFn({
|
|
813
|
+
init: initParams,
|
|
814
|
+
context
|
|
815
|
+
})
|
|
816
|
+
};
|
|
817
|
+
let body;
|
|
818
|
+
if (isFormData(overriddenInit.body) || overriddenInit.body instanceof URLSearchParams || isBlob(overriddenInit.body)) {
|
|
819
|
+
body = overriddenInit.body;
|
|
820
|
+
} else if (this.isJsonMime(headers["Content-Type"])) {
|
|
821
|
+
body = JSON.stringify(overriddenInit.body);
|
|
822
|
+
} else {
|
|
823
|
+
body = overriddenInit.body;
|
|
824
|
+
}
|
|
825
|
+
const init = {
|
|
826
|
+
...overriddenInit,
|
|
827
|
+
body
|
|
828
|
+
};
|
|
829
|
+
return { url, init };
|
|
830
|
+
}
|
|
831
|
+
fetchApi = async (url, init) => {
|
|
832
|
+
let fetchParams = { url, init };
|
|
833
|
+
for (const middleware of this.middleware) {
|
|
834
|
+
if (middleware.pre) {
|
|
835
|
+
fetchParams = await middleware.pre({
|
|
836
|
+
fetch: this.fetchApi,
|
|
837
|
+
...fetchParams
|
|
838
|
+
}) || fetchParams;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
let response = void 0;
|
|
842
|
+
try {
|
|
843
|
+
response = await (this.configuration.fetchApi || fetch)(
|
|
844
|
+
fetchParams.url,
|
|
845
|
+
fetchParams.init
|
|
846
|
+
);
|
|
847
|
+
} catch (e) {
|
|
848
|
+
for (const middleware of this.middleware) {
|
|
849
|
+
if (middleware.onError) {
|
|
850
|
+
response = await middleware.onError({
|
|
851
|
+
fetch: this.fetchApi,
|
|
852
|
+
url: fetchParams.url,
|
|
853
|
+
init: fetchParams.init,
|
|
854
|
+
error: e,
|
|
855
|
+
response: response ? response.clone() : void 0
|
|
856
|
+
}) || response;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
if (response === void 0) {
|
|
860
|
+
if (e instanceof Error) {
|
|
861
|
+
throw new FetchError(
|
|
862
|
+
e,
|
|
863
|
+
"The request failed and the interceptors did not return an alternative response"
|
|
864
|
+
);
|
|
865
|
+
} else {
|
|
866
|
+
throw e;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
for (const middleware of this.middleware) {
|
|
871
|
+
if (middleware.post) {
|
|
872
|
+
response = await middleware.post({
|
|
873
|
+
fetch: this.fetchApi,
|
|
874
|
+
url: fetchParams.url,
|
|
875
|
+
init: fetchParams.init,
|
|
876
|
+
response: response.clone()
|
|
877
|
+
}) || response;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
return response;
|
|
881
|
+
};
|
|
882
|
+
/**
|
|
883
|
+
* Create a shallow clone of `this` by constructing a new instance
|
|
884
|
+
* and then shallow cloning data members.
|
|
885
|
+
*/
|
|
886
|
+
clone() {
|
|
887
|
+
const constructor = this.constructor;
|
|
888
|
+
const next = new constructor(this.configuration);
|
|
889
|
+
next.middleware = this.middleware.slice();
|
|
890
|
+
return next;
|
|
891
|
+
}
|
|
892
|
+
};
|
|
893
|
+
function isBlob(value) {
|
|
894
|
+
return typeof Blob !== "undefined" && value instanceof Blob;
|
|
895
|
+
}
|
|
896
|
+
function isFormData(value) {
|
|
897
|
+
return typeof FormData !== "undefined" && value instanceof FormData;
|
|
898
|
+
}
|
|
899
|
+
var ResponseError = class extends Error {
|
|
900
|
+
constructor(response, msg) {
|
|
901
|
+
super(msg);
|
|
902
|
+
this.response = response;
|
|
903
|
+
}
|
|
904
|
+
response;
|
|
905
|
+
name = "ResponseError";
|
|
906
|
+
};
|
|
907
|
+
var FetchError = class extends Error {
|
|
908
|
+
constructor(cause, msg) {
|
|
909
|
+
super(msg);
|
|
910
|
+
this.cause = cause;
|
|
911
|
+
}
|
|
912
|
+
cause;
|
|
913
|
+
name = "FetchError";
|
|
914
|
+
};
|
|
915
|
+
function querystring(params, prefix = "") {
|
|
916
|
+
return Object.keys(params).map((key) => querystringSingleKey(key, params[key], prefix)).filter((part) => part.length > 0).join("&");
|
|
917
|
+
}
|
|
918
|
+
function querystringSingleKey(key, value, keyPrefix = "") {
|
|
919
|
+
const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key);
|
|
920
|
+
if (value instanceof Array) {
|
|
921
|
+
const multiValue = value.map((singleValue) => encodeURIComponent(String(singleValue))).join(`&${encodeURIComponent(fullKey)}=`);
|
|
922
|
+
return `${encodeURIComponent(fullKey)}=${multiValue}`;
|
|
923
|
+
}
|
|
924
|
+
if (value instanceof Set) {
|
|
925
|
+
const valueAsArray = Array.from(value);
|
|
926
|
+
return querystringSingleKey(key, valueAsArray, keyPrefix);
|
|
927
|
+
}
|
|
928
|
+
if (value instanceof Date) {
|
|
929
|
+
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`;
|
|
930
|
+
}
|
|
931
|
+
if (value instanceof Object) {
|
|
932
|
+
return querystring(value, fullKey);
|
|
933
|
+
}
|
|
934
|
+
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`;
|
|
935
|
+
}
|
|
936
|
+
function mapValues(data, fn) {
|
|
937
|
+
return Object.keys(data).reduce(
|
|
938
|
+
(acc, key) => ({ ...acc, [key]: fn(data[key]) }),
|
|
939
|
+
{}
|
|
940
|
+
);
|
|
941
|
+
}
|
|
942
|
+
function CompanyCreditBalanceFromJSON(json) {
|
|
943
|
+
return CompanyCreditBalanceFromJSONTyped(json, false);
|
|
944
|
+
}
|
|
945
|
+
function CompanyCreditBalanceFromJSONTyped(json, ignoreDiscriminator) {
|
|
946
|
+
if (json == null) {
|
|
947
|
+
return json;
|
|
948
|
+
}
|
|
949
|
+
return {
|
|
950
|
+
remaining: json["remaining"],
|
|
951
|
+
reserved: json["reserved"],
|
|
952
|
+
settled: json["settled"]
|
|
953
|
+
};
|
|
954
|
+
}
|
|
676
955
|
function TrialStatusFromJSON(json) {
|
|
677
956
|
return TrialStatusFromJSONTyped(json, false);
|
|
678
957
|
}
|
|
@@ -701,6 +980,7 @@ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
701
980
|
return json;
|
|
702
981
|
}
|
|
703
982
|
return {
|
|
983
|
+
creditBalances: json["credit_balances"] == null ? void 0 : mapValues(json["credit_balances"], CompanyCreditBalanceFromJSON),
|
|
704
984
|
flags: json["flags"].map(CheckFlagResponseDataFromJSON),
|
|
705
985
|
plan: json["plan"] == null ? void 0 : DatastreamCompanyPlanFromJSON(json["plan"])
|
|
706
986
|
};
|
|
@@ -783,7 +1063,10 @@ var CheckFlagReturnFromJSON = (json) => {
|
|
|
783
1063
|
return {
|
|
784
1064
|
featureUsageExceeded,
|
|
785
1065
|
companyId: companyId == null ? void 0 : companyId,
|
|
1066
|
+
creditId: entitlement?.creditId == null ? void 0 : entitlement.creditId,
|
|
786
1067
|
creditRemaining: entitlement?.creditRemaining == null ? void 0 : entitlement.creditRemaining,
|
|
1068
|
+
creditReserved: entitlement?.creditReserved == null ? void 0 : entitlement.creditReserved,
|
|
1069
|
+
creditSettled: entitlement?.creditSettled == null ? void 0 : entitlement.creditSettled,
|
|
787
1070
|
error: error == null ? void 0 : error,
|
|
788
1071
|
featureAllocation: resolvedAllocation == null ? void 0 : resolvedAllocation,
|
|
789
1072
|
featureUsage: resolvedUsage == null ? void 0 : resolvedUsage,
|
|
@@ -809,6 +1092,22 @@ var CheckPlanReturnFromJSON = (json) => {
|
|
|
809
1092
|
trialStatus: trialStatus == null ? void 0 : trialStatus
|
|
810
1093
|
};
|
|
811
1094
|
};
|
|
1095
|
+
var CreditBalancesFromJSON = (json) => {
|
|
1096
|
+
if (json == null || typeof json !== "object") {
|
|
1097
|
+
return {};
|
|
1098
|
+
}
|
|
1099
|
+
const balances = {};
|
|
1100
|
+
for (const [creditId, raw] of Object.entries(json)) {
|
|
1101
|
+
if (raw == null || typeof raw !== "object") continue;
|
|
1102
|
+
const { remaining, reserved, settled } = CompanyCreditBalanceFromJSON(raw);
|
|
1103
|
+
if (typeof remaining !== "number" || typeof reserved !== "number" || typeof settled !== "number") {
|
|
1104
|
+
continue;
|
|
1105
|
+
}
|
|
1106
|
+
balances[creditId] = { remaining, reserved, settled };
|
|
1107
|
+
}
|
|
1108
|
+
return balances;
|
|
1109
|
+
};
|
|
1110
|
+
var cacheVersion = "bb56e75d";
|
|
812
1111
|
function contextString(context) {
|
|
813
1112
|
const sortedContext = Object.keys(context).reduce((acc, key) => {
|
|
814
1113
|
const sortedKeys = Object.keys(
|
|
@@ -823,8 +1122,12 @@ function contextString(context) {
|
|
|
823
1122
|
}, {});
|
|
824
1123
|
return JSON.stringify(sortedContext);
|
|
825
1124
|
}
|
|
826
|
-
var version = "1.
|
|
1125
|
+
var version = "1.5.0";
|
|
827
1126
|
var anonymousIdKey = "schematicId";
|
|
1127
|
+
var flagStateCachePrefix = "schematicCache";
|
|
1128
|
+
var flagStateCacheMaxContexts = 10;
|
|
1129
|
+
var flagStateCacheDefaultMaxAgeMs = 7 * 24 * 60 * 60 * 1e3;
|
|
1130
|
+
var emptyCreditBalances = Object.freeze({});
|
|
828
1131
|
var Schematic = class {
|
|
829
1132
|
additionalHeaders = {};
|
|
830
1133
|
apiKey;
|
|
@@ -841,11 +1144,17 @@ var Schematic = class {
|
|
|
841
1144
|
isPending = true;
|
|
842
1145
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
843
1146
|
planListeners = /* @__PURE__ */ new Set();
|
|
1147
|
+
creditBalanceListeners = /* @__PURE__ */ new Set();
|
|
844
1148
|
storage;
|
|
1149
|
+
persistFlagState = true;
|
|
1150
|
+
flagStateCacheKey;
|
|
1151
|
+
flagStateCacheMaxAgeMs = flagStateCacheDefaultMaxAgeMs;
|
|
1152
|
+
cachedFlagState = null;
|
|
845
1153
|
useWebSocket = false;
|
|
846
1154
|
checks = {};
|
|
847
1155
|
featureUsageEventMap = {};
|
|
848
1156
|
planChecks = {};
|
|
1157
|
+
creditBalances = {};
|
|
849
1158
|
webSocketUrl = "wss://api.schematichq.com";
|
|
850
1159
|
webSocketConnectionTimeout = 1e4;
|
|
851
1160
|
webSocketReconnect = true;
|
|
@@ -874,11 +1183,16 @@ var Schematic = class {
|
|
|
874
1183
|
fallbackCheckCache = {};
|
|
875
1184
|
constructor(apiKey, options) {
|
|
876
1185
|
this.apiKey = apiKey;
|
|
1186
|
+
this.flagStateCacheKey = `${flagStateCachePrefix}:${apiKey}`;
|
|
877
1187
|
this.eventQueue = [];
|
|
878
1188
|
this.contextDependentEventQueue = [];
|
|
879
1189
|
this.useWebSocket = options?.useWebSocket ?? false;
|
|
880
1190
|
this.debugEnabled = options?.debug ?? false;
|
|
881
1191
|
this.offlineEnabled = options?.offline ?? false;
|
|
1192
|
+
this.persistFlagState = options?.persistFlagState ?? true;
|
|
1193
|
+
if (typeof options?.flagStateCacheMaxAgeMs === "number" && options.flagStateCacheMaxAgeMs > 0) {
|
|
1194
|
+
this.flagStateCacheMaxAgeMs = options.flagStateCacheMaxAgeMs;
|
|
1195
|
+
}
|
|
882
1196
|
if (typeof window !== "undefined" && typeof window.location !== "undefined") {
|
|
883
1197
|
const params = new URLSearchParams(window.location.search);
|
|
884
1198
|
const debugParam = params.get("schematic_debug");
|
|
@@ -911,6 +1225,7 @@ var Schematic = class {
|
|
|
911
1225
|
} catch {
|
|
912
1226
|
}
|
|
913
1227
|
}
|
|
1228
|
+
this.hydrateFlagStateFromCache();
|
|
914
1229
|
if (options?.apiUrl !== void 0) {
|
|
915
1230
|
this.apiUrl = options.apiUrl;
|
|
916
1231
|
}
|
|
@@ -1204,6 +1519,29 @@ var Schematic = class {
|
|
|
1204
1519
|
});
|
|
1205
1520
|
this.notifyPlanListeners(plan);
|
|
1206
1521
|
}
|
|
1522
|
+
if (message.credit_balances !== void 0 && message.credit_balances !== null) {
|
|
1523
|
+
const contextStr = contextString(context);
|
|
1524
|
+
const updates = CreditBalancesFromJSON(message.credit_balances);
|
|
1525
|
+
const previous = this.creditBalances[contextStr] ?? {};
|
|
1526
|
+
let changed = false;
|
|
1527
|
+
const merged = { ...previous };
|
|
1528
|
+
for (const [creditId, next] of Object.entries(updates)) {
|
|
1529
|
+
const current = previous[creditId];
|
|
1530
|
+
if (current === void 0 || current.remaining !== next.remaining || current.reserved !== next.reserved || current.settled !== next.settled) {
|
|
1531
|
+
merged[creditId] = next;
|
|
1532
|
+
changed = true;
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
if (changed) {
|
|
1536
|
+
this.creditBalances[contextStr] = merged;
|
|
1537
|
+
this.debug(
|
|
1538
|
+
`WebSocket credit balance update received. Notifying listeners`,
|
|
1539
|
+
{ creditBalances: merged }
|
|
1540
|
+
);
|
|
1541
|
+
this.notifyCreditBalanceListeners(merged);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
this.persistContextToCache(contextString(context));
|
|
1207
1545
|
this.flushContextDependentEventQueue();
|
|
1208
1546
|
this.setIsPending(false);
|
|
1209
1547
|
};
|
|
@@ -1311,7 +1649,32 @@ var Schematic = class {
|
|
|
1311
1649
|
return;
|
|
1312
1650
|
}
|
|
1313
1651
|
try {
|
|
1314
|
-
|
|
1652
|
+
const newContextStr = contextString(context);
|
|
1653
|
+
const cacheHit = this.hasCachedValuesForContext(newContextStr);
|
|
1654
|
+
if (cacheHit) {
|
|
1655
|
+
this.debug(
|
|
1656
|
+
`setContext: cache hit for context, pre-resolving from cached values`
|
|
1657
|
+
);
|
|
1658
|
+
this.context = context;
|
|
1659
|
+
this.flushContextDependentEventQueue();
|
|
1660
|
+
this.setIsPending(false);
|
|
1661
|
+
const cachedChecks = this.checks[newContextStr] ?? {};
|
|
1662
|
+
for (const [flagKey, check] of Object.entries(cachedChecks)) {
|
|
1663
|
+
if (check === void 0) continue;
|
|
1664
|
+
this.notifyFlagCheckListeners(flagKey, check);
|
|
1665
|
+
this.notifyFlagValueListeners(flagKey, check.value);
|
|
1666
|
+
}
|
|
1667
|
+
const cachedPlan = this.planChecks[newContextStr];
|
|
1668
|
+
if (cachedPlan !== void 0) {
|
|
1669
|
+
this.notifyPlanListeners(cachedPlan);
|
|
1670
|
+
}
|
|
1671
|
+
const cachedCreditBalances = this.creditBalances[newContextStr];
|
|
1672
|
+
if (cachedCreditBalances !== void 0) {
|
|
1673
|
+
this.notifyCreditBalanceListeners(cachedCreditBalances);
|
|
1674
|
+
}
|
|
1675
|
+
} else {
|
|
1676
|
+
this.setIsPending(true);
|
|
1677
|
+
}
|
|
1315
1678
|
if (!this.conn) {
|
|
1316
1679
|
if (this.isConnecting) {
|
|
1317
1680
|
this.debug(
|
|
@@ -1322,7 +1685,7 @@ var Schematic = class {
|
|
|
1322
1685
|
}
|
|
1323
1686
|
if (this.conn !== null) {
|
|
1324
1687
|
const socket2 = await this.conn;
|
|
1325
|
-
await this.wsSendMessage(socket2, context);
|
|
1688
|
+
await this.wsSendMessage(socket2, context, cacheHit);
|
|
1326
1689
|
return;
|
|
1327
1690
|
}
|
|
1328
1691
|
}
|
|
@@ -1338,7 +1701,7 @@ var Schematic = class {
|
|
|
1338
1701
|
this.conn = this.wsConnect();
|
|
1339
1702
|
const socket2 = await this.conn;
|
|
1340
1703
|
this.isConnecting = false;
|
|
1341
|
-
await this.wsSendMessage(socket2, context);
|
|
1704
|
+
await this.wsSendMessage(socket2, context, cacheHit);
|
|
1342
1705
|
return;
|
|
1343
1706
|
} catch (error) {
|
|
1344
1707
|
this.isConnecting = false;
|
|
@@ -1346,7 +1709,7 @@ var Schematic = class {
|
|
|
1346
1709
|
}
|
|
1347
1710
|
}
|
|
1348
1711
|
const socket = await this.conn;
|
|
1349
|
-
await this.wsSendMessage(socket, context);
|
|
1712
|
+
await this.wsSendMessage(socket, context, cacheHit);
|
|
1350
1713
|
} catch (error) {
|
|
1351
1714
|
console.warn("Failed to establish WebSocket connection:", error);
|
|
1352
1715
|
this.context = context;
|
|
@@ -1406,10 +1769,12 @@ var Schematic = class {
|
|
|
1406
1769
|
`Optimistically updating feature usage for event: ${eventName}`,
|
|
1407
1770
|
{ quantity }
|
|
1408
1771
|
);
|
|
1772
|
+
let dirty = false;
|
|
1409
1773
|
Object.entries(flagsForEvent).forEach(([flagKey, check]) => {
|
|
1410
1774
|
if (check === void 0) return;
|
|
1411
1775
|
const updatedCheck = { ...check };
|
|
1412
1776
|
if (typeof updatedCheck.featureUsage === "number") {
|
|
1777
|
+
dirty = true;
|
|
1413
1778
|
updatedCheck.featureUsage += quantity;
|
|
1414
1779
|
if (typeof updatedCheck.featureAllocation === "number") {
|
|
1415
1780
|
const wasExceeded = updatedCheck.featureUsageExceeded === true;
|
|
@@ -1439,6 +1804,9 @@ var Schematic = class {
|
|
|
1439
1804
|
this.notifyFlagValueListeners(flagKey, updatedCheck.value);
|
|
1440
1805
|
}
|
|
1441
1806
|
});
|
|
1807
|
+
if (dirty) {
|
|
1808
|
+
this.persistContextToCache(contextString(this.context));
|
|
1809
|
+
}
|
|
1442
1810
|
};
|
|
1443
1811
|
/**
|
|
1444
1812
|
* Event processing
|
|
@@ -1541,6 +1909,206 @@ var Schematic = class {
|
|
|
1541
1909
|
this.storage.setItem(anonymousIdKey, generatedAnonymousId);
|
|
1542
1910
|
return generatedAnonymousId;
|
|
1543
1911
|
};
|
|
1912
|
+
hasCachedValuesForContext = (contextStr) => {
|
|
1913
|
+
const cachedChecks = this.checks[contextStr];
|
|
1914
|
+
if (cachedChecks !== void 0 && Object.keys(cachedChecks).length > 0) {
|
|
1915
|
+
return true;
|
|
1916
|
+
}
|
|
1917
|
+
if (this.planChecks[contextStr] !== void 0) {
|
|
1918
|
+
return true;
|
|
1919
|
+
}
|
|
1920
|
+
const cachedCreditBalances = this.creditBalances[contextStr];
|
|
1921
|
+
return cachedCreditBalances !== void 0 && Object.keys(cachedCreditBalances).length > 0;
|
|
1922
|
+
};
|
|
1923
|
+
readFlagStateCache = () => {
|
|
1924
|
+
if (!this.persistFlagState || this.storage === void 0) {
|
|
1925
|
+
return null;
|
|
1926
|
+
}
|
|
1927
|
+
let raw;
|
|
1928
|
+
try {
|
|
1929
|
+
raw = this.storage.getItem(this.flagStateCacheKey);
|
|
1930
|
+
} catch (error) {
|
|
1931
|
+
this.debug("Failed to read flag state cache:", error);
|
|
1932
|
+
return null;
|
|
1933
|
+
}
|
|
1934
|
+
if (raw === null || raw === void 0) {
|
|
1935
|
+
return null;
|
|
1936
|
+
}
|
|
1937
|
+
let parsed;
|
|
1938
|
+
try {
|
|
1939
|
+
parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
1940
|
+
} catch (error) {
|
|
1941
|
+
this.debug("Flag state cache is not valid JSON, ignoring:", error);
|
|
1942
|
+
return null;
|
|
1943
|
+
}
|
|
1944
|
+
if (parsed === null || typeof parsed !== "object" || parsed.version !== cacheVersion || typeof parsed.contexts !== "object" || parsed.contexts === null) {
|
|
1945
|
+
this.debug(
|
|
1946
|
+
`Flag state cache invalid or version mismatch (expected ${cacheVersion}), ignoring`,
|
|
1947
|
+
{
|
|
1948
|
+
parsedType: typeof parsed,
|
|
1949
|
+
version: parsed?.version
|
|
1950
|
+
}
|
|
1951
|
+
);
|
|
1952
|
+
return null;
|
|
1953
|
+
}
|
|
1954
|
+
return parsed;
|
|
1955
|
+
};
|
|
1956
|
+
reviveCachedCheck = (raw) => {
|
|
1957
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
1958
|
+
const obj = raw;
|
|
1959
|
+
if (typeof obj.flag !== "string" || typeof obj.value !== "boolean" || typeof obj.reason !== "string") {
|
|
1960
|
+
return null;
|
|
1961
|
+
}
|
|
1962
|
+
const revived = { ...obj };
|
|
1963
|
+
if (typeof revived.featureUsageResetAt === "string") {
|
|
1964
|
+
const d = new Date(revived.featureUsageResetAt);
|
|
1965
|
+
revived.featureUsageResetAt = isNaN(d.getTime()) ? void 0 : d;
|
|
1966
|
+
}
|
|
1967
|
+
return revived;
|
|
1968
|
+
};
|
|
1969
|
+
reviveCachedPlan = (raw) => {
|
|
1970
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
1971
|
+
const obj = raw;
|
|
1972
|
+
if (typeof obj.id !== "string" || typeof obj.name !== "string") {
|
|
1973
|
+
return null;
|
|
1974
|
+
}
|
|
1975
|
+
const revived = { ...obj };
|
|
1976
|
+
if (typeof revived.trialEndDate === "string") {
|
|
1977
|
+
const d = new Date(revived.trialEndDate);
|
|
1978
|
+
revived.trialEndDate = isNaN(d.getTime()) ? void 0 : d;
|
|
1979
|
+
}
|
|
1980
|
+
return revived;
|
|
1981
|
+
};
|
|
1982
|
+
reviveCachedCreditBalances = (raw) => {
|
|
1983
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
1984
|
+
const revived = {};
|
|
1985
|
+
for (const [creditId, value] of Object.entries(
|
|
1986
|
+
raw
|
|
1987
|
+
)) {
|
|
1988
|
+
if (value === null || typeof value !== "object") continue;
|
|
1989
|
+
const obj = value;
|
|
1990
|
+
if (typeof obj.remaining !== "number" || typeof obj.reserved !== "number" || typeof obj.settled !== "number") {
|
|
1991
|
+
continue;
|
|
1992
|
+
}
|
|
1993
|
+
revived[creditId] = {
|
|
1994
|
+
remaining: obj.remaining,
|
|
1995
|
+
reserved: obj.reserved,
|
|
1996
|
+
settled: obj.settled
|
|
1997
|
+
};
|
|
1998
|
+
}
|
|
1999
|
+
return Object.keys(revived).length > 0 ? revived : null;
|
|
2000
|
+
};
|
|
2001
|
+
hydrateFlagStateFromCache = () => {
|
|
2002
|
+
const parsed = this.readFlagStateCache();
|
|
2003
|
+
if (parsed === null) return;
|
|
2004
|
+
const cutoff = Date.now() - this.flagStateCacheMaxAgeMs;
|
|
2005
|
+
const fresh = {};
|
|
2006
|
+
let contextsLoaded = 0;
|
|
2007
|
+
let contextsExpired = 0;
|
|
2008
|
+
for (const [contextStr, entry] of Object.entries(parsed.contexts)) {
|
|
2009
|
+
if (entry === null || typeof entry !== "object") continue;
|
|
2010
|
+
if (typeof entry.updatedAt !== "number") continue;
|
|
2011
|
+
if (entry.updatedAt < cutoff) {
|
|
2012
|
+
contextsExpired += 1;
|
|
2013
|
+
continue;
|
|
2014
|
+
}
|
|
2015
|
+
const revivedChecks = {};
|
|
2016
|
+
if (entry.checks !== null && typeof entry.checks === "object") {
|
|
2017
|
+
for (const [flagKey, rawCheck] of Object.entries(entry.checks)) {
|
|
2018
|
+
const revived = this.reviveCachedCheck(rawCheck);
|
|
2019
|
+
if (revived === null || revived.flag !== flagKey) continue;
|
|
2020
|
+
revivedChecks[flagKey] = revived;
|
|
2021
|
+
if (typeof revived.featureUsageEvent === "string") {
|
|
2022
|
+
this.updateFeatureUsageEventMap(revived);
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
if (Object.keys(revivedChecks).length > 0) {
|
|
2026
|
+
this.checks[contextStr] = revivedChecks;
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
let revivedPlan;
|
|
2030
|
+
if (entry.plan !== void 0 && entry.plan !== null) {
|
|
2031
|
+
const p = this.reviveCachedPlan(entry.plan);
|
|
2032
|
+
if (p !== null) {
|
|
2033
|
+
revivedPlan = p;
|
|
2034
|
+
this.planChecks[contextStr] = p;
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
let revivedCreditBalances;
|
|
2038
|
+
if (entry.creditBalances !== void 0 && entry.creditBalances !== null) {
|
|
2039
|
+
const balances = this.reviveCachedCreditBalances(entry.creditBalances);
|
|
2040
|
+
if (balances !== null) {
|
|
2041
|
+
revivedCreditBalances = balances;
|
|
2042
|
+
this.creditBalances[contextStr] = balances;
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
fresh[contextStr] = {
|
|
2046
|
+
checks: revivedChecks,
|
|
2047
|
+
plan: revivedPlan,
|
|
2048
|
+
creditBalances: revivedCreditBalances,
|
|
2049
|
+
updatedAt: entry.updatedAt
|
|
2050
|
+
};
|
|
2051
|
+
contextsLoaded += 1;
|
|
2052
|
+
}
|
|
2053
|
+
this.cachedFlagState = { version: cacheVersion, contexts: fresh };
|
|
2054
|
+
this.debug(
|
|
2055
|
+
`Hydrated flag state cache: ${contextsLoaded} loaded, ${contextsExpired} expired`
|
|
2056
|
+
);
|
|
2057
|
+
};
|
|
2058
|
+
persistContextToCache = (contextStr) => {
|
|
2059
|
+
const checksForContext = this.checks[contextStr];
|
|
2060
|
+
const planForContext = this.planChecks[contextStr];
|
|
2061
|
+
const creditBalancesForContext = this.creditBalances[contextStr];
|
|
2062
|
+
if (checksForContext === void 0 && planForContext === void 0 && creditBalancesForContext === void 0) {
|
|
2063
|
+
return;
|
|
2064
|
+
}
|
|
2065
|
+
if (this.cachedFlagState === null) {
|
|
2066
|
+
this.cachedFlagState = (this.persistFlagState ? this.readFlagStateCache() : null) ?? {
|
|
2067
|
+
version: cacheVersion,
|
|
2068
|
+
contexts: {}
|
|
2069
|
+
};
|
|
2070
|
+
}
|
|
2071
|
+
const cleanChecks = {};
|
|
2072
|
+
if (checksForContext !== void 0) {
|
|
2073
|
+
for (const [flagKey, check] of Object.entries(checksForContext)) {
|
|
2074
|
+
if (check !== void 0) cleanChecks[flagKey] = check;
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
this.cachedFlagState.contexts[contextStr] = {
|
|
2078
|
+
checks: cleanChecks,
|
|
2079
|
+
plan: planForContext,
|
|
2080
|
+
creditBalances: creditBalancesForContext,
|
|
2081
|
+
updatedAt: Date.now()
|
|
2082
|
+
};
|
|
2083
|
+
const entries = Object.entries(this.cachedFlagState.contexts);
|
|
2084
|
+
if (entries.length > flagStateCacheMaxContexts) {
|
|
2085
|
+
entries.sort((a, b) => b[1].updatedAt - a[1].updatedAt);
|
|
2086
|
+
const survivors = entries.slice(0, flagStateCacheMaxContexts);
|
|
2087
|
+
const survivorKeys = new Set(survivors.map(([k]) => k));
|
|
2088
|
+
for (const key of Object.keys(this.checks)) {
|
|
2089
|
+
if (!survivorKeys.has(key)) delete this.checks[key];
|
|
2090
|
+
}
|
|
2091
|
+
for (const key of Object.keys(this.planChecks)) {
|
|
2092
|
+
if (!survivorKeys.has(key)) delete this.planChecks[key];
|
|
2093
|
+
}
|
|
2094
|
+
for (const key of Object.keys(this.creditBalances)) {
|
|
2095
|
+
if (!survivorKeys.has(key)) delete this.creditBalances[key];
|
|
2096
|
+
}
|
|
2097
|
+
this.cachedFlagState = {
|
|
2098
|
+
version: cacheVersion,
|
|
2099
|
+
contexts: Object.fromEntries(survivors)
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
if (!this.persistFlagState || this.storage === void 0) return;
|
|
2103
|
+
try {
|
|
2104
|
+
this.storage.setItem(
|
|
2105
|
+
this.flagStateCacheKey,
|
|
2106
|
+
JSON.stringify(this.cachedFlagState)
|
|
2107
|
+
);
|
|
2108
|
+
} catch (error) {
|
|
2109
|
+
this.debug("Failed to write flag state cache:", error);
|
|
2110
|
+
}
|
|
2111
|
+
};
|
|
1544
2112
|
handleEvent = (eventType, eventBody) => {
|
|
1545
2113
|
const event = {
|
|
1546
2114
|
api_key: this.apiKey,
|
|
@@ -1801,6 +2369,9 @@ var Schematic = class {
|
|
|
1801
2369
|
if (this.conn !== null) {
|
|
1802
2370
|
try {
|
|
1803
2371
|
const socket = await this.conn;
|
|
2372
|
+
if (this.currentWebSocket === socket) {
|
|
2373
|
+
this.currentWebSocket = null;
|
|
2374
|
+
}
|
|
1804
2375
|
if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
|
|
1805
2376
|
socket.close();
|
|
1806
2377
|
}
|
|
@@ -1966,6 +2537,7 @@ var Schematic = class {
|
|
|
1966
2537
|
this.debug(`Creating WebSocket connection ${connectionId} to ${wsUrl}`);
|
|
1967
2538
|
let timeoutId = null;
|
|
1968
2539
|
let isResolved = false;
|
|
2540
|
+
let didOpen = false;
|
|
1969
2541
|
timeoutId = setTimeout(() => {
|
|
1970
2542
|
if (!isResolved) {
|
|
1971
2543
|
isResolved = true;
|
|
@@ -1979,6 +2551,7 @@ var Schematic = class {
|
|
|
1979
2551
|
webSocket.onopen = () => {
|
|
1980
2552
|
if (isResolved) return;
|
|
1981
2553
|
isResolved = true;
|
|
2554
|
+
didOpen = true;
|
|
1982
2555
|
if (timeoutId !== null) {
|
|
1983
2556
|
clearTimeout(timeoutId);
|
|
1984
2557
|
}
|
|
@@ -2004,11 +2577,12 @@ var Schematic = class {
|
|
|
2004
2577
|
}
|
|
2005
2578
|
this.debug(`WebSocket connection ${connectionId} closed`);
|
|
2006
2579
|
this.conn = null;
|
|
2580
|
+
const wasCurrent = this.currentWebSocket === webSocket;
|
|
2007
2581
|
if (this.currentWebSocket === webSocket) {
|
|
2008
2582
|
this.currentWebSocket = null;
|
|
2009
2583
|
this.isConnecting = false;
|
|
2010
2584
|
}
|
|
2011
|
-
if (
|
|
2585
|
+
if (wasCurrent && didOpen && !this.wsIntentionalDisconnect && this.webSocketReconnect) {
|
|
2012
2586
|
this.attemptReconnect();
|
|
2013
2587
|
}
|
|
2014
2588
|
};
|
|
@@ -2104,6 +2678,16 @@ var Schematic = class {
|
|
|
2104
2678
|
const plan = this.planChecks[contextStr];
|
|
2105
2679
|
return plan;
|
|
2106
2680
|
};
|
|
2681
|
+
/** Get the company's lease-aware credit balances for the current context, keyed by credit ID */
|
|
2682
|
+
getCreditBalances = () => {
|
|
2683
|
+
const contextStr = contextString(this.context);
|
|
2684
|
+
return this.creditBalances[contextStr] ?? emptyCreditBalances;
|
|
2685
|
+
};
|
|
2686
|
+
/** Get the company's lease-aware balance for a single credit type in the current context */
|
|
2687
|
+
getCreditBalance = (creditId) => {
|
|
2688
|
+
const contextStr = contextString(this.context);
|
|
2689
|
+
return this.creditBalances[contextStr]?.[creditId];
|
|
2690
|
+
};
|
|
2107
2691
|
// flag checks state
|
|
2108
2692
|
getFlagCheck = (flagKey) => {
|
|
2109
2693
|
const contextStr = contextString(this.context);
|
|
@@ -2163,6 +2747,13 @@ var Schematic = class {
|
|
|
2163
2747
|
this.planListeners.delete(listener);
|
|
2164
2748
|
};
|
|
2165
2749
|
};
|
|
2750
|
+
/** Register an event listener that will be notified with the company's credit balances (keyed by credit ID) whenever they change */
|
|
2751
|
+
addCreditBalanceListener = (listener) => {
|
|
2752
|
+
this.creditBalanceListeners.add(listener);
|
|
2753
|
+
return () => {
|
|
2754
|
+
this.creditBalanceListeners.delete(listener);
|
|
2755
|
+
};
|
|
2756
|
+
};
|
|
2166
2757
|
notifyFlagCheckListeners = (flagKey, check) => {
|
|
2167
2758
|
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
2168
2759
|
if (listeners.size > 0) {
|
|
@@ -2226,6 +2817,17 @@ var Schematic = class {
|
|
|
2226
2817
|
});
|
|
2227
2818
|
});
|
|
2228
2819
|
};
|
|
2820
|
+
notifyCreditBalanceListeners = (value) => {
|
|
2821
|
+
const listeners = this.creditBalanceListeners ?? [];
|
|
2822
|
+
if (listeners.size > 0) {
|
|
2823
|
+
this.debug(`Notifying ${listeners.size} credit balance listeners`, {
|
|
2824
|
+
value
|
|
2825
|
+
});
|
|
2826
|
+
}
|
|
2827
|
+
listeners.forEach(
|
|
2828
|
+
(listener) => notifyCreditBalanceListener(listener, value)
|
|
2829
|
+
);
|
|
2830
|
+
};
|
|
2229
2831
|
};
|
|
2230
2832
|
var notifyPendingListener = (listener, value) => {
|
|
2231
2833
|
if (listener.length > 0) {
|
|
@@ -2255,12 +2857,19 @@ var notifyPlanListener = (listener, value) => {
|
|
|
2255
2857
|
listener();
|
|
2256
2858
|
}
|
|
2257
2859
|
};
|
|
2860
|
+
var notifyCreditBalanceListener = (listener, value) => {
|
|
2861
|
+
if (listener.length > 0) {
|
|
2862
|
+
listener(value);
|
|
2863
|
+
} else {
|
|
2864
|
+
listener();
|
|
2865
|
+
}
|
|
2866
|
+
};
|
|
2258
2867
|
|
|
2259
2868
|
// src/context/schematic.ts
|
|
2260
2869
|
import { inject, onScopeDispose } from "vue";
|
|
2261
2870
|
|
|
2262
2871
|
// src/version.ts
|
|
2263
|
-
var version2 = "1.
|
|
2872
|
+
var version2 = "1.5.0";
|
|
2264
2873
|
|
|
2265
2874
|
// src/context/schematic.ts
|
|
2266
2875
|
var SchematicSymbol = Symbol("schematic");
|
|
@@ -2393,6 +3002,35 @@ var useSchematicPlan = (opts) => {
|
|
|
2393
3002
|
});
|
|
2394
3003
|
return plan;
|
|
2395
3004
|
};
|
|
3005
|
+
var useSchematicCreditBalance = (creditId, opts) => {
|
|
3006
|
+
const client = useSchematicClient(opts);
|
|
3007
|
+
const creditBalance = ref(
|
|
3008
|
+
client.getCreditBalance(creditId)
|
|
3009
|
+
);
|
|
3010
|
+
const isPending = ref(client.getIsPending());
|
|
3011
|
+
let unsubscribeBalance = null;
|
|
3012
|
+
let unsubscribePending = null;
|
|
3013
|
+
onMounted(() => {
|
|
3014
|
+
unsubscribeBalance = client.addCreditBalanceListener(() => {
|
|
3015
|
+
creditBalance.value = client.getCreditBalance(creditId);
|
|
3016
|
+
});
|
|
3017
|
+
unsubscribePending = client.addIsPendingListener(() => {
|
|
3018
|
+
isPending.value = client.getIsPending();
|
|
3019
|
+
});
|
|
3020
|
+
});
|
|
3021
|
+
onScopeDispose2(() => {
|
|
3022
|
+
unsubscribeBalance?.();
|
|
3023
|
+
unsubscribePending?.();
|
|
3024
|
+
});
|
|
3025
|
+
return {
|
|
3026
|
+
/** The spendable balance; 0 while loading or when the company holds no balance in this credit */
|
|
3027
|
+
balance: computed(() => creditBalance.value?.settled ?? 0),
|
|
3028
|
+
/** True while the balance is still loading and no value has arrived yet */
|
|
3029
|
+
isLoading: computed(
|
|
3030
|
+
() => creditBalance.value === void 0 && isPending.value
|
|
3031
|
+
)
|
|
3032
|
+
};
|
|
3033
|
+
};
|
|
2396
3034
|
var useSchematicIsPending = (opts) => {
|
|
2397
3035
|
const client = useSchematicClient(opts);
|
|
2398
3036
|
const isPending = ref(client.getIsPending());
|
|
@@ -2415,6 +3053,7 @@ export {
|
|
|
2415
3053
|
useSchematic,
|
|
2416
3054
|
useSchematicClient,
|
|
2417
3055
|
useSchematicContext,
|
|
3056
|
+
useSchematicCreditBalance,
|
|
2418
3057
|
useSchematicEntitlement,
|
|
2419
3058
|
useSchematicEvents,
|
|
2420
3059
|
useSchematicFlag,
|