From 91ffac57e6de791c2db43f81bb261c49699449c6 Mon Sep 17 00:00:00 2001
From: petruki <31597636+petruki@users.noreply.github.com>
Date: Thu, 8 Jan 2026 10:59:03 -0800
Subject: [PATCH 1/3] feat: added persisted Switchers for better resource
utilization
---
.devcontainer/Dockerfile | 2 +-
.github/workflows/master.yml | 6 +-
.github/workflows/sonar.yml | 4 +-
README.md | 78 +++++++++++++-------------
deno.jsonc | 2 +-
src/client.ts | 16 +++++-
src/switcher.ts | 92 ++++++++++++++++++++++---------
tests/deps.ts | 4 +-
tests/playground/index.ts | 40 +++++++-------
tests/switcher-client.test.ts | 13 +++--
tests/switcher-functional.test.ts | 21 ++++++-
11 files changed, 175 insertions(+), 103 deletions(-)
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index ad4c0a8..be7d10b 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -1,4 +1,4 @@
-FROM denoland/deno:2.5.4
+FROM denoland/deno:2.6.4
# Install tools
RUN apt-get update && \
diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml
index e8d47dd..1a1dc99 100644
--- a/.github/workflows/master.yml
+++ b/.github/workflows/master.yml
@@ -17,10 +17,10 @@ jobs:
with:
fetch-depth: 0
- - name: Setup Deno v2.6.3
+ - name: Setup Deno v2.6.4
uses: denoland/setup-deno@v2
with:
- deno-version: v2.6.3
+ deno-version: v2.6.4
- name: Setup LCOV
run: sudo apt install -y lcov
@@ -45,7 +45,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- deno-version: [v1.46.3, v2.6.3]
+ deno-version: [v1.46.3, v2.6.4]
os: [ ubuntu-latest, windows-latest ]
runs-on: ${{ matrix.os }}
diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml
index a69ed3f..0614086 100644
--- a/.github/workflows/sonar.yml
+++ b/.github/workflows/sonar.yml
@@ -33,10 +33,10 @@ jobs:
ref: ${{ steps.pr.outputs.head_sha }}
fetch-depth: 0
- - name: Setup Deno v2.6.3
+ - name: Setup Deno v2.6.4
uses: denoland/setup-deno@v2
with:
- deno-version: v2.6.3
+ deno-version: v2.6.4
- name: Setup LCOV
run: sudo apt install -y lcov
diff --git a/README.md b/README.md
index debed6d..29749f0 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,5 @@
-# Switcher4Deno
-
-Switcher4Deno
+Switcher Client Deno SDK
A Deno SDK for Switcher API
@@ -22,37 +20,37 @@ A Deno SDK for Switcher API
## ๐ Table of Contents
-- [๐ฏ About](#-about)
- - [โจ Key Features](#-key-features)
-- [๐ Quick Start](#-quick-start)
+- [About](#-about)
+ - [Key Features](#-key-features)
+- [Quick Start](#-quick-start)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Basic Setup](#basic-setup)
-- [โ๏ธ Configuration](#๏ธ-configuration)
+- [Configuration](#๏ธ-configuration)
- [Context Parameters](#context-parameters)
- [Advanced Options](#advanced-options)
- [Options Reference](#options-reference)
-- [๐ก Usage Examples](#-usage-examples)
+- [Usage Examples](#-usage-examples)
- [1. Basic Feature Flag Check](#1-basic-feature-flag-check)
- [2. Strategy Validation with Input Preparation](#2-strategy-validation-with-input-preparation)
- [3. All-in-One Execution](#3-all-in-one-execution)
- [4. Performance Optimization with Throttling](#4-performance-optimization-with-throttling)
- [5. Hybrid Mode - Force Remote Resolution](#5-hybrid-mode---force-remote-resolution)
-- [๐งช Testing & Development](#-testing--development)
+- [Testing & Development](#-testing--development)
- [Built-in Stub Feature](#built-in-stub-feature)
- [Test Mode](#test-mode)
- [Smoke Testing](#smoke-testing)
-- [๐ธ Snapshot Management](#-snapshot-management)
+- [Snapshot Management](#-snapshot-management)
- [Loading Snapshots](#loading-snapshots)
- [Real-time Snapshot Monitoring](#real-time-snapshot-monitoring)
- [Snapshot Version Checking](#snapshot-version-checking)
- [Automatic Snapshot Updates](#automatic-snapshot-updates)
-## ๐ฏ About
+## About
-**Switcher4Deno** is a feature-rich SDK for integrating [Switcher API](https://github.com/switcherapi/switcher-api) into your Deno applications. It provides robust feature flag management with enterprise-grade capabilities.
+**Switcher Client Deno** (former Switcher4Deno) is a feature-rich SDK for integrating [Switcher API](https://github.com/switcherapi/switcher-api) into your Deno applications. It provides robust feature flag management with enterprise-grade capabilities.
-### โจ Key Features
+### Key Features
- ๐ **Zero Latency**: Local mode with snapshot files or in-memory for instant feature flag resolution
- ๐ **Hybrid Configuration**: Silent mode with automatic fallback handling
@@ -60,11 +58,11 @@ A Deno SDK for Switcher API
- โก **Performance Optimized**: Throttling optimizes remote API calls to reduce bottlenecks in critical code paths
- ๐ ๏ธ **Developer Tools**: Runtime snapshot updates without app restart and automatic sync with remote API
-## ๐ Quick Start
+## Quick Start
### Prerequisites
-- **Deno**: Version 1.4x or higher
+- **Deno**: Version 1.4x or above
- **Required Permissions**:
```bash
--allow-read --allow-write --allow-net
@@ -85,7 +83,7 @@ import { Client } from 'https://deno.land/x/switcher4deno@v[VERSION]/mod.ts';
```ts
import { Client } from "@switcherapi/switcher-client-deno";
-// Initialize the client context
+// 1. Initialize the client
Client.buildContext({
url: 'https://api.switcherapi.com',
apiKey: '[YOUR_API_KEY]',
@@ -94,15 +92,15 @@ Client.buildContext({
environment: 'default'
});
-// Get a switcher instance
-const switcher = Client.getSwitcher();
+// 2. Get a switcher instance
+const switcher = Client.getSwitcher('FEATURE01');
-// Check if a feature is enabled
-const isEnabled = await switcher.isItOn('FEATURE01');
+// 3. Check if a feature is enabled
+const isEnabled = await switcher.isItOn();
console.log('Feature enabled:', isEnabled);
```
-## โ๏ธ Configuration
+## Configuration
### Context Parameters
| Parameter | Type | Required | Description |
@@ -153,31 +151,29 @@ Client.buildContext({
> **โ ๏ธ Note on regexSafe**: This feature protects against reDOS attacks but uses Web Workers, which are incompatible with compiled executables.
-## ๐ก Usage Examples
+## Usage Examples
### 1. Basic Feature Flag Check
Simple on/off checks for feature flags:
```ts
+// Non-persisted switcher instance
const switcher = Client.getSwitcher();
-
-// Synchronous (local mode only)
-const isEnabled = switcher.isItOn('FEATURE01') as boolean;
-const isEnabledBool = switcher.isItOnBool('FEATURE01');
-// Returns: true or false
-
-// With detailed response
-const response = switcher.detail().isItOn('FEATURE01') as SwitcherResult;
-const detailedResponse = switcher.isItOnDetail('FEATURE01');
-// Returns: { result: true, reason: 'Success', metadata: {} }
-
-// Asynchronous (remote/hybrid mode)
-const isEnabledAsync = await switcher.isItOn('FEATURE01');
-const isEnabledBoolAsync = await switcher.isItOnBool('FEATURE01', true);
-const responseAsync = await switcher.detail().isItOn('FEATURE01');
-const detailedResponseAsync = await switcher.isItOnDetail('FEATURE01', true);
-// Returns: Promise or Promise
+// Persisted switcher instance
+const switcher = Client.getSwitcher('FEATURE01');
+
+// ๐ Synchronous (local mode only)
+const isEnabled = switcher.isItOn(); // Returns: boolean
+const isEnabledBool = switcher.isItOnBool(); // Returns: boolean
+const detailResult = switcher.detail().isItOn(); // Returns: { result, reason, metadata }
+const detailDirect = switcher.isItOnDetail(); // Returns: { result, reason, metadata }
+
+// ๐ Asynchronous (remote/hybrid mode)
+const isEnabledAsync = await switcher.isItOn(); // Returns: Promise
+const isEnabledBoolAsync = await switcher.isItOnBool(true); // Returns: Promise
+const detailResultAsync = await switcher.detail().isItOn(); // Returns: Promise
+const detailDirectAsync = await switcher.isItOnDetail(true); // Returns: Promise
```
### 2. Strategy Validation with Input Preparation
@@ -243,7 +239,7 @@ This is useful for:
- Critical features that must be resolved remotely
- Real-time configuration updates
-## ๐งช Testing & Development
+## Testing & Development
### Built-in Stub Feature
@@ -301,7 +297,7 @@ try {
}
```
-## ๐ธ Snapshot Management
+## Snapshot Management
Snapshots enable zero-latency local mode by caching your feature flag configuration.
diff --git a/deno.jsonc b/deno.jsonc
index 4d3fea3..de987dd 100644
--- a/deno.jsonc
+++ b/deno.jsonc
@@ -1,7 +1,7 @@
{
"name": "@switcherapi/switcher-client-deno",
"version": "2.4.1",
- "description": "Switcher4Deno is a Feature Flag Deno Client SDK for Switcher API",
+ "description": "Switcher Client Deno is a Feature Flag Deno Client SDK for Switcher API",
"tasks": {
"cache-reload": "deno cache --reload --lock=deno.lock mod.ts",
"fmt": "deno fmt mod.ts src/ --options-single-quote --options-line-width=120 --check",
diff --git a/src/client.ts b/src/client.ts
index d948bfe..2d58565 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -46,6 +46,7 @@ import { SnapshotWatcher } from './lib/snapshotWatcher.ts';
*/
export class Client {
private static readonly _snapshotWatcher = new SnapshotWatcher();
+ private static readonly _switchers = new Map();
private static _testEnabled: boolean;
private static _context: SwitcherContext;
@@ -131,8 +132,21 @@ export class Client {
* Creates a new instance of Switcher
*/
static getSwitcher(key?: string): Switcher {
- return new Switcher(util.get(key, ''))
+ const keyValue = util.get(key, '');
+ const persistedSwitcher = Client._switchers.get(keyValue);
+
+ if (persistedSwitcher) {
+ return persistedSwitcher;
+ }
+
+ const switcher = new Switcher(keyValue)
.restrictRelay(GlobalOptions.restrictRelay);
+
+ if (keyValue) {
+ Client._switchers.set(keyValue, switcher);
+ }
+
+ return switcher;
}
/**
diff --git a/src/switcher.ts b/src/switcher.ts
index 9525fb6..78a52af 100644
--- a/src/switcher.ts
+++ b/src/switcher.ts
@@ -27,8 +27,8 @@ export type SwitcherExecutionResult = Promise | boolea
* const { result, reason, metadata } = switcher.isItOnDetail();
*
* // Force asynchronous execution
- * const isOnAsync = await switcher.isItOnBool('MY_SWITCHER', true);
- * const detailAsync = await switcher.isItOnDetail('MY_SWITCHER', true);
+ * const isOnAsync = await switcher.isItOnBool(true);
+ * const detailAsync = await switcher.isItOnDetail(true);
* ```
*/
export class Switcher extends SwitcherBuilder implements SwitcherRequest {
@@ -38,73 +38,113 @@ export class Switcher extends SwitcherBuilder implements SwitcherRequest {
}
/**
- * Execute criteria with boolean result (synchronous version)
+ * Execute criteria with boolean result (synchronous, uses persisted key)
+ *
+ * @returns boolean result
+ */
+ isItOnBool(): boolean;
+
+ /**
+ * Execute criteria with boolean result (synchronous)
*
* @param key - switcher key
+ * @returns boolean result
+ */
+ isItOnBool(key: string): boolean;
+
+ /**
+ * Execute criteria with boolean result (asynchronous, uses persisted key)
+ *
* @param forceAsync - when true, forces async execution
- * @returns boolean value
+ * @returns Promise result
*/
- isItOnBool(key: string, forceAsync?: false): boolean;
+ isItOnBool(forceAsync: true): Promise;
/**
- * Execute criteria with boolean result (asynchronous version)
+ * Execute criteria with boolean result (asynchronous)
*
* @param key - switcher key
* @param forceAsync - when true, forces async execution
- * @returns Promise value
+ * @returns Promise result
*/
- isItOnBool(key: string, forceAsync?: true): Promise;
+ isItOnBool(key: string, forceAsync: true): Promise;
/**
* Execute criteria with boolean result
*
- * @param key - switcher key
- * @param forceAsync - when true, forces async execution
- * @returns boolean value or Promise based on execution mode
+ * @param arg1 - switcher key or forceAsync boolean
+ * @param arg2 - when true, forces async execution
+ * @returns boolean result or Promise based on execution mode
*/
- isItOnBool(key: string, forceAsync?: boolean): Promise | boolean {
+ isItOnBool(arg1?: string | boolean, arg2?: boolean): Promise | boolean {
this.detail(false);
- if (forceAsync) {
- return this.isItOn(key) as Promise;
+ // Handle case where first argument is forceAsync boolean
+ if (typeof arg1 === 'boolean') {
+ arg2 = arg1;
+ arg1 = undefined;
}
- return this.isItOn(key) as boolean;
+ if (arg2) {
+ return this.isItOn(arg1) as Promise;
+ }
+
+ return this.isItOn(arg1) as boolean;
}
/**
- * Execute criteria with detail information (synchronous version)
+ * Execute criteria with detail information (synchronous)
*
- * @param key - switcher key
- * @param forceAsync - when true, forces async execution
* @returns SwitcherResult object
*/
- isItOnDetail(key: string, forceAsync?: false): SwitcherResult;
+ isItOnDetail(): SwitcherResult;
/**
- * Execute criteria with detail information (asynchronous version)
+ * Execute criteria with detail information (synchronous)
*
* @param key - switcher key
+ * @returns SwitcherResult object
+ */
+ isItOnDetail(key: string): SwitcherResult;
+
+ /**
+ * Execute criteria with detail information (asynchronous, uses persisted key)
+ *
* @param forceAsync - when true, forces async execution
* @returns Promise object
*/
- isItOnDetail(key: string, forceAsync?: true): Promise;
+ isItOnDetail(forceAsync: true): Promise;
/**
- * Execute criteria with detail information
+ * Execute criteria with detail information (asynchronous)
*
* @param key - switcher key
* @param forceAsync - when true, forces async execution
+ * @returns Promise object
+ */
+ isItOnDetail(key: string, forceAsync: true): Promise;
+
+ /**
+ * Execute criteria with detail information
+ *
+ * @param arg1 - switcher key
+ * @param arg2 - when true, forces async execution
* @returns SwitcherResult or Promise based on execution mode
*/
- isItOnDetail(key: string, forceAsync?: boolean): Promise | SwitcherResult {
+ isItOnDetail(arg1?: string | boolean, arg2?: boolean): Promise | SwitcherResult {
this.detail(true);
- if (forceAsync) {
- return this.isItOn(key) as Promise;
+ // Handle case where first argument is forceAsync boolean
+ if (typeof arg1 === 'boolean') {
+ arg2 = arg1;
+ arg1 = undefined;
+ }
+
+ if (arg2) {
+ return this.isItOn(arg1) as Promise;
}
- return this.isItOn(key) as SwitcherResult;
+ return this.isItOn(arg1) as SwitcherResult;
}
/**
diff --git a/tests/deps.ts b/tests/deps.ts
index 03af5d6..d681351 100644
--- a/tests/deps.ts
+++ b/tests/deps.ts
@@ -10,7 +10,9 @@ export {
assertExists,
assertNotEquals,
assertGreater,
- assertArrayIncludes
+ assertArrayIncludes,
+ assertStrictEquals,
+ assertNotStrictEquals
} from 'jsr:@std/assert@1.0.16';
export { assertSpyCalls, spy } from 'jsr:@std/testing@1.0.16/mock';
export {
diff --git a/tests/playground/index.ts b/tests/playground/index.ts
index 2d88f43..b5158ff 100644
--- a/tests/playground/index.ts
+++ b/tests/playground/index.ts
@@ -25,7 +25,7 @@ async function setupSwitcher(local: boolean) {
}
/**
- * This code snippet is a minimal example of how to configure and use Switcher4Deno locally.
+ * This code snippet is a minimal example of how to configure and use switcher-client-deno (former: Switcher4Deno) locally.
* No remote API account is required.
*
* Snapshot is loaded from file at tests/playground/snapshot/local.json
@@ -61,11 +61,11 @@ const _testSimpleAPICall = async (local: boolean) => {
.then(() => console.log('Switcher checked'))
.catch(error => console.log(error));
- switcher = Client.getSwitcher();
+ switcher = Client.getSwitcher(SWITCHER_KEY);
setInterval(async () => {
const time = Date.now();
- const result = await switcher.detail().isItOn(SWITCHER_KEY);
+ const result = await switcher.detail().isItOn();
console.log(`- ${Date.now() - time} ms - ${JSON.stringify(result)}`);
}, 1000);
};
@@ -77,14 +77,14 @@ const _testThrottledAPICall = async () => {
await Client.checkSwitchers([SWITCHER_KEY]);
Client.subscribeNotifyError((error) => console.log(error));
- switcher = Client.getSwitcher();
- switcher.throttle(1000);
+ switcher = Client.getSwitcher(SWITCHER_KEY);
setInterval(async () => {
const time = Date.now();
const result = await switcher
+ .throttle(1000)
.detail()
- .isItOn(SWITCHER_KEY);
+ .isItOn();
console.log(`- ${Date.now() - time} ms - ${JSON.stringify(result)}`);
}, 1000);
@@ -100,14 +100,14 @@ const _testSnapshotUpdate = async () => {
console.log('checkSnapshot:', await Client.checkSnapshot());
};
-// Does not require remote API
+// Requires remote API
const _testAsyncCall = async () => {
- setupSwitcher(true);
- switcher = Client.getSwitcher();
+ setupSwitcher(false);
+ switcher = Client.getSwitcher(SWITCHER_KEY);
- console.log("Sync:", await switcher.isItOn(SWITCHER_KEY));
+ console.log("Sync:", await switcher.isItOn());
- (switcher.isItOn(SWITCHER_KEY) as Promise)
+ (switcher.isItOn() as Promise)
.then(res => console.log('Promise result:', res))
.catch(error => console.log(error));
};
@@ -115,17 +115,17 @@ const _testAsyncCall = async () => {
// Does not require remote API
const _testBypasser = async () => {
setupSwitcher(true);
- switcher = Client.getSwitcher();
+ switcher = Client.getSwitcher(SWITCHER_KEY);
- let result = await switcher.isItOn(SWITCHER_KEY);
+ let result = await switcher.isItOn();
console.log(result);
Client.assume(SWITCHER_KEY).true();
- result = await switcher.isItOn(SWITCHER_KEY);
+ result = await switcher.isItOn();
console.log(result);
Client.forget(SWITCHER_KEY);
- result = await switcher.isItOn(SWITCHER_KEY);
+ result = await switcher.isItOn();
console.log(result);
Client.unloadSnapshot();
@@ -149,7 +149,7 @@ const _testWatchSnapshot = async () => {
setInterval(() => {
const time = Date.now();
- const result = switcher.isItOn(SWITCHER_KEY);
+ const result = switcher.isItOn();
console.log(`- ${Date.now() - time} ms - ${JSON.stringify(result)}`);
}, 1000);
@@ -166,13 +166,13 @@ const _testWatchSnapshotContextOptions = async () => {
await Client.loadSnapshot();
- const switcher = Client.getSwitcher();
+ const switcher = Client.getSwitcher(SWITCHER_KEY);
setInterval(async () => {
const time = Date.now();
const result = await switcher
.detail()
- .isItOn(SWITCHER_KEY);
+ .isItOn();
console.log(`- ${Date.now() - time} ms - ${JSON.stringify(result)}`);
}, 1000);
@@ -184,7 +184,7 @@ const _testSnapshotAutoUpdate = async () => {
{ local: true, logger: true });
await Client.loadSnapshot({ fetchRemote: true });
- const switcher = Client.getSwitcher();
+ const switcher = Client.getSwitcher(SWITCHER_KEY);
Client.scheduleSnapshotAutoUpdate(3, {
success: (updated) => console.log('In-memory snapshot updated', updated),
@@ -193,7 +193,7 @@ const _testSnapshotAutoUpdate = async () => {
setInterval(async () => {
const time = Date.now();
- await switcher.isItOn(SWITCHER_KEY);
+ await switcher.isItOn();
console.clear();
console.log(JSON.stringify(Client.getLogger(SWITCHER_KEY)), `executed in ${Date.now() - time}ms`);
}, 2000);
diff --git a/tests/switcher-client.test.ts b/tests/switcher-client.test.ts
index 7180512..b2ee7d7 100644
--- a/tests/switcher-client.test.ts
+++ b/tests/switcher-client.test.ts
@@ -43,13 +43,14 @@ describe('E2E test - Client local #1:', function () {
await switcher
.checkValue('Japan')
.checkNetwork('10.0.0.3')
- .prepare();
+ .prepare('FF2FOR2020');
- assertTrue(await switcher.isItOn('FF2FOR2020') === true);
- assertTrue(switcher.isItOnBool('FF2FOR2020') === true);
- assertTrue(await switcher.isItOnBool('FF2FOR2020', true) === true);
- assertTrue(switcher.isItOnDetail('FF2FOR2020').result === true);
- assertTrue((await switcher.isItOnDetail('FF2FOR2020', true)).result === true);
+ assertTrue(switcher.isItOn() === true);
+ assertTrue(await switcher.isItOn() === true);
+ assertTrue(switcher.isItOnBool() === true);
+ assertTrue(await switcher.isItOnBool(true) === true);
+ assertTrue(switcher.isItOnDetail().result === true);
+ assertTrue((await switcher.isItOnDetail(true)).result === true);
});
it('should get execution from logger', async function () {
diff --git a/tests/switcher-functional.test.ts b/tests/switcher-functional.test.ts
index 2ca1ba9..ef4c93f 100644
--- a/tests/switcher-functional.test.ts
+++ b/tests/switcher-functional.test.ts
@@ -1,6 +1,6 @@
import { describe, it, afterAll, afterEach, beforeEach,
assertEquals, assertRejects, assertThrows, assertFalse,
- assertSpyCalls, spy } from './deps.ts';
+ assertSpyCalls, assertStrictEquals, assertNotStrictEquals, spy } from './deps.ts';
import { given, givenError, tearDown, assertTrue, generateAuth, generateResult, generateDetailedResult, sleep } from './helper/utils.ts'
import { Client, type SwitcherResult, type SwitcherContext } from '../mod.ts';
@@ -52,6 +52,25 @@ describe('Integrated test - Client:', function () {
assertTrue(await switcher.isItOn());
});
+ it('should be valid - using persisted switcher key', async function () {
+ // given API responses
+ given('POST@/criteria/auth', generateAuth('[auth_token]', 5));
+ given('POST@/criteria', generateResult(true));
+
+ // test
+ Client.buildContext(contextSettings);
+
+ // Get switcher multiple times with the same key
+ const switcher1 = Client.getSwitcher('MY_PERSISTED_SWITCHER_KEY');
+ const switcher2 = Client.getSwitcher('MY_PERSISTED_SWITCHER_KEY');
+ const differentSwitcher = Client.getSwitcher('DIFFERENT_KEY');
+
+ // Verify they are the same instance (persisted)
+ assertStrictEquals(switcher1, switcher2, 'Switcher instances should be the same (persisted)');
+ assertNotStrictEquals(switcher1, differentSwitcher, 'Different keys should create different instances');
+ assertTrue(await switcher1.isItOn());
+ });
+
it('should NOT throw error when default result is provided using remote', async function () {
// given API responses
given('POST@/criteria/auth', generateAuth('[auth_token]', 5));
From 05ea3b26390959d69e0c16bf85eb7d3a4b3409b7 Mon Sep 17 00:00:00 2001
From: petruki <31597636+petruki@users.noreply.github.com>
Date: Thu, 8 Jan 2026 11:02:13 -0800
Subject: [PATCH 2/3] chore(docs): elaborated getSwitcher new persistent option
---
src/client.ts | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/client.ts b/src/client.ts
index 2d58565..043dc61 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -129,7 +129,9 @@ export class Client {
}
/**
- * Creates a new instance of Switcher
+ * Creates a new instance of Switcher.
+ *
+ * Provide a key if you want to persist the instance.
*/
static getSwitcher(key?: string): Switcher {
const keyValue = util.get(key, '');
From c77e3817d2490e781db75f4fb5acf59360f3eedb Mon Sep 17 00:00:00 2001
From: petruki <31597636+petruki@users.noreply.github.com>
Date: Thu, 8 Jan 2026 11:06:31 -0800
Subject: [PATCH 3/3] chore: formatting issue
---
src/client.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/client.ts b/src/client.ts
index 043dc61..e93671e 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -130,7 +130,7 @@ export class Client {
/**
* Creates a new instance of Switcher.
- *
+ *
* Provide a key if you want to persist the instance.
*/
static getSwitcher(key?: string): Switcher {