@schematichq/schematic-react 1.2.3 → 1.2.4
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 +44 -0
- package/dist/schematic-react.cjs.js +230 -18
- package/dist/schematic-react.esm.js +230 -18
- package/package.json +3 -3
package/README.md
CHANGED
@@ -126,6 +126,50 @@ const MyComponent = () => {
|
|
126
126
|
};
|
127
127
|
```
|
128
128
|
|
129
|
+
## Troubleshooting
|
130
|
+
|
131
|
+
For debugging and development, Schematic supports two special modes:
|
132
|
+
|
133
|
+
### Debug Mode
|
134
|
+
|
135
|
+
Enables console logging of all Schematic operations:
|
136
|
+
|
137
|
+
```typescript
|
138
|
+
// Enable at initialization
|
139
|
+
import { SchematicProvider } from "@schematichq/schematic-react";
|
140
|
+
|
141
|
+
ReactDOM.render(
|
142
|
+
<SchematicProvider publishableKey="your-publishable-key" debug={true}>
|
143
|
+
<App />
|
144
|
+
</SchematicProvider>,
|
145
|
+
document.getElementById("root"),
|
146
|
+
);
|
147
|
+
|
148
|
+
// Or via URL parameter
|
149
|
+
// https://yoursite.com/?schematic_debug=true
|
150
|
+
```
|
151
|
+
|
152
|
+
### Offline Mode
|
153
|
+
|
154
|
+
Prevents network requests and returns fallback values for all flag checks:
|
155
|
+
|
156
|
+
```typescript
|
157
|
+
// Enable at initialization
|
158
|
+
import { SchematicProvider } from "@schematichq/schematic-react";
|
159
|
+
|
160
|
+
ReactDOM.render(
|
161
|
+
<SchematicProvider publishableKey="your-publishable-key" offline={true}>
|
162
|
+
<App />
|
163
|
+
</SchematicProvider>,
|
164
|
+
document.getElementById("root"),
|
165
|
+
);
|
166
|
+
|
167
|
+
// Or via URL parameter
|
168
|
+
// https://yoursite.com/?schematic_offline=true
|
169
|
+
```
|
170
|
+
|
171
|
+
Offline mode automatically enables debug mode to help with troubleshooting.
|
172
|
+
|
129
173
|
## License
|
130
174
|
|
131
175
|
MIT
|
@@ -671,6 +671,26 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
671
671
|
value: json["value"]
|
672
672
|
};
|
673
673
|
}
|
674
|
+
function EventBodyFlagCheckToJSON(json) {
|
675
|
+
return EventBodyFlagCheckToJSONTyped(json, false);
|
676
|
+
}
|
677
|
+
function EventBodyFlagCheckToJSONTyped(value, ignoreDiscriminator = false) {
|
678
|
+
if (value == null) {
|
679
|
+
return value;
|
680
|
+
}
|
681
|
+
return {
|
682
|
+
company_id: value["companyId"],
|
683
|
+
error: value["error"],
|
684
|
+
flag_id: value["flagId"],
|
685
|
+
flag_key: value["flagKey"],
|
686
|
+
reason: value["reason"],
|
687
|
+
req_company: value["reqCompany"],
|
688
|
+
req_user: value["reqUser"],
|
689
|
+
rule_id: value["ruleId"],
|
690
|
+
user_id: value["userId"],
|
691
|
+
value: value["value"]
|
692
|
+
};
|
693
|
+
}
|
674
694
|
function CheckFlagResponseFromJSON(json) {
|
675
695
|
return CheckFlagResponseFromJSONTyped(json, false);
|
676
696
|
}
|
@@ -773,7 +793,7 @@ function contextString(context) {
|
|
773
793
|
}, {});
|
774
794
|
return JSON.stringify(sortedContext);
|
775
795
|
}
|
776
|
-
var version = "1.2.
|
796
|
+
var version = "1.2.2";
|
777
797
|
var anonymousIdKey = "schematicId";
|
778
798
|
var Schematic = class {
|
779
799
|
additionalHeaders = {};
|
@@ -781,6 +801,8 @@ var Schematic = class {
|
|
781
801
|
apiUrl = "https://api.schematichq.com";
|
782
802
|
conn = null;
|
783
803
|
context = {};
|
804
|
+
debugEnabled = false;
|
805
|
+
offlineEnabled = false;
|
784
806
|
eventQueue;
|
785
807
|
eventUrl = "https://c.schematichq.com";
|
786
808
|
flagCheckListeners = {};
|
@@ -795,6 +817,26 @@ var Schematic = class {
|
|
795
817
|
this.apiKey = apiKey;
|
796
818
|
this.eventQueue = [];
|
797
819
|
this.useWebSocket = options?.useWebSocket ?? false;
|
820
|
+
this.debugEnabled = options?.debug ?? false;
|
821
|
+
this.offlineEnabled = options?.offline ?? false;
|
822
|
+
if (typeof window !== "undefined" && typeof window.location !== "undefined") {
|
823
|
+
const params = new URLSearchParams(window.location.search);
|
824
|
+
const debugParam = params.get("schematic_debug");
|
825
|
+
if (debugParam !== null && (debugParam === "" || debugParam === "true" || debugParam === "1")) {
|
826
|
+
this.debugEnabled = true;
|
827
|
+
}
|
828
|
+
const offlineParam = params.get("schematic_offline");
|
829
|
+
if (offlineParam !== null && (offlineParam === "" || offlineParam === "true" || offlineParam === "1")) {
|
830
|
+
this.offlineEnabled = true;
|
831
|
+
this.debugEnabled = true;
|
832
|
+
}
|
833
|
+
}
|
834
|
+
if (this.offlineEnabled && options?.debug !== false) {
|
835
|
+
this.debugEnabled = true;
|
836
|
+
}
|
837
|
+
if (this.offlineEnabled) {
|
838
|
+
this.setIsPending(false);
|
839
|
+
}
|
798
840
|
this.additionalHeaders = {
|
799
841
|
"X-Schematic-Client-Version": `schematic-js@${version}`,
|
800
842
|
...options?.additionalHeaders ?? {}
|
@@ -818,6 +860,13 @@ var Schematic = class {
|
|
818
860
|
this.flushEventQueue();
|
819
861
|
});
|
820
862
|
}
|
863
|
+
if (this.offlineEnabled) {
|
864
|
+
this.debug(
|
865
|
+
"Initialized with offline mode enabled - no network requests will be made"
|
866
|
+
);
|
867
|
+
} else if (this.debugEnabled) {
|
868
|
+
this.debug("Initialized with debug mode enabled");
|
869
|
+
}
|
821
870
|
}
|
822
871
|
/**
|
823
872
|
* Get value for a single flag.
|
@@ -830,6 +879,14 @@ var Schematic = class {
|
|
830
879
|
const { fallback = false, key } = options;
|
831
880
|
const context = options.context || this.context;
|
832
881
|
const contextStr = contextString(context);
|
882
|
+
this.debug(`checkFlag: ${key}`, { context, fallback });
|
883
|
+
if (this.isOffline()) {
|
884
|
+
this.debug(`checkFlag offline result: ${key}`, {
|
885
|
+
value: fallback,
|
886
|
+
offlineMode: true
|
887
|
+
});
|
888
|
+
return fallback;
|
889
|
+
}
|
833
890
|
if (!this.useWebSocket) {
|
834
891
|
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
835
892
|
return fetch(requestUrl, {
|
@@ -846,17 +903,32 @@ var Schematic = class {
|
|
846
903
|
}
|
847
904
|
return response.json();
|
848
905
|
}).then((response) => {
|
849
|
-
|
906
|
+
const parsedResponse = CheckFlagResponseFromJSON(response);
|
907
|
+
this.debug(`checkFlag result: ${key}`, parsedResponse);
|
908
|
+
const result = CheckFlagReturnFromJSON(parsedResponse.data);
|
909
|
+
this.submitFlagCheckEvent(key, result, context);
|
910
|
+
return result.value;
|
850
911
|
}).catch((error) => {
|
851
912
|
console.error("There was a problem with the fetch operation:", error);
|
913
|
+
const errorResult = {
|
914
|
+
flag: key,
|
915
|
+
value: fallback,
|
916
|
+
reason: "API request failed",
|
917
|
+
error: error instanceof Error ? error.message : String(error)
|
918
|
+
};
|
919
|
+
this.submitFlagCheckEvent(key, errorResult, context);
|
852
920
|
return fallback;
|
853
921
|
});
|
854
922
|
}
|
855
923
|
try {
|
856
924
|
const existingVals = this.checks[contextStr];
|
857
|
-
if (this.conn && typeof existingVals !== "undefined" && typeof existingVals[key] !== "undefined") {
|
925
|
+
if (this.conn !== null && typeof existingVals !== "undefined" && typeof existingVals[key] !== "undefined") {
|
926
|
+
this.debug(`checkFlag cached result: ${key}`, existingVals[key]);
|
858
927
|
return existingVals[key].value;
|
859
928
|
}
|
929
|
+
if (this.isOffline()) {
|
930
|
+
return fallback;
|
931
|
+
}
|
860
932
|
try {
|
861
933
|
await this.setContext(context);
|
862
934
|
} catch (error) {
|
@@ -867,16 +939,74 @@ var Schematic = class {
|
|
867
939
|
return this.fallbackToRest(key, context, fallback);
|
868
940
|
}
|
869
941
|
const contextVals = this.checks[contextStr] ?? {};
|
870
|
-
|
942
|
+
const flagCheck = contextVals[key];
|
943
|
+
const result = flagCheck?.value ?? fallback;
|
944
|
+
this.debug(
|
945
|
+
`checkFlag WebSocket result: ${key}`,
|
946
|
+
typeof flagCheck !== "undefined" ? flagCheck : { value: fallback, fallbackUsed: true }
|
947
|
+
);
|
948
|
+
if (typeof flagCheck !== "undefined") {
|
949
|
+
this.submitFlagCheckEvent(key, flagCheck, context);
|
950
|
+
}
|
951
|
+
return result;
|
871
952
|
} catch (error) {
|
872
953
|
console.error("Unexpected error in checkFlag:", error);
|
954
|
+
const errorResult = {
|
955
|
+
flag: key,
|
956
|
+
value: fallback,
|
957
|
+
reason: "Unexpected error in flag check",
|
958
|
+
error: error instanceof Error ? error.message : String(error)
|
959
|
+
};
|
960
|
+
this.submitFlagCheckEvent(key, errorResult, context);
|
873
961
|
return fallback;
|
874
962
|
}
|
875
963
|
}
|
964
|
+
/**
|
965
|
+
* Helper function to log debug messages
|
966
|
+
* Only logs if debug mode is enabled
|
967
|
+
*/
|
968
|
+
debug(message, ...args) {
|
969
|
+
if (this.debugEnabled) {
|
970
|
+
console.log(`[Schematic] ${message}`, ...args);
|
971
|
+
}
|
972
|
+
}
|
973
|
+
/**
|
974
|
+
* Helper function to check if client is in offline mode
|
975
|
+
*/
|
976
|
+
isOffline() {
|
977
|
+
return this.offlineEnabled;
|
978
|
+
}
|
979
|
+
/**
|
980
|
+
* Submit a flag check event
|
981
|
+
* Records data about a flag check for analytics
|
982
|
+
*/
|
983
|
+
submitFlagCheckEvent(flagKey, result, context) {
|
984
|
+
const eventBody = {
|
985
|
+
flagKey,
|
986
|
+
value: result.value,
|
987
|
+
reason: result.reason,
|
988
|
+
flagId: result.flagId,
|
989
|
+
ruleId: result.ruleId,
|
990
|
+
companyId: result.companyId,
|
991
|
+
userId: result.userId,
|
992
|
+
error: result.error,
|
993
|
+
reqCompany: context.company,
|
994
|
+
reqUser: context.user
|
995
|
+
};
|
996
|
+
this.debug(`submitting flag check event:`, eventBody);
|
997
|
+
return this.handleEvent("flag_check", EventBodyFlagCheckToJSON(eventBody));
|
998
|
+
}
|
876
999
|
/**
|
877
1000
|
* Helper method for falling back to REST API when WebSocket connection fails
|
878
1001
|
*/
|
879
1002
|
async fallbackToRest(key, context, fallback) {
|
1003
|
+
if (this.isOffline()) {
|
1004
|
+
this.debug(`fallbackToRest offline result: ${key}`, {
|
1005
|
+
value: fallback,
|
1006
|
+
offlineMode: true
|
1007
|
+
});
|
1008
|
+
return fallback;
|
1009
|
+
}
|
880
1010
|
try {
|
881
1011
|
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
882
1012
|
const response = await fetch(requestUrl, {
|
@@ -891,19 +1021,36 @@ var Schematic = class {
|
|
891
1021
|
if (!response.ok) {
|
892
1022
|
throw new Error("Network response was not ok");
|
893
1023
|
}
|
894
|
-
const
|
895
|
-
|
1024
|
+
const responseJson = await response.json();
|
1025
|
+
const data = CheckFlagResponseFromJSON(responseJson);
|
1026
|
+
this.debug(`fallbackToRest result: ${key}`, data);
|
1027
|
+
const result = CheckFlagReturnFromJSON(data.data);
|
1028
|
+
this.submitFlagCheckEvent(key, result, context);
|
1029
|
+
return result.value;
|
896
1030
|
} catch (error) {
|
897
1031
|
console.error("REST API call failed, using fallback value:", error);
|
1032
|
+
const errorResult = {
|
1033
|
+
flag: key,
|
1034
|
+
value: fallback,
|
1035
|
+
reason: "API request failed (fallback)",
|
1036
|
+
error: error instanceof Error ? error.message : String(error)
|
1037
|
+
};
|
1038
|
+
this.submitFlagCheckEvent(key, errorResult, context);
|
898
1039
|
return fallback;
|
899
1040
|
}
|
900
1041
|
}
|
901
1042
|
/**
|
902
1043
|
* Make an API call to fetch all flag values for a given context.
|
903
1044
|
* Recommended for use in REST mode only.
|
1045
|
+
* In offline mode, returns an empty object.
|
904
1046
|
*/
|
905
1047
|
checkFlags = async (context) => {
|
906
1048
|
context = context || this.context;
|
1049
|
+
this.debug(`checkFlags`, { context });
|
1050
|
+
if (this.isOffline()) {
|
1051
|
+
this.debug(`checkFlags offline result: returning empty object`);
|
1052
|
+
return {};
|
1053
|
+
}
|
907
1054
|
const requestUrl = `${this.apiUrl}/flags/check`;
|
908
1055
|
const requestBody = JSON.stringify(context);
|
909
1056
|
return fetch(requestUrl, {
|
@@ -921,6 +1068,7 @@ var Schematic = class {
|
|
921
1068
|
return response.json();
|
922
1069
|
}).then((responseJson) => {
|
923
1070
|
const resp = CheckFlagsResponseFromJSON(responseJson);
|
1071
|
+
this.debug(`checkFlags result:`, resp);
|
924
1072
|
return (resp?.data?.flags ?? []).reduce(
|
925
1073
|
(accum, flag) => {
|
926
1074
|
accum[flag.flag] = flag.value;
|
@@ -939,6 +1087,7 @@ var Schematic = class {
|
|
939
1087
|
* send an identify event to the Schematic API which will upsert a user and company.
|
940
1088
|
*/
|
941
1089
|
identify = (body) => {
|
1090
|
+
this.debug(`identify:`, body);
|
942
1091
|
try {
|
943
1092
|
this.setContext({
|
944
1093
|
company: body.company?.keys,
|
@@ -956,10 +1105,15 @@ var Schematic = class {
|
|
956
1105
|
* 2. Send the context to the server
|
957
1106
|
* 3. Wait for initial flag values to be returned
|
958
1107
|
* The promise resolves when initial flag values are received.
|
1108
|
+
* In offline mode, this will just set the context locally without connecting.
|
959
1109
|
*/
|
960
1110
|
setContext = async (context) => {
|
961
|
-
if (
|
1111
|
+
if (this.isOffline()) {
|
962
1112
|
this.context = context;
|
1113
|
+
this.setIsPending(false);
|
1114
|
+
return Promise.resolve();
|
1115
|
+
}
|
1116
|
+
if (!this.useWebSocket) {
|
963
1117
|
return Promise.resolve();
|
964
1118
|
}
|
965
1119
|
try {
|
@@ -980,12 +1134,14 @@ var Schematic = class {
|
|
980
1134
|
*/
|
981
1135
|
track = (body) => {
|
982
1136
|
const { company, user, event, traits } = body;
|
983
|
-
|
1137
|
+
const trackData = {
|
984
1138
|
company: company ?? this.context.company,
|
985
1139
|
event,
|
986
1140
|
traits: traits ?? {},
|
987
1141
|
user: user ?? this.context.user
|
988
|
-
}
|
1142
|
+
};
|
1143
|
+
this.debug(`track:`, trackData);
|
1144
|
+
return this.handleEvent("track", trackData);
|
989
1145
|
};
|
990
1146
|
/**
|
991
1147
|
* Event processing
|
@@ -1028,8 +1184,13 @@ var Schematic = class {
|
|
1028
1184
|
sendEvent = async (event) => {
|
1029
1185
|
const captureUrl = `${this.eventUrl}/e`;
|
1030
1186
|
const payload = JSON.stringify(event);
|
1187
|
+
this.debug(`sending event:`, { url: captureUrl, event });
|
1188
|
+
if (this.isOffline()) {
|
1189
|
+
this.debug(`event not sent (offline mode):`, { event });
|
1190
|
+
return Promise.resolve();
|
1191
|
+
}
|
1031
1192
|
try {
|
1032
|
-
await fetch(captureUrl, {
|
1193
|
+
const response = await fetch(captureUrl, {
|
1033
1194
|
method: "POST",
|
1034
1195
|
headers: {
|
1035
1196
|
...this.additionalHeaders ?? {},
|
@@ -1037,6 +1198,10 @@ var Schematic = class {
|
|
1037
1198
|
},
|
1038
1199
|
body: payload
|
1039
1200
|
});
|
1201
|
+
this.debug(`event sent:`, {
|
1202
|
+
status: response.status,
|
1203
|
+
statusText: response.statusText
|
1204
|
+
});
|
1040
1205
|
} catch (error) {
|
1041
1206
|
console.error("Error sending Schematic event: ", error);
|
1042
1207
|
}
|
@@ -1051,8 +1216,13 @@ var Schematic = class {
|
|
1051
1216
|
*/
|
1052
1217
|
/**
|
1053
1218
|
* If using websocket mode, close the connection when done.
|
1219
|
+
* In offline mode, this is a no-op.
|
1054
1220
|
*/
|
1055
1221
|
cleanup = async () => {
|
1222
|
+
if (this.isOffline()) {
|
1223
|
+
this.debug("cleanup: skipped (offline mode)");
|
1224
|
+
return Promise.resolve();
|
1225
|
+
}
|
1056
1226
|
if (this.conn) {
|
1057
1227
|
try {
|
1058
1228
|
const socket = await this.conn;
|
@@ -1066,16 +1236,26 @@ var Schematic = class {
|
|
1066
1236
|
};
|
1067
1237
|
// Open a websocket connection
|
1068
1238
|
wsConnect = () => {
|
1239
|
+
if (this.isOffline()) {
|
1240
|
+
this.debug("wsConnect: skipped (offline mode)");
|
1241
|
+
return Promise.reject(
|
1242
|
+
new Error("WebSocket connection skipped in offline mode")
|
1243
|
+
);
|
1244
|
+
}
|
1069
1245
|
return new Promise((resolve, reject) => {
|
1070
1246
|
const wsUrl = `${this.webSocketUrl}/flags/bootstrap?apiKey=${this.apiKey}`;
|
1247
|
+
this.debug(`connecting to WebSocket:`, wsUrl);
|
1071
1248
|
const webSocket = new WebSocket(wsUrl);
|
1072
1249
|
webSocket.onopen = () => {
|
1250
|
+
this.debug(`WebSocket connection opened`);
|
1073
1251
|
resolve(webSocket);
|
1074
1252
|
};
|
1075
1253
|
webSocket.onerror = (error) => {
|
1254
|
+
this.debug(`WebSocket connection error:`, error);
|
1076
1255
|
reject(error);
|
1077
1256
|
};
|
1078
1257
|
webSocket.onclose = () => {
|
1258
|
+
this.debug(`WebSocket connection closed`);
|
1079
1259
|
this.conn = null;
|
1080
1260
|
};
|
1081
1261
|
});
|
@@ -1083,21 +1263,37 @@ var Schematic = class {
|
|
1083
1263
|
// Send a message on the websocket indicating interest in a particular evaluation context
|
1084
1264
|
// and wait for the initial set of flag values to be returned
|
1085
1265
|
wsSendMessage = (socket, context) => {
|
1266
|
+
if (this.isOffline()) {
|
1267
|
+
this.debug("wsSendMessage: skipped (offline mode)");
|
1268
|
+
this.setIsPending(false);
|
1269
|
+
return Promise.resolve();
|
1270
|
+
}
|
1086
1271
|
return new Promise((resolve, reject) => {
|
1087
1272
|
if (contextString(context) == contextString(this.context)) {
|
1273
|
+
this.debug(`WebSocket context unchanged, skipping update`);
|
1088
1274
|
return resolve(this.setIsPending(false));
|
1089
1275
|
}
|
1276
|
+
this.debug(`WebSocket context updated:`, context);
|
1090
1277
|
this.context = context;
|
1091
1278
|
const sendMessage = () => {
|
1092
1279
|
let resolved = false;
|
1093
1280
|
const messageHandler = (event) => {
|
1094
1281
|
const message = JSON.parse(event.data);
|
1282
|
+
this.debug(`WebSocket message received:`, message);
|
1095
1283
|
if (!(contextString(context) in this.checks)) {
|
1096
1284
|
this.checks[contextString(context)] = {};
|
1097
1285
|
}
|
1098
1286
|
(message.flags ?? []).forEach((flag) => {
|
1099
1287
|
const flagCheck = CheckFlagReturnFromJSON(flag);
|
1100
1288
|
this.checks[contextString(context)][flagCheck.flag] = flagCheck;
|
1289
|
+
this.debug(`WebSocket flag update:`, {
|
1290
|
+
flag: flagCheck.flag,
|
1291
|
+
value: flagCheck.value,
|
1292
|
+
flagCheck
|
1293
|
+
});
|
1294
|
+
if (this.flagCheckListeners[flag.flag]?.size > 0 || this.flagValueListeners[flag.flag]?.size > 0) {
|
1295
|
+
this.submitFlagCheckEvent(flagCheck.flag, flagCheck, context);
|
1296
|
+
}
|
1101
1297
|
this.notifyFlagCheckListeners(flag.flag, flagCheck);
|
1102
1298
|
this.notifyFlagValueListeners(flag.flag, flagCheck.value);
|
1103
1299
|
});
|
@@ -1108,19 +1304,23 @@ var Schematic = class {
|
|
1108
1304
|
}
|
1109
1305
|
};
|
1110
1306
|
socket.addEventListener("message", messageHandler);
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
);
|
1307
|
+
const clientVersion = this.additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
|
1308
|
+
const messagePayload = {
|
1309
|
+
apiKey: this.apiKey,
|
1310
|
+
clientVersion,
|
1311
|
+
data: context
|
1312
|
+
};
|
1313
|
+
this.debug(`WebSocket sending message:`, messagePayload);
|
1314
|
+
socket.send(JSON.stringify(messagePayload));
|
1118
1315
|
};
|
1119
1316
|
if (socket.readyState === WebSocket.OPEN) {
|
1317
|
+
this.debug(`WebSocket already open, sending message`);
|
1120
1318
|
sendMessage();
|
1121
1319
|
} else if (socket.readyState === WebSocket.CONNECTING) {
|
1320
|
+
this.debug(`WebSocket connecting, waiting for open to send message`);
|
1122
1321
|
socket.addEventListener("open", sendMessage);
|
1123
1322
|
} else {
|
1323
|
+
this.debug(`WebSocket is closed, cannot send message`);
|
1124
1324
|
reject("WebSocket is not open or connecting");
|
1125
1325
|
}
|
1126
1326
|
});
|
@@ -1177,10 +1377,22 @@ var Schematic = class {
|
|
1177
1377
|
};
|
1178
1378
|
notifyFlagCheckListeners = (flagKey, check) => {
|
1179
1379
|
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
1380
|
+
if (listeners.size > 0) {
|
1381
|
+
this.debug(
|
1382
|
+
`Notifying ${listeners.size} flag check listeners for ${flagKey}`,
|
1383
|
+
check
|
1384
|
+
);
|
1385
|
+
}
|
1180
1386
|
listeners.forEach((listener) => notifyFlagCheckListener(listener, check));
|
1181
1387
|
};
|
1182
1388
|
notifyFlagValueListeners = (flagKey, value) => {
|
1183
1389
|
const listeners = this.flagValueListeners?.[flagKey] ?? [];
|
1390
|
+
if (listeners.size > 0) {
|
1391
|
+
this.debug(
|
1392
|
+
`Notifying ${listeners.size} flag value listeners for ${flagKey}`,
|
1393
|
+
{ value }
|
1394
|
+
);
|
1395
|
+
}
|
1184
1396
|
listeners.forEach((listener) => notifyFlagValueListener(listener, value));
|
1185
1397
|
};
|
1186
1398
|
};
|
@@ -1210,7 +1422,7 @@ var notifyFlagValueListener = (listener, value) => {
|
|
1210
1422
|
var import_react = __toESM(require("react"));
|
1211
1423
|
|
1212
1424
|
// src/version.ts
|
1213
|
-
var version2 = "1.2.
|
1425
|
+
var version2 = "1.2.4";
|
1214
1426
|
|
1215
1427
|
// src/context/schematic.tsx
|
1216
1428
|
var import_jsx_runtime = require("react/jsx-runtime");
|
@@ -626,6 +626,26 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
626
626
|
value: json["value"]
|
627
627
|
};
|
628
628
|
}
|
629
|
+
function EventBodyFlagCheckToJSON(json) {
|
630
|
+
return EventBodyFlagCheckToJSONTyped(json, false);
|
631
|
+
}
|
632
|
+
function EventBodyFlagCheckToJSONTyped(value, ignoreDiscriminator = false) {
|
633
|
+
if (value == null) {
|
634
|
+
return value;
|
635
|
+
}
|
636
|
+
return {
|
637
|
+
company_id: value["companyId"],
|
638
|
+
error: value["error"],
|
639
|
+
flag_id: value["flagId"],
|
640
|
+
flag_key: value["flagKey"],
|
641
|
+
reason: value["reason"],
|
642
|
+
req_company: value["reqCompany"],
|
643
|
+
req_user: value["reqUser"],
|
644
|
+
rule_id: value["ruleId"],
|
645
|
+
user_id: value["userId"],
|
646
|
+
value: value["value"]
|
647
|
+
};
|
648
|
+
}
|
629
649
|
function CheckFlagResponseFromJSON(json) {
|
630
650
|
return CheckFlagResponseFromJSONTyped(json, false);
|
631
651
|
}
|
@@ -728,7 +748,7 @@ function contextString(context) {
|
|
728
748
|
}, {});
|
729
749
|
return JSON.stringify(sortedContext);
|
730
750
|
}
|
731
|
-
var version = "1.2.
|
751
|
+
var version = "1.2.2";
|
732
752
|
var anonymousIdKey = "schematicId";
|
733
753
|
var Schematic = class {
|
734
754
|
additionalHeaders = {};
|
@@ -736,6 +756,8 @@ var Schematic = class {
|
|
736
756
|
apiUrl = "https://api.schematichq.com";
|
737
757
|
conn = null;
|
738
758
|
context = {};
|
759
|
+
debugEnabled = false;
|
760
|
+
offlineEnabled = false;
|
739
761
|
eventQueue;
|
740
762
|
eventUrl = "https://c.schematichq.com";
|
741
763
|
flagCheckListeners = {};
|
@@ -750,6 +772,26 @@ var Schematic = class {
|
|
750
772
|
this.apiKey = apiKey;
|
751
773
|
this.eventQueue = [];
|
752
774
|
this.useWebSocket = options?.useWebSocket ?? false;
|
775
|
+
this.debugEnabled = options?.debug ?? false;
|
776
|
+
this.offlineEnabled = options?.offline ?? false;
|
777
|
+
if (typeof window !== "undefined" && typeof window.location !== "undefined") {
|
778
|
+
const params = new URLSearchParams(window.location.search);
|
779
|
+
const debugParam = params.get("schematic_debug");
|
780
|
+
if (debugParam !== null && (debugParam === "" || debugParam === "true" || debugParam === "1")) {
|
781
|
+
this.debugEnabled = true;
|
782
|
+
}
|
783
|
+
const offlineParam = params.get("schematic_offline");
|
784
|
+
if (offlineParam !== null && (offlineParam === "" || offlineParam === "true" || offlineParam === "1")) {
|
785
|
+
this.offlineEnabled = true;
|
786
|
+
this.debugEnabled = true;
|
787
|
+
}
|
788
|
+
}
|
789
|
+
if (this.offlineEnabled && options?.debug !== false) {
|
790
|
+
this.debugEnabled = true;
|
791
|
+
}
|
792
|
+
if (this.offlineEnabled) {
|
793
|
+
this.setIsPending(false);
|
794
|
+
}
|
753
795
|
this.additionalHeaders = {
|
754
796
|
"X-Schematic-Client-Version": `schematic-js@${version}`,
|
755
797
|
...options?.additionalHeaders ?? {}
|
@@ -773,6 +815,13 @@ var Schematic = class {
|
|
773
815
|
this.flushEventQueue();
|
774
816
|
});
|
775
817
|
}
|
818
|
+
if (this.offlineEnabled) {
|
819
|
+
this.debug(
|
820
|
+
"Initialized with offline mode enabled - no network requests will be made"
|
821
|
+
);
|
822
|
+
} else if (this.debugEnabled) {
|
823
|
+
this.debug("Initialized with debug mode enabled");
|
824
|
+
}
|
776
825
|
}
|
777
826
|
/**
|
778
827
|
* Get value for a single flag.
|
@@ -785,6 +834,14 @@ var Schematic = class {
|
|
785
834
|
const { fallback = false, key } = options;
|
786
835
|
const context = options.context || this.context;
|
787
836
|
const contextStr = contextString(context);
|
837
|
+
this.debug(`checkFlag: ${key}`, { context, fallback });
|
838
|
+
if (this.isOffline()) {
|
839
|
+
this.debug(`checkFlag offline result: ${key}`, {
|
840
|
+
value: fallback,
|
841
|
+
offlineMode: true
|
842
|
+
});
|
843
|
+
return fallback;
|
844
|
+
}
|
788
845
|
if (!this.useWebSocket) {
|
789
846
|
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
790
847
|
return fetch(requestUrl, {
|
@@ -801,17 +858,32 @@ var Schematic = class {
|
|
801
858
|
}
|
802
859
|
return response.json();
|
803
860
|
}).then((response) => {
|
804
|
-
|
861
|
+
const parsedResponse = CheckFlagResponseFromJSON(response);
|
862
|
+
this.debug(`checkFlag result: ${key}`, parsedResponse);
|
863
|
+
const result = CheckFlagReturnFromJSON(parsedResponse.data);
|
864
|
+
this.submitFlagCheckEvent(key, result, context);
|
865
|
+
return result.value;
|
805
866
|
}).catch((error) => {
|
806
867
|
console.error("There was a problem with the fetch operation:", error);
|
868
|
+
const errorResult = {
|
869
|
+
flag: key,
|
870
|
+
value: fallback,
|
871
|
+
reason: "API request failed",
|
872
|
+
error: error instanceof Error ? error.message : String(error)
|
873
|
+
};
|
874
|
+
this.submitFlagCheckEvent(key, errorResult, context);
|
807
875
|
return fallback;
|
808
876
|
});
|
809
877
|
}
|
810
878
|
try {
|
811
879
|
const existingVals = this.checks[contextStr];
|
812
|
-
if (this.conn && typeof existingVals !== "undefined" && typeof existingVals[key] !== "undefined") {
|
880
|
+
if (this.conn !== null && typeof existingVals !== "undefined" && typeof existingVals[key] !== "undefined") {
|
881
|
+
this.debug(`checkFlag cached result: ${key}`, existingVals[key]);
|
813
882
|
return existingVals[key].value;
|
814
883
|
}
|
884
|
+
if (this.isOffline()) {
|
885
|
+
return fallback;
|
886
|
+
}
|
815
887
|
try {
|
816
888
|
await this.setContext(context);
|
817
889
|
} catch (error) {
|
@@ -822,16 +894,74 @@ var Schematic = class {
|
|
822
894
|
return this.fallbackToRest(key, context, fallback);
|
823
895
|
}
|
824
896
|
const contextVals = this.checks[contextStr] ?? {};
|
825
|
-
|
897
|
+
const flagCheck = contextVals[key];
|
898
|
+
const result = flagCheck?.value ?? fallback;
|
899
|
+
this.debug(
|
900
|
+
`checkFlag WebSocket result: ${key}`,
|
901
|
+
typeof flagCheck !== "undefined" ? flagCheck : { value: fallback, fallbackUsed: true }
|
902
|
+
);
|
903
|
+
if (typeof flagCheck !== "undefined") {
|
904
|
+
this.submitFlagCheckEvent(key, flagCheck, context);
|
905
|
+
}
|
906
|
+
return result;
|
826
907
|
} catch (error) {
|
827
908
|
console.error("Unexpected error in checkFlag:", error);
|
909
|
+
const errorResult = {
|
910
|
+
flag: key,
|
911
|
+
value: fallback,
|
912
|
+
reason: "Unexpected error in flag check",
|
913
|
+
error: error instanceof Error ? error.message : String(error)
|
914
|
+
};
|
915
|
+
this.submitFlagCheckEvent(key, errorResult, context);
|
828
916
|
return fallback;
|
829
917
|
}
|
830
918
|
}
|
919
|
+
/**
|
920
|
+
* Helper function to log debug messages
|
921
|
+
* Only logs if debug mode is enabled
|
922
|
+
*/
|
923
|
+
debug(message, ...args) {
|
924
|
+
if (this.debugEnabled) {
|
925
|
+
console.log(`[Schematic] ${message}`, ...args);
|
926
|
+
}
|
927
|
+
}
|
928
|
+
/**
|
929
|
+
* Helper function to check if client is in offline mode
|
930
|
+
*/
|
931
|
+
isOffline() {
|
932
|
+
return this.offlineEnabled;
|
933
|
+
}
|
934
|
+
/**
|
935
|
+
* Submit a flag check event
|
936
|
+
* Records data about a flag check for analytics
|
937
|
+
*/
|
938
|
+
submitFlagCheckEvent(flagKey, result, context) {
|
939
|
+
const eventBody = {
|
940
|
+
flagKey,
|
941
|
+
value: result.value,
|
942
|
+
reason: result.reason,
|
943
|
+
flagId: result.flagId,
|
944
|
+
ruleId: result.ruleId,
|
945
|
+
companyId: result.companyId,
|
946
|
+
userId: result.userId,
|
947
|
+
error: result.error,
|
948
|
+
reqCompany: context.company,
|
949
|
+
reqUser: context.user
|
950
|
+
};
|
951
|
+
this.debug(`submitting flag check event:`, eventBody);
|
952
|
+
return this.handleEvent("flag_check", EventBodyFlagCheckToJSON(eventBody));
|
953
|
+
}
|
831
954
|
/**
|
832
955
|
* Helper method for falling back to REST API when WebSocket connection fails
|
833
956
|
*/
|
834
957
|
async fallbackToRest(key, context, fallback) {
|
958
|
+
if (this.isOffline()) {
|
959
|
+
this.debug(`fallbackToRest offline result: ${key}`, {
|
960
|
+
value: fallback,
|
961
|
+
offlineMode: true
|
962
|
+
});
|
963
|
+
return fallback;
|
964
|
+
}
|
835
965
|
try {
|
836
966
|
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
837
967
|
const response = await fetch(requestUrl, {
|
@@ -846,19 +976,36 @@ var Schematic = class {
|
|
846
976
|
if (!response.ok) {
|
847
977
|
throw new Error("Network response was not ok");
|
848
978
|
}
|
849
|
-
const
|
850
|
-
|
979
|
+
const responseJson = await response.json();
|
980
|
+
const data = CheckFlagResponseFromJSON(responseJson);
|
981
|
+
this.debug(`fallbackToRest result: ${key}`, data);
|
982
|
+
const result = CheckFlagReturnFromJSON(data.data);
|
983
|
+
this.submitFlagCheckEvent(key, result, context);
|
984
|
+
return result.value;
|
851
985
|
} catch (error) {
|
852
986
|
console.error("REST API call failed, using fallback value:", error);
|
987
|
+
const errorResult = {
|
988
|
+
flag: key,
|
989
|
+
value: fallback,
|
990
|
+
reason: "API request failed (fallback)",
|
991
|
+
error: error instanceof Error ? error.message : String(error)
|
992
|
+
};
|
993
|
+
this.submitFlagCheckEvent(key, errorResult, context);
|
853
994
|
return fallback;
|
854
995
|
}
|
855
996
|
}
|
856
997
|
/**
|
857
998
|
* Make an API call to fetch all flag values for a given context.
|
858
999
|
* Recommended for use in REST mode only.
|
1000
|
+
* In offline mode, returns an empty object.
|
859
1001
|
*/
|
860
1002
|
checkFlags = async (context) => {
|
861
1003
|
context = context || this.context;
|
1004
|
+
this.debug(`checkFlags`, { context });
|
1005
|
+
if (this.isOffline()) {
|
1006
|
+
this.debug(`checkFlags offline result: returning empty object`);
|
1007
|
+
return {};
|
1008
|
+
}
|
862
1009
|
const requestUrl = `${this.apiUrl}/flags/check`;
|
863
1010
|
const requestBody = JSON.stringify(context);
|
864
1011
|
return fetch(requestUrl, {
|
@@ -876,6 +1023,7 @@ var Schematic = class {
|
|
876
1023
|
return response.json();
|
877
1024
|
}).then((responseJson) => {
|
878
1025
|
const resp = CheckFlagsResponseFromJSON(responseJson);
|
1026
|
+
this.debug(`checkFlags result:`, resp);
|
879
1027
|
return (resp?.data?.flags ?? []).reduce(
|
880
1028
|
(accum, flag) => {
|
881
1029
|
accum[flag.flag] = flag.value;
|
@@ -894,6 +1042,7 @@ var Schematic = class {
|
|
894
1042
|
* send an identify event to the Schematic API which will upsert a user and company.
|
895
1043
|
*/
|
896
1044
|
identify = (body) => {
|
1045
|
+
this.debug(`identify:`, body);
|
897
1046
|
try {
|
898
1047
|
this.setContext({
|
899
1048
|
company: body.company?.keys,
|
@@ -911,10 +1060,15 @@ var Schematic = class {
|
|
911
1060
|
* 2. Send the context to the server
|
912
1061
|
* 3. Wait for initial flag values to be returned
|
913
1062
|
* The promise resolves when initial flag values are received.
|
1063
|
+
* In offline mode, this will just set the context locally without connecting.
|
914
1064
|
*/
|
915
1065
|
setContext = async (context) => {
|
916
|
-
if (
|
1066
|
+
if (this.isOffline()) {
|
917
1067
|
this.context = context;
|
1068
|
+
this.setIsPending(false);
|
1069
|
+
return Promise.resolve();
|
1070
|
+
}
|
1071
|
+
if (!this.useWebSocket) {
|
918
1072
|
return Promise.resolve();
|
919
1073
|
}
|
920
1074
|
try {
|
@@ -935,12 +1089,14 @@ var Schematic = class {
|
|
935
1089
|
*/
|
936
1090
|
track = (body) => {
|
937
1091
|
const { company, user, event, traits } = body;
|
938
|
-
|
1092
|
+
const trackData = {
|
939
1093
|
company: company ?? this.context.company,
|
940
1094
|
event,
|
941
1095
|
traits: traits ?? {},
|
942
1096
|
user: user ?? this.context.user
|
943
|
-
}
|
1097
|
+
};
|
1098
|
+
this.debug(`track:`, trackData);
|
1099
|
+
return this.handleEvent("track", trackData);
|
944
1100
|
};
|
945
1101
|
/**
|
946
1102
|
* Event processing
|
@@ -983,8 +1139,13 @@ var Schematic = class {
|
|
983
1139
|
sendEvent = async (event) => {
|
984
1140
|
const captureUrl = `${this.eventUrl}/e`;
|
985
1141
|
const payload = JSON.stringify(event);
|
1142
|
+
this.debug(`sending event:`, { url: captureUrl, event });
|
1143
|
+
if (this.isOffline()) {
|
1144
|
+
this.debug(`event not sent (offline mode):`, { event });
|
1145
|
+
return Promise.resolve();
|
1146
|
+
}
|
986
1147
|
try {
|
987
|
-
await fetch(captureUrl, {
|
1148
|
+
const response = await fetch(captureUrl, {
|
988
1149
|
method: "POST",
|
989
1150
|
headers: {
|
990
1151
|
...this.additionalHeaders ?? {},
|
@@ -992,6 +1153,10 @@ var Schematic = class {
|
|
992
1153
|
},
|
993
1154
|
body: payload
|
994
1155
|
});
|
1156
|
+
this.debug(`event sent:`, {
|
1157
|
+
status: response.status,
|
1158
|
+
statusText: response.statusText
|
1159
|
+
});
|
995
1160
|
} catch (error) {
|
996
1161
|
console.error("Error sending Schematic event: ", error);
|
997
1162
|
}
|
@@ -1006,8 +1171,13 @@ var Schematic = class {
|
|
1006
1171
|
*/
|
1007
1172
|
/**
|
1008
1173
|
* If using websocket mode, close the connection when done.
|
1174
|
+
* In offline mode, this is a no-op.
|
1009
1175
|
*/
|
1010
1176
|
cleanup = async () => {
|
1177
|
+
if (this.isOffline()) {
|
1178
|
+
this.debug("cleanup: skipped (offline mode)");
|
1179
|
+
return Promise.resolve();
|
1180
|
+
}
|
1011
1181
|
if (this.conn) {
|
1012
1182
|
try {
|
1013
1183
|
const socket = await this.conn;
|
@@ -1021,16 +1191,26 @@ var Schematic = class {
|
|
1021
1191
|
};
|
1022
1192
|
// Open a websocket connection
|
1023
1193
|
wsConnect = () => {
|
1194
|
+
if (this.isOffline()) {
|
1195
|
+
this.debug("wsConnect: skipped (offline mode)");
|
1196
|
+
return Promise.reject(
|
1197
|
+
new Error("WebSocket connection skipped in offline mode")
|
1198
|
+
);
|
1199
|
+
}
|
1024
1200
|
return new Promise((resolve, reject) => {
|
1025
1201
|
const wsUrl = `${this.webSocketUrl}/flags/bootstrap?apiKey=${this.apiKey}`;
|
1202
|
+
this.debug(`connecting to WebSocket:`, wsUrl);
|
1026
1203
|
const webSocket = new WebSocket(wsUrl);
|
1027
1204
|
webSocket.onopen = () => {
|
1205
|
+
this.debug(`WebSocket connection opened`);
|
1028
1206
|
resolve(webSocket);
|
1029
1207
|
};
|
1030
1208
|
webSocket.onerror = (error) => {
|
1209
|
+
this.debug(`WebSocket connection error:`, error);
|
1031
1210
|
reject(error);
|
1032
1211
|
};
|
1033
1212
|
webSocket.onclose = () => {
|
1213
|
+
this.debug(`WebSocket connection closed`);
|
1034
1214
|
this.conn = null;
|
1035
1215
|
};
|
1036
1216
|
});
|
@@ -1038,21 +1218,37 @@ var Schematic = class {
|
|
1038
1218
|
// Send a message on the websocket indicating interest in a particular evaluation context
|
1039
1219
|
// and wait for the initial set of flag values to be returned
|
1040
1220
|
wsSendMessage = (socket, context) => {
|
1221
|
+
if (this.isOffline()) {
|
1222
|
+
this.debug("wsSendMessage: skipped (offline mode)");
|
1223
|
+
this.setIsPending(false);
|
1224
|
+
return Promise.resolve();
|
1225
|
+
}
|
1041
1226
|
return new Promise((resolve, reject) => {
|
1042
1227
|
if (contextString(context) == contextString(this.context)) {
|
1228
|
+
this.debug(`WebSocket context unchanged, skipping update`);
|
1043
1229
|
return resolve(this.setIsPending(false));
|
1044
1230
|
}
|
1231
|
+
this.debug(`WebSocket context updated:`, context);
|
1045
1232
|
this.context = context;
|
1046
1233
|
const sendMessage = () => {
|
1047
1234
|
let resolved = false;
|
1048
1235
|
const messageHandler = (event) => {
|
1049
1236
|
const message = JSON.parse(event.data);
|
1237
|
+
this.debug(`WebSocket message received:`, message);
|
1050
1238
|
if (!(contextString(context) in this.checks)) {
|
1051
1239
|
this.checks[contextString(context)] = {};
|
1052
1240
|
}
|
1053
1241
|
(message.flags ?? []).forEach((flag) => {
|
1054
1242
|
const flagCheck = CheckFlagReturnFromJSON(flag);
|
1055
1243
|
this.checks[contextString(context)][flagCheck.flag] = flagCheck;
|
1244
|
+
this.debug(`WebSocket flag update:`, {
|
1245
|
+
flag: flagCheck.flag,
|
1246
|
+
value: flagCheck.value,
|
1247
|
+
flagCheck
|
1248
|
+
});
|
1249
|
+
if (this.flagCheckListeners[flag.flag]?.size > 0 || this.flagValueListeners[flag.flag]?.size > 0) {
|
1250
|
+
this.submitFlagCheckEvent(flagCheck.flag, flagCheck, context);
|
1251
|
+
}
|
1056
1252
|
this.notifyFlagCheckListeners(flag.flag, flagCheck);
|
1057
1253
|
this.notifyFlagValueListeners(flag.flag, flagCheck.value);
|
1058
1254
|
});
|
@@ -1063,19 +1259,23 @@ var Schematic = class {
|
|
1063
1259
|
}
|
1064
1260
|
};
|
1065
1261
|
socket.addEventListener("message", messageHandler);
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
);
|
1262
|
+
const clientVersion = this.additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
|
1263
|
+
const messagePayload = {
|
1264
|
+
apiKey: this.apiKey,
|
1265
|
+
clientVersion,
|
1266
|
+
data: context
|
1267
|
+
};
|
1268
|
+
this.debug(`WebSocket sending message:`, messagePayload);
|
1269
|
+
socket.send(JSON.stringify(messagePayload));
|
1073
1270
|
};
|
1074
1271
|
if (socket.readyState === WebSocket.OPEN) {
|
1272
|
+
this.debug(`WebSocket already open, sending message`);
|
1075
1273
|
sendMessage();
|
1076
1274
|
} else if (socket.readyState === WebSocket.CONNECTING) {
|
1275
|
+
this.debug(`WebSocket connecting, waiting for open to send message`);
|
1077
1276
|
socket.addEventListener("open", sendMessage);
|
1078
1277
|
} else {
|
1278
|
+
this.debug(`WebSocket is closed, cannot send message`);
|
1079
1279
|
reject("WebSocket is not open or connecting");
|
1080
1280
|
}
|
1081
1281
|
});
|
@@ -1132,10 +1332,22 @@ var Schematic = class {
|
|
1132
1332
|
};
|
1133
1333
|
notifyFlagCheckListeners = (flagKey, check) => {
|
1134
1334
|
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
1335
|
+
if (listeners.size > 0) {
|
1336
|
+
this.debug(
|
1337
|
+
`Notifying ${listeners.size} flag check listeners for ${flagKey}`,
|
1338
|
+
check
|
1339
|
+
);
|
1340
|
+
}
|
1135
1341
|
listeners.forEach((listener) => notifyFlagCheckListener(listener, check));
|
1136
1342
|
};
|
1137
1343
|
notifyFlagValueListeners = (flagKey, value) => {
|
1138
1344
|
const listeners = this.flagValueListeners?.[flagKey] ?? [];
|
1345
|
+
if (listeners.size > 0) {
|
1346
|
+
this.debug(
|
1347
|
+
`Notifying ${listeners.size} flag value listeners for ${flagKey}`,
|
1348
|
+
{ value }
|
1349
|
+
);
|
1350
|
+
}
|
1139
1351
|
listeners.forEach((listener) => notifyFlagValueListener(listener, value));
|
1140
1352
|
};
|
1141
1353
|
};
|
@@ -1165,7 +1377,7 @@ var notifyFlagValueListener = (listener, value) => {
|
|
1165
1377
|
import React, { createContext, useEffect, useMemo, useRef } from "react";
|
1166
1378
|
|
1167
1379
|
// src/version.ts
|
1168
|
-
var version2 = "1.2.
|
1380
|
+
var version2 = "1.2.4";
|
1169
1381
|
|
1170
1382
|
// src/context/schematic.tsx
|
1171
1383
|
import { jsx } from "react/jsx-runtime";
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@schematichq/schematic-react",
|
3
|
-
"version": "1.2.
|
3
|
+
"version": "1.2.4",
|
4
4
|
"main": "dist/schematic-react.cjs.js",
|
5
5
|
"module": "dist/schematic-react.esm.js",
|
6
6
|
"types": "dist/schematic-react.d.ts",
|
@@ -28,7 +28,7 @@
|
|
28
28
|
"tsc": "npx tsc"
|
29
29
|
},
|
30
30
|
"dependencies": {
|
31
|
-
"@schematichq/schematic-js": "^1.2.
|
31
|
+
"@schematichq/schematic-js": "^1.2.2"
|
32
32
|
},
|
33
33
|
"devDependencies": {
|
34
34
|
"@microsoft/api-extractor": "^7.49.2",
|
@@ -36,7 +36,7 @@
|
|
36
36
|
"@types/react": "^19.0.8",
|
37
37
|
"@typescript-eslint/eslint-plugin": "^8.23.0",
|
38
38
|
"@typescript-eslint/parser": "^8.23.0",
|
39
|
-
"esbuild": "^0.
|
39
|
+
"esbuild": "^0.25.0",
|
40
40
|
"esbuild-jest": "^0.5.0",
|
41
41
|
"eslint": "^8.57.1",
|
42
42
|
"eslint-plugin-import": "^2.31.0",
|