{"id":13801502,"url":"https://github.com/switcherapi/switcher-client-deno","last_synced_at":"2026-05-17T19:04:28.906Z","repository":{"id":44423739,"uuid":"510123151","full_name":"switcherapi/switcher-client-deno","owner":"switcherapi","description":"[TS] Switcher Client - Deno SDK to work with Switcher API - Cloud-based Feature Flag ","archived":false,"fork":false,"pushed_at":"2024-04-13T23:08:35.000Z","size":221,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2024-04-14T12:04:10.651Z","etag":null,"topics":["deno","feature-flags","switcher-api","typescript"],"latest_commit_sha":null,"homepage":"https://deno.land/x/switcher4deno","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/switcherapi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-07-03T19:59:35.000Z","updated_at":"2024-05-15T05:00:55.363Z","dependencies_parsed_at":"2023-12-13T05:23:33.199Z","dependency_job_id":"469db4a9-5229-49f8-8d51-f5fc5435fdc6","html_url":"https://github.com/switcherapi/switcher-client-deno","commit_stats":{"total_commits":29,"total_committers":1,"mean_commits":29.0,"dds":0.0,"last_synced_commit":"5db3f0bf5d1d94e72fe5897f235fd0e59b665a2c"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/switcherapi%2Fswitcher-client-deno","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/switcherapi%2Fswitcher-client-deno/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/switcherapi%2Fswitcher-client-deno/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/switcherapi%2Fswitcher-client-deno/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/switcherapi","download_url":"https://codeload.github.com/switcherapi/switcher-client-deno/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246395573,"owners_count":20770240,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deno","feature-flags","switcher-api","typescript"],"created_at":"2024-08-04T00:01:23.557Z","updated_at":"2026-05-17T19:04:28.893Z","avatar_url":"https://github.com/switcherapi.png","language":"TypeScript","funding_links":[],"categories":["Modules"],"sub_categories":["Utils"],"readme":"\u003cdiv align=\"center\"\u003e\n\u003cb\u003eSwitcher Client Deno SDK\u003c/b\u003e\u003cbr\u003e\nA Deno SDK for Switcher API\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![Master CI](https://github.com/switcherapi/switcher-client-deno/actions/workflows/master.yml/badge.svg)](https://github.com/switcherapi/switcher-client-deno/actions/workflows/master.yml)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=switcherapi_switcher-client-deno\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=switcherapi_switcher-client-deno)\n[![deno.land/x/switcher4deno](https://shield.deno.dev/x/switcher4deno)](https://deno.land/x/switcher4deno)\n[![JSR](https://jsr.io/badges/@switcherapi/switcher-client-deno)](https://jsr.io/@switcherapi/switcher-client-deno)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Slack: Switcher-HQ](https://img.shields.io/badge/slack-@switcher/hq-blue.svg?logo=slack)](https://switcher-hq.slack.com/)\n\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/switcherapi/switcherapi-assets/blob/master/logo/switcherapi_denoclient_transparency_1280.png\" alt=\"Switcher API: Deno Client\" /\u003e\n\u003c/div\u003e\n\n## Table of Contents\n\n- [About](#-about)\n  - [Key Features](#-key-features)\n- [Quick Start](#-quick-start)\n  - [Prerequisites](#prerequisites)\n  - [Installation](#installation)\n  - [Basic Setup](#basic-setup)\n- [Configuration](#️-configuration)\n  - [Context Parameters](#context-parameters)\n  - [Advanced Options](#advanced-options)\n  - [Options Reference](#options-reference)\n- [Usage Examples](#-usage-examples)\n  - [Basic Feature Flag Check](#basic-feature-flag-check)\n  - [Strategy Validation with Input Preparation](#strategy-validation-with-input-preparation)\n  - [All-in-One Execution](#all-in-one-execution)\n  - [Performance Optimization with Throttling](#performance-optimization-with-throttling)\n  - [Hybrid Mode - Force Remote Resolution](#hybrid-mode---force-remote-resolution)\n  - [Flush Cached Executions for a Switcher](#flush-cached-executions-for-a-switcher)\n  - [Circuit Breaker](#circuit-breaker-silent-mode)\n- [Testing \u0026 Development](#-testing--development)\n  - [Built-in Stub Feature](#built-in-stub-feature)\n  - [Test Mode](#test-mode)\n  - [Smoke Testing](#smoke-testing)\n- [Snapshot Management](#-snapshot-management)\n  - [Loading Snapshots](#loading-snapshots)\n  - [Real-time Snapshot Monitoring](#real-time-snapshot-monitoring)\n  - [Snapshot Version Checking](#snapshot-version-checking)\n  - [Automatic Snapshot Updates](#automatic-snapshot-updates)\n\n## About\n\n**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.\n\n### Key Features\n\n- 🚀 **Zero Latency**: Local mode with snapshot files or in-memory for instant feature flag resolution\n- 🔄 **Hybrid Configuration**: Silent mode with automatic fallback handling\n- 🧪 **Testing Ready**: Built-in stub implementation for comprehensive testing\n- ⚡ **Performance Optimized**: Throttling optimizes remote API calls to reduce bottlenecks in critical code paths\n- 🛠️ **Developer Tools**: Runtime snapshot updates without app restart and automatic sync with remote API\n\n## Quick Start\n\n### Prerequisites\n\n- **Deno**: Version 1.4x, 2.x or above\n- **Permissions**:\n\n| Permission | Required For |\n|------------|--------------|\n| `--allow-read` | Reading snapshot files and SSL certificates |\n| `--allow-write` | Writing snapshot files (if enabled) |\n| `--allow-net` | Communicating with the Switcher API |\n| `--allow-env` | Accessing environment variables for configuration |\n| `--unstable-http` | Required for custom SSL certificates in Deno v1.4x (see [Advanced Options](#advanced-options)) |\n\n### Installation\n\n```ts\n// Via JSR (Recommended)\nimport { Client } from \"@switcherapi/switcher-client-deno@[VERSION]\";\n\n// Via deno.land\nimport { Client } from 'https://deno.land/x/switcher4deno@v[VERSION]/mod.ts';\n```\n\n### Basic Setup\n\n```ts\nimport { Client } from \"@switcherapi/switcher-client-deno\";\n\n// 1. Initialize the client\nClient.buildContext({\n  url: 'https://api.switcherapi.com',\n  apiKey: '[YOUR_API_KEY]',\n  domain: 'My Domain',\n  component: 'MyApp',\n  environment: 'default'\n});\n\n// 2. Get a switcher instance\nconst switcher = Client.getSwitcher('FEATURE01');\n\n// 3. Check if a feature is enabled\nconst isEnabled = await switcher.isItOn();\nconsole.log('Feature enabled:', isEnabled);\n```\n\n## Configuration\n### Context Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `domain` | string | ✅ | Your Switcher domain name |\n| `url` | string | | Switcher API endpoint |\n| `apiKey` | string | | API key for your component |\n| `component` | string | | Your application name |\n| `environment` | string | | Environment name (default: 'default' for production) |\n\n### Advanced Options\n\nConfigure additional features for enhanced functionality:\n\n```ts\nClient.buildContext({ \n  url, apiKey, domain, component, environment \n}, {\n  local: true,                          // Enable local mode\n  freeze: false,                        // Prevent background updates\n  logger: true,                         // Enable request logging\n  snapshotLocation: './snapshot/',      // Snapshot files directory\n  snapshotAutoUpdateInterval: 30,       // Auto-update interval (seconds)\n  snapshotWatcher: true,                // Monitor snapshot changes\n  silentMode: '5m',                     // Fallback timeout\n  restrictRelay: true,                  // Relay restrictions in local mode\n  regexSafe: true,                      // Prevent reDOS attacks\n  certPath: './certs/ca.pem',           // SSL certificate path\n  remoteTimeout: 2000                   // Remote Criteria API timeout (milliseconds)\n});\n```\n\n#### Options Reference\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `local` | boolean | Use only snapshot files/in-memory (no API calls) |\n| `freeze` | boolean | Disable background cache updates with throttling |\n| `logger` | boolean | Enable logging for debugging (`Client.getLogger('KEY')`) |\n| `snapshotLocation` | string | Directory for snapshot files |\n| `snapshotAutoUpdateInterval` | number | Auto-update interval in seconds (0 = disabled) |\n| `snapshotWatcher` | boolean | Watch for snapshot file changes |\n| `silentMode` | string | Fallback timeout (e.g., '5s', '2m', '1h') |\n| `restrictRelay` | boolean | Enable relay restrictions in local mode |\n| `regexSafe` | boolean | Protection against reDOS attacks |\n| `regexMaxBlackList` | number | Max cached regex failures |\n| `regexMaxTimeLimit` | number | Regex timeout in milliseconds |\n| `certPath` | string | Path to SSL certificate file |\n| `remoteTimeout` | number | Remote Criteria API timeout in milliseconds |\n\n\u003e **⚠️ Note on regexSafe**: This feature protects against reDOS attacks but uses Web Workers, which are incompatible with compiled executables.\n\n## Usage Examples\n\n### Basic Feature Flag Check\n\nSimple on/off checks for feature flags:\n\n```ts\n// Non-persisted switcher instance\nconst switcher = Client.getSwitcher();\n// Persisted switcher instance\nconst switcher = Client.getSwitcher('FEATURE01');\n\n// 🚀 Synchronous (local mode only)\nconst isEnabled = switcher.isItOn();              // Returns: boolean\nconst isEnabledBool = switcher.isItOnBool();      // Returns: boolean\nconst detailResult = switcher.detail().isItOn();  // Returns: { result, reason, metadata }\nconst detailDirect = switcher.isItOnDetail();     // Returns: { result, reason, metadata }\n\n// 🌐 Asynchronous (remote/hybrid mode)\nconst isEnabledAsync = await switcher.isItOn();               // Returns: Promise\u003cboolean\u003e\nconst isEnabledBoolAsync = await switcher.isItOnBool(true);   // Returns: Promise\u003cboolean\u003e\nconst detailResultAsync = await switcher.detail().isItOn();   // Returns: Promise\u003cSwitcherResult\u003e\nconst detailDirectAsync = await switcher.isItOnDetail(true);  // Returns: Promise\u003cSwitcherResult\u003e\n```\n\n### Strategy Validation with Input Preparation\n\nPrepare context data before evaluation:\n\n```ts\n// Prepare input in advance\nawait switcher.checkValue('USER_1').prepare('FEATURE01');\nconst result = await switcher.isItOn();\n\n// Or chain preparations\nawait switcher\n  .checkValue('premium_user')\n  .checkNetwork('192.168.1.0/24')\n  .prepare('ADVANCED_FEATURE');\n```\n\n### All-in-One Execution\n\nComplex feature flag evaluation with multiple strategies:\n\n```ts\nconst result = await switcher\n  .defaultResult(true)          // Fallback value if API fails\n  .throttle(1000)               // Cache result for 1 second\n  .checkValue('User 1')         // VALUE strategy\n  .checkNetwork('192.168.0.1')  // NETWORK strategy\n  .isItOn('FEATURE01');\n```\n\n### Performance Optimization with Throttling\n\nReduce API calls for high-frequency checks:\n\n```ts\nconst switcher = Client.getSwitcher();\n\n// Cache result for 1 second\nconst result = await switcher\n  .throttle(1000)\n  .isItOn('FEATURE01');\n\n// Handle throttling errors\nClient.subscribeNotifyError((error) =\u003e {\n  console.error('Switcher error:', error);\n});\n```\n\n### Hybrid Mode - Force Remote Resolution\n\nOverride local mode for specific switchers:\n\n```ts\n// Force remote resolution even in local mode\nconst result = await switcher\n  .remote()\n  .isItOn('CRITICAL_FEATURE');\n```\n\nThis is useful for:\n- Relay strategies requiring remote calls\n- Critical features that must be resolved remotely\n- Real-time configuration updates\n\n### Flush Cached Executions for a Switcher\n\nWhen using throttling, you can clear cached results for a specific switcher:\n\n```ts\n// Clear cached results for a specific switcher\nClient.getSwitcher('FEATURE01').flushExecutions();\n```\n\n### Circuit Breaker: Silent Mode\n\nThis feature allows you to specify how long the client SDK should attempt to restore connectivity in case of remote API failures.\n\nWhen the API is unavailable, the SDK will automatically operate in silent mode, evaluating Switchers using a local snapshot. It is important to note that any Switcher Key configured must be able to resolve without external dependencies (e.g., Switcher Relay).\n\nMake sure to configure the scheduled snapshot auto-update to keep the local snapshot up to date with the remote API. \n\nHere is an example - in-memory snapshot with auto-update every 30 seconds:\n\n```ts\nClient.buildContext({ \n  url, apiKey, domain, component, environment \n}, {\n  snapshotAutoUpdateInterval: 30,\n  silentMode: '5m',\n});\n```\n\n## Testing \u0026 Development\n\n### Built-in Stub Feature\n\nMock feature flag responses for comprehensive testing:\n\n```ts\n// Simple true/false mocking\nClient.assume('FEATURE01').true();\nconsole.log(switcher.isItOn('FEATURE01')); // Always returns true\n\nClient.assume('FEATURE01').false();\nconsole.log(switcher.isItOn('FEATURE01')); // Always returns false\n\n// Reset to normal behavior\nClient.forget('FEATURE01');\n\n// Mock with metadata (simulating Relay responses)\nClient.assume('FEATURE01')\n  .false()\n  .withMetadata({ message: 'Feature disabled for maintenance' });\n\nconst response = await switcher.detail().isItOn('FEATURE01') as SwitcherResult;\nconsole.log(response.result);           // false\nconsole.log(response.metadata.message); // 'Feature disabled for maintenance'\n\n// Conditional mocking based on input\nClient.assume('FEATURE01').true().when(StrategiesType.VALUE, 'premium_user');\nconsole.log(switcher.checkValue('premium_user').isItOn('FEATURE01')); // true\nconsole.log(switcher.checkValue('basic_user').isItOn('FEATURE01'));   // false\n\n// Mock with multiple values\nClient.assume('FEATURE01').true().when(StrategiesType.NETWORK, ['192.168.1.1', '10.0.0.1']);\n```\n\n### Test Mode\n\nEnable test mode to prevent file locking during automated testing:\n\n```ts\n// In your test setup\nClient.testMode();\n```\n\n### Smoke Testing\n\nValidate feature flag during startup to catch configuration issues early:\n\n```ts\ntry {\n  await Client.checkSwitchers(['FEATURE01', 'FEATURE02', 'CRITICAL_FEATURE']);\n  console.log('✅ All switchers configured correctly');\n} catch (error) {\n  console.error('❌ Configuration issues found:', error.message);\n  process.exit(1);\n}\n```\n\n## Snapshot Management\n\nSnapshots enable zero-latency local mode by caching your feature flag configuration.\n\n### Loading Snapshots\n\n```ts\n// Load snapshot from API\nconst version = await Client.loadSnapshot();\nconsole.log('Loaded snapshot version:', version);\n```\n\n### Real-time Snapshot Monitoring\n\n#### Option 1: Programmatic Watching\n\n```ts\nClient.watchSnapshot({\n  success: () =\u003e console.log('✅ Snapshot updated successfully'),\n  reject: (err: Error) =\u003e console.error('❌ Snapshot update failed:', err)\n});\n```\n\n#### Option 2: Configuration-based Watching\n\n```ts\nClient.buildContext({ domain, component, environment }, {\n  local: true,\n  snapshotLocation: './snapshot/',\n  snapshotWatcher: true  // Enable automatic monitoring\n});\n```\n\n### Snapshot Version Checking\n\nVerify snapshot currency for external management:\n\n```ts\nconst isLatest = Client.checkSnapshot();\nconsole.log('Snapshot is up to date:', isLatest);\n```\n\n### Automatic Snapshot Updates\n\nSchedule periodic updates for local mode with automatic refresh:\n\n```ts\n// Update every 3 seconds\nClient.scheduleSnapshotAutoUpdate(3, {\n    success: (updated) =\u003e console.log('Snapshot updated', updated),\n    reject: (err: Error) =\u003e console.log(err)\n});\n```\n\n# AI Disclaimer\n\nThis project's core foundation was built and maintained by a human from day one. However, we have leveraged AI tools to assist in various aspects of the development process, such as troubleshooting, code optimization, and documentation. We have thoroughly reviewed and tested all AI-generated contributions to ensure they meet our quality standards and align with our project's goals. We are committed to transparency about our use of AI and will continue to disclose any significant AI contributions in the future. \n\nExternal contributions from the community are **equally valued and will be reviewed with the same standards, regardless of whether they were assisted by AI or not**. We encourage all contributors to disclose their use of AI tools in their contributions to maintain transparency and foster trust within our community.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswitcherapi%2Fswitcher-client-deno","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswitcherapi%2Fswitcher-client-deno","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswitcherapi%2Fswitcher-client-deno/lists"}