@schematichq/schematic-vue 1.2.16 → 1.4.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/LICENSE +1 -2
- package/README.md +98 -0
- package/dist/schematic-vue.cjs.js +221 -100
- package/dist/schematic-vue.d.ts +26 -0
- package/dist/schematic-vue.esm.js +221 -100
- package/package.json +6 -5
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2023-2026 Schematic, Inc.
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
SOFTWARE.
|
|
22
|
-
|
package/README.md
CHANGED
|
@@ -137,6 +137,104 @@ const {
|
|
|
137
137
|
|
|
138
138
|
_Note: `useSchematicIsPending` is checking if entitlement data has been loaded, typically via `identify`. It should, therefore, be used to wrap flag and entitlement checks, but never the initial call to `identify`._
|
|
139
139
|
|
|
140
|
+
### Company plan information
|
|
141
|
+
|
|
142
|
+
To access the current company's plan and trial status, you can use the `useSchematicPlan` composable:
|
|
143
|
+
|
|
144
|
+
```vue
|
|
145
|
+
<script setup lang="ts">
|
|
146
|
+
import { useSchematicPlan } from "@schematichq/schematic-vue";
|
|
147
|
+
|
|
148
|
+
const plan = useSchematicPlan();
|
|
149
|
+
</script>
|
|
150
|
+
|
|
151
|
+
<template>
|
|
152
|
+
<div v-if="!plan">No plan assigned</div>
|
|
153
|
+
<div v-else>
|
|
154
|
+
<p>Current plan: {{ plan.name }}</p>
|
|
155
|
+
|
|
156
|
+
<p v-if="plan.trialStatus === 'active'">
|
|
157
|
+
Trial ends: {{ plan.trialEndDate?.toLocaleDateString() }}
|
|
158
|
+
</p>
|
|
159
|
+
|
|
160
|
+
<p v-if="plan.trialStatus === 'expired'">
|
|
161
|
+
Your trial has ended. <a href="/upgrade">Upgrade now</a>
|
|
162
|
+
</p>
|
|
163
|
+
</div>
|
|
164
|
+
</template>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The composable returns an object with the following properties:
|
|
168
|
+
|
|
169
|
+
| Property | Type | Description |
|
|
170
|
+
| --- | --- | --- |
|
|
171
|
+
| `id` | `string` | The plan ID |
|
|
172
|
+
| `name` | `string` | The plan name |
|
|
173
|
+
| `trialEndDate` | `Date \| undefined` | The trial end date, if the company has or had a trial |
|
|
174
|
+
| `trialStatus` | `"active" \| "expired" \| "converted" \| undefined` | The company's trial status: `active` if the trial is ongoing, `expired` if the trial ended without conversion, `converted` if the company converted to a paid plan, or `undefined` if the company has never trialed |
|
|
175
|
+
|
|
176
|
+
## Fallback Behavior
|
|
177
|
+
|
|
178
|
+
The SDK includes built-in fallback behavior you can use to ensure your application continues to function even when unable to reach Schematic (e.g., during service disruptions or network issues).
|
|
179
|
+
|
|
180
|
+
### Flag Check Fallbacks
|
|
181
|
+
|
|
182
|
+
When flag checks cannot reach Schematic, they use fallback values in the following priority order:
|
|
183
|
+
|
|
184
|
+
1. Callsite fallback - fallback values can be provided directly in the composable options
|
|
185
|
+
2. Initialization defaults - fallback values configured via `flagCheckDefaults` or `flagValueDefaults` options when initializing the plugin
|
|
186
|
+
3. Default value - Returns `false` if no fallback is configured
|
|
187
|
+
|
|
188
|
+
```vue
|
|
189
|
+
<script setup lang="ts">
|
|
190
|
+
// Provide a fallback value at the callsite
|
|
191
|
+
import { useSchematicFlag } from "@schematichq/schematic-vue";
|
|
192
|
+
|
|
193
|
+
const isFeatureEnabled = useSchematicFlag("feature-flag", {
|
|
194
|
+
fallback: true, // Used if API request fails
|
|
195
|
+
});
|
|
196
|
+
</script>
|
|
197
|
+
|
|
198
|
+
<template>
|
|
199
|
+
<Feature v-if="isFeatureEnabled" />
|
|
200
|
+
<Fallback v-else />
|
|
201
|
+
</template>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
// Or configure defaults at initialization
|
|
206
|
+
import { createApp } from "vue";
|
|
207
|
+
import { SchematicPlugin } from "@schematichq/schematic-vue";
|
|
208
|
+
|
|
209
|
+
const app = createApp(App);
|
|
210
|
+
app.use(SchematicPlugin, {
|
|
211
|
+
publishableKey: "your-publishable-key",
|
|
212
|
+
flagValueDefaults: {
|
|
213
|
+
"feature-flag": true, // Used if API request fails and no callsite fallback
|
|
214
|
+
},
|
|
215
|
+
flagCheckDefaults: {
|
|
216
|
+
"another-flag": {
|
|
217
|
+
flag: "another-flag",
|
|
218
|
+
value: true,
|
|
219
|
+
reason: "Default value",
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Event Queueing and Retry
|
|
226
|
+
|
|
227
|
+
When events (track, identify) cannot be sent due to network issues, they are automatically queued and retried:
|
|
228
|
+
|
|
229
|
+
- Events are queued in memory (up to 100 events by default, configurable via `maxEventQueueSize`)
|
|
230
|
+
- Failed events are retried with exponential backoff (up to 5 attempts by default, configurable via `maxEventRetries`)
|
|
231
|
+
- Events are automatically flushed when the network connection is restored
|
|
232
|
+
- Events queued when the page is hidden are sent when the page becomes visible
|
|
233
|
+
|
|
234
|
+
### WebSocket Fallback
|
|
235
|
+
|
|
236
|
+
In WebSocket mode, if the WebSocket connection fails, the SDK will provide the last known value or the configured fallback values as [outlined above](/#flag-check-fallbacks). The WebSocket will also automatically attempt to re-establish it's connection with Schematic using an exponential backoff.
|
|
237
|
+
|
|
140
238
|
## Options API Support
|
|
141
239
|
|
|
142
240
|
While the primary API uses the Composition API, you can still use these composables in the Options API:
|
|
@@ -30,7 +30,8 @@ __export(index_exports, {
|
|
|
30
30
|
useSchematicEntitlement: () => useSchematicEntitlement,
|
|
31
31
|
useSchematicEvents: () => useSchematicEvents,
|
|
32
32
|
useSchematicFlag: () => useSchematicFlag,
|
|
33
|
-
useSchematicIsPending: () => useSchematicIsPending
|
|
33
|
+
useSchematicIsPending: () => useSchematicIsPending,
|
|
34
|
+
useSchematicPlan: () => useSchematicPlan
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(index_exports);
|
|
36
37
|
|
|
@@ -642,6 +643,36 @@ function v4(options, buf, offset) {
|
|
|
642
643
|
}
|
|
643
644
|
var v4_default = v4;
|
|
644
645
|
var import_polyfill = __toESM(require_browser_polyfill());
|
|
646
|
+
function EntitlementValueTypeFromJSON(json) {
|
|
647
|
+
return EntitlementValueTypeFromJSONTyped(json, false);
|
|
648
|
+
}
|
|
649
|
+
function EntitlementValueTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
650
|
+
return json;
|
|
651
|
+
}
|
|
652
|
+
function FeatureEntitlementFromJSON(json) {
|
|
653
|
+
return FeatureEntitlementFromJSONTyped(json, false);
|
|
654
|
+
}
|
|
655
|
+
function FeatureEntitlementFromJSONTyped(json, ignoreDiscriminator) {
|
|
656
|
+
if (json == null) {
|
|
657
|
+
return json;
|
|
658
|
+
}
|
|
659
|
+
return {
|
|
660
|
+
allocation: json["allocation"] == null ? void 0 : json["allocation"],
|
|
661
|
+
creditId: json["credit_id"] == null ? void 0 : json["credit_id"],
|
|
662
|
+
creditRemaining: json["credit_remaining"] == null ? void 0 : json["credit_remaining"],
|
|
663
|
+
creditTotal: json["credit_total"] == null ? void 0 : json["credit_total"],
|
|
664
|
+
creditUsed: json["credit_used"] == null ? void 0 : json["credit_used"],
|
|
665
|
+
eventName: json["event_name"] == null ? void 0 : json["event_name"],
|
|
666
|
+
featureId: json["feature_id"],
|
|
667
|
+
featureKey: json["feature_key"],
|
|
668
|
+
metricPeriod: json["metric_period"] == null ? void 0 : json["metric_period"],
|
|
669
|
+
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"],
|
|
671
|
+
softLimit: json["soft_limit"] == null ? void 0 : json["soft_limit"],
|
|
672
|
+
usage: json["usage"] == null ? void 0 : json["usage"],
|
|
673
|
+
valueType: EntitlementValueTypeFromJSON(json["value_type"])
|
|
674
|
+
};
|
|
675
|
+
}
|
|
645
676
|
function CheckFlagResponseDataFromJSON(json) {
|
|
646
677
|
return CheckFlagResponseDataFromJSONTyped(json, false);
|
|
647
678
|
}
|
|
@@ -651,6 +682,7 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
651
682
|
}
|
|
652
683
|
return {
|
|
653
684
|
companyId: json["company_id"] == null ? void 0 : json["company_id"],
|
|
685
|
+
entitlement: json["entitlement"] == null ? void 0 : FeatureEntitlementFromJSON(json["entitlement"]),
|
|
654
686
|
error: json["error"] == null ? void 0 : json["error"],
|
|
655
687
|
featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
|
|
656
688
|
featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
|
|
@@ -666,26 +698,6 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
666
698
|
value: json["value"]
|
|
667
699
|
};
|
|
668
700
|
}
|
|
669
|
-
function EventBodyFlagCheckToJSON(json) {
|
|
670
|
-
return EventBodyFlagCheckToJSONTyped(json, false);
|
|
671
|
-
}
|
|
672
|
-
function EventBodyFlagCheckToJSONTyped(value, ignoreDiscriminator = false) {
|
|
673
|
-
if (value == null) {
|
|
674
|
-
return value;
|
|
675
|
-
}
|
|
676
|
-
return {
|
|
677
|
-
company_id: value["companyId"],
|
|
678
|
-
error: value["error"],
|
|
679
|
-
flag_id: value["flagId"],
|
|
680
|
-
flag_key: value["flagKey"],
|
|
681
|
-
reason: value["reason"],
|
|
682
|
-
req_company: value["reqCompany"],
|
|
683
|
-
req_user: value["reqUser"],
|
|
684
|
-
rule_id: value["ruleId"],
|
|
685
|
-
user_id: value["userId"],
|
|
686
|
-
value: value["value"]
|
|
687
|
-
};
|
|
688
|
-
}
|
|
689
701
|
function CheckFlagResponseFromJSON(json) {
|
|
690
702
|
return CheckFlagResponseFromJSONTyped(json, false);
|
|
691
703
|
}
|
|
@@ -698,6 +710,26 @@ function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
698
710
|
params: json["params"]
|
|
699
711
|
};
|
|
700
712
|
}
|
|
713
|
+
function TrialStatusFromJSON(json) {
|
|
714
|
+
return TrialStatusFromJSONTyped(json, false);
|
|
715
|
+
}
|
|
716
|
+
function TrialStatusFromJSONTyped(json, ignoreDiscriminator) {
|
|
717
|
+
return json;
|
|
718
|
+
}
|
|
719
|
+
function DatastreamCompanyPlanFromJSON(json) {
|
|
720
|
+
return DatastreamCompanyPlanFromJSONTyped(json, false);
|
|
721
|
+
}
|
|
722
|
+
function DatastreamCompanyPlanFromJSONTyped(json, ignoreDiscriminator) {
|
|
723
|
+
if (json == null) {
|
|
724
|
+
return json;
|
|
725
|
+
}
|
|
726
|
+
return {
|
|
727
|
+
id: json["id"],
|
|
728
|
+
name: json["name"],
|
|
729
|
+
trialEndDate: json["trial_end_date"] == null ? void 0 : new Date(json["trial_end_date"]),
|
|
730
|
+
trialStatus: json["trial_status"] == null ? void 0 : TrialStatusFromJSON(json["trial_status"])
|
|
731
|
+
};
|
|
732
|
+
}
|
|
701
733
|
function CheckFlagsResponseDataFromJSON(json) {
|
|
702
734
|
return CheckFlagsResponseDataFromJSONTyped(json, false);
|
|
703
735
|
}
|
|
@@ -706,7 +738,8 @@ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
706
738
|
return json;
|
|
707
739
|
}
|
|
708
740
|
return {
|
|
709
|
-
flags: json["flags"].map(CheckFlagResponseDataFromJSON)
|
|
741
|
+
flags: json["flags"].map(CheckFlagResponseDataFromJSON),
|
|
742
|
+
plan: json["plan"] == null ? void 0 : DatastreamCompanyPlanFromJSON(json["plan"])
|
|
710
743
|
};
|
|
711
744
|
}
|
|
712
745
|
function CheckFlagsResponseFromJSON(json) {
|
|
@@ -721,6 +754,26 @@ function CheckFlagsResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
721
754
|
params: json["params"]
|
|
722
755
|
};
|
|
723
756
|
}
|
|
757
|
+
function EventBodyFlagCheckToJSON(json) {
|
|
758
|
+
return EventBodyFlagCheckToJSONTyped(json, false);
|
|
759
|
+
}
|
|
760
|
+
function EventBodyFlagCheckToJSONTyped(value, ignoreDiscriminator = false) {
|
|
761
|
+
if (value == null) {
|
|
762
|
+
return value;
|
|
763
|
+
}
|
|
764
|
+
return {
|
|
765
|
+
company_id: value["companyId"],
|
|
766
|
+
error: value["error"],
|
|
767
|
+
flag_id: value["flagId"],
|
|
768
|
+
flag_key: value["flagKey"],
|
|
769
|
+
reason: value["reason"],
|
|
770
|
+
req_company: value["reqCompany"],
|
|
771
|
+
req_user: value["reqUser"],
|
|
772
|
+
rule_id: value["ruleId"],
|
|
773
|
+
user_id: value["userId"],
|
|
774
|
+
value: value["value"]
|
|
775
|
+
};
|
|
776
|
+
}
|
|
724
777
|
var RuleType = /* @__PURE__ */ ((RuleType2) => {
|
|
725
778
|
RuleType2["GLOBAL_OVERRIDE"] = "global_override";
|
|
726
779
|
RuleType2["COMPANY_OVERRIDE"] = "company_override";
|
|
@@ -741,6 +794,7 @@ var UsagePeriod = /* @__PURE__ */ ((UsagePeriod2) => {
|
|
|
741
794
|
var CheckFlagReturnFromJSON = (json) => {
|
|
742
795
|
const {
|
|
743
796
|
companyId,
|
|
797
|
+
entitlement,
|
|
744
798
|
error,
|
|
745
799
|
featureAllocation,
|
|
746
800
|
featureUsage,
|
|
@@ -758,24 +812,40 @@ var CheckFlagReturnFromJSON = (json) => {
|
|
|
758
812
|
const featureUsageExceeded = !value && // if flag is not false, then we haven't exceeded usage
|
|
759
813
|
(ruleType == "company_override_usage_exceeded" || // if the rule type is one of these, then we have exceeded usage
|
|
760
814
|
ruleType == "plan_entitlement_usage_exceeded");
|
|
815
|
+
const resolvedAllocation = entitlement?.allocation ?? featureAllocation;
|
|
816
|
+
const resolvedUsage = entitlement?.usage ?? featureUsage;
|
|
817
|
+
const resolvedEvent = entitlement?.eventName ?? featureUsageEvent;
|
|
818
|
+
const resolvedPeriod = entitlement?.metricPeriod ?? featureUsagePeriod;
|
|
819
|
+
const resolvedResetAt = entitlement?.metricResetAt ?? featureUsageResetAt;
|
|
761
820
|
return {
|
|
762
821
|
featureUsageExceeded,
|
|
763
822
|
companyId: companyId == null ? void 0 : companyId,
|
|
823
|
+
creditRemaining: entitlement?.creditRemaining == null ? void 0 : entitlement.creditRemaining,
|
|
764
824
|
error: error == null ? void 0 : error,
|
|
765
|
-
featureAllocation:
|
|
766
|
-
featureUsage:
|
|
767
|
-
featureUsageEvent:
|
|
768
|
-
featureUsagePeriod:
|
|
769
|
-
featureUsageResetAt:
|
|
825
|
+
featureAllocation: resolvedAllocation == null ? void 0 : resolvedAllocation,
|
|
826
|
+
featureUsage: resolvedUsage == null ? void 0 : resolvedUsage,
|
|
827
|
+
featureUsageEvent: resolvedEvent == null ? void 0 : resolvedEvent,
|
|
828
|
+
featureUsagePeriod: resolvedPeriod == null ? void 0 : resolvedPeriod,
|
|
829
|
+
featureUsageResetAt: resolvedResetAt == null ? void 0 : resolvedResetAt,
|
|
770
830
|
flag,
|
|
771
831
|
flagId: flagId == null ? void 0 : flagId,
|
|
772
832
|
reason,
|
|
773
833
|
ruleId: ruleId == null ? void 0 : ruleId,
|
|
774
834
|
ruleType: ruleType == null ? void 0 : ruleType,
|
|
835
|
+
softLimit: entitlement?.softLimit == null ? void 0 : entitlement.softLimit,
|
|
775
836
|
userId: userId == null ? void 0 : userId,
|
|
776
837
|
value
|
|
777
838
|
};
|
|
778
839
|
};
|
|
840
|
+
var CheckPlanReturnFromJSON = (json) => {
|
|
841
|
+
const { id, name, trialEndDate, trialStatus } = DatastreamCompanyPlanFromJSON(json);
|
|
842
|
+
return {
|
|
843
|
+
id,
|
|
844
|
+
name,
|
|
845
|
+
trialEndDate: trialEndDate == null ? void 0 : trialEndDate,
|
|
846
|
+
trialStatus: trialStatus == null ? void 0 : trialStatus
|
|
847
|
+
};
|
|
848
|
+
};
|
|
779
849
|
function contextString(context) {
|
|
780
850
|
const sortedContext = Object.keys(context).reduce((acc, key) => {
|
|
781
851
|
const sortedKeys = Object.keys(
|
|
@@ -790,7 +860,7 @@ function contextString(context) {
|
|
|
790
860
|
}, {});
|
|
791
861
|
return JSON.stringify(sortedContext);
|
|
792
862
|
}
|
|
793
|
-
var version = "1.
|
|
863
|
+
var version = "1.4.0";
|
|
794
864
|
var anonymousIdKey = "schematicId";
|
|
795
865
|
var Schematic = class {
|
|
796
866
|
additionalHeaders = {};
|
|
@@ -807,10 +877,12 @@ var Schematic = class {
|
|
|
807
877
|
flagValueListeners = {};
|
|
808
878
|
isPending = true;
|
|
809
879
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
880
|
+
planListeners = /* @__PURE__ */ new Set();
|
|
810
881
|
storage;
|
|
811
882
|
useWebSocket = false;
|
|
812
883
|
checks = {};
|
|
813
884
|
featureUsageEventMap = {};
|
|
885
|
+
planChecks = {};
|
|
814
886
|
webSocketUrl = "wss://api.schematichq.com";
|
|
815
887
|
webSocketConnectionTimeout = 1e4;
|
|
816
888
|
webSocketReconnect = true;
|
|
@@ -836,6 +908,7 @@ var Schematic = class {
|
|
|
836
908
|
retryTimer = null;
|
|
837
909
|
flagValueDefaults = {};
|
|
838
910
|
flagCheckDefaults = {};
|
|
911
|
+
fallbackCheckCache = {};
|
|
839
912
|
constructor(apiKey, options) {
|
|
840
913
|
this.apiKey = apiKey;
|
|
841
914
|
this.eventQueue = [];
|
|
@@ -1004,8 +1077,8 @@ var Schematic = class {
|
|
|
1004
1077
|
/**
|
|
1005
1078
|
* Get value for a single flag.
|
|
1006
1079
|
* In WebSocket mode, returns cached values if connection is active, otherwise establishes
|
|
1007
|
-
* new connection and then returns the
|
|
1008
|
-
* connection fails.
|
|
1080
|
+
* new connection and then returns the requested value. Falls back to preconfigured fallback
|
|
1081
|
+
* values if WebSocket connection fails.
|
|
1009
1082
|
* In REST mode, makes an API call for each check.
|
|
1010
1083
|
*/
|
|
1011
1084
|
async checkFlag(options) {
|
|
@@ -1074,10 +1147,17 @@ var Schematic = class {
|
|
|
1074
1147
|
await this.setContext(context);
|
|
1075
1148
|
} catch (error) {
|
|
1076
1149
|
console.warn(
|
|
1077
|
-
"WebSocket connection failed,
|
|
1150
|
+
"WebSocket connection failed, using fallback value:",
|
|
1078
1151
|
error
|
|
1079
1152
|
);
|
|
1080
|
-
|
|
1153
|
+
const errorResult = this.resolveFallbackCheckFlagReturn(
|
|
1154
|
+
key,
|
|
1155
|
+
fallback,
|
|
1156
|
+
"WebSocket connection failed",
|
|
1157
|
+
error instanceof Error ? error.message : String(error)
|
|
1158
|
+
);
|
|
1159
|
+
this.submitFlagCheckEvent(key, errorResult, context);
|
|
1160
|
+
return errorResult.value;
|
|
1081
1161
|
}
|
|
1082
1162
|
const contextVals = this.checks[contextStr] ?? {};
|
|
1083
1163
|
const flagCheck = contextVals[key];
|
|
@@ -1088,6 +1168,13 @@ var Schematic = class {
|
|
|
1088
1168
|
);
|
|
1089
1169
|
if (typeof flagCheck !== "undefined") {
|
|
1090
1170
|
this.submitFlagCheckEvent(key, flagCheck, context);
|
|
1171
|
+
} else {
|
|
1172
|
+
const fallbackResult = this.resolveFallbackCheckFlagReturn(
|
|
1173
|
+
key,
|
|
1174
|
+
fallback,
|
|
1175
|
+
"No flag values available"
|
|
1176
|
+
);
|
|
1177
|
+
this.submitFlagCheckEvent(key, fallbackResult, context);
|
|
1091
1178
|
}
|
|
1092
1179
|
return result;
|
|
1093
1180
|
} catch (error) {
|
|
@@ -1128,28 +1215,32 @@ var Schematic = class {
|
|
|
1128
1215
|
this.checks[contextStr] = {};
|
|
1129
1216
|
}
|
|
1130
1217
|
this.checks[contextStr][flagCheck.flag] = flagCheck;
|
|
1131
|
-
this.debug(`WebSocket flag update:`, {
|
|
1132
|
-
flag: flagCheck.flag,
|
|
1133
|
-
value: flagCheck.value,
|
|
1134
|
-
flagCheck
|
|
1135
|
-
});
|
|
1136
1218
|
if (typeof flagCheck.featureUsageEvent === "string") {
|
|
1137
1219
|
this.updateFeatureUsageEventMap(flagCheck);
|
|
1138
1220
|
}
|
|
1139
1221
|
if ((this.flagCheckListeners[flag.flag]?.size ?? 0) > 0 || (this.flagValueListeners[flag.flag]?.size ?? 0) > 0) {
|
|
1140
1222
|
this.submitFlagCheckEvent(flagCheck.flag, flagCheck, context);
|
|
1141
1223
|
}
|
|
1142
|
-
this.debug(
|
|
1143
|
-
flag
|
|
1144
|
-
|
|
1145
|
-
|
|
1224
|
+
this.debug(
|
|
1225
|
+
`WebSocket flag update received. Notifying listeners for ${flag.flag}`,
|
|
1226
|
+
{
|
|
1227
|
+
flag: flag.flag,
|
|
1228
|
+
value: flagCheck.value,
|
|
1229
|
+
flagCheck
|
|
1230
|
+
}
|
|
1231
|
+
);
|
|
1146
1232
|
this.notifyFlagCheckListeners(flag.flag, flagCheck);
|
|
1147
1233
|
this.notifyFlagValueListeners(flag.flag, flagCheck.value);
|
|
1148
|
-
this.debug(`Finished notifying listeners for flag ${flag.flag}`, {
|
|
1149
|
-
flag: flag.flag,
|
|
1150
|
-
value: flagCheck.value
|
|
1151
|
-
});
|
|
1152
1234
|
});
|
|
1235
|
+
if (message.plan !== void 0 && message.plan !== null) {
|
|
1236
|
+
const plan = CheckPlanReturnFromJSON(message.plan);
|
|
1237
|
+
const contextStr = contextString(context);
|
|
1238
|
+
this.planChecks[contextStr] = plan;
|
|
1239
|
+
this.debug(`WebSocket plan update received. Notifying listeners`, {
|
|
1240
|
+
plan
|
|
1241
|
+
});
|
|
1242
|
+
this.notifyPlanListeners(plan);
|
|
1243
|
+
}
|
|
1153
1244
|
this.flushContextDependentEventQueue();
|
|
1154
1245
|
this.setIsPending(false);
|
|
1155
1246
|
};
|
|
@@ -1180,53 +1271,6 @@ var Schematic = class {
|
|
|
1180
1271
|
this.debug(`submitting flag check event:`, eventBody);
|
|
1181
1272
|
return this.handleEvent("flag_check", EventBodyFlagCheckToJSON(eventBody));
|
|
1182
1273
|
}
|
|
1183
|
-
/**
|
|
1184
|
-
* Helper method for falling back to REST API when WebSocket connection fails
|
|
1185
|
-
*/
|
|
1186
|
-
async fallbackToRest(key, context, fallback) {
|
|
1187
|
-
if (this.isOffline()) {
|
|
1188
|
-
const resolvedFallback = this.resolveFallbackValue(key, fallback);
|
|
1189
|
-
this.debug(`fallbackToRest offline result: ${key}`, {
|
|
1190
|
-
value: resolvedFallback,
|
|
1191
|
-
offlineMode: true
|
|
1192
|
-
});
|
|
1193
|
-
return resolvedFallback;
|
|
1194
|
-
}
|
|
1195
|
-
try {
|
|
1196
|
-
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
|
1197
|
-
const response = await fetch(requestUrl, {
|
|
1198
|
-
method: "POST",
|
|
1199
|
-
headers: {
|
|
1200
|
-
...this.additionalHeaders ?? {},
|
|
1201
|
-
"Content-Type": "application/json;charset=UTF-8",
|
|
1202
|
-
"X-Schematic-Api-Key": this.apiKey
|
|
1203
|
-
},
|
|
1204
|
-
body: JSON.stringify(context)
|
|
1205
|
-
});
|
|
1206
|
-
if (!response.ok) {
|
|
1207
|
-
throw new Error("Network response was not ok");
|
|
1208
|
-
}
|
|
1209
|
-
const responseJson = await response.json();
|
|
1210
|
-
const data = CheckFlagResponseFromJSON(responseJson);
|
|
1211
|
-
this.debug(`fallbackToRest result: ${key}`, data);
|
|
1212
|
-
const result = CheckFlagReturnFromJSON(data.data);
|
|
1213
|
-
if (typeof result.featureUsageEvent === "string") {
|
|
1214
|
-
this.updateFeatureUsageEventMap(result);
|
|
1215
|
-
}
|
|
1216
|
-
this.submitFlagCheckEvent(key, result, context);
|
|
1217
|
-
return result.value;
|
|
1218
|
-
} catch (error) {
|
|
1219
|
-
console.warn("REST API call failed, using fallback value:", error);
|
|
1220
|
-
const errorResult = this.resolveFallbackCheckFlagReturn(
|
|
1221
|
-
key,
|
|
1222
|
-
fallback,
|
|
1223
|
-
"API request failed (fallback)",
|
|
1224
|
-
error instanceof Error ? error.message : String(error)
|
|
1225
|
-
);
|
|
1226
|
-
this.submitFlagCheckEvent(key, errorResult, context);
|
|
1227
|
-
return errorResult.value;
|
|
1228
|
-
}
|
|
1229
|
-
}
|
|
1230
1274
|
/**
|
|
1231
1275
|
* Make an API call to fetch all flag values for a given context.
|
|
1232
1276
|
* Recommended for use in REST mode only.
|
|
@@ -1300,6 +1344,9 @@ var Schematic = class {
|
|
|
1300
1344
|
this.setIsPending(false);
|
|
1301
1345
|
return Promise.resolve();
|
|
1302
1346
|
}
|
|
1347
|
+
if (contextString(context) === contextString(this.context) && this.conn !== null && !this.isPending) {
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1303
1350
|
try {
|
|
1304
1351
|
this.setIsPending(true);
|
|
1305
1352
|
if (!this.conn) {
|
|
@@ -1339,7 +1386,10 @@ var Schematic = class {
|
|
|
1339
1386
|
await this.wsSendMessage(socket, context);
|
|
1340
1387
|
} catch (error) {
|
|
1341
1388
|
console.warn("Failed to establish WebSocket connection:", error);
|
|
1342
|
-
|
|
1389
|
+
this.context = context;
|
|
1390
|
+
this.flushContextDependentEventQueue();
|
|
1391
|
+
this.setIsPending(false);
|
|
1392
|
+
this.attemptReconnect();
|
|
1343
1393
|
}
|
|
1344
1394
|
};
|
|
1345
1395
|
/**
|
|
@@ -1980,7 +2030,10 @@ var Schematic = class {
|
|
|
1980
2030
|
clearTimeout(timeoutId);
|
|
1981
2031
|
}
|
|
1982
2032
|
this.debug(`WebSocket connection ${connectionId} error:`, error);
|
|
1983
|
-
|
|
2033
|
+
const wrappedError = new Error(
|
|
2034
|
+
"WebSocket connection failed during handshake"
|
|
2035
|
+
);
|
|
2036
|
+
reject(wrappedError);
|
|
1984
2037
|
};
|
|
1985
2038
|
webSocket.onclose = () => {
|
|
1986
2039
|
if (timeoutId !== null) {
|
|
@@ -2027,6 +2080,20 @@ var Schematic = class {
|
|
|
2027
2080
|
}
|
|
2028
2081
|
};
|
|
2029
2082
|
socket.addEventListener("message", messageHandler);
|
|
2083
|
+
socket.addEventListener("close", (event) => {
|
|
2084
|
+
if (!resolved) {
|
|
2085
|
+
resolved = true;
|
|
2086
|
+
if (event.code === 4001) {
|
|
2087
|
+
reject(
|
|
2088
|
+
new Error(
|
|
2089
|
+
`Authentication failed: ${event.reason !== "" ? event.reason : "Invalid API key"}`
|
|
2090
|
+
)
|
|
2091
|
+
);
|
|
2092
|
+
} else {
|
|
2093
|
+
reject(new Error("WebSocket connection closed unexpectedly"));
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
});
|
|
2030
2097
|
this.currentWebSocket = socket;
|
|
2031
2098
|
const clientVersion = this.additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
|
|
2032
2099
|
const messagePayload = {
|
|
@@ -2063,11 +2130,17 @@ var Schematic = class {
|
|
|
2063
2130
|
};
|
|
2064
2131
|
};
|
|
2065
2132
|
setIsPending = (isPending) => {
|
|
2133
|
+
if (this.isPending === isPending) return;
|
|
2066
2134
|
this.isPending = isPending;
|
|
2067
2135
|
this.isPendingListeners.forEach(
|
|
2068
2136
|
(listener) => notifyPendingListener(listener, isPending)
|
|
2069
2137
|
);
|
|
2070
2138
|
};
|
|
2139
|
+
getPlan = () => {
|
|
2140
|
+
const contextStr = contextString(this.context);
|
|
2141
|
+
const plan = this.planChecks[contextStr];
|
|
2142
|
+
return plan;
|
|
2143
|
+
};
|
|
2071
2144
|
// flag checks state
|
|
2072
2145
|
getFlagCheck = (flagKey) => {
|
|
2073
2146
|
const contextStr = contextString(this.context);
|
|
@@ -2077,11 +2150,14 @@ var Schematic = class {
|
|
|
2077
2150
|
return check;
|
|
2078
2151
|
}
|
|
2079
2152
|
if (flagKey in this.flagCheckDefaults || flagKey in this.flagValueDefaults) {
|
|
2080
|
-
|
|
2081
|
-
flagKey
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2153
|
+
if (!(flagKey in this.fallbackCheckCache)) {
|
|
2154
|
+
this.fallbackCheckCache[flagKey] = this.resolveFallbackCheckFlagReturn(
|
|
2155
|
+
flagKey,
|
|
2156
|
+
void 0,
|
|
2157
|
+
"Default value used"
|
|
2158
|
+
);
|
|
2159
|
+
}
|
|
2160
|
+
return this.fallbackCheckCache[flagKey];
|
|
2085
2161
|
}
|
|
2086
2162
|
return void 0;
|
|
2087
2163
|
};
|
|
@@ -2118,6 +2194,12 @@ var Schematic = class {
|
|
|
2118
2194
|
this.flagCheckListeners[flagKey].delete(listener);
|
|
2119
2195
|
};
|
|
2120
2196
|
};
|
|
2197
|
+
addPlanListener = (listener) => {
|
|
2198
|
+
this.planListeners.add(listener);
|
|
2199
|
+
return () => {
|
|
2200
|
+
this.planListeners.delete(listener);
|
|
2201
|
+
};
|
|
2202
|
+
};
|
|
2121
2203
|
notifyFlagCheckListeners = (flagKey, check) => {
|
|
2122
2204
|
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
2123
2205
|
if (listeners.size > 0) {
|
|
@@ -2166,6 +2248,21 @@ var Schematic = class {
|
|
|
2166
2248
|
});
|
|
2167
2249
|
});
|
|
2168
2250
|
};
|
|
2251
|
+
notifyPlanListeners = (value) => {
|
|
2252
|
+
const listeners = this.planListeners ?? [];
|
|
2253
|
+
if (listeners.size > 0) {
|
|
2254
|
+
this.debug(`Notifying ${listeners.size} plan listeners`, { value });
|
|
2255
|
+
}
|
|
2256
|
+
listeners.forEach((listener, index) => {
|
|
2257
|
+
this.debug(`Calling listener ${index} for plan`, {
|
|
2258
|
+
value
|
|
2259
|
+
});
|
|
2260
|
+
notifyPlanListener(listener, value);
|
|
2261
|
+
this.debug(`Listener ${index} for plan completed`, {
|
|
2262
|
+
value
|
|
2263
|
+
});
|
|
2264
|
+
});
|
|
2265
|
+
};
|
|
2169
2266
|
};
|
|
2170
2267
|
var notifyPendingListener = (listener, value) => {
|
|
2171
2268
|
if (listener.length > 0) {
|
|
@@ -2188,12 +2285,19 @@ var notifyFlagValueListener = (listener, value) => {
|
|
|
2188
2285
|
listener();
|
|
2189
2286
|
}
|
|
2190
2287
|
};
|
|
2288
|
+
var notifyPlanListener = (listener, value) => {
|
|
2289
|
+
if (listener.length > 0) {
|
|
2290
|
+
listener(value);
|
|
2291
|
+
} else {
|
|
2292
|
+
listener();
|
|
2293
|
+
}
|
|
2294
|
+
};
|
|
2191
2295
|
|
|
2192
2296
|
// src/context/schematic.ts
|
|
2193
2297
|
var import_vue = require("vue");
|
|
2194
2298
|
|
|
2195
2299
|
// src/version.ts
|
|
2196
|
-
var version2 = "1.
|
|
2300
|
+
var version2 = "1.4.0";
|
|
2197
2301
|
|
|
2198
2302
|
// src/context/schematic.ts
|
|
2199
2303
|
var SchematicSymbol = Symbol("schematic");
|
|
@@ -2309,6 +2413,23 @@ var useSchematicEntitlement = (key, opts) => {
|
|
|
2309
2413
|
userId: (0, import_vue2.computed)(() => flagCheck.value.userId)
|
|
2310
2414
|
};
|
|
2311
2415
|
};
|
|
2416
|
+
var useSchematicPlan = (opts) => {
|
|
2417
|
+
const client = useSchematicClient(opts);
|
|
2418
|
+
const fallback = opts?.fallback;
|
|
2419
|
+
const plan = (0, import_vue2.ref)(
|
|
2420
|
+
client.getPlan() ?? fallback
|
|
2421
|
+
);
|
|
2422
|
+
let unsubscribe = null;
|
|
2423
|
+
(0, import_vue2.onMounted)(() => {
|
|
2424
|
+
unsubscribe = client.addPlanListener((value) => {
|
|
2425
|
+
plan.value = value;
|
|
2426
|
+
});
|
|
2427
|
+
});
|
|
2428
|
+
(0, import_vue2.onScopeDispose)(() => {
|
|
2429
|
+
unsubscribe?.();
|
|
2430
|
+
});
|
|
2431
|
+
return plan;
|
|
2432
|
+
};
|
|
2312
2433
|
var useSchematicIsPending = (opts) => {
|
|
2313
2434
|
const client = useSchematicClient(opts);
|
|
2314
2435
|
const isPending = (0, import_vue2.ref)(client.getIsPending());
|
package/dist/schematic-vue.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { App } from 'vue';
|
|
2
2
|
import { CheckFlagReturn } from '@schematichq/schematic-js';
|
|
3
|
+
import { CheckPlanReturn } from '@schematichq/schematic-js';
|
|
3
4
|
import { ComputedRef } from 'vue';
|
|
4
5
|
import { Event as Event_2 } from '@schematichq/schematic-js';
|
|
5
6
|
import { EventBody } from '@schematichq/schematic-js';
|
|
@@ -21,6 +22,8 @@ declare type BaseSchematicPluginOptions = Omit<SchematicJS.SchematicOptions, "cl
|
|
|
21
22
|
|
|
22
23
|
export { CheckFlagReturn }
|
|
23
24
|
|
|
25
|
+
export { CheckPlanReturn }
|
|
26
|
+
|
|
24
27
|
export { Event_2 as Event }
|
|
25
28
|
|
|
26
29
|
export { EventBody }
|
|
@@ -142,6 +145,7 @@ export declare const useSchematicEntitlement: (key: string, opts?: UseSchematicF
|
|
|
142
145
|
check: ComputedRef< {
|
|
143
146
|
featureUsageExceeded?: boolean | undefined;
|
|
144
147
|
companyId?: string | undefined;
|
|
148
|
+
creditRemaining?: number | undefined;
|
|
145
149
|
error?: string | undefined;
|
|
146
150
|
featureAllocation?: number | undefined;
|
|
147
151
|
featureUsage?: number | undefined;
|
|
@@ -153,6 +157,7 @@ export declare const useSchematicEntitlement: (key: string, opts?: UseSchematicF
|
|
|
153
157
|
reason: string;
|
|
154
158
|
ruleId?: string | undefined;
|
|
155
159
|
ruleType?: SchematicJS.RuleType | undefined;
|
|
160
|
+
softLimit?: number | undefined;
|
|
156
161
|
userId?: string | undefined;
|
|
157
162
|
value: boolean;
|
|
158
163
|
}>;
|
|
@@ -236,4 +241,25 @@ export declare type UseSchematicFlagOpts = SchematicComposableOpts & {
|
|
|
236
241
|
*/
|
|
237
242
|
export declare const useSchematicIsPending: (opts?: SchematicComposableOpts) => Ref<boolean>;
|
|
238
243
|
|
|
244
|
+
/**
|
|
245
|
+
* Get the current plan for the identified company
|
|
246
|
+
* Returns a reactive ref that updates when the plan changes
|
|
247
|
+
*
|
|
248
|
+
* @param opts - Optional configuration including fallback value
|
|
249
|
+
* @returns Ref<SchematicJS.CheckPlanReturn | undefined> - Reactive plan data
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```typescript
|
|
253
|
+
* const plan = useSchematicPlan()
|
|
254
|
+
*
|
|
255
|
+
* // In template
|
|
256
|
+
* <div v-if="plan">Current plan: {{ plan.name }}</div>
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
export declare const useSchematicPlan: (opts?: UseSchematicPlanOpts) => Ref<SchematicJS.CheckPlanReturn | undefined>;
|
|
260
|
+
|
|
261
|
+
export declare type UseSchematicPlanOpts = SchematicComposableOpts & {
|
|
262
|
+
fallback?: SchematicJS.CheckPlanReturn;
|
|
263
|
+
};
|
|
264
|
+
|
|
239
265
|
export { }
|
|
@@ -606,6 +606,36 @@ function v4(options, buf, offset) {
|
|
|
606
606
|
}
|
|
607
607
|
var v4_default = v4;
|
|
608
608
|
var import_polyfill = __toESM(require_browser_polyfill());
|
|
609
|
+
function EntitlementValueTypeFromJSON(json) {
|
|
610
|
+
return EntitlementValueTypeFromJSONTyped(json, false);
|
|
611
|
+
}
|
|
612
|
+
function EntitlementValueTypeFromJSONTyped(json, ignoreDiscriminator) {
|
|
613
|
+
return json;
|
|
614
|
+
}
|
|
615
|
+
function FeatureEntitlementFromJSON(json) {
|
|
616
|
+
return FeatureEntitlementFromJSONTyped(json, false);
|
|
617
|
+
}
|
|
618
|
+
function FeatureEntitlementFromJSONTyped(json, ignoreDiscriminator) {
|
|
619
|
+
if (json == null) {
|
|
620
|
+
return json;
|
|
621
|
+
}
|
|
622
|
+
return {
|
|
623
|
+
allocation: json["allocation"] == null ? void 0 : json["allocation"],
|
|
624
|
+
creditId: json["credit_id"] == null ? void 0 : json["credit_id"],
|
|
625
|
+
creditRemaining: json["credit_remaining"] == null ? void 0 : json["credit_remaining"],
|
|
626
|
+
creditTotal: json["credit_total"] == null ? void 0 : json["credit_total"],
|
|
627
|
+
creditUsed: json["credit_used"] == null ? void 0 : json["credit_used"],
|
|
628
|
+
eventName: json["event_name"] == null ? void 0 : json["event_name"],
|
|
629
|
+
featureId: json["feature_id"],
|
|
630
|
+
featureKey: json["feature_key"],
|
|
631
|
+
metricPeriod: json["metric_period"] == null ? void 0 : json["metric_period"],
|
|
632
|
+
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"],
|
|
634
|
+
softLimit: json["soft_limit"] == null ? void 0 : json["soft_limit"],
|
|
635
|
+
usage: json["usage"] == null ? void 0 : json["usage"],
|
|
636
|
+
valueType: EntitlementValueTypeFromJSON(json["value_type"])
|
|
637
|
+
};
|
|
638
|
+
}
|
|
609
639
|
function CheckFlagResponseDataFromJSON(json) {
|
|
610
640
|
return CheckFlagResponseDataFromJSONTyped(json, false);
|
|
611
641
|
}
|
|
@@ -615,6 +645,7 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
615
645
|
}
|
|
616
646
|
return {
|
|
617
647
|
companyId: json["company_id"] == null ? void 0 : json["company_id"],
|
|
648
|
+
entitlement: json["entitlement"] == null ? void 0 : FeatureEntitlementFromJSON(json["entitlement"]),
|
|
618
649
|
error: json["error"] == null ? void 0 : json["error"],
|
|
619
650
|
featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
|
|
620
651
|
featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
|
|
@@ -630,26 +661,6 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
630
661
|
value: json["value"]
|
|
631
662
|
};
|
|
632
663
|
}
|
|
633
|
-
function EventBodyFlagCheckToJSON(json) {
|
|
634
|
-
return EventBodyFlagCheckToJSONTyped(json, false);
|
|
635
|
-
}
|
|
636
|
-
function EventBodyFlagCheckToJSONTyped(value, ignoreDiscriminator = false) {
|
|
637
|
-
if (value == null) {
|
|
638
|
-
return value;
|
|
639
|
-
}
|
|
640
|
-
return {
|
|
641
|
-
company_id: value["companyId"],
|
|
642
|
-
error: value["error"],
|
|
643
|
-
flag_id: value["flagId"],
|
|
644
|
-
flag_key: value["flagKey"],
|
|
645
|
-
reason: value["reason"],
|
|
646
|
-
req_company: value["reqCompany"],
|
|
647
|
-
req_user: value["reqUser"],
|
|
648
|
-
rule_id: value["ruleId"],
|
|
649
|
-
user_id: value["userId"],
|
|
650
|
-
value: value["value"]
|
|
651
|
-
};
|
|
652
|
-
}
|
|
653
664
|
function CheckFlagResponseFromJSON(json) {
|
|
654
665
|
return CheckFlagResponseFromJSONTyped(json, false);
|
|
655
666
|
}
|
|
@@ -662,6 +673,26 @@ function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
662
673
|
params: json["params"]
|
|
663
674
|
};
|
|
664
675
|
}
|
|
676
|
+
function TrialStatusFromJSON(json) {
|
|
677
|
+
return TrialStatusFromJSONTyped(json, false);
|
|
678
|
+
}
|
|
679
|
+
function TrialStatusFromJSONTyped(json, ignoreDiscriminator) {
|
|
680
|
+
return json;
|
|
681
|
+
}
|
|
682
|
+
function DatastreamCompanyPlanFromJSON(json) {
|
|
683
|
+
return DatastreamCompanyPlanFromJSONTyped(json, false);
|
|
684
|
+
}
|
|
685
|
+
function DatastreamCompanyPlanFromJSONTyped(json, ignoreDiscriminator) {
|
|
686
|
+
if (json == null) {
|
|
687
|
+
return json;
|
|
688
|
+
}
|
|
689
|
+
return {
|
|
690
|
+
id: json["id"],
|
|
691
|
+
name: json["name"],
|
|
692
|
+
trialEndDate: json["trial_end_date"] == null ? void 0 : new Date(json["trial_end_date"]),
|
|
693
|
+
trialStatus: json["trial_status"] == null ? void 0 : TrialStatusFromJSON(json["trial_status"])
|
|
694
|
+
};
|
|
695
|
+
}
|
|
665
696
|
function CheckFlagsResponseDataFromJSON(json) {
|
|
666
697
|
return CheckFlagsResponseDataFromJSONTyped(json, false);
|
|
667
698
|
}
|
|
@@ -670,7 +701,8 @@ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
670
701
|
return json;
|
|
671
702
|
}
|
|
672
703
|
return {
|
|
673
|
-
flags: json["flags"].map(CheckFlagResponseDataFromJSON)
|
|
704
|
+
flags: json["flags"].map(CheckFlagResponseDataFromJSON),
|
|
705
|
+
plan: json["plan"] == null ? void 0 : DatastreamCompanyPlanFromJSON(json["plan"])
|
|
674
706
|
};
|
|
675
707
|
}
|
|
676
708
|
function CheckFlagsResponseFromJSON(json) {
|
|
@@ -685,6 +717,26 @@ function CheckFlagsResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
|
685
717
|
params: json["params"]
|
|
686
718
|
};
|
|
687
719
|
}
|
|
720
|
+
function EventBodyFlagCheckToJSON(json) {
|
|
721
|
+
return EventBodyFlagCheckToJSONTyped(json, false);
|
|
722
|
+
}
|
|
723
|
+
function EventBodyFlagCheckToJSONTyped(value, ignoreDiscriminator = false) {
|
|
724
|
+
if (value == null) {
|
|
725
|
+
return value;
|
|
726
|
+
}
|
|
727
|
+
return {
|
|
728
|
+
company_id: value["companyId"],
|
|
729
|
+
error: value["error"],
|
|
730
|
+
flag_id: value["flagId"],
|
|
731
|
+
flag_key: value["flagKey"],
|
|
732
|
+
reason: value["reason"],
|
|
733
|
+
req_company: value["reqCompany"],
|
|
734
|
+
req_user: value["reqUser"],
|
|
735
|
+
rule_id: value["ruleId"],
|
|
736
|
+
user_id: value["userId"],
|
|
737
|
+
value: value["value"]
|
|
738
|
+
};
|
|
739
|
+
}
|
|
688
740
|
var RuleType = /* @__PURE__ */ ((RuleType2) => {
|
|
689
741
|
RuleType2["GLOBAL_OVERRIDE"] = "global_override";
|
|
690
742
|
RuleType2["COMPANY_OVERRIDE"] = "company_override";
|
|
@@ -705,6 +757,7 @@ var UsagePeriod = /* @__PURE__ */ ((UsagePeriod2) => {
|
|
|
705
757
|
var CheckFlagReturnFromJSON = (json) => {
|
|
706
758
|
const {
|
|
707
759
|
companyId,
|
|
760
|
+
entitlement,
|
|
708
761
|
error,
|
|
709
762
|
featureAllocation,
|
|
710
763
|
featureUsage,
|
|
@@ -722,24 +775,40 @@ var CheckFlagReturnFromJSON = (json) => {
|
|
|
722
775
|
const featureUsageExceeded = !value && // if flag is not false, then we haven't exceeded usage
|
|
723
776
|
(ruleType == "company_override_usage_exceeded" || // if the rule type is one of these, then we have exceeded usage
|
|
724
777
|
ruleType == "plan_entitlement_usage_exceeded");
|
|
778
|
+
const resolvedAllocation = entitlement?.allocation ?? featureAllocation;
|
|
779
|
+
const resolvedUsage = entitlement?.usage ?? featureUsage;
|
|
780
|
+
const resolvedEvent = entitlement?.eventName ?? featureUsageEvent;
|
|
781
|
+
const resolvedPeriod = entitlement?.metricPeriod ?? featureUsagePeriod;
|
|
782
|
+
const resolvedResetAt = entitlement?.metricResetAt ?? featureUsageResetAt;
|
|
725
783
|
return {
|
|
726
784
|
featureUsageExceeded,
|
|
727
785
|
companyId: companyId == null ? void 0 : companyId,
|
|
786
|
+
creditRemaining: entitlement?.creditRemaining == null ? void 0 : entitlement.creditRemaining,
|
|
728
787
|
error: error == null ? void 0 : error,
|
|
729
|
-
featureAllocation:
|
|
730
|
-
featureUsage:
|
|
731
|
-
featureUsageEvent:
|
|
732
|
-
featureUsagePeriod:
|
|
733
|
-
featureUsageResetAt:
|
|
788
|
+
featureAllocation: resolvedAllocation == null ? void 0 : resolvedAllocation,
|
|
789
|
+
featureUsage: resolvedUsage == null ? void 0 : resolvedUsage,
|
|
790
|
+
featureUsageEvent: resolvedEvent == null ? void 0 : resolvedEvent,
|
|
791
|
+
featureUsagePeriod: resolvedPeriod == null ? void 0 : resolvedPeriod,
|
|
792
|
+
featureUsageResetAt: resolvedResetAt == null ? void 0 : resolvedResetAt,
|
|
734
793
|
flag,
|
|
735
794
|
flagId: flagId == null ? void 0 : flagId,
|
|
736
795
|
reason,
|
|
737
796
|
ruleId: ruleId == null ? void 0 : ruleId,
|
|
738
797
|
ruleType: ruleType == null ? void 0 : ruleType,
|
|
798
|
+
softLimit: entitlement?.softLimit == null ? void 0 : entitlement.softLimit,
|
|
739
799
|
userId: userId == null ? void 0 : userId,
|
|
740
800
|
value
|
|
741
801
|
};
|
|
742
802
|
};
|
|
803
|
+
var CheckPlanReturnFromJSON = (json) => {
|
|
804
|
+
const { id, name, trialEndDate, trialStatus } = DatastreamCompanyPlanFromJSON(json);
|
|
805
|
+
return {
|
|
806
|
+
id,
|
|
807
|
+
name,
|
|
808
|
+
trialEndDate: trialEndDate == null ? void 0 : trialEndDate,
|
|
809
|
+
trialStatus: trialStatus == null ? void 0 : trialStatus
|
|
810
|
+
};
|
|
811
|
+
};
|
|
743
812
|
function contextString(context) {
|
|
744
813
|
const sortedContext = Object.keys(context).reduce((acc, key) => {
|
|
745
814
|
const sortedKeys = Object.keys(
|
|
@@ -754,7 +823,7 @@ function contextString(context) {
|
|
|
754
823
|
}, {});
|
|
755
824
|
return JSON.stringify(sortedContext);
|
|
756
825
|
}
|
|
757
|
-
var version = "1.
|
|
826
|
+
var version = "1.4.0";
|
|
758
827
|
var anonymousIdKey = "schematicId";
|
|
759
828
|
var Schematic = class {
|
|
760
829
|
additionalHeaders = {};
|
|
@@ -771,10 +840,12 @@ var Schematic = class {
|
|
|
771
840
|
flagValueListeners = {};
|
|
772
841
|
isPending = true;
|
|
773
842
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
843
|
+
planListeners = /* @__PURE__ */ new Set();
|
|
774
844
|
storage;
|
|
775
845
|
useWebSocket = false;
|
|
776
846
|
checks = {};
|
|
777
847
|
featureUsageEventMap = {};
|
|
848
|
+
planChecks = {};
|
|
778
849
|
webSocketUrl = "wss://api.schematichq.com";
|
|
779
850
|
webSocketConnectionTimeout = 1e4;
|
|
780
851
|
webSocketReconnect = true;
|
|
@@ -800,6 +871,7 @@ var Schematic = class {
|
|
|
800
871
|
retryTimer = null;
|
|
801
872
|
flagValueDefaults = {};
|
|
802
873
|
flagCheckDefaults = {};
|
|
874
|
+
fallbackCheckCache = {};
|
|
803
875
|
constructor(apiKey, options) {
|
|
804
876
|
this.apiKey = apiKey;
|
|
805
877
|
this.eventQueue = [];
|
|
@@ -968,8 +1040,8 @@ var Schematic = class {
|
|
|
968
1040
|
/**
|
|
969
1041
|
* Get value for a single flag.
|
|
970
1042
|
* In WebSocket mode, returns cached values if connection is active, otherwise establishes
|
|
971
|
-
* new connection and then returns the
|
|
972
|
-
* connection fails.
|
|
1043
|
+
* new connection and then returns the requested value. Falls back to preconfigured fallback
|
|
1044
|
+
* values if WebSocket connection fails.
|
|
973
1045
|
* In REST mode, makes an API call for each check.
|
|
974
1046
|
*/
|
|
975
1047
|
async checkFlag(options) {
|
|
@@ -1038,10 +1110,17 @@ var Schematic = class {
|
|
|
1038
1110
|
await this.setContext(context);
|
|
1039
1111
|
} catch (error) {
|
|
1040
1112
|
console.warn(
|
|
1041
|
-
"WebSocket connection failed,
|
|
1113
|
+
"WebSocket connection failed, using fallback value:",
|
|
1042
1114
|
error
|
|
1043
1115
|
);
|
|
1044
|
-
|
|
1116
|
+
const errorResult = this.resolveFallbackCheckFlagReturn(
|
|
1117
|
+
key,
|
|
1118
|
+
fallback,
|
|
1119
|
+
"WebSocket connection failed",
|
|
1120
|
+
error instanceof Error ? error.message : String(error)
|
|
1121
|
+
);
|
|
1122
|
+
this.submitFlagCheckEvent(key, errorResult, context);
|
|
1123
|
+
return errorResult.value;
|
|
1045
1124
|
}
|
|
1046
1125
|
const contextVals = this.checks[contextStr] ?? {};
|
|
1047
1126
|
const flagCheck = contextVals[key];
|
|
@@ -1052,6 +1131,13 @@ var Schematic = class {
|
|
|
1052
1131
|
);
|
|
1053
1132
|
if (typeof flagCheck !== "undefined") {
|
|
1054
1133
|
this.submitFlagCheckEvent(key, flagCheck, context);
|
|
1134
|
+
} else {
|
|
1135
|
+
const fallbackResult = this.resolveFallbackCheckFlagReturn(
|
|
1136
|
+
key,
|
|
1137
|
+
fallback,
|
|
1138
|
+
"No flag values available"
|
|
1139
|
+
);
|
|
1140
|
+
this.submitFlagCheckEvent(key, fallbackResult, context);
|
|
1055
1141
|
}
|
|
1056
1142
|
return result;
|
|
1057
1143
|
} catch (error) {
|
|
@@ -1092,28 +1178,32 @@ var Schematic = class {
|
|
|
1092
1178
|
this.checks[contextStr] = {};
|
|
1093
1179
|
}
|
|
1094
1180
|
this.checks[contextStr][flagCheck.flag] = flagCheck;
|
|
1095
|
-
this.debug(`WebSocket flag update:`, {
|
|
1096
|
-
flag: flagCheck.flag,
|
|
1097
|
-
value: flagCheck.value,
|
|
1098
|
-
flagCheck
|
|
1099
|
-
});
|
|
1100
1181
|
if (typeof flagCheck.featureUsageEvent === "string") {
|
|
1101
1182
|
this.updateFeatureUsageEventMap(flagCheck);
|
|
1102
1183
|
}
|
|
1103
1184
|
if ((this.flagCheckListeners[flag.flag]?.size ?? 0) > 0 || (this.flagValueListeners[flag.flag]?.size ?? 0) > 0) {
|
|
1104
1185
|
this.submitFlagCheckEvent(flagCheck.flag, flagCheck, context);
|
|
1105
1186
|
}
|
|
1106
|
-
this.debug(
|
|
1107
|
-
flag
|
|
1108
|
-
|
|
1109
|
-
|
|
1187
|
+
this.debug(
|
|
1188
|
+
`WebSocket flag update received. Notifying listeners for ${flag.flag}`,
|
|
1189
|
+
{
|
|
1190
|
+
flag: flag.flag,
|
|
1191
|
+
value: flagCheck.value,
|
|
1192
|
+
flagCheck
|
|
1193
|
+
}
|
|
1194
|
+
);
|
|
1110
1195
|
this.notifyFlagCheckListeners(flag.flag, flagCheck);
|
|
1111
1196
|
this.notifyFlagValueListeners(flag.flag, flagCheck.value);
|
|
1112
|
-
this.debug(`Finished notifying listeners for flag ${flag.flag}`, {
|
|
1113
|
-
flag: flag.flag,
|
|
1114
|
-
value: flagCheck.value
|
|
1115
|
-
});
|
|
1116
1197
|
});
|
|
1198
|
+
if (message.plan !== void 0 && message.plan !== null) {
|
|
1199
|
+
const plan = CheckPlanReturnFromJSON(message.plan);
|
|
1200
|
+
const contextStr = contextString(context);
|
|
1201
|
+
this.planChecks[contextStr] = plan;
|
|
1202
|
+
this.debug(`WebSocket plan update received. Notifying listeners`, {
|
|
1203
|
+
plan
|
|
1204
|
+
});
|
|
1205
|
+
this.notifyPlanListeners(plan);
|
|
1206
|
+
}
|
|
1117
1207
|
this.flushContextDependentEventQueue();
|
|
1118
1208
|
this.setIsPending(false);
|
|
1119
1209
|
};
|
|
@@ -1144,53 +1234,6 @@ var Schematic = class {
|
|
|
1144
1234
|
this.debug(`submitting flag check event:`, eventBody);
|
|
1145
1235
|
return this.handleEvent("flag_check", EventBodyFlagCheckToJSON(eventBody));
|
|
1146
1236
|
}
|
|
1147
|
-
/**
|
|
1148
|
-
* Helper method for falling back to REST API when WebSocket connection fails
|
|
1149
|
-
*/
|
|
1150
|
-
async fallbackToRest(key, context, fallback) {
|
|
1151
|
-
if (this.isOffline()) {
|
|
1152
|
-
const resolvedFallback = this.resolveFallbackValue(key, fallback);
|
|
1153
|
-
this.debug(`fallbackToRest offline result: ${key}`, {
|
|
1154
|
-
value: resolvedFallback,
|
|
1155
|
-
offlineMode: true
|
|
1156
|
-
});
|
|
1157
|
-
return resolvedFallback;
|
|
1158
|
-
}
|
|
1159
|
-
try {
|
|
1160
|
-
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
|
1161
|
-
const response = await fetch(requestUrl, {
|
|
1162
|
-
method: "POST",
|
|
1163
|
-
headers: {
|
|
1164
|
-
...this.additionalHeaders ?? {},
|
|
1165
|
-
"Content-Type": "application/json;charset=UTF-8",
|
|
1166
|
-
"X-Schematic-Api-Key": this.apiKey
|
|
1167
|
-
},
|
|
1168
|
-
body: JSON.stringify(context)
|
|
1169
|
-
});
|
|
1170
|
-
if (!response.ok) {
|
|
1171
|
-
throw new Error("Network response was not ok");
|
|
1172
|
-
}
|
|
1173
|
-
const responseJson = await response.json();
|
|
1174
|
-
const data = CheckFlagResponseFromJSON(responseJson);
|
|
1175
|
-
this.debug(`fallbackToRest result: ${key}`, data);
|
|
1176
|
-
const result = CheckFlagReturnFromJSON(data.data);
|
|
1177
|
-
if (typeof result.featureUsageEvent === "string") {
|
|
1178
|
-
this.updateFeatureUsageEventMap(result);
|
|
1179
|
-
}
|
|
1180
|
-
this.submitFlagCheckEvent(key, result, context);
|
|
1181
|
-
return result.value;
|
|
1182
|
-
} catch (error) {
|
|
1183
|
-
console.warn("REST API call failed, using fallback value:", error);
|
|
1184
|
-
const errorResult = this.resolveFallbackCheckFlagReturn(
|
|
1185
|
-
key,
|
|
1186
|
-
fallback,
|
|
1187
|
-
"API request failed (fallback)",
|
|
1188
|
-
error instanceof Error ? error.message : String(error)
|
|
1189
|
-
);
|
|
1190
|
-
this.submitFlagCheckEvent(key, errorResult, context);
|
|
1191
|
-
return errorResult.value;
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
1237
|
/**
|
|
1195
1238
|
* Make an API call to fetch all flag values for a given context.
|
|
1196
1239
|
* Recommended for use in REST mode only.
|
|
@@ -1264,6 +1307,9 @@ var Schematic = class {
|
|
|
1264
1307
|
this.setIsPending(false);
|
|
1265
1308
|
return Promise.resolve();
|
|
1266
1309
|
}
|
|
1310
|
+
if (contextString(context) === contextString(this.context) && this.conn !== null && !this.isPending) {
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1267
1313
|
try {
|
|
1268
1314
|
this.setIsPending(true);
|
|
1269
1315
|
if (!this.conn) {
|
|
@@ -1303,7 +1349,10 @@ var Schematic = class {
|
|
|
1303
1349
|
await this.wsSendMessage(socket, context);
|
|
1304
1350
|
} catch (error) {
|
|
1305
1351
|
console.warn("Failed to establish WebSocket connection:", error);
|
|
1306
|
-
|
|
1352
|
+
this.context = context;
|
|
1353
|
+
this.flushContextDependentEventQueue();
|
|
1354
|
+
this.setIsPending(false);
|
|
1355
|
+
this.attemptReconnect();
|
|
1307
1356
|
}
|
|
1308
1357
|
};
|
|
1309
1358
|
/**
|
|
@@ -1944,7 +1993,10 @@ var Schematic = class {
|
|
|
1944
1993
|
clearTimeout(timeoutId);
|
|
1945
1994
|
}
|
|
1946
1995
|
this.debug(`WebSocket connection ${connectionId} error:`, error);
|
|
1947
|
-
|
|
1996
|
+
const wrappedError = new Error(
|
|
1997
|
+
"WebSocket connection failed during handshake"
|
|
1998
|
+
);
|
|
1999
|
+
reject(wrappedError);
|
|
1948
2000
|
};
|
|
1949
2001
|
webSocket.onclose = () => {
|
|
1950
2002
|
if (timeoutId !== null) {
|
|
@@ -1991,6 +2043,20 @@ var Schematic = class {
|
|
|
1991
2043
|
}
|
|
1992
2044
|
};
|
|
1993
2045
|
socket.addEventListener("message", messageHandler);
|
|
2046
|
+
socket.addEventListener("close", (event) => {
|
|
2047
|
+
if (!resolved) {
|
|
2048
|
+
resolved = true;
|
|
2049
|
+
if (event.code === 4001) {
|
|
2050
|
+
reject(
|
|
2051
|
+
new Error(
|
|
2052
|
+
`Authentication failed: ${event.reason !== "" ? event.reason : "Invalid API key"}`
|
|
2053
|
+
)
|
|
2054
|
+
);
|
|
2055
|
+
} else {
|
|
2056
|
+
reject(new Error("WebSocket connection closed unexpectedly"));
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
});
|
|
1994
2060
|
this.currentWebSocket = socket;
|
|
1995
2061
|
const clientVersion = this.additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
|
|
1996
2062
|
const messagePayload = {
|
|
@@ -2027,11 +2093,17 @@ var Schematic = class {
|
|
|
2027
2093
|
};
|
|
2028
2094
|
};
|
|
2029
2095
|
setIsPending = (isPending) => {
|
|
2096
|
+
if (this.isPending === isPending) return;
|
|
2030
2097
|
this.isPending = isPending;
|
|
2031
2098
|
this.isPendingListeners.forEach(
|
|
2032
2099
|
(listener) => notifyPendingListener(listener, isPending)
|
|
2033
2100
|
);
|
|
2034
2101
|
};
|
|
2102
|
+
getPlan = () => {
|
|
2103
|
+
const contextStr = contextString(this.context);
|
|
2104
|
+
const plan = this.planChecks[contextStr];
|
|
2105
|
+
return plan;
|
|
2106
|
+
};
|
|
2035
2107
|
// flag checks state
|
|
2036
2108
|
getFlagCheck = (flagKey) => {
|
|
2037
2109
|
const contextStr = contextString(this.context);
|
|
@@ -2041,11 +2113,14 @@ var Schematic = class {
|
|
|
2041
2113
|
return check;
|
|
2042
2114
|
}
|
|
2043
2115
|
if (flagKey in this.flagCheckDefaults || flagKey in this.flagValueDefaults) {
|
|
2044
|
-
|
|
2045
|
-
flagKey
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2116
|
+
if (!(flagKey in this.fallbackCheckCache)) {
|
|
2117
|
+
this.fallbackCheckCache[flagKey] = this.resolveFallbackCheckFlagReturn(
|
|
2118
|
+
flagKey,
|
|
2119
|
+
void 0,
|
|
2120
|
+
"Default value used"
|
|
2121
|
+
);
|
|
2122
|
+
}
|
|
2123
|
+
return this.fallbackCheckCache[flagKey];
|
|
2049
2124
|
}
|
|
2050
2125
|
return void 0;
|
|
2051
2126
|
};
|
|
@@ -2082,6 +2157,12 @@ var Schematic = class {
|
|
|
2082
2157
|
this.flagCheckListeners[flagKey].delete(listener);
|
|
2083
2158
|
};
|
|
2084
2159
|
};
|
|
2160
|
+
addPlanListener = (listener) => {
|
|
2161
|
+
this.planListeners.add(listener);
|
|
2162
|
+
return () => {
|
|
2163
|
+
this.planListeners.delete(listener);
|
|
2164
|
+
};
|
|
2165
|
+
};
|
|
2085
2166
|
notifyFlagCheckListeners = (flagKey, check) => {
|
|
2086
2167
|
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
2087
2168
|
if (listeners.size > 0) {
|
|
@@ -2130,6 +2211,21 @@ var Schematic = class {
|
|
|
2130
2211
|
});
|
|
2131
2212
|
});
|
|
2132
2213
|
};
|
|
2214
|
+
notifyPlanListeners = (value) => {
|
|
2215
|
+
const listeners = this.planListeners ?? [];
|
|
2216
|
+
if (listeners.size > 0) {
|
|
2217
|
+
this.debug(`Notifying ${listeners.size} plan listeners`, { value });
|
|
2218
|
+
}
|
|
2219
|
+
listeners.forEach((listener, index) => {
|
|
2220
|
+
this.debug(`Calling listener ${index} for plan`, {
|
|
2221
|
+
value
|
|
2222
|
+
});
|
|
2223
|
+
notifyPlanListener(listener, value);
|
|
2224
|
+
this.debug(`Listener ${index} for plan completed`, {
|
|
2225
|
+
value
|
|
2226
|
+
});
|
|
2227
|
+
});
|
|
2228
|
+
};
|
|
2133
2229
|
};
|
|
2134
2230
|
var notifyPendingListener = (listener, value) => {
|
|
2135
2231
|
if (listener.length > 0) {
|
|
@@ -2152,12 +2248,19 @@ var notifyFlagValueListener = (listener, value) => {
|
|
|
2152
2248
|
listener();
|
|
2153
2249
|
}
|
|
2154
2250
|
};
|
|
2251
|
+
var notifyPlanListener = (listener, value) => {
|
|
2252
|
+
if (listener.length > 0) {
|
|
2253
|
+
listener(value);
|
|
2254
|
+
} else {
|
|
2255
|
+
listener();
|
|
2256
|
+
}
|
|
2257
|
+
};
|
|
2155
2258
|
|
|
2156
2259
|
// src/context/schematic.ts
|
|
2157
2260
|
import { inject, onScopeDispose } from "vue";
|
|
2158
2261
|
|
|
2159
2262
|
// src/version.ts
|
|
2160
|
-
var version2 = "1.
|
|
2263
|
+
var version2 = "1.4.0";
|
|
2161
2264
|
|
|
2162
2265
|
// src/context/schematic.ts
|
|
2163
2266
|
var SchematicSymbol = Symbol("schematic");
|
|
@@ -2273,6 +2376,23 @@ var useSchematicEntitlement = (key, opts) => {
|
|
|
2273
2376
|
userId: computed(() => flagCheck.value.userId)
|
|
2274
2377
|
};
|
|
2275
2378
|
};
|
|
2379
|
+
var useSchematicPlan = (opts) => {
|
|
2380
|
+
const client = useSchematicClient(opts);
|
|
2381
|
+
const fallback = opts?.fallback;
|
|
2382
|
+
const plan = ref(
|
|
2383
|
+
client.getPlan() ?? fallback
|
|
2384
|
+
);
|
|
2385
|
+
let unsubscribe = null;
|
|
2386
|
+
onMounted(() => {
|
|
2387
|
+
unsubscribe = client.addPlanListener((value) => {
|
|
2388
|
+
plan.value = value;
|
|
2389
|
+
});
|
|
2390
|
+
});
|
|
2391
|
+
onScopeDispose2(() => {
|
|
2392
|
+
unsubscribe?.();
|
|
2393
|
+
});
|
|
2394
|
+
return plan;
|
|
2395
|
+
};
|
|
2276
2396
|
var useSchematicIsPending = (opts) => {
|
|
2277
2397
|
const client = useSchematicClient(opts);
|
|
2278
2398
|
const isPending = ref(client.getIsPending());
|
|
@@ -2298,7 +2418,8 @@ export {
|
|
|
2298
2418
|
useSchematicEntitlement,
|
|
2299
2419
|
useSchematicEvents,
|
|
2300
2420
|
useSchematicFlag,
|
|
2301
|
-
useSchematicIsPending
|
|
2421
|
+
useSchematicIsPending,
|
|
2422
|
+
useSchematicPlan
|
|
2302
2423
|
};
|
|
2303
2424
|
/*! Bundled license information:
|
|
2304
2425
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schematichq/schematic-vue",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"main": "dist/schematic-vue.cjs.js",
|
|
5
5
|
"module": "dist/schematic-vue.esm.js",
|
|
6
6
|
"types": "dist/schematic-vue.d.ts",
|
|
@@ -28,17 +28,14 @@
|
|
|
28
28
|
"tsc": "npx tsc",
|
|
29
29
|
"prepare": "husky"
|
|
30
30
|
},
|
|
31
|
-
"dependencies": {
|
|
32
|
-
"@schematichq/schematic-js": "^1.2.16"
|
|
33
|
-
},
|
|
34
31
|
"devDependencies": {
|
|
35
32
|
"@eslint/js": "^9.24.0",
|
|
36
33
|
"@microsoft/api-extractor": "^7.52.2",
|
|
34
|
+
"@schematichq/schematic-js": "^1.4.0",
|
|
37
35
|
"@testing-library/dom": "^10.4.1",
|
|
38
36
|
"@types/jest": "^30.0.0",
|
|
39
37
|
"@vue/test-utils": "^2.4.6",
|
|
40
38
|
"esbuild": "^0.25.2",
|
|
41
|
-
"esbuild-jest": "^0.5.0",
|
|
42
39
|
"eslint": "^9.24.0",
|
|
43
40
|
"eslint-plugin-import": "^2.32.0",
|
|
44
41
|
"eslint-plugin-vue": "^9.30.0",
|
|
@@ -56,5 +53,9 @@
|
|
|
56
53
|
"peerDependencies": {
|
|
57
54
|
"vue": ">=3.3"
|
|
58
55
|
},
|
|
56
|
+
"resolutions": {
|
|
57
|
+
"handlebars": ">=4.7.9",
|
|
58
|
+
"minimatch": ">=3.1.3"
|
|
59
|
+
},
|
|
59
60
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
60
61
|
}
|