@hyphen/sdk 1.8.0 → 1.10.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 CHANGED
@@ -11,8 +11,8 @@ The Hyphen Node.js SDK is a JavaScript library that allows developers to easily
11
11
 
12
12
  # Table of Contents
13
13
  - [Installation](#installation)
14
- - [Basic Usage](#basic-usage)
15
- - [Toggle](#toggle)
14
+ - [Basic Usage with Hyphen](#basic-usage-with-hyphen)
15
+ - [Toggle - Feature Flag Service](#toggle---feature-flag-service)
16
16
  - [Toggle Options](#toggle-options)
17
17
  - [Toggle API](#toggle-api)
18
18
  - [Toggle Hooks](#toggle-hooks)
@@ -20,9 +20,10 @@ The Hyphen Node.js SDK is a JavaScript library that allows developers to easily
20
20
  - [Toggle Caching](#toggle-caching)
21
21
  - [Toggle Environment Variables](#toggle-environment-variables)
22
22
  - [Toggle Self-Hosted](#toggle-self-hosted)
23
- - [ENV](#env)
23
+ - [ENV - Secret Management Service](#env---secret-management-service)
24
24
  - [Loading Environment Variables](#loading-environment-variables)
25
- - [Net Info](#net-info)
25
+ - [Net Info - Geo Information Service](#net-info---geo-information-service)
26
+ - [Link - Short Code Service](#link---short-code-service)
26
27
  - [Contributing](#contributing)
27
28
  - [Testing Your Changes](#testing-your-changes)
28
29
  - [License and Copyright](#license-and-copyright)
@@ -35,11 +36,95 @@ To install the Hyphen Node.js SDK, you can use npm or yarn. Run the following co
35
36
  npm install @hyphen/sdk
36
37
  ```
37
38
 
38
- # Basic Usage
39
+ # Basic Usage with Hyphen
39
40
 
40
- There are many ways to use the Hyphen Node.js SDK. Because of this we have created examples for each of the different ways in each secton of the documentation.
41
+ There are many ways to use the Hyphen Node.js SDK. Because of this we have created examples for each of the different ways in each secton of the documentation. To get started, you can create an instance of the `Hyphen` class and use its methods to interact with the various services.
41
42
 
42
- # Toggle
43
+ ```javascript
44
+ import { Hyphen } from '@hyphen/sdk';
45
+
46
+ const hyphen = new Hyphen({
47
+ publicApiKey: 'your_public_api_key',
48
+ applicationId: 'your_application_id',
49
+ });
50
+ const result = await hyphen.toggle.getBoolean('hyphen-sdk-boolean', false);
51
+ console.log('Boolean toggle value:', result); // true
52
+ ```
53
+
54
+ You can also use `netInfo` to access the network information service.
55
+
56
+ ```javascript
57
+ import { Hyphen, ToggleContext } from '@hyphen/sdk';
58
+
59
+ const context: ToggleContext = {
60
+ targetingKey: 'user-123',
61
+ ipAddress: '203.0.113.42',
62
+ customAttributes: {
63
+ subscriptionLevel: 'premium',
64
+ region: 'us-east',
65
+ },
66
+ user: {
67
+ id: 'user-123',
68
+ email: 'john.doe@example.com',
69
+ name: 'John Doe',
70
+ customAttributes: {
71
+ role: 'admin',
72
+ },
73
+ },
74
+ };
75
+
76
+ const hyphen = new Hyphen({
77
+ publicApiKey: 'your_public_api_key',
78
+ toggle: {
79
+ applicationId: 'your_application_id',
80
+ context: context,
81
+ },
82
+ });
83
+ const result = await hyphen.toggle.getBoolean('hyphen-sdk-boolean', false);
84
+ console.log('Boolean toggle value:', result); // true
85
+ ```
86
+
87
+ You can also use `netInfo` to access the network information service.
88
+
89
+ ```javascript
90
+ import { Hyphen } from '@hyphen/sdk';
91
+
92
+ const hyphen = new Hyphen({
93
+ apiKey: 'your_api_key',
94
+ });
95
+ const result = await hyphen.netInfo.getIpInfo('8.8.8.8');
96
+ console.log('Geo IP information:', result);
97
+ ```
98
+
99
+ If you need to set the `apiKey` or `publicApiKey` after initializing `Hyphen` you can do so and it will cascade the setting to the individual services:
100
+
101
+ ```javascript
102
+ import { Hyphen } from '@hyphen/sdk';
103
+
104
+ const hyphen = new Hyphen();
105
+ hyphen.apiKey = 'your_api_key';
106
+ const result = await hyphen.netInfo.getIpInfo('8.8.8.8');
107
+ console.log('Geo IP information:', result);
108
+ ```
109
+
110
+ Finally, `error`, `warn`, and `info` emitters are enabled from each of the services and you can access them by doing the following example with `error`:
111
+
112
+ ```javascript
113
+ import { Hyphen } from '@hyphen/sdk';
114
+
115
+ const hyphen = new Hyphen({ apiKey: 'your_api_key'});
116
+
117
+ hyphen.on('error', (error) => {
118
+ console.log(error);
119
+ });
120
+
121
+ const result = await hyphen.netInfo.getIpInfo('8.8.8.8');
122
+ console.log('Geo IP information:', result);
123
+ ```
124
+
125
+ The rest of the examples for each service show you accessing the service instance directly.
126
+
127
+ # Toggle - Feature Flag Service
43
128
 
44
129
  [Toggle](https://hyphen.ai/toggle) is our feature flag service that allows you to control the rollout of new features to your users. You can access your feature flags using the `Toggle` class.
45
130
 
@@ -487,7 +572,7 @@ const result = await toggle.getBoolean('hyphen-sdk-boolean', false);
487
572
  console.log('Boolean toggle value:', result); // true
488
573
  ```
489
574
 
490
- # ENV
575
+ # ENV - Secret Management Service
491
576
 
492
577
  Hyphens secret management service known as [ENV](https://hyphen.ai/env) allows you to manage your environment variables in a secure way. The Hyphen Node.js SDK provides a simple way to access your environment variables.
493
578
 
@@ -532,7 +617,7 @@ import { loadEnv } from '@hyphen/sdk';
532
617
  loadEnv({ local: false });
533
618
  ```
534
619
 
535
- # Net Info
620
+ # Net Info - Geo Information Service
536
621
 
537
622
  The Hyphen Node.js SDK also provides a `NetInfo` class that allows you to fetch geo information about an IP address. This can be useful for debugging or logging purposes. You can read more about it:
538
623
 
@@ -566,6 +651,38 @@ console.log('IP Infos:', ipInfos);
566
651
 
567
652
  You can also set the API key using the `HYPHEN_API_KEY` environment variable. This is useful for keeping your API key secure and not hardcoding it in your code.
568
653
 
654
+ # Link - Short Code Service
655
+
656
+ The Hyphen Node.js SDK also provides a `Link` class that allows you to create and manage short codes. This can be useful for generating short links for your application. Here is an example of creating a short code:
657
+
658
+ ```javascript
659
+ import { Link } from '@hyphen/sdk';
660
+ const link = new Link({
661
+ organizationId: 'your_organization_id',
662
+ apiKey: 'your_api_key',
663
+ });
664
+ const longUrl = 'https://hyphen.ai';
665
+ const domain = 'test.h4n.link';
666
+ const options = {
667
+ tags: ['sdk-test', 'unit-test'],
668
+ };
669
+ const response = await link.createShortCode(longUrl, domain, options);
670
+ console.log('Short Code Response:', response);
671
+ ```
672
+
673
+ if you want to delete a short code you can do it like this:
674
+
675
+ ```javascript
676
+ import { Link } from '@hyphen/sdk';
677
+ const link = new Link({
678
+ organizationId: 'your_organization_id',
679
+ apiKey: 'your_api_key',
680
+ });
681
+ const code = 'code_1234567890'; // It is the code identifier for the short code you want to delete
682
+ const response = await link.deleteShortCode(code);
683
+ console.log('Delete Short Code Response:', response);
684
+ ```
685
+
569
686
  # Contributing
570
687
 
571
688
  We welcome contributions to the Hyphen Node.js SDK! If you have an idea for a new feature, bug fix, or improvement, please follow these steps:
@@ -606,9 +723,19 @@ Once you have created the project, added the toggles, and created your applicati
606
723
  HYPHEN_PUBLIC_API_KEY=your_public_api_key
607
724
  HYPHEN_API_KEY=your_api_key
608
725
  HYPHEN_APPLICATION_ID=your_project_id
726
+ HYPHEN_LINK_DOMAIN=your_link_domain
727
+ HYPHEN_ORGANIZATION_ID=your_organization_id
609
728
  ```
610
729
 
611
- The `HYPHEN_PUBLIC_API_KEY` is the public API key for your Hyphen project, `HYPHEN_API_KEY` is the API key used for things such as `NetInfo` and is located under settings in the dashboard, and `HYPHEN_APPLICATION_ID` is the application ID for your Hyphen project.
730
+ A bit more information about the environment variables:
731
+
732
+ | Variable | Example Value | Description |
733
+ |----------------|----------------|----------------|
734
+ | *HYPHEN_PUBLIC_API_KEY* | `public_api_key` | The public API key for your Hyphen project. You can find this in the Hyphen dashboard. |
735
+ | *HYPHEN_API_KEY* | `api_key` | The API key for your Hyphen project. You can find this in the Hyphen dashboard. |
736
+ | *HYPHEN_APPLICATION_ID* | `application_id` | The application ID for your Hyphen project. You can find this in the Hyphen dashboard. |
737
+ | *HYPHEN_LINK_DOMAIN* | `test.h4n.link` | The domain for the Link service. This is used for generating links. |
738
+ | *HYPHEN_ORGANIZATION_ID* | `org_668575c0e169cde974a5c76a` | | The organization ID for your Hyphen project. This is used for the Link service. |
612
739
 
613
740
  Then run the tests with the following command:
614
741
 
package/dist/index.cjs CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
+ Hyphen: () => Hyphen,
34
35
  Toggle: () => Toggle,
35
36
  ToggleHooks: () => ToggleHooks,
36
37
  loadEnv: () => loadEnv
@@ -442,8 +443,471 @@ function loadEnv(options) {
442
443
  }
443
444
  }
444
445
  __name(loadEnv, "loadEnv");
446
+
447
+ // src/hyphen.ts
448
+ var import_hookified3 = require("hookified");
449
+
450
+ // src/net-info.ts
451
+ var import_node_process3 = __toESM(require("process"), 1);
452
+
453
+ // src/base-service.ts
454
+ var import_hookified2 = require("hookified");
455
+ var import_cacheable = require("cacheable");
456
+ var import_axios = __toESM(require("axios"), 1);
457
+ var import_pino = __toESM(require("pino"), 1);
458
+ var ErrorMessages = /* @__PURE__ */ function(ErrorMessages2) {
459
+ ErrorMessages2["API_KEY_REQUIRED"] = "API key is required. Please provide it via options or set the HYPHEN_API_KEY environment variable.";
460
+ ErrorMessages2["PUBLIC_API_KEY_SHOULD_NOT_BE_USED"] = "The provided API key is a public API key. Please provide a valid non public API key for authentication.";
461
+ return ErrorMessages2;
462
+ }({});
463
+ var BaseService = class extends import_hookified2.Hookified {
464
+ static {
465
+ __name(this, "BaseService");
466
+ }
467
+ _log = (0, import_pino.default)();
468
+ _cache = new import_cacheable.Cacheable();
469
+ _throwErrors = false;
470
+ constructor(options) {
471
+ super(options);
472
+ if (options && options.throwErrors !== void 0) {
473
+ this._throwErrors = options.throwErrors;
474
+ }
475
+ }
476
+ get log() {
477
+ return this._log;
478
+ }
479
+ set log(value) {
480
+ this._log = value;
481
+ }
482
+ get cache() {
483
+ return this._cache;
484
+ }
485
+ set cache(value) {
486
+ this._cache = value;
487
+ }
488
+ get throwErrors() {
489
+ return this._throwErrors;
490
+ }
491
+ set throwErrors(value) {
492
+ this._throwErrors = value;
493
+ }
494
+ error(message, ...args) {
495
+ this._log.error(message, ...args);
496
+ this.emit("error", message, ...args);
497
+ if (this.throwErrors) {
498
+ throw new Error(message);
499
+ }
500
+ }
501
+ warn(message, ...args) {
502
+ this._log.warn(message, ...args);
503
+ this.emit("warn", message, ...args);
504
+ }
505
+ info(message, ...args) {
506
+ this._log.info(message, ...args);
507
+ this.emit("info", message, ...args);
508
+ }
509
+ async get(url, config2) {
510
+ return import_axios.default.get(url, config2);
511
+ }
512
+ async post(url, data, config2) {
513
+ return import_axios.default.post(url, data, config2);
514
+ }
515
+ async put(url, data, config2) {
516
+ return import_axios.default.put(url, data, config2);
517
+ }
518
+ async delete(url, config2) {
519
+ return import_axios.default.delete(url, config2);
520
+ }
521
+ async patch(url, data, config2) {
522
+ return import_axios.default.patch(url, data, config2);
523
+ }
524
+ createHeaders(apiKey) {
525
+ const headers = {
526
+ "content-type": "application/json",
527
+ accept: "application/json"
528
+ };
529
+ if (apiKey) {
530
+ headers["x-api-key"] = apiKey;
531
+ }
532
+ return headers;
533
+ }
534
+ };
535
+
536
+ // src/net-info.ts
537
+ loadEnv();
538
+ var NetInfo = class extends BaseService {
539
+ static {
540
+ __name(this, "NetInfo");
541
+ }
542
+ _apiKey;
543
+ _baseUri = "https://net.info";
544
+ constructor(options) {
545
+ super(options);
546
+ if (options?.baseUri) {
547
+ this._baseUri = options.baseUri;
548
+ }
549
+ this.setApiKey(options?.apiKey);
550
+ if (!this._apiKey && import_node_process3.default.env.HYPHEN_API_KEY) {
551
+ this.setApiKey(import_node_process3.default.env.HYPHEN_API_KEY);
552
+ }
553
+ if (!this._apiKey) {
554
+ this.error(ErrorMessages.API_KEY_REQUIRED);
555
+ }
556
+ }
557
+ /**
558
+ * Gets or sets the API key for authentication.
559
+ * If not set, it will try to use the `HYPHEN_API_KEY` environment variable.
560
+ * @type {string | undefined}
561
+ */
562
+ get apiKey() {
563
+ return this._apiKey;
564
+ }
565
+ /**
566
+ * Sets the API key for authentication.
567
+ * @param {string | undefined} value - The API key to set.
568
+ */
569
+ set apiKey(value) {
570
+ this.setApiKey(value);
571
+ }
572
+ /**
573
+ * Gets or sets the base URI for the API.
574
+ * @type {string}
575
+ */
576
+ get baseUri() {
577
+ return this._baseUri;
578
+ }
579
+ /**
580
+ * Sets the base URI for the API.
581
+ * @param {string} value - The base URI to set.
582
+ */
583
+ set baseUri(value) {
584
+ this._baseUri = value;
585
+ }
586
+ setApiKey(value) {
587
+ if (value?.startsWith("public_")) {
588
+ this.error(ErrorMessages.PUBLIC_API_KEY_SHOULD_NOT_BE_USED);
589
+ return;
590
+ }
591
+ this._apiKey = value;
592
+ }
593
+ /**
594
+ * Fetches GeoIP information for a given IP address.
595
+ * @param {string} ip - The IP address to fetch GeoIP information for.
596
+ * @returns {Promise<ipInfo | ipInfoError>} - A promise that resolves to the ip information or an error.
597
+ */
598
+ async getIpInfo(ip) {
599
+ try {
600
+ if (!this._apiKey) {
601
+ throw new Error(ErrorMessages.API_KEY_REQUIRED);
602
+ }
603
+ const url = `${this._baseUri}/ip/${ip}`;
604
+ const headers = this.createHeaders(this._apiKey);
605
+ const response = await this.get(url, {
606
+ headers
607
+ });
608
+ if (response.status !== 200) {
609
+ const errorResult = {
610
+ ip,
611
+ type: "error",
612
+ errorMessage: `Failed to fetch ip info: ${response.statusText}`
613
+ };
614
+ return errorResult;
615
+ }
616
+ return response.data;
617
+ } catch (error) {
618
+ this.error(`Failed to fetch ip info: ${error instanceof Error ? error.message : "Unknown error"}`);
619
+ const errorResult = {
620
+ ip,
621
+ type: "error",
622
+ errorMessage: error instanceof Error ? error.message : "Unknown error"
623
+ };
624
+ return errorResult;
625
+ }
626
+ }
627
+ async getIpInfos(ips) {
628
+ if (!Array.isArray(ips) || ips.length === 0) {
629
+ this.error("The provided IPs array is invalid. It should be a non-empty array of strings.");
630
+ return [];
631
+ }
632
+ const errorResults = [];
633
+ try {
634
+ if (!this._apiKey) {
635
+ throw new Error(ErrorMessages.API_KEY_REQUIRED);
636
+ }
637
+ const url = `${this._baseUri}/ip`;
638
+ const headers = this.createHeaders(this._apiKey);
639
+ const response = await this.post(url, ips, {
640
+ headers
641
+ });
642
+ if (response.status !== 200) {
643
+ errorResults.push({
644
+ ip: "",
645
+ type: "error",
646
+ errorMessage: `Failed to fetch ip infos: ${response.statusText}`
647
+ });
648
+ return errorResults;
649
+ }
650
+ const responseData = response?.data;
651
+ return responseData.data;
652
+ } catch (error) {
653
+ this.error(`Failed to fetch ip infos: ${error instanceof Error ? error.message : "Unknown error"}`);
654
+ errorResults.push({
655
+ ip: "",
656
+ type: "error",
657
+ errorMessage: error instanceof Error ? error.message : "Unknown error"
658
+ });
659
+ return errorResults;
660
+ }
661
+ }
662
+ };
663
+
664
+ // src/link.ts
665
+ var import_node_process4 = __toESM(require("process"), 1);
666
+ loadEnv();
667
+ var defaultLinkUris = [
668
+ "https://api.hyphen.ai/api/organizations/{organizationId}/link/codes/"
669
+ ];
670
+ var Link = class extends BaseService {
671
+ static {
672
+ __name(this, "Link");
673
+ }
674
+ _uris = defaultLinkUris;
675
+ _organizationId;
676
+ _apiKey;
677
+ constructor(options) {
678
+ super(options);
679
+ this._uris = options?.uris ?? defaultLinkUris;
680
+ this._organizationId = options?.organizationId;
681
+ if (options?.apiKey) {
682
+ this.setApiKey(options.apiKey);
683
+ }
684
+ if (!this._apiKey && import_node_process4.default.env.HYPHEN_API_KEY) {
685
+ this.setApiKey(import_node_process4.default.env.HYPHEN_API_KEY);
686
+ }
687
+ if (!this._organizationId && import_node_process4.default.env.HYPHEN_ORGANIZATION_ID) {
688
+ this._organizationId = import_node_process4.default.env.HYPHEN_ORGANIZATION_ID;
689
+ }
690
+ }
691
+ /**
692
+ * Get the URIs for the link service. The default is `["https://api.hyphen.ai/api/organizations/{organizationId}/link/codes/"]`.
693
+ * @returns {string[]} The URIs for the link service.
694
+ */
695
+ get uris() {
696
+ return this._uris;
697
+ }
698
+ /**
699
+ * Set the URIs for the link service. The default is `["https://api.hyphen.ai/api/organizations/{organizationId}/link/codes/"]`.
700
+ * @param {string[]} uris - The URIs to set.
701
+ */
702
+ set uris(uris) {
703
+ this._uris = uris;
704
+ }
705
+ /**
706
+ * Get the organization ID for the link service. This is required to access the link service.
707
+ * @returns {string | undefined} The organization ID.
708
+ */
709
+ get organizationId() {
710
+ return this._organizationId;
711
+ }
712
+ /**
713
+ * Set the organization ID for the link service. This is required to access the link service.
714
+ * @param {string | undefined} organizationId - The organization ID to set.
715
+ */
716
+ set organizationId(organizationId) {
717
+ this._organizationId = organizationId;
718
+ }
719
+ /**
720
+ * Get the API key for the link service. This is required to access the link service.
721
+ * @returns {string | undefined} The API key.
722
+ */
723
+ get apiKey() {
724
+ return this._apiKey;
725
+ }
726
+ /**
727
+ * Set the API key for the link service. This is required to access the link service.
728
+ * @param {string | undefined} apiKey - The API key to set.
729
+ */
730
+ set apiKey(apiKey) {
731
+ this.setApiKey(apiKey);
732
+ }
733
+ /**
734
+ * Set the API key for the link service. If the API key starts with 'public_', an error is thrown.
735
+ * This is to ensure that the API key is not a public key, which should not be used for authenticated requests.
736
+ * @param {string} apiKey
737
+ */
738
+ setApiKey(apiKey) {
739
+ if (apiKey?.startsWith("public_")) {
740
+ throw new Error('API key cannot start with "public_"');
741
+ }
742
+ if (apiKey) {
743
+ this._apiKey = apiKey;
744
+ }
745
+ }
746
+ async createShortCode(longUrl, domain, options) {
747
+ if (!this._organizationId) {
748
+ throw new Error("Organization ID is required to create a short code.");
749
+ }
750
+ const url = this._uris[0].replace("{organizationId}", this._organizationId);
751
+ const body = {
752
+ // eslint-disable-next-line @typescript-eslint/naming-convention
753
+ long_url: longUrl,
754
+ domain,
755
+ code: options?.code,
756
+ title: options?.title,
757
+ tags: options?.tags
758
+ };
759
+ const headers = this.createHeaders(this._apiKey);
760
+ const response = await this.post(url, body, {
761
+ headers
762
+ });
763
+ if (response.status === 201) {
764
+ return response.data;
765
+ }
766
+ throw new Error(`Failed to create short code: ${response.statusText}`);
767
+ }
768
+ /**
769
+ * Delete a short code.
770
+ * @param {string} code The short code to delete. Example: 'code_686bed403c3991bd676bba4d'
771
+ * @returns {Promise<boolean>} A promise that resolves to true if the short code was deleted successfully, or false if it was not.
772
+ */
773
+ async deleteShortCode(code) {
774
+ if (!this._organizationId) {
775
+ throw new Error("Organization ID is required to delete a short code.");
776
+ }
777
+ let url = this._uris[0].replace("{organizationId}", this._organizationId);
778
+ url = url.endsWith("/") ? `${url}${code}/` : `${url}/${code}/`;
779
+ const headers = this.createHeaders(this._apiKey);
780
+ delete headers["content-type"];
781
+ const response = await this.delete(url, {
782
+ headers
783
+ });
784
+ if (response.status === 204) {
785
+ return true;
786
+ }
787
+ throw new Error(`Failed to delete short code: ${response.statusText}`);
788
+ }
789
+ };
790
+
791
+ // src/hyphen.ts
792
+ var Hyphen = class extends import_hookified3.Hookified {
793
+ static {
794
+ __name(this, "Hyphen");
795
+ }
796
+ _netInfo;
797
+ _toggle;
798
+ _link;
799
+ _publicApiKey;
800
+ _apiKey;
801
+ constructor(options) {
802
+ super(options);
803
+ const toggleOptions = options?.toggle ?? {};
804
+ const netInfoOptions = options?.netInfo ?? {};
805
+ const linkOptions = options?.link ?? {};
806
+ if (options?.publicApiKey) {
807
+ this._publicApiKey = options.publicApiKey;
808
+ toggleOptions.publicApiKey = options.publicApiKey;
809
+ }
810
+ if (options?.apiKey) {
811
+ this._apiKey = options.apiKey;
812
+ netInfoOptions.apiKey = options.apiKey;
813
+ linkOptions.apiKey = options.apiKey;
814
+ }
815
+ if (options?.throwErrors !== void 0) {
816
+ toggleOptions.throwErrors = options.throwErrors;
817
+ netInfoOptions.throwErrors = options.throwErrors;
818
+ linkOptions.throwErrors = options.throwErrors;
819
+ }
820
+ this._netInfo = new NetInfo(netInfoOptions);
821
+ this._netInfo.on("error", (message, ...args) => this.emit("error", message, ...args));
822
+ this._netInfo.on("info", (message, ...args) => this.emit("info", message, ...args));
823
+ this._netInfo.on("warn", (message, ...args) => this.emit("warn", message, ...args));
824
+ this._toggle = new Toggle(toggleOptions);
825
+ this._toggle.on("error", (message, ...args) => this.emit("error", message, ...args));
826
+ this._toggle.on("info", (message, ...args) => this.emit("info", message, ...args));
827
+ this._toggle.on("warn", (message, ...args) => this.emit("warn", message, ...args));
828
+ this._link = new Link(linkOptions);
829
+ this._link.on("error", (message, ...args) => this.emit("error", message, ...args));
830
+ this._link.on("info", (message, ...args) => this.emit("info", message, ...args));
831
+ this._link.on("warn", (message, ...args) => this.emit("warn", message, ...args));
832
+ }
833
+ /**
834
+ * Get the NetInfo service instance.
835
+ * @returns {NetInfo} The NetInfo service instance.
836
+ */
837
+ get netInfo() {
838
+ return this._netInfo;
839
+ }
840
+ /**
841
+ * Get the Toggle service instance.
842
+ * @returns {Toggle} The Toggle service instance.
843
+ */
844
+ get toggle() {
845
+ return this._toggle;
846
+ }
847
+ /**
848
+ * Get the Link service instance.
849
+ * @returns {Link} The Link service instance.
850
+ */
851
+ get link() {
852
+ return this._link;
853
+ }
854
+ /**
855
+ * Get the public API key for the Hyphen service.
856
+ * This is used for public endpoints that do not require authentication.
857
+ * @returns {string | undefined} The public API key.
858
+ */
859
+ get publicApiKey() {
860
+ return this._publicApiKey;
861
+ }
862
+ /**
863
+ * Set the public API key for the Hyphen service. If set, this will also update the underlying services.
864
+ * This is used for public endpoints that do not require authentication such as the Toggle service.
865
+ * @param {string | undefined} value - The public API key to set.
866
+ */
867
+ set publicApiKey(value) {
868
+ this._publicApiKey = value;
869
+ this._toggle.publicApiKey = value;
870
+ }
871
+ /**
872
+ * Get the API key for the Hyphen service.
873
+ * This is used for authenticated endpoints that require an API key such as the NetInfo and Link services.
874
+ * @returns {string | undefined} The API key.
875
+ */
876
+ get apiKey() {
877
+ return this._apiKey;
878
+ }
879
+ /**
880
+ * Set the API key for the Hyphen service. If set, this will also update the underlying services.
881
+ * This is used for authenticated endpoints that require an API key such as the NetInfo and Link services.
882
+ * @param {string | undefined} value - The API key to set.
883
+ */
884
+ set apiKey(value) {
885
+ this._apiKey = value;
886
+ this._netInfo.apiKey = value;
887
+ this._link.apiKey = value;
888
+ }
889
+ /**
890
+ * Get whether to throw errors or not.
891
+ * If set to true, errors will be thrown instead of logged.
892
+ * @returns {boolean} Whether to throw errors or not.
893
+ */
894
+ get throwErrors() {
895
+ return this._netInfo.throwErrors && this._toggle.throwErrors && this._link.throwErrors;
896
+ }
897
+ /**
898
+ * Set whether to throw errors or not. If set to true, errors will be thrown instead of logged.
899
+ * This will update the underlying services as well.
900
+ * @param {boolean} value - Whether to throw errors or not.
901
+ */
902
+ set throwErrors(value) {
903
+ this._netInfo.throwErrors = value;
904
+ this._toggle.throwErrors = value;
905
+ this._link.throwErrors = value;
906
+ }
907
+ };
445
908
  // Annotate the CommonJS export names for ESM import in node:
446
909
  0 && (module.exports = {
910
+ Hyphen,
447
911
  Toggle,
448
912
  ToggleHooks,
449
913
  loadEnv