@hyphen/sdk 1.12.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -99
- package/dist/index.cjs +599 -302
- package/dist/index.d.cts +527 -164
- package/dist/index.d.ts +527 -164
- package/dist/index.js +599 -301
- package/package.json +10 -13
package/dist/index.cjs
CHANGED
|
@@ -33,7 +33,6 @@ var index_exports = {};
|
|
|
33
33
|
__export(index_exports, {
|
|
34
34
|
Hyphen: () => Hyphen,
|
|
35
35
|
Toggle: () => Toggle,
|
|
36
|
-
ToggleHooks: () => ToggleHooks,
|
|
37
36
|
env: () => env,
|
|
38
37
|
loadEnv: () => loadEnv
|
|
39
38
|
});
|
|
@@ -101,7 +100,7 @@ var import_node_buffer = require("buffer");
|
|
|
101
100
|
var import_node_process2 = __toESM(require("process"), 1);
|
|
102
101
|
|
|
103
102
|
// src/base-service.ts
|
|
104
|
-
var
|
|
103
|
+
var import_net = require("@cacheable/net");
|
|
105
104
|
var import_cacheable = require("cacheable");
|
|
106
105
|
var import_hookified = require("hookified");
|
|
107
106
|
var import_pino = __toESM(require("pino"), 1);
|
|
@@ -117,11 +116,15 @@ var BaseService = class extends import_hookified.Hookified {
|
|
|
117
116
|
_log = (0, import_pino.default)();
|
|
118
117
|
_cache = new import_cacheable.Cacheable();
|
|
119
118
|
_throwErrors = false;
|
|
119
|
+
_net;
|
|
120
120
|
constructor(options) {
|
|
121
121
|
super(options);
|
|
122
122
|
if (options && options.throwErrors !== void 0) {
|
|
123
123
|
this._throwErrors = options.throwErrors;
|
|
124
124
|
}
|
|
125
|
+
this._net = new import_net.CacheableNet({
|
|
126
|
+
cache: this._cache
|
|
127
|
+
});
|
|
125
128
|
}
|
|
126
129
|
get log() {
|
|
127
130
|
return this._log;
|
|
@@ -134,6 +137,7 @@ var BaseService = class extends import_hookified.Hookified {
|
|
|
134
137
|
}
|
|
135
138
|
set cache(value) {
|
|
136
139
|
this._cache = value;
|
|
140
|
+
this._net.cache = value;
|
|
137
141
|
}
|
|
138
142
|
get throwErrors() {
|
|
139
143
|
return this._throwErrors;
|
|
@@ -157,22 +161,96 @@ var BaseService = class extends import_hookified.Hookified {
|
|
|
157
161
|
this.emit("info", message, ...args);
|
|
158
162
|
}
|
|
159
163
|
async get(url, config2) {
|
|
160
|
-
|
|
164
|
+
let finalUrl = url;
|
|
165
|
+
if (config2?.params) {
|
|
166
|
+
const params = new URLSearchParams(config2.params);
|
|
167
|
+
finalUrl = `${url}?${params.toString()}`;
|
|
168
|
+
}
|
|
169
|
+
const { params: _, ...fetchConfig } = config2 || {};
|
|
170
|
+
const response = await this._net.get(finalUrl, fetchConfig);
|
|
171
|
+
return {
|
|
172
|
+
data: response.data,
|
|
173
|
+
status: response.response.status,
|
|
174
|
+
statusText: response.response.statusText,
|
|
175
|
+
headers: response.response.headers,
|
|
176
|
+
config: config2,
|
|
177
|
+
request: void 0
|
|
178
|
+
};
|
|
161
179
|
}
|
|
162
180
|
async post(url, data, config2) {
|
|
163
|
-
|
|
181
|
+
const response = await this._net.post(url, data, config2);
|
|
182
|
+
return {
|
|
183
|
+
data: response.data,
|
|
184
|
+
status: response.response.status,
|
|
185
|
+
statusText: response.response.statusText,
|
|
186
|
+
headers: response.response.headers,
|
|
187
|
+
config: config2,
|
|
188
|
+
request: void 0
|
|
189
|
+
};
|
|
164
190
|
}
|
|
165
191
|
async put(url, data, config2) {
|
|
166
|
-
|
|
192
|
+
const response = await this._net.put(url, data, config2);
|
|
193
|
+
return {
|
|
194
|
+
data: response.data,
|
|
195
|
+
status: response.response.status,
|
|
196
|
+
statusText: response.response.statusText,
|
|
197
|
+
headers: response.response.headers,
|
|
198
|
+
config: config2,
|
|
199
|
+
request: void 0
|
|
200
|
+
};
|
|
167
201
|
}
|
|
168
202
|
async delete(url, config2) {
|
|
169
|
-
|
|
170
|
-
|
|
203
|
+
const headers = {
|
|
204
|
+
...config2?.headers
|
|
205
|
+
};
|
|
206
|
+
if (headers) {
|
|
207
|
+
delete headers["content-type"];
|
|
171
208
|
}
|
|
172
|
-
|
|
209
|
+
const { data: configData, ...restConfig } = config2 || {};
|
|
210
|
+
let body;
|
|
211
|
+
if (configData) {
|
|
212
|
+
body = typeof configData === "string" ? (
|
|
213
|
+
/* c8 ignore next */
|
|
214
|
+
configData
|
|
215
|
+
) : JSON.stringify(configData);
|
|
216
|
+
if (!headers["content-type"] && !headers["Content-Type"]) {
|
|
217
|
+
headers["content-type"] = "application/json";
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const response = await this._net.fetch(url, {
|
|
221
|
+
...restConfig,
|
|
222
|
+
headers,
|
|
223
|
+
body,
|
|
224
|
+
method: "DELETE"
|
|
225
|
+
});
|
|
226
|
+
let data;
|
|
227
|
+
if (response.status !== 204) {
|
|
228
|
+
const text = await response.text();
|
|
229
|
+
try {
|
|
230
|
+
data = text ? JSON.parse(text) : void 0;
|
|
231
|
+
} catch {
|
|
232
|
+
data = text;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
data,
|
|
237
|
+
status: response.status,
|
|
238
|
+
statusText: response.statusText,
|
|
239
|
+
headers: response.headers,
|
|
240
|
+
config: config2,
|
|
241
|
+
request: void 0
|
|
242
|
+
};
|
|
173
243
|
}
|
|
174
244
|
async patch(url, data, config2) {
|
|
175
|
-
|
|
245
|
+
const response = await this._net.patch(url, data, config2);
|
|
246
|
+
return {
|
|
247
|
+
data: response.data,
|
|
248
|
+
status: response.response.status,
|
|
249
|
+
statusText: response.response.statusText,
|
|
250
|
+
headers: response.response.headers,
|
|
251
|
+
config: config2,
|
|
252
|
+
request: void 0
|
|
253
|
+
};
|
|
176
254
|
}
|
|
177
255
|
createHeaders(apiKey) {
|
|
178
256
|
const headers = {
|
|
@@ -690,363 +768,606 @@ var NetInfo = class extends BaseService {
|
|
|
690
768
|
};
|
|
691
769
|
|
|
692
770
|
// src/toggle.ts
|
|
693
|
-
var
|
|
694
|
-
var import_openfeature_server_provider = require("@hyphen/openfeature-server-provider");
|
|
695
|
-
var import_server_sdk = require("@openfeature/server-sdk");
|
|
696
|
-
var import_dotenv2 = __toESM(require("dotenv"), 1);
|
|
771
|
+
var import_net2 = require("@cacheable/net");
|
|
697
772
|
var import_hookified2 = require("hookified");
|
|
698
|
-
import_dotenv2.default.config();
|
|
699
|
-
var ToggleHooks = /* @__PURE__ */ (function(ToggleHooks2) {
|
|
700
|
-
ToggleHooks2["beforeGetBoolean"] = "beforeGetBoolean";
|
|
701
|
-
ToggleHooks2["afterGetBoolean"] = "afterGetBoolean";
|
|
702
|
-
ToggleHooks2["beforeGetString"] = "beforeGetString";
|
|
703
|
-
ToggleHooks2["afterGetString"] = "afterGetString";
|
|
704
|
-
ToggleHooks2["beforeGetNumber"] = "beforeGetNumber";
|
|
705
|
-
ToggleHooks2["afterGetNumber"] = "afterGetNumber";
|
|
706
|
-
ToggleHooks2["beforeGetObject"] = "beforeGetObject";
|
|
707
|
-
ToggleHooks2["afterGetObject"] = "afterGetObject";
|
|
708
|
-
return ToggleHooks2;
|
|
709
|
-
})({});
|
|
710
773
|
var Toggle = class extends import_hookified2.Hookified {
|
|
711
774
|
static {
|
|
712
775
|
__name(this, "Toggle");
|
|
713
776
|
}
|
|
714
|
-
|
|
715
|
-
|
|
777
|
+
_publicApiKey;
|
|
778
|
+
_organizationId;
|
|
779
|
+
_applicationId;
|
|
716
780
|
_environment;
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
*
|
|
724
|
-
* @param
|
|
781
|
+
_horizonUrls = [];
|
|
782
|
+
_net = new import_net2.CacheableNet();
|
|
783
|
+
_defaultContext;
|
|
784
|
+
_defaultTargetingKey = `${Math.random().toString(36).substring(7)}`;
|
|
785
|
+
/**
|
|
786
|
+
* Creates a new Toggle instance.
|
|
787
|
+
*
|
|
788
|
+
* @param options - Configuration options for the toggle client
|
|
789
|
+
*
|
|
790
|
+
* @example
|
|
791
|
+
* ```typescript
|
|
792
|
+
* // Minimal configuration
|
|
793
|
+
* const toggle = new Toggle({
|
|
794
|
+
* publicApiKey: 'public_your-key',
|
|
795
|
+
* applicationId: 'app-123'
|
|
796
|
+
* });
|
|
797
|
+
*
|
|
798
|
+
* // With full options
|
|
799
|
+
* const toggle = new Toggle({
|
|
800
|
+
* publicApiKey: 'public_your-key',
|
|
801
|
+
* applicationId: 'app-123',
|
|
802
|
+
* environment: 'production',
|
|
803
|
+
* defaultContext: { targetingKey: 'user-456' },
|
|
804
|
+
* horizonUrls: ['https://my-horizon.example.com']
|
|
805
|
+
* });
|
|
806
|
+
* ```
|
|
725
807
|
*/
|
|
726
808
|
constructor(options) {
|
|
727
809
|
super();
|
|
728
|
-
|
|
729
|
-
|
|
810
|
+
if (options?.applicationId) {
|
|
811
|
+
this._applicationId = options.applicationId;
|
|
812
|
+
}
|
|
813
|
+
if (options?.environment) {
|
|
814
|
+
this._environment = options.environment;
|
|
815
|
+
} else {
|
|
816
|
+
this._environment = "development";
|
|
817
|
+
}
|
|
818
|
+
if (options?.defaultContext) {
|
|
819
|
+
this._defaultContext = options.defaultContext;
|
|
820
|
+
}
|
|
730
821
|
if (options?.publicApiKey) {
|
|
731
|
-
this.
|
|
822
|
+
this._publicApiKey = options.publicApiKey;
|
|
823
|
+
this._organizationId = this.getOrgIdFromPublicKey(this._publicApiKey);
|
|
824
|
+
}
|
|
825
|
+
if (options?.horizonUrls) {
|
|
826
|
+
this._horizonUrls = options.horizonUrls;
|
|
827
|
+
} else {
|
|
828
|
+
this._horizonUrls = this.getDefaultHorizonUrls(this._publicApiKey);
|
|
829
|
+
}
|
|
830
|
+
if (options?.defaultTargetKey) {
|
|
831
|
+
this._defaultTargetingKey = options?.defaultTargetKey;
|
|
832
|
+
} else {
|
|
833
|
+
if (this._defaultContext) {
|
|
834
|
+
this._defaultTargetingKey = this.getTargetingKey(this._defaultContext);
|
|
835
|
+
} else {
|
|
836
|
+
this._defaultTargetingKey = this.generateTargetKey();
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
if (options?.cache) {
|
|
840
|
+
this._net.cache = options.cache;
|
|
732
841
|
}
|
|
733
|
-
this._environment = options?.environment ?? import_node_process4.default.env.NODE_ENV ?? "development";
|
|
734
|
-
this._context = options?.context;
|
|
735
|
-
this._uris = options?.uris;
|
|
736
|
-
this._caching = options?.caching;
|
|
737
842
|
}
|
|
738
843
|
/**
|
|
739
|
-
*
|
|
740
|
-
*
|
|
844
|
+
* Gets the public API key used for authentication.
|
|
845
|
+
*
|
|
846
|
+
* @returns The current public API key or undefined if not set
|
|
741
847
|
*/
|
|
742
|
-
get
|
|
743
|
-
return this.
|
|
848
|
+
get publicApiKey() {
|
|
849
|
+
return this._publicApiKey;
|
|
744
850
|
}
|
|
745
851
|
/**
|
|
746
|
-
*
|
|
747
|
-
*
|
|
852
|
+
* Sets the public API key used for authentication.
|
|
853
|
+
*
|
|
854
|
+
* @param value - The public API key string or undefined to clear
|
|
855
|
+
* @throws {Error} If the key doesn't start with "public_"
|
|
748
856
|
*/
|
|
749
|
-
set
|
|
750
|
-
this.
|
|
857
|
+
set publicApiKey(value) {
|
|
858
|
+
this.setPublicKey(value);
|
|
751
859
|
}
|
|
752
860
|
/**
|
|
753
|
-
*
|
|
754
|
-
*
|
|
861
|
+
* Gets the default context used for toggle evaluations.
|
|
862
|
+
*
|
|
863
|
+
* @returns The current default ToggleContext
|
|
755
864
|
*/
|
|
756
|
-
get
|
|
757
|
-
return this.
|
|
865
|
+
get defaultContext() {
|
|
866
|
+
return this._defaultContext;
|
|
758
867
|
}
|
|
759
868
|
/**
|
|
760
|
-
*
|
|
761
|
-
*
|
|
869
|
+
* Sets the default context used for toggle evaluations.
|
|
870
|
+
*
|
|
871
|
+
* @param value - The ToggleContext to use as default
|
|
762
872
|
*/
|
|
763
|
-
set
|
|
764
|
-
|
|
765
|
-
this._publicApiKey = void 0;
|
|
766
|
-
this._client = void 0;
|
|
767
|
-
return;
|
|
768
|
-
}
|
|
769
|
-
this.setPublicApiKey(value);
|
|
873
|
+
set defaultContext(value) {
|
|
874
|
+
this._defaultContext = value;
|
|
770
875
|
}
|
|
771
876
|
/**
|
|
772
|
-
*
|
|
773
|
-
*
|
|
877
|
+
* Gets the organization ID extracted from the public API key.
|
|
878
|
+
*
|
|
879
|
+
* @returns The organization ID string or undefined if not available
|
|
774
880
|
*/
|
|
775
|
-
get
|
|
776
|
-
return this.
|
|
881
|
+
get organizationId() {
|
|
882
|
+
return this._organizationId;
|
|
777
883
|
}
|
|
778
884
|
/**
|
|
779
|
-
*
|
|
780
|
-
*
|
|
885
|
+
* Gets the Horizon endpoint URLs used for load balancing.
|
|
886
|
+
*
|
|
887
|
+
* These URLs are used to distribute requests across multiple Horizon endpoints.
|
|
888
|
+
* If endpoints fail, the system will attempt to use the default horizon endpoint service.
|
|
889
|
+
*
|
|
890
|
+
* @returns Array of Horizon endpoint URLs
|
|
891
|
+
* @see {@link https://hyphen.ai/horizon} for more information
|
|
781
892
|
*/
|
|
782
|
-
|
|
783
|
-
this.
|
|
893
|
+
get horizonUrls() {
|
|
894
|
+
return this._horizonUrls;
|
|
784
895
|
}
|
|
785
896
|
/**
|
|
786
|
-
*
|
|
787
|
-
*
|
|
897
|
+
* Sets the Horizon endpoint URLs for load balancing.
|
|
898
|
+
*
|
|
899
|
+
* Configures multiple Horizon endpoints that will be used for load balancing.
|
|
900
|
+
* When endpoints fail, the system will fall back to the default horizon endpoint service.
|
|
901
|
+
*
|
|
902
|
+
* @param value - Array of Horizon endpoint URLs or empty array to clear
|
|
903
|
+
* @see {@link https://hyphen.ai/horizon} for more information
|
|
904
|
+
*
|
|
905
|
+
* @example
|
|
906
|
+
* ```typescript
|
|
907
|
+
* const toggle = new Toggle();
|
|
908
|
+
* toggle.horizonUrls = [
|
|
909
|
+
* 'https://org1.toggle.hyphen.cloud',
|
|
910
|
+
* 'https://org2.toggle.hyphen.cloud'
|
|
911
|
+
* ];
|
|
912
|
+
* ```
|
|
788
913
|
*/
|
|
789
|
-
|
|
790
|
-
|
|
914
|
+
set horizonUrls(value) {
|
|
915
|
+
this._horizonUrls = value;
|
|
791
916
|
}
|
|
792
917
|
/**
|
|
793
|
-
*
|
|
794
|
-
*
|
|
918
|
+
* Gets the application ID used for toggle context.
|
|
919
|
+
*
|
|
920
|
+
* @returns The current application ID or undefined if not set
|
|
795
921
|
*/
|
|
796
|
-
|
|
797
|
-
this.
|
|
922
|
+
get applicationId() {
|
|
923
|
+
return this._applicationId;
|
|
798
924
|
}
|
|
799
925
|
/**
|
|
800
|
-
*
|
|
801
|
-
*
|
|
926
|
+
* Sets the application ID used for toggle context.
|
|
927
|
+
*
|
|
928
|
+
* @param value - The application ID string or undefined to clear
|
|
802
929
|
*/
|
|
803
|
-
|
|
804
|
-
|
|
930
|
+
set applicationId(value) {
|
|
931
|
+
this._applicationId = value;
|
|
805
932
|
}
|
|
806
933
|
/**
|
|
807
|
-
*
|
|
808
|
-
*
|
|
934
|
+
* Gets the environment used for toggle context.
|
|
935
|
+
*
|
|
936
|
+
* @returns The current environment (defaults to 'development')
|
|
809
937
|
*/
|
|
810
|
-
|
|
811
|
-
this.
|
|
938
|
+
get environment() {
|
|
939
|
+
return this._environment;
|
|
812
940
|
}
|
|
813
941
|
/**
|
|
814
|
-
*
|
|
815
|
-
*
|
|
942
|
+
* Sets the environment used for toggle context.
|
|
943
|
+
*
|
|
944
|
+
* @param value - The environment string or undefined to clear
|
|
816
945
|
*/
|
|
817
|
-
|
|
818
|
-
|
|
946
|
+
set environment(value) {
|
|
947
|
+
this._environment = value;
|
|
819
948
|
}
|
|
820
949
|
/**
|
|
821
|
-
*
|
|
822
|
-
*
|
|
950
|
+
* Gets the default targeting key used for toggle evaluations.
|
|
951
|
+
*
|
|
952
|
+
* @returns The current default targeting key or undefined if not set
|
|
823
953
|
*/
|
|
824
|
-
|
|
825
|
-
this.
|
|
954
|
+
get defaultTargetingKey() {
|
|
955
|
+
return this._defaultTargetingKey;
|
|
826
956
|
}
|
|
827
957
|
/**
|
|
828
|
-
*
|
|
829
|
-
*
|
|
958
|
+
* Sets the default targeting key used for toggle evaluations.
|
|
959
|
+
*
|
|
960
|
+
* @param value - The targeting key string or undefined to clear
|
|
830
961
|
*/
|
|
831
|
-
|
|
832
|
-
|
|
962
|
+
set defaultTargetingKey(value) {
|
|
963
|
+
this._defaultTargetingKey = value;
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Gets the Cacheable instance used for caching fetch operations.
|
|
967
|
+
*
|
|
968
|
+
* @returns The current Cacheable instance
|
|
969
|
+
*/
|
|
970
|
+
get cache() {
|
|
971
|
+
return this._net.cache;
|
|
833
972
|
}
|
|
834
973
|
/**
|
|
835
|
-
*
|
|
836
|
-
*
|
|
974
|
+
* Sets the Cacheable instance for caching fetch operations.
|
|
975
|
+
*
|
|
976
|
+
* @param cache - The Cacheable instance to use for caching
|
|
837
977
|
*/
|
|
838
|
-
set
|
|
839
|
-
this.
|
|
978
|
+
set cache(cache) {
|
|
979
|
+
this._net.cache = cache;
|
|
840
980
|
}
|
|
841
981
|
/**
|
|
842
|
-
*
|
|
843
|
-
*
|
|
844
|
-
*
|
|
845
|
-
*
|
|
846
|
-
*
|
|
982
|
+
* Retrieves a toggle value with generic type support.
|
|
983
|
+
*
|
|
984
|
+
* This is the core method for fetching toggle values. All convenience methods
|
|
985
|
+
* (getBoolean, getString, getNumber, getObject) delegate to this method.
|
|
986
|
+
*
|
|
987
|
+
* @template T - The expected type of the toggle value
|
|
988
|
+
* @param toggleKey - The key of the toggle to retrieve
|
|
989
|
+
* @param defaultValue - The value to return if the toggle is not found or an error occurs
|
|
990
|
+
* @param options - Optional configuration including context override
|
|
991
|
+
* @returns Promise resolving to the toggle value or defaultValue
|
|
992
|
+
*
|
|
993
|
+
* @example
|
|
994
|
+
* ```typescript
|
|
995
|
+
* const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
|
|
996
|
+
*
|
|
997
|
+
* // Get a boolean
|
|
998
|
+
* const enabled = await toggle.get<boolean>('feature-flag', false);
|
|
999
|
+
*
|
|
1000
|
+
* // Get an object with type safety
|
|
1001
|
+
* interface Config { theme: string; }
|
|
1002
|
+
* const config = await toggle.get<Config>('app-config', { theme: 'light' });
|
|
1003
|
+
*
|
|
1004
|
+
* // Override context for a single request
|
|
1005
|
+
* const value = await toggle.get('key', 'default', {
|
|
1006
|
+
* context: { targetingKey: 'user-456' }
|
|
1007
|
+
* });
|
|
1008
|
+
* ```
|
|
847
1009
|
*/
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
1010
|
+
async get(toggleKey, defaultValue, options) {
|
|
1011
|
+
try {
|
|
1012
|
+
const context = {
|
|
1013
|
+
application: this._applicationId ?? "",
|
|
1014
|
+
environment: this._environment ?? "development"
|
|
1015
|
+
};
|
|
1016
|
+
if (options?.context) {
|
|
1017
|
+
context.targetingKey = options?.context.targetingKey;
|
|
1018
|
+
context.ipAddress = options?.context.ipAddress;
|
|
1019
|
+
context.user = options?.context.user;
|
|
1020
|
+
context.customAttributes = options?.context.customAttributes;
|
|
1021
|
+
} else {
|
|
1022
|
+
context.targetingKey = this._defaultContext?.targetingKey;
|
|
1023
|
+
context.ipAddress = this._defaultContext?.ipAddress;
|
|
1024
|
+
context.user = this._defaultContext?.user;
|
|
1025
|
+
context.customAttributes = this._defaultContext?.customAttributes;
|
|
853
1026
|
}
|
|
854
|
-
|
|
1027
|
+
const fetchOptions = {
|
|
1028
|
+
headers: {}
|
|
1029
|
+
};
|
|
1030
|
+
if (!context.targetingKey) {
|
|
1031
|
+
context.targetingKey = this.getTargetingKey(context);
|
|
1032
|
+
}
|
|
1033
|
+
if (this._publicApiKey) {
|
|
1034
|
+
fetchOptions.headers["x-api-key"] = this._publicApiKey;
|
|
1035
|
+
} else {
|
|
1036
|
+
throw new Error("You must set the publicApiKey");
|
|
1037
|
+
}
|
|
1038
|
+
if (context.application === "") {
|
|
1039
|
+
throw new Error("You must set the applicationId");
|
|
1040
|
+
}
|
|
1041
|
+
const result = await this.fetch("/toggle/evaluate", context, fetchOptions);
|
|
1042
|
+
if (result?.toggles) {
|
|
1043
|
+
return result.toggles[toggleKey].value;
|
|
1044
|
+
}
|
|
1045
|
+
} catch (error) {
|
|
1046
|
+
this.emit("error", error);
|
|
855
1047
|
}
|
|
856
|
-
|
|
857
|
-
this._client = void 0;
|
|
1048
|
+
return defaultValue;
|
|
858
1049
|
}
|
|
859
1050
|
/**
|
|
860
|
-
*
|
|
861
|
-
*
|
|
1051
|
+
* Retrieves a boolean toggle value.
|
|
1052
|
+
*
|
|
1053
|
+
* This is a convenience method that wraps the generic get() method with boolean type safety.
|
|
1054
|
+
*
|
|
1055
|
+
* @param toggleKey - The key of the toggle to retrieve
|
|
1056
|
+
* @param defaultValue - The boolean value to return if the toggle is not found or an error occurs
|
|
1057
|
+
* @param options - Optional configuration including context for toggle evaluation
|
|
1058
|
+
* @returns Promise resolving to the boolean toggle value or defaultValue
|
|
1059
|
+
*
|
|
1060
|
+
* @example
|
|
1061
|
+
* ```typescript
|
|
1062
|
+
* const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
|
|
1063
|
+
* const isFeatureEnabled = await toggle.getBoolean('feature-flag', false);
|
|
1064
|
+
* console.log(isFeatureEnabled); // true or false
|
|
1065
|
+
* ```
|
|
862
1066
|
*/
|
|
863
|
-
|
|
864
|
-
this.
|
|
865
|
-
this._client = void 0;
|
|
1067
|
+
async getBoolean(toggleKey, defaultValue, options) {
|
|
1068
|
+
return this.get(toggleKey, defaultValue, options);
|
|
866
1069
|
}
|
|
867
1070
|
/**
|
|
868
|
-
*
|
|
869
|
-
*
|
|
870
|
-
* This is
|
|
871
|
-
*
|
|
1071
|
+
* Retrieves a string toggle value.
|
|
1072
|
+
*
|
|
1073
|
+
* This is a convenience method that wraps the generic get() method with string type safety.
|
|
1074
|
+
*
|
|
1075
|
+
* @param toggleKey - The key of the toggle to retrieve
|
|
1076
|
+
* @param defaultValue - The string value to return if the toggle is not found or an error occurs
|
|
1077
|
+
* @param options - Optional configuration including context for toggle evaluation
|
|
1078
|
+
* @returns Promise resolving to the string toggle value or defaultValue
|
|
1079
|
+
*
|
|
1080
|
+
* @example
|
|
1081
|
+
* ```typescript
|
|
1082
|
+
* const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
|
|
1083
|
+
* const message = await toggle.getString('welcome-message', 'Hello World');
|
|
1084
|
+
* console.log(message); // 'Welcome to our app!' or 'Hello World'
|
|
1085
|
+
* ```
|
|
872
1086
|
*/
|
|
873
|
-
async
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
1087
|
+
async getString(toggleKey, defaultValue, options) {
|
|
1088
|
+
return this.get(toggleKey, defaultValue, options);
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Retrieves an object toggle value.
|
|
1092
|
+
*
|
|
1093
|
+
* This is a convenience method that wraps the generic get() method with object type safety.
|
|
1094
|
+
* Note that the toggle service may return JSON as a string, which should be parsed if needed.
|
|
1095
|
+
*
|
|
1096
|
+
* @template T - The expected object type
|
|
1097
|
+
* @param toggleKey - The key of the toggle to retrieve
|
|
1098
|
+
* @param defaultValue - The object value to return if the toggle is not found or an error occurs
|
|
1099
|
+
* @param options - Optional configuration including context for toggle evaluation
|
|
1100
|
+
* @returns Promise resolving to the object toggle value or defaultValue
|
|
1101
|
+
*
|
|
1102
|
+
* @example
|
|
1103
|
+
* ```typescript
|
|
1104
|
+
* const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
|
|
1105
|
+
* const config = await toggle.getObject('app-config', { theme: 'light' });
|
|
1106
|
+
* console.log(config); // { theme: 'dark', features: ['a', 'b'] } or { theme: 'light' }
|
|
1107
|
+
* ```
|
|
1108
|
+
*/
|
|
1109
|
+
async getObject(toggleKey, defaultValue, options) {
|
|
1110
|
+
return this.get(toggleKey, defaultValue, options);
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Retrieves a number toggle value.
|
|
1114
|
+
*
|
|
1115
|
+
* This is a convenience method that wraps the generic get() method with number type safety.
|
|
1116
|
+
*
|
|
1117
|
+
* @param toggleKey - The key of the toggle to retrieve
|
|
1118
|
+
* @param defaultValue - The number value to return if the toggle is not found or an error occurs
|
|
1119
|
+
* @param options - Optional configuration including context for toggle evaluation
|
|
1120
|
+
* @returns Promise resolving to the number toggle value or defaultValue
|
|
1121
|
+
*
|
|
1122
|
+
* @example
|
|
1123
|
+
* ```typescript
|
|
1124
|
+
* const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
|
|
1125
|
+
* const maxRetries = await toggle.getNumber('max-retries', 3);
|
|
1126
|
+
* console.log(maxRetries); // 5 or 3
|
|
1127
|
+
* ```
|
|
1128
|
+
*/
|
|
1129
|
+
async getNumber(toggleKey, defaultValue, options) {
|
|
1130
|
+
return this.get(toggleKey, defaultValue, options);
|
|
1131
|
+
}
|
|
1132
|
+
/**
|
|
1133
|
+
* Makes an HTTP POST request to the specified URL with automatic authentication.
|
|
1134
|
+
*
|
|
1135
|
+
* This method uses browser-compatible fetch and automatically includes the
|
|
1136
|
+
* public API key in the x-api-key header if available. It supports load
|
|
1137
|
+
* balancing across multiple horizon URLs with fallback behavior.
|
|
1138
|
+
*
|
|
1139
|
+
* @template T - The expected response type
|
|
1140
|
+
* @param path - The API path to request (e.g., '/api/toggles')
|
|
1141
|
+
* @param payload - The JSON payload to send in the request body
|
|
1142
|
+
* @param options - Optional fetch configuration. Cache is set at .cache
|
|
1143
|
+
* @returns Promise resolving to the parsed JSON response
|
|
1144
|
+
* @throws {Error} If no horizon URLs are configured or all requests fail
|
|
1145
|
+
*
|
|
1146
|
+
* @example
|
|
1147
|
+
* ```typescript
|
|
1148
|
+
* const toggle = new Toggle({
|
|
1149
|
+
* publicApiKey: 'public_your-key-here',
|
|
1150
|
+
* horizonUrls: ['https://api.hyphen.cloud']
|
|
1151
|
+
* });
|
|
1152
|
+
*
|
|
1153
|
+
* interface ToggleResponse {
|
|
1154
|
+
* enabled: boolean;
|
|
1155
|
+
* value: string;
|
|
1156
|
+
* }
|
|
1157
|
+
*
|
|
1158
|
+
* const result = await toggle.fetch<ToggleResponse>('/api/toggle/feature-flag', {
|
|
1159
|
+
* context: { targetingKey: 'user-123' }
|
|
1160
|
+
* });
|
|
1161
|
+
* console.log(result.enabled); // true/false
|
|
1162
|
+
* ```
|
|
1163
|
+
*/
|
|
1164
|
+
async fetch(path2, payload, options) {
|
|
1165
|
+
if (this._horizonUrls.length === 0) {
|
|
1166
|
+
throw new Error("No horizon URLs configured. Set horizonUrls or provide a valid publicApiKey.");
|
|
1167
|
+
}
|
|
1168
|
+
const headers = {
|
|
1169
|
+
"Content-Type": "application/json"
|
|
1170
|
+
};
|
|
1171
|
+
if (options?.headers) {
|
|
1172
|
+
if (options.headers instanceof Headers) {
|
|
1173
|
+
options.headers.forEach((value, key) => {
|
|
1174
|
+
headers[key] = value;
|
|
1175
|
+
});
|
|
1176
|
+
} else if (Array.isArray(options.headers)) {
|
|
1177
|
+
options.headers.forEach(([key, value]) => {
|
|
1178
|
+
headers[key] = value;
|
|
1179
|
+
});
|
|
890
1180
|
} else {
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
1181
|
+
Object.assign(headers, options.headers);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
if (this._publicApiKey) {
|
|
1185
|
+
headers["x-api-key"] = this._publicApiKey;
|
|
1186
|
+
}
|
|
1187
|
+
const fetchOptions = {
|
|
1188
|
+
method: "POST",
|
|
1189
|
+
...options,
|
|
1190
|
+
headers,
|
|
1191
|
+
body: payload ? JSON.stringify(payload) : options?.body
|
|
1192
|
+
};
|
|
1193
|
+
const errors = [];
|
|
1194
|
+
for (const baseUrl of this._horizonUrls) {
|
|
1195
|
+
try {
|
|
1196
|
+
const url = `${baseUrl.replace(/\/$/, "")}${path2.startsWith("/") ? path2 : `/${path2}`}`;
|
|
1197
|
+
const response = await this._net.fetch(url, fetchOptions);
|
|
1198
|
+
if (!response.ok) {
|
|
1199
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
1200
|
+
}
|
|
1201
|
+
const data = await response.json();
|
|
1202
|
+
return data;
|
|
1203
|
+
} catch (error) {
|
|
1204
|
+
const fetchError = error instanceof Error ? error : new Error("Unknown fetch error");
|
|
1205
|
+
const statusMatch = fetchError.message.match(/status (\d{3})/);
|
|
1206
|
+
if (statusMatch) {
|
|
1207
|
+
const status = statusMatch[1];
|
|
1208
|
+
errors.push(new Error(`HTTP ${status}: ${fetchError.message}`));
|
|
1209
|
+
} else {
|
|
1210
|
+
errors.push(fetchError);
|
|
894
1211
|
}
|
|
895
1212
|
}
|
|
896
|
-
this._client = import_server_sdk.OpenFeature.getClient(this._context);
|
|
897
1213
|
}
|
|
898
|
-
|
|
1214
|
+
throw new Error(`All horizon URLs failed. Last errors: ${errors.map((e) => e.message).join(", ")}`);
|
|
899
1215
|
}
|
|
900
1216
|
/**
|
|
901
|
-
*
|
|
902
|
-
*
|
|
903
|
-
*
|
|
904
|
-
*
|
|
905
|
-
*
|
|
906
|
-
*
|
|
1217
|
+
* Validates and sets the public API key.
|
|
1218
|
+
*
|
|
1219
|
+
* This method is used internally by the publicApiKey setter to validate
|
|
1220
|
+
* that the key starts with "public_" prefix. If the key is invalid,
|
|
1221
|
+
* an error is thrown.
|
|
1222
|
+
*
|
|
1223
|
+
* @param key - The public API key string or undefined to clear
|
|
1224
|
+
* @throws {Error} If the key doesn't start with "public_"
|
|
1225
|
+
*
|
|
1226
|
+
* @example
|
|
1227
|
+
* ```typescript
|
|
1228
|
+
* const toggle = new Toggle();
|
|
1229
|
+
*
|
|
1230
|
+
* // Valid key
|
|
1231
|
+
* toggle.setPublicKey('public_abc123'); // OK
|
|
1232
|
+
*
|
|
1233
|
+
* // Invalid key
|
|
1234
|
+
* toggle.setPublicKey('invalid_key'); // Throws error
|
|
1235
|
+
*
|
|
1236
|
+
* // Clear key
|
|
1237
|
+
* toggle.setPublicKey(undefined); // OK
|
|
1238
|
+
* ```
|
|
907
1239
|
*/
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
return this.getBoolean(key, defaultValue, options);
|
|
912
|
-
}
|
|
913
|
-
case "string": {
|
|
914
|
-
return this.getString(key, defaultValue, options);
|
|
915
|
-
}
|
|
916
|
-
case "number": {
|
|
917
|
-
return this.getNumber(key, defaultValue, options);
|
|
918
|
-
}
|
|
919
|
-
default: {
|
|
920
|
-
return this.getObject(key, defaultValue, options);
|
|
921
|
-
}
|
|
1240
|
+
setPublicKey(key) {
|
|
1241
|
+
if (key !== void 0 && !key.startsWith("public_")) {
|
|
1242
|
+
throw new Error("Public API key must start with 'public_'");
|
|
922
1243
|
}
|
|
1244
|
+
this._publicApiKey = key;
|
|
923
1245
|
}
|
|
924
1246
|
/**
|
|
925
|
-
*
|
|
926
|
-
*
|
|
927
|
-
*
|
|
928
|
-
*
|
|
929
|
-
*
|
|
930
|
-
*
|
|
1247
|
+
* Extracts the organization ID from a public API key.
|
|
1248
|
+
*
|
|
1249
|
+
* The public key format is: `public_<base64-encoded-data>`
|
|
1250
|
+
* The base64 data contains: `orgId:secretData`
|
|
1251
|
+
* Only alphanumeric characters, underscores, and hyphens are considered valid in org IDs.
|
|
1252
|
+
*
|
|
1253
|
+
* @param publicKey - The public API key to extract the organization ID from
|
|
1254
|
+
* @returns The organization ID if valid and extractable, undefined otherwise
|
|
1255
|
+
*
|
|
1256
|
+
* @example
|
|
1257
|
+
* ```typescript
|
|
1258
|
+
* const toggle = new Toggle();
|
|
1259
|
+
* const orgId = toggle.getOrgIdFromPublicKey('public_dGVzdC1vcmc6c2VjcmV0');
|
|
1260
|
+
* console.log(orgId); // 'test-org'
|
|
1261
|
+
* ```
|
|
931
1262
|
*/
|
|
932
|
-
|
|
1263
|
+
getOrgIdFromPublicKey(publicKey) {
|
|
933
1264
|
try {
|
|
934
|
-
const
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
const result = await client.getBooleanValue(data.key, data.defaultValue, data.options?.context);
|
|
942
|
-
const resultData = {
|
|
943
|
-
key,
|
|
944
|
-
defaultValue,
|
|
945
|
-
options,
|
|
946
|
-
result
|
|
947
|
-
};
|
|
948
|
-
await this.hook("afterGetBoolean", resultData);
|
|
949
|
-
return resultData.result;
|
|
950
|
-
} catch (error) {
|
|
951
|
-
this.emit("error", error);
|
|
952
|
-
if (this._throwErrors) {
|
|
953
|
-
throw error;
|
|
954
|
-
}
|
|
1265
|
+
const keyWithoutPrefix = publicKey.replace(/^public_/, "");
|
|
1266
|
+
const decoded = globalThis.atob ? globalThis.atob(keyWithoutPrefix) : Buffer.from(keyWithoutPrefix, "base64").toString();
|
|
1267
|
+
const [orgId] = decoded.split(":");
|
|
1268
|
+
const isValidOrgId = /^[a-zA-Z0-9_-]+$/.test(orgId);
|
|
1269
|
+
return isValidOrgId ? orgId : void 0;
|
|
1270
|
+
} catch {
|
|
1271
|
+
return void 0;
|
|
955
1272
|
}
|
|
956
|
-
return defaultValue;
|
|
957
1273
|
}
|
|
958
1274
|
/**
|
|
959
|
-
*
|
|
960
|
-
*
|
|
961
|
-
*
|
|
962
|
-
*
|
|
963
|
-
*
|
|
1275
|
+
* Builds the default Horizon API URL for the given public key.
|
|
1276
|
+
*
|
|
1277
|
+
* If a valid organization ID can be extracted from the public key, returns an
|
|
1278
|
+
* organization-specific URL. Otherwise, returns the default fallback URL.
|
|
1279
|
+
*
|
|
1280
|
+
* @param publicKey - The public API key to build the URL for
|
|
1281
|
+
* @returns Organization-specific URL or default fallback URL
|
|
1282
|
+
*
|
|
1283
|
+
* @example
|
|
1284
|
+
* ```typescript
|
|
1285
|
+
* const toggle = new Toggle();
|
|
1286
|
+
*
|
|
1287
|
+
* // With valid org ID
|
|
1288
|
+
* const orgUrl = toggle.buildDefaultHorizonUrl('public_dGVzdC1vcmc6c2VjcmV0');
|
|
1289
|
+
* console.log(orgUrl); // 'https://test-org.toggle.hyphen.cloud'
|
|
1290
|
+
*
|
|
1291
|
+
* // With invalid key
|
|
1292
|
+
* const defaultUrl = toggle.buildDefaultHorizonUrl('invalid-key');
|
|
1293
|
+
* console.log(defaultUrl); // 'https://toggle.hyphen.cloud'
|
|
1294
|
+
* ```
|
|
964
1295
|
*/
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
defaultValue,
|
|
970
|
-
options
|
|
971
|
-
};
|
|
972
|
-
await this.hook("beforeGetString", data);
|
|
973
|
-
const client = await this.getClient();
|
|
974
|
-
const result = await client.getStringValue(data.key, data.defaultValue, data.options?.context);
|
|
975
|
-
const resultData = {
|
|
976
|
-
key,
|
|
977
|
-
defaultValue,
|
|
978
|
-
options,
|
|
979
|
-
result
|
|
980
|
-
};
|
|
981
|
-
await this.hook("afterGetString", resultData);
|
|
982
|
-
return resultData.result;
|
|
983
|
-
} catch (error) {
|
|
984
|
-
this.emit("error", error);
|
|
985
|
-
if (this._throwErrors) {
|
|
986
|
-
throw error;
|
|
987
|
-
}
|
|
1296
|
+
getDefaultHorizonUrl(publicKey) {
|
|
1297
|
+
if (publicKey) {
|
|
1298
|
+
const orgId = this.getOrgIdFromPublicKey(publicKey);
|
|
1299
|
+
return orgId ? `https://${orgId}.toggle.hyphen.cloud` : "https://toggle.hyphen.cloud";
|
|
988
1300
|
}
|
|
989
|
-
return
|
|
1301
|
+
return "https://toggle.hyphen.cloud";
|
|
990
1302
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1303
|
+
/**
|
|
1304
|
+
* Gets the default Horizon URLs for load balancing and failover.
|
|
1305
|
+
*
|
|
1306
|
+
* If a public key is provided, returns an array with the organization-specific
|
|
1307
|
+
* URL as primary and the default Hyphen URL as fallback. Without a public key,
|
|
1308
|
+
* returns only the default Hyphen URL.
|
|
1309
|
+
*
|
|
1310
|
+
* @param publicKey - Optional public API key to derive organization-specific URL
|
|
1311
|
+
* @returns Array of Horizon URLs for load balancing
|
|
1312
|
+
*
|
|
1313
|
+
* @example
|
|
1314
|
+
* ```typescript
|
|
1315
|
+
* const toggle = new Toggle();
|
|
1316
|
+
*
|
|
1317
|
+
* // Without public key - returns default only
|
|
1318
|
+
* const defaultUrls = toggle.getDefaultHorizonUrls();
|
|
1319
|
+
* // ['https://toggle.hyphen.cloud']
|
|
1320
|
+
*
|
|
1321
|
+
* // With public key - returns org-specific + fallback
|
|
1322
|
+
* const urls = toggle.getDefaultHorizonUrls('public_dGVzdC1vcmc6c2VjcmV0');
|
|
1323
|
+
* // ['https://test-org.toggle.hyphen.cloud', 'https://toggle.hyphen.cloud']
|
|
1324
|
+
* ```
|
|
1325
|
+
*/
|
|
1326
|
+
getDefaultHorizonUrls(publicKey) {
|
|
1327
|
+
let result = [
|
|
1328
|
+
this.getDefaultHorizonUrl()
|
|
1329
|
+
];
|
|
1330
|
+
if (publicKey) {
|
|
1331
|
+
const defaultUrl = result[0];
|
|
1332
|
+
const orgUrl = this.getDefaultHorizonUrl(publicKey);
|
|
1333
|
+
result = [];
|
|
1334
|
+
if (orgUrl !== defaultUrl) {
|
|
1335
|
+
result.push(orgUrl);
|
|
1013
1336
|
}
|
|
1337
|
+
result.push(defaultUrl);
|
|
1014
1338
|
}
|
|
1015
|
-
return
|
|
1339
|
+
return result;
|
|
1016
1340
|
}
|
|
1017
1341
|
/**
|
|
1018
|
-
*
|
|
1019
|
-
*
|
|
1020
|
-
* @
|
|
1021
|
-
* @param {T} defaultValue - The default value to return if the feature flag is not set or does not evaluate.
|
|
1022
|
-
* @param {ToggleRequestOptions} options - The options to use for the request. This can be used to override the context.
|
|
1023
|
-
* @returns {Promise<T>} - The value of the feature flag
|
|
1342
|
+
* Generates a unique targeting key based on available context.
|
|
1343
|
+
*
|
|
1344
|
+
* @returns A targeting key in the format: `[app]-[env]-[random]` or simplified versions
|
|
1024
1345
|
*/
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
if (this._throwErrors) {
|
|
1046
|
-
throw error;
|
|
1047
|
-
}
|
|
1346
|
+
generateTargetKey() {
|
|
1347
|
+
const randomSuffix = Math.random().toString(36).substring(7);
|
|
1348
|
+
const app = this._applicationId || "";
|
|
1349
|
+
const env2 = this._environment || "";
|
|
1350
|
+
const components = [
|
|
1351
|
+
app,
|
|
1352
|
+
env2,
|
|
1353
|
+
randomSuffix
|
|
1354
|
+
].filter(Boolean);
|
|
1355
|
+
return components.join("-");
|
|
1356
|
+
}
|
|
1357
|
+
/**
|
|
1358
|
+
* Extracts targeting key from a toggle context with fallback logic.
|
|
1359
|
+
*
|
|
1360
|
+
* @param context - The toggle context to extract targeting key from
|
|
1361
|
+
* @returns The targeting key string
|
|
1362
|
+
*/
|
|
1363
|
+
getTargetingKey(context) {
|
|
1364
|
+
if (context.targetingKey) {
|
|
1365
|
+
return context.targetingKey;
|
|
1048
1366
|
}
|
|
1049
|
-
|
|
1367
|
+
if (context.user) {
|
|
1368
|
+
return context.user.id;
|
|
1369
|
+
}
|
|
1370
|
+
return this._defaultTargetingKey;
|
|
1050
1371
|
}
|
|
1051
1372
|
};
|
|
1052
1373
|
|
|
@@ -1074,11 +1395,6 @@ var Hyphen = class extends import_hookified3.Hookified {
|
|
|
1074
1395
|
netInfoOptions.apiKey = options.apiKey;
|
|
1075
1396
|
linkOptions.apiKey = options.apiKey;
|
|
1076
1397
|
}
|
|
1077
|
-
if (options?.throwErrors !== void 0) {
|
|
1078
|
-
toggleOptions.throwErrors = options.throwErrors;
|
|
1079
|
-
netInfoOptions.throwErrors = options.throwErrors;
|
|
1080
|
-
linkOptions.throwErrors = options.throwErrors;
|
|
1081
|
-
}
|
|
1082
1398
|
this._netInfo = new NetInfo(netInfoOptions);
|
|
1083
1399
|
this._netInfo.on("error", (message, ...args) => this.emit("error", message, ...args));
|
|
1084
1400
|
this._netInfo.on("info", (message, ...args) => this.emit("info", message, ...args));
|
|
@@ -1148,30 +1464,11 @@ var Hyphen = class extends import_hookified3.Hookified {
|
|
|
1148
1464
|
this._netInfo.apiKey = value;
|
|
1149
1465
|
this._link.apiKey = value;
|
|
1150
1466
|
}
|
|
1151
|
-
/**
|
|
1152
|
-
* Get whether to throw errors or not.
|
|
1153
|
-
* If set to true, errors will be thrown instead of logged.
|
|
1154
|
-
* @returns {boolean} Whether to throw errors or not.
|
|
1155
|
-
*/
|
|
1156
|
-
get throwErrors() {
|
|
1157
|
-
return this._netInfo.throwErrors && this._toggle.throwErrors && this._link.throwErrors;
|
|
1158
|
-
}
|
|
1159
|
-
/**
|
|
1160
|
-
* Set whether to throw errors or not. If set to true, errors will be thrown instead of logged.
|
|
1161
|
-
* This will update the underlying services as well.
|
|
1162
|
-
* @param {boolean} value - Whether to throw errors or not.
|
|
1163
|
-
*/
|
|
1164
|
-
set throwErrors(value) {
|
|
1165
|
-
this._netInfo.throwErrors = value;
|
|
1166
|
-
this._toggle.throwErrors = value;
|
|
1167
|
-
this._link.throwErrors = value;
|
|
1168
|
-
}
|
|
1169
1467
|
};
|
|
1170
1468
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1171
1469
|
0 && (module.exports = {
|
|
1172
1470
|
Hyphen,
|
|
1173
1471
|
Toggle,
|
|
1174
|
-
ToggleHooks,
|
|
1175
1472
|
env,
|
|
1176
1473
|
loadEnv
|
|
1177
1474
|
});
|