@flipflag/sdk 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 FlipFlag
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # FlipFlag SDK
2
+
3
+ A lightweight client-side SDK for working with **FlipFlag**.
4
+ It allows you to:
5
+
6
+ - Declare features programmatically
7
+ - Auto-create features on the server
8
+ - Check whether a feature is enabled
9
+ - Periodically sync feature states
10
+ - Manage feature definitions (options + metadata)
11
+
12
+ The SDK includes full TypeScript types and a Jest test suite.
13
+
14
+ ---
15
+
16
+ ## Installation
17
+
18
+ ```sh
19
+ npm install @flipflag/sdk
20
+ # or
21
+ yarn add @flipflag/sdk
22
+ ```
23
+
24
+ ---
25
+
26
+ ## Usage
27
+
28
+ ### Initialize the manager
29
+
30
+ ```ts
31
+ import { FlipFlag } from '@flipflag/sdk';
32
+
33
+ const manager = new FlipFlag({
34
+ publicKey: 'YOUR_PUBLIC_KEY',
35
+ privateKey: 'YOUR_PRIVATE_KEY', // optional for read-only mode
36
+ });
37
+
38
+ await manager.init();
39
+ ```
40
+
41
+ ### Declare a feature
42
+
43
+ ```ts
44
+ manager.declareFeature('newFeature', {
45
+ times: [
46
+ {
47
+ start: new Date(),
48
+ },
49
+ ],
50
+ });
51
+ ```
52
+
53
+ If the feature does not exist on the server and you provided a `privateKey`,
54
+ the SDK will automatically create it.
55
+
56
+ ### Check if a feature is enabled
57
+
58
+ ```ts
59
+ if (manager.isEnabled('newFeature')) {
60
+ console.log('Feature is enabled!');
61
+ }
62
+ ```
63
+
64
+ If the feature has not been declared yet, a placeholder is created automatically
65
+ and `false` is returned.
66
+
67
+ ---
68
+
69
+ ## Automatic Syncing
70
+
71
+ After calling `init()`, the manager:
72
+
73
+ - Loads all features using your `publicKey`
74
+ - Starts a **10-second interval** that refreshes feature states
75
+ - Keeps local cache in `declaredFeatures`
76
+
77
+ To stop syncing:
78
+
79
+ ```ts
80
+ manager.destroy();
81
+ ```
82
+
83
+ This clears the interval and resets the cache.
84
+
85
+ ---
86
+
87
+ ## TypeScript Types
88
+
89
+ ```ts
90
+ export interface IManagerOptions {
91
+ apiUrl?: string;
92
+ publicKey: string;
93
+ privateKey?: string;
94
+ }
95
+
96
+ export interface IDeclareFeatureTime {
97
+ start: Date;
98
+ end?: Date;
99
+ }
100
+
101
+ export interface IDeclareFeatureOptions {
102
+ times: IDeclareFeatureTime[];
103
+ }
104
+
105
+ export interface IFeatureFlag {
106
+ enabled: boolean;
107
+ }
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Running Tests
113
+
114
+ This SDK comes with full Jest test coverage, including:
115
+
116
+ - Mocked `fetch` requests
117
+ - Interval polling behavior
118
+ - Feature creation
119
+ - Error handling
120
+ - Local cache logic
121
+
122
+ ---
123
+
124
+ ## Example: Full Integration
125
+
126
+ ```ts
127
+ import { FlipFlag } from '@flipflag/sdk';
128
+
129
+ async function main() {
130
+ const manager = new FlipFlag({
131
+ publicKey: 'pk_live_123',
132
+ privateKey: 'sk_live_123',
133
+ });
134
+
135
+ await manager.init();
136
+
137
+ manager.declareFeature('demoFeature', {
138
+ times: [
139
+ { start: new Date() },
140
+ ],
141
+ });
142
+
143
+ if (manager.isEnabled('demoFeature')) {
144
+ console.log('Demo feature is active!');
145
+ }
146
+ }
147
+
148
+ main();
149
+ ```
150
+
151
+ ---
152
+
153
+ ## License
154
+
155
+ MIT License.
@@ -0,0 +1 @@
1
+ export { FlipFlag } from './provider.js';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import{FlipFlag as p}from"./provider.js";export{p as FlipFlag};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ class r{constructor(e){this.opts=e,this.inited=!1,this.interval=null,this.featuresTimes={},this.featuresFlags={},this.featuresUsage=[],this.options={apiUrl:"https://api.flipflag.dev",...e},this.interval=null}async init(){await this.getFeaturesFlags(),this.interval=setInterval(()=>{this.getFeaturesFlags(),this.syncFeaturesTimes(),this.syncFeaturesUsage()},1e4),this.inited=!0}destroy(){this.inited=!1,this.interval&&clearInterval(this.interval),this.featuresTimes={},this.featuresFlags={},this.featuresUsage=[]}declareFeature(e,t){this.featuresTimes[e]=t}isEnabled(e){const t=this.getLocalFeatureFlag(e);return t?(this.upsertFeaturesUsage(e),t.enabled):(this.createFeature(e,{times:[]}),!1)}upsertFeaturesUsage(e){const t=this.featuresUsage.find(s=>s.featureName===e);if(t){t.usedAt=new Date;return}this.featuresUsage.push({featureName:e,usedAt:new Date})}async createFeature(e,t){if(!this.options.privateKey)return null;const s=this.getBaseUrl(),i=new URL("/v1/sdk/feature",s);fetch(i.toString(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({featureName:e,privateKey:this.options.privateKey,...t})}).catch(a=>{console.error("Create Feature:",a)})}getBaseUrl(){if(this.options.apiUrl)return this.options.apiUrl.replace(/\/+$/,"");throw new Error("Base API URL is not configured. Please provide apiUrl in the SDK options.")}async getFeaturesFlags(){if(!this.options.publicKey)throw new Error("Public key is missing. Please provide a valid publicKey in the SDK configuration.");try{const e=this.getBaseUrl(),t=new URL("/v1/sdk/feature/flags",e);t.searchParams.append("publicKey",this.options.publicKey);const s=await fetch(t.toString(),{method:"GET",headers:{"Content-Type":"application/json"}});if(!s.ok&&!this.inited){const i=await s.text();throw new Error(`Failed to get features: ${s.status} - ${i}`)}this.featuresFlags=await s.json()}catch(e){console.error("Get list features flag:",e)}}async syncFeaturesTimes(){if(!this.options.privateKey)return null;Object.entries(this.featuresTimes).forEach(([t,s])=>{this.createFeature(t,s)})}async syncFeaturesUsage(){if(!this.options.publicKey)throw new Error("Public key is missing. Please provide a valid publicKey in the SDK configuration.");const e=this.getBaseUrl(),t=new URL("/v1/sdk/feature/usages",e);fetch(t.toString(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({publicKey:this.options.publicKey,usages:this.featuresUsage})}).catch(s=>{console.error("Feature Usage Sync:",s)})}getLocalFeatureFlag(e){return this.featuresFlags[e]}}export{r as FlipFlag};
@@ -0,0 +1,116 @@
1
+ import { IManagerOptions, IDeclareFeatureOptions } from './types/provider.js';
2
+
3
+ /**
4
+ * Manager for interacting with FlipFlag.
5
+ * Handles feature declaration, loading remote states, and periodic syncing.
6
+ */
7
+ declare class FlipFlag {
8
+ protected readonly opts: IManagerOptions;
9
+ /** Indicates whether initialization has completed */
10
+ private inited;
11
+ /** Interval handler for periodic feature refreshing */
12
+ private interval;
13
+ /** Options passed to the manager (merged with defaults) */
14
+ private options;
15
+ /**
16
+ * Local cache of declared features times.
17
+ * Keyed by feature name.
18
+ */
19
+ private featuresTimes;
20
+ /**
21
+ * Local cache of declared features flags and their metadata.
22
+ * Keyed by feature name.
23
+ */
24
+ private featuresFlags;
25
+ /**
26
+ * Local cache of feature-flag usage events.
27
+ * Each entry represents an interaction with a specific feature flag
28
+ * (read, update, check) along with related metadata.
29
+ */
30
+ private featuresUsage;
31
+ /**
32
+ * @param opts Manager configuration (publicKey, privateKey, apiUrl, etc.)
33
+ */
34
+ constructor(opts: IManagerOptions);
35
+ /**
36
+ * Initializes the manager:
37
+ * - Loads the initial feature flags from the server
38
+ * - Starts a 10-second polling loop to:
39
+ * • refresh feature flags
40
+ * • synchronize feature activation times
41
+ */
42
+ init(): Promise<void>;
43
+ /**
44
+ * Destroys the manager:
45
+ * - Stops the periodic sync
46
+ * - Clears all locally declared features
47
+ */
48
+ destroy(): void;
49
+ /**
50
+ * Declares a feature locally.
51
+ * If the feature has not been loaded or created yet, it triggers creation.
52
+ *
53
+ * @param featureName Name of the feature
54
+ * @param options Declaration settings (e.g., times)
55
+ */
56
+ declareFeature(featureName: string, options: IDeclareFeatureOptions): void;
57
+ /**
58
+ * Checks whether a feature is enabled.
59
+ * If the feature does not exist locally, it will be created with empty options.
60
+ *
61
+ * @param featureName Name of the feature
62
+ * @returns `true` if enabled, otherwise `false`
63
+ */
64
+ isEnabled(featureName: string): boolean;
65
+ /**
66
+ * Updates or inserts a feature usage record.
67
+ * If the feature was already used before, its timestamp is updated.
68
+ * Otherwise, a new usage entry is created.
69
+ *
70
+ * @param featureName - Name of the feature that was checked/used
71
+ */
72
+ private upsertFeaturesUsage;
73
+ /**
74
+ * Creates a new feature on the server.
75
+ * Requires a privateKey; otherwise the request is ignored.
76
+ *
77
+ * @param featureName Name of the feature
78
+ * @param options Feature declaration options
79
+ * @returns Created feature data or null if privateKey is missing
80
+ */
81
+ private createFeature;
82
+ private getBaseUrl;
83
+ /**
84
+ * Fetches all features associated with the publicKey.
85
+ * Populates the local `featuresTimes` cache.
86
+ *
87
+ * Throws an error only during initial initialization;
88
+ * later polling failures are ignored.
89
+ */
90
+ private getFeaturesFlags;
91
+ /**
92
+ * Fetches all features associated with the publicKey.
93
+ * Populates the local `featuresTimes` cache.
94
+ *
95
+ * Throws an error only during initial initialization;
96
+ * later polling failures are ignored.
97
+ */
98
+ private syncFeaturesTimes;
99
+ /**
100
+ * Sends the collected feature usage data to the server.
101
+ * Requires a valid `publicKey` provided in the SDK configuration.
102
+ *
103
+ * Throws an error if the `publicKey` is missing;
104
+ * network or server errors during sync are not awaited or propagated.
105
+ */
106
+ private syncFeaturesUsage;
107
+ /**
108
+ * Returns a locally cached feature flag by name.
109
+ *
110
+ * @param featureName Name of the feature
111
+ * @returns The feature or undefined if it does not exist
112
+ */
113
+ private getLocalFeatureFlag;
114
+ }
115
+
116
+ export { FlipFlag };
@@ -0,0 +1,2 @@
1
+ class r{constructor(e){this.opts=e,this.inited=!1,this.interval=null,this.featuresTimes={},this.featuresFlags={},this.featuresUsage=[],this.options={apiUrl:"https://api.flipflag.dev",...e},this.interval=null}async init(){await this.getFeaturesFlags(),this.interval=setInterval(()=>{this.getFeaturesFlags(),this.syncFeaturesTimes(),this.syncFeaturesUsage()},1e4),this.inited=!0}destroy(){this.inited=!1,this.interval&&clearInterval(this.interval),this.featuresTimes={},this.featuresFlags={},this.featuresUsage=[]}declareFeature(e,t){this.featuresTimes[e]=t}isEnabled(e){const t=this.getLocalFeatureFlag(e);return t?(this.upsertFeaturesUsage(e),t.enabled):(this.createFeature(e,{times:[]}),!1)}upsertFeaturesUsage(e){const t=this.featuresUsage.find(s=>s.featureName===e);if(t){t.usedAt=new Date;return}this.featuresUsage.push({featureName:e,usedAt:new Date})}async createFeature(e,t){if(!this.options.privateKey)return null;const s=this.getBaseUrl(),i=new URL("/v1/sdk/feature",s);fetch(i.toString(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({featureName:e,privateKey:this.options.privateKey,...t})}).catch(a=>{console.error("Create Feature:",a)})}getBaseUrl(){if(this.options.apiUrl)return this.options.apiUrl.replace(/\/+$/,"");throw new Error("Base API URL is not configured. Please provide apiUrl in the SDK options.")}async getFeaturesFlags(){if(!this.options.publicKey)throw new Error("Public key is missing. Please provide a valid publicKey in the SDK configuration.");try{const e=this.getBaseUrl(),t=new URL("/v1/sdk/feature/flags",e);t.searchParams.append("publicKey",this.options.publicKey);const s=await fetch(t.toString(),{method:"GET",headers:{"Content-Type":"application/json"}});if(!s.ok&&!this.inited){const i=await s.text();throw new Error(`Failed to get features: ${s.status} - ${i}`)}this.featuresFlags=await s.json()}catch(e){console.error("Get list features flag:",e)}}async syncFeaturesTimes(){if(!this.options.privateKey)return null;Object.entries(this.featuresTimes).forEach(([e,t])=>{this.createFeature(e,t)})}async syncFeaturesUsage(){if(!this.options.publicKey)throw new Error("Public key is missing. Please provide a valid publicKey in the SDK configuration.");const e=this.getBaseUrl(),t=new URL("/v1/sdk/feature/usages",e);fetch(t.toString(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({publicKey:this.options.publicKey,usages:this.featuresUsage})}).catch(s=>{console.error("Feature Usage Sync:",s)})}getLocalFeatureFlag(e){return this.featuresFlags[e]}}export{r as FlipFlag};
2
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sources":["../src/provider.ts"],"sourcesContent":["import {\n IDeclareFeatureOptions,\n IFeatureFlag,\n IFeatureFlagUsage,\n IManagerOptions,\n} from './types/provider';\n\n/**\n * Manager for interacting with FlipFlag.\n * Handles feature declaration, loading remote states, and periodic syncing.\n */\nexport class FlipFlag {\n /** Indicates whether initialization has completed */\n private inited = false;\n /** Interval handler for periodic feature refreshing */\n private interval: NodeJS.Timeout | null = null;\n /** Options passed to the manager (merged with defaults) */\n private options: Partial<IManagerOptions>;\n /**\n * Local cache of declared features times.\n * Keyed by feature name.\n */\n private featuresTimes: Record<string, IDeclareFeatureOptions> = {};\n /**\n * Local cache of declared features flags and their metadata.\n * Keyed by feature name.\n */\n private featuresFlags: Record<string, IFeatureFlag> = {};\n /**\n * Local cache of feature-flag usage events.\n * Each entry represents an interaction with a specific feature flag\n * (read, update, check) along with related metadata.\n */\n private featuresUsage: IFeatureFlagUsage[] = [];\n\n /**\n * @param opts Manager configuration (publicKey, privateKey, apiUrl, etc.)\n */\n constructor(protected readonly opts: IManagerOptions) {\n this.options = { apiUrl: 'https://api.flipflag.dev', ...opts };\n this.interval = null;\n }\n\n /**\n * Initializes the manager:\n * - Loads the initial feature flags from the server\n * - Starts a 10-second polling loop to:\n * • refresh feature flags\n * • synchronize feature activation times\n */\n public async init() {\n await this.getFeaturesFlags();\n\n this.interval = setInterval(() => {\n this.getFeaturesFlags();\n this.syncFeaturesTimes();\n this.syncFeaturesUsage();\n }, 10_000);\n\n this.inited = true;\n }\n\n /**\n * Destroys the manager:\n * - Stops the periodic sync\n * - Clears all locally declared features\n */\n public destroy() {\n this.inited = false;\n if (this.interval) clearInterval(this.interval);\n this.featuresTimes = {};\n this.featuresFlags = {};\n this.featuresUsage = [];\n }\n\n /**\n * Declares a feature locally.\n * If the feature has not been loaded or created yet, it triggers creation.\n *\n * @param featureName Name of the feature\n * @param options Declaration settings (e.g., times)\n */\n declareFeature(featureName: string, options: IDeclareFeatureOptions) {\n this.featuresTimes[featureName] = options;\n }\n\n /**\n * Checks whether a feature is enabled.\n * If the feature does not exist locally, it will be created with empty options.\n *\n * @param featureName Name of the feature\n * @returns `true` if enabled, otherwise `false`\n */\n isEnabled(featureName: string) {\n const feature = this.getLocalFeatureFlag(featureName);\n\n if (!feature) {\n this.createFeature(featureName, { times: [] });\n\n return false;\n }\n\n this.upsertFeaturesUsage(featureName);\n\n return feature.enabled;\n }\n\n /**\n * Updates or inserts a feature usage record.\n * If the feature was already used before, its timestamp is updated.\n * Otherwise, a new usage entry is created.\n *\n * @param featureName - Name of the feature that was checked/used\n */\n private upsertFeaturesUsage(featureName: string) {\n const existing = this.featuresUsage.find(\n (u) => u.featureName === featureName\n );\n\n if (existing) {\n existing.usedAt = new Date();\n return;\n }\n\n this.featuresUsage.push({\n featureName,\n usedAt: new Date(),\n });\n }\n\n /**\n * Creates a new feature on the server.\n * Requires a privateKey; otherwise the request is ignored.\n *\n * @param featureName Name of the feature\n * @param options Feature declaration options\n * @returns Created feature data or null if privateKey is missing\n */\n private async createFeature(\n featureName: string,\n options: IDeclareFeatureOptions\n ) {\n if (!this.options.privateKey) {\n return null;\n }\n\n const baseUrl = this.getBaseUrl();\n const url = new URL('/v1/sdk/feature', baseUrl);\n\n fetch(url.toString(), {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n featureName,\n privateKey: this.options.privateKey,\n ...options,\n }),\n }).catch((error) => {\n console.error('Create Feature:', error);\n });\n }\n\n private getBaseUrl() {\n if (this.options.apiUrl) {\n return this.options.apiUrl.replace(/\\/+$/, '');\n }\n\n throw new Error(\n 'Base API URL is not configured. Please provide apiUrl in the SDK options.'\n );\n }\n\n /**\n * Fetches all features associated with the publicKey.\n * Populates the local `featuresTimes` cache.\n *\n * Throws an error only during initial initialization;\n * later polling failures are ignored.\n */\n private async getFeaturesFlags() {\n if (!this.options.publicKey) {\n throw new Error(\n 'Public key is missing. Please provide a valid publicKey in the SDK configuration.'\n );\n }\n\n try {\n const baseUrl = this.getBaseUrl();\n const url = new URL('/v1/sdk/feature/flags', baseUrl);\n url.searchParams.append('publicKey', this.options.publicKey);\n\n const response = await fetch(url.toString(), {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok && !this.inited) {\n const errorText = await response.text();\n throw new Error(\n `Failed to get features: ${response.status} - ${errorText}`\n );\n }\n\n this.featuresFlags = await response.json();\n } catch (error) {\n console.error('Get list features flag:', error);\n }\n }\n\n /**\n * Fetches all features associated with the publicKey.\n * Populates the local `featuresTimes` cache.\n *\n * Throws an error only during initial initialization;\n * later polling failures are ignored.\n */\n private async syncFeaturesTimes() {\n if (!this.options.privateKey) {\n return null;\n }\n\n const list = Object.entries(this.featuresTimes);\n list.forEach(([featureName, options]: [string, IDeclareFeatureOptions]) => {\n this.createFeature(featureName, options);\n });\n }\n\n /**\n * Sends the collected feature usage data to the server.\n * Requires a valid `publicKey` provided in the SDK configuration.\n *\n * Throws an error if the `publicKey` is missing;\n * network or server errors during sync are not awaited or propagated.\n */\n private async syncFeaturesUsage() {\n if (!this.options.publicKey) {\n throw new Error(\n 'Public key is missing. Please provide a valid publicKey in the SDK configuration.'\n );\n }\n\n const baseUrl = this.getBaseUrl();\n const url = new URL('/v1/sdk/feature/usages', baseUrl);\n\n fetch(url.toString(), {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n publicKey: this.options.publicKey,\n usages: this.featuresUsage,\n }),\n }).catch((error) => {\n console.error('Feature Usage Sync:', error);\n });\n }\n\n /**\n * Returns a locally cached feature flag by name.\n *\n * @param featureName Name of the feature\n * @returns The feature or undefined if it does not exist\n */\n private getLocalFeatureFlag(featureName: string) {\n return this.featuresFlags[featureName];\n }\n}\n"],"names":["FlipFlag","opts","featureName","options","feature","existing","u","baseUrl","url","error","response","errorText"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ interface IManagerOptions {
2
+ apiUrl?: string;
3
+ publicKey: string;
4
+ privateKey?: string;
5
+ }
6
+ interface IDeclareFeatureTime {
7
+ email: string;
8
+ start: Date;
9
+ end?: Date;
10
+ }
11
+ interface IDeclareFeatureOptions {
12
+ times: IDeclareFeatureTime[];
13
+ }
14
+
15
+ export type { IDeclareFeatureOptions, IDeclareFeatureTime, IManagerOptions };
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@flipflag/sdk",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "types": "dist/index.d.ts",
6
+ "description": "A lightweight client-side SDK for working with FlipFlag",
7
+ "main": "dist/index.js",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "keywords": [
19
+ "FlipFlag",
20
+ "Feature Flags",
21
+ "Feature Toggle",
22
+ "Client SDK",
23
+ "Flag Management",
24
+ "Remote Config",
25
+ "Cloud",
26
+ "Integration",
27
+ "JavaScript",
28
+ "TypeScript",
29
+ "SDK"
30
+ ],
31
+ "scripts": {
32
+ "build": "rimraf dist && rollup -c rollup.config.js",
33
+ "typecheck": "tsc --noEmit",
34
+ "prettier:formatting": "npx prettier --write ./src",
35
+ "test": "jest"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/flipflag-dev/sdk.git"
40
+ },
41
+ "author": "Polevov Evgenii <epolevov@emd.one>",
42
+ "license": "MIT",
43
+ "bugs": {
44
+ "url": "https://github.com/flipflag-dev/sdk/issues"
45
+ },
46
+ "release": {
47
+ "branches": [
48
+ "main"
49
+ ],
50
+ "repositoryUrl": "https://github.com/flipflag-dev/sdk.git",
51
+ "plugins": [
52
+ "@semantic-release/commit-analyzer",
53
+ "@semantic-release/release-notes-generator",
54
+ "@semantic-release/npm",
55
+ [
56
+ "@semantic-release/git",
57
+ {
58
+ "message": "chore(release): ${nextRelease.version} \n\n${nextRelease.notes}"
59
+ }
60
+ ],
61
+ "@semantic-release/github"
62
+ ]
63
+ },
64
+ "publishConfig": {
65
+ "access": "public"
66
+ },
67
+ "overrides": {
68
+ "@semantic-release/npm": {
69
+ "npm": "11.6.2"
70
+ }
71
+ },
72
+ "homepage": "https://github.com/flipflag-dev/sdk.git#readme",
73
+ "devDependencies": {
74
+ "@jest/globals": "^30.2.0",
75
+ "@rollup/plugin-alias": "^6.0.0",
76
+ "@rollup/plugin-commonjs": "^29.0.0",
77
+ "@rollup/plugin-node-resolve": "^16.0.3",
78
+ "@semantic-release/commit-analyzer": "^13.0.1",
79
+ "@semantic-release/git": "^10.0.1",
80
+ "@semantic-release/github": "^12.0.2",
81
+ "@semantic-release/npm": "^13.1.2",
82
+ "@semantic-release/release-notes-generator": "^14.1.0",
83
+ "@types/jest": "^30.0.0",
84
+ "jest": "^30.2.0",
85
+ "rimraf": "^6.1.2",
86
+ "rollup": "^4.53.3",
87
+ "rollup-plugin-dts": "^6.2.3",
88
+ "rollup-plugin-esbuild": "^6.2.1",
89
+ "ts-jest": "^29.4.5"
90
+ }
91
+ }