@flipflag/sdk 1.3.0 → 1.4.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/dist/browser.d.ts +1 -1
- package/dist/browser.js +1 -1
- package/dist/browser.min.js +1 -1
- package/dist/{flipflag-core-v7AUprKd.d.ts → flipflag-core-3rbGd7Gt.d.ts} +8 -1
- package/dist/{flipflag-core-BNqlFhCW.js → flipflag-core-B6FA6FN1.js} +14 -5
- package/dist/flipflag-core-B6FA6FN1.js.map +1 -0
- package/dist/flipflag-core-BiEpOSVM.js +2 -0
- package/dist/flipflag-core-BiEpOSVM.js.map +1 -0
- package/dist/node.d.ts +1 -1
- package/dist/node.js +1 -1
- package/dist/node.min.js +1 -1
- package/package.json +1 -1
- package/dist/flipflag-core-BNqlFhCW.js.map +0 -1
- package/dist/flipflag-core-DHCsP2TB.js +0 -2
- package/dist/flipflag-core-DHCsP2TB.js.map +0 -1
package/dist/browser.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as FlipFlagCore, I as IManagerOptions, a as FlipFlagYaml } from './flipflag-core-
|
|
1
|
+
import { F as FlipFlagCore, I as IManagerOptions, a as FlipFlagYaml } from './flipflag-core-3rbGd7Gt.js';
|
|
2
2
|
|
|
3
3
|
declare class FlipFlag extends FlipFlagCore {
|
|
4
4
|
constructor(opts: IManagerOptions, initialConfig?: FlipFlagYaml);
|
package/dist/browser.js
CHANGED
package/dist/browser.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{F as s}from"./flipflag-core-
|
|
1
|
+
import{F as s}from"./flipflag-core-BiEpOSVM.js";class o extends s{constructor(e,r){super(e),r&&this.declareFromObject(r)}}export{o as FlipFlag};
|
|
2
2
|
//# sourceMappingURL=browser.min.js.map
|
|
@@ -17,6 +17,11 @@ interface IManagerOptions {
|
|
|
17
17
|
* Default: 30000 (30 seconds)
|
|
18
18
|
*/
|
|
19
19
|
pollingInterval?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Sync interval in milliseconds (for syncing times and usage).
|
|
22
|
+
* Default: 90000 (90 seconds)
|
|
23
|
+
*/
|
|
24
|
+
syncInterval?: number;
|
|
20
25
|
}
|
|
21
26
|
type YamlTime = {
|
|
22
27
|
started: string;
|
|
@@ -38,7 +43,8 @@ declare class FlipFlagCore {
|
|
|
38
43
|
protected readonly opts: IManagerOptions;
|
|
39
44
|
private readonly loader?;
|
|
40
45
|
private inited;
|
|
41
|
-
private
|
|
46
|
+
private pollingIntervalTimer;
|
|
47
|
+
private syncIntervalTimer;
|
|
42
48
|
protected options: Partial<IManagerOptions>;
|
|
43
49
|
private featuresTimes;
|
|
44
50
|
private featuresFlags;
|
|
@@ -48,6 +54,7 @@ declare class FlipFlagCore {
|
|
|
48
54
|
destroy(): void;
|
|
49
55
|
isEnabled(featureName: string): boolean;
|
|
50
56
|
declareFromObject(doc: FlipFlagYaml): void;
|
|
57
|
+
sync(): Promise<void>;
|
|
51
58
|
private applyYamlConfig;
|
|
52
59
|
private upsertFeaturesUsage;
|
|
53
60
|
private getBaseUrl;
|
|
@@ -3,13 +3,15 @@ class FlipFlagCore {
|
|
|
3
3
|
this.opts = opts;
|
|
4
4
|
this.loader = loader;
|
|
5
5
|
this.inited = false;
|
|
6
|
-
this.
|
|
6
|
+
this.pollingIntervalTimer = null;
|
|
7
|
+
this.syncIntervalTimer = null;
|
|
7
8
|
this.featuresTimes = {};
|
|
8
9
|
this.featuresFlags = {};
|
|
9
10
|
this.featuresUsage = [];
|
|
10
11
|
this.options = {
|
|
11
12
|
apiUrl: "https://api.flipflag.dev",
|
|
12
13
|
pollingInterval: 3e4,
|
|
14
|
+
syncInterval: 9e4,
|
|
13
15
|
...opts
|
|
14
16
|
};
|
|
15
17
|
}
|
|
@@ -20,16 +22,19 @@ class FlipFlagCore {
|
|
|
20
22
|
}
|
|
21
23
|
await this.getFeaturesFlags();
|
|
22
24
|
await this.syncFeaturesTimes();
|
|
23
|
-
this.
|
|
25
|
+
this.pollingIntervalTimer = setInterval(() => {
|
|
24
26
|
this.getFeaturesFlags();
|
|
27
|
+
}, this.options.pollingInterval);
|
|
28
|
+
this.syncIntervalTimer = setInterval(() => {
|
|
25
29
|
this.syncFeaturesTimes();
|
|
26
30
|
this.syncFeaturesUsage();
|
|
27
|
-
}, this.options.
|
|
31
|
+
}, this.options.syncInterval);
|
|
28
32
|
this.inited = true;
|
|
29
33
|
}
|
|
30
34
|
destroy() {
|
|
31
35
|
this.inited = false;
|
|
32
|
-
if (this.
|
|
36
|
+
if (this.pollingIntervalTimer) clearInterval(this.pollingIntervalTimer);
|
|
37
|
+
if (this.syncIntervalTimer) clearInterval(this.syncIntervalTimer);
|
|
33
38
|
this.featuresTimes = {};
|
|
34
39
|
this.featuresFlags = {};
|
|
35
40
|
this.featuresUsage = [];
|
|
@@ -46,6 +51,10 @@ class FlipFlagCore {
|
|
|
46
51
|
declareFromObject(doc) {
|
|
47
52
|
this.applyYamlConfig(doc);
|
|
48
53
|
}
|
|
54
|
+
async sync() {
|
|
55
|
+
await this.syncFeaturesTimes();
|
|
56
|
+
await this.syncFeaturesUsage();
|
|
57
|
+
}
|
|
49
58
|
applyYamlConfig(doc) {
|
|
50
59
|
var _a;
|
|
51
60
|
for (const [featureName, cfg] of Object.entries(doc)) {
|
|
@@ -149,4 +158,4 @@ class FlipFlagCore {
|
|
|
149
158
|
}
|
|
150
159
|
|
|
151
160
|
export { FlipFlagCore as F };
|
|
152
|
-
//# sourceMappingURL=flipflag-core-
|
|
161
|
+
//# sourceMappingURL=flipflag-core-B6FA6FN1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flipflag-core-B6FA6FN1.js","sources":["../src/core/flipflag-core.ts"],"sourcesContent":["import {\n FlipFlagYaml,\n IDeclareFeatureOptions,\n IDeclareFeatureTime,\n IFeatureFlag,\n IFeatureFlagUsage,\n IManagerOptions,\n} from \"../types/provider\";\nimport { ConfigLoader } from \"../platform/config-loader\";\n\nexport class FlipFlagCore {\n private inited = false;\n private pollingIntervalTimer: any = null;\n private syncIntervalTimer: any = null;\n\n protected options: Partial<IManagerOptions>;\n private featuresTimes: Record<string, IDeclareFeatureOptions> = {};\n private featuresFlags: Record<string, IFeatureFlag> = {};\n private featuresUsage: IFeatureFlagUsage[] = [];\n\n constructor(\n protected readonly opts: IManagerOptions,\n private readonly loader?: ConfigLoader,\n ) {\n this.options = {\n apiUrl: \"https://api.flipflag.dev\",\n pollingInterval: 30_000,\n syncInterval: 90_000,\n ...opts,\n };\n }\n\n public async init() {\n if (this.loader) {\n const yamlDoc = await this.loader.load();\n if (yamlDoc) this.applyYamlConfig(yamlDoc);\n }\n\n await this.getFeaturesFlags();\n await this.syncFeaturesTimes();\n\n this.pollingIntervalTimer = setInterval(() => {\n this.getFeaturesFlags();\n }, this.options.pollingInterval);\n\n this.syncIntervalTimer = setInterval(() => {\n this.syncFeaturesTimes();\n this.syncFeaturesUsage();\n }, this.options.syncInterval);\n\n this.inited = true;\n }\n\n public destroy() {\n this.inited = false;\n if (this.pollingIntervalTimer) clearInterval(this.pollingIntervalTimer);\n if (this.syncIntervalTimer) clearInterval(this.syncIntervalTimer);\n this.featuresTimes = {};\n this.featuresFlags = {};\n this.featuresUsage = [];\n }\n\n public isEnabled(featureName: string) {\n const feature = this.featuresFlags[featureName];\n if (!feature) {\n this.createFeature(featureName, { times: [] });\n return false;\n }\n this.upsertFeaturesUsage(featureName);\n return feature.enabled;\n }\n\n public declareFromObject(doc: FlipFlagYaml) {\n this.applyYamlConfig(doc);\n }\n\n public async sync() {\n await this.syncFeaturesTimes();\n await this.syncFeaturesUsage();\n }\n\n private applyYamlConfig(doc: FlipFlagYaml) {\n for (const [featureName, cfg] of Object.entries(doc)) {\n const times = (cfg?.times ?? []).map((t) => ({\n email: doc[featureName].contributor,\n start: t.started,\n end: t.finished ?? null,\n })) as IDeclareFeatureTime[];\n\n for (const t of times) {\n if (Number.isNaN(Date.parse(t.start))) {\n throw new Error(\n `FlipFlag: invalid \"started\" date in ${featureName}: ${t.start}`,\n );\n }\n if (t.end !== null && Number.isNaN(Date.parse(String(t.end)))) {\n throw new Error(\n `FlipFlag: invalid \"finished\" date in ${featureName}: ${t.end}`,\n );\n }\n }\n\n this.featuresTimes[featureName] = { times };\n }\n }\n\n private upsertFeaturesUsage(featureName: string) {\n const existing = this.featuresUsage.find(\n (u) => u.featureName === featureName,\n );\n if (existing) {\n existing.usedAt = new Date();\n return;\n }\n this.featuresUsage.push({ featureName, usedAt: new Date() });\n }\n\n private getBaseUrl() {\n if (this.options.apiUrl) return this.options.apiUrl.replace(/\\/+$/, \"\");\n throw new Error(\n \"Base API URL is not configured. Please provide apiUrl in the SDK options.\",\n );\n }\n\n private async createFeature(\n featureName: string,\n options: IDeclareFeatureOptions,\n ) {\n if (!this.options.privateKey) return null;\n\n const url = new URL(\"/v1/sdk/feature\", this.getBaseUrl());\n fetch(url.toString(), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n featureName,\n privateKey: this.options.privateKey,\n ...options,\n }),\n }).catch((e) => console.error(\"Create Feature:\", e));\n }\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 url = new URL(\"/v1/sdk/feature/flags\", this.getBaseUrl());\n url.searchParams.append(\"publicKey\", this.options.publicKey);\n\n const res = await fetch(url.toString(), {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" },\n });\n if (!res.ok && !this.inited) {\n const errorText = await res.text();\n throw new Error(`Failed to get features: ${res.status} - ${errorText}`);\n }\n\n this.featuresFlags = await res.json();\n } catch (e) {\n console.error(\"Get list features flag:\", e);\n }\n }\n\n private async syncFeaturesTimes() {\n if (!this.options.privateKey) return null;\n for (const [featureName, options] of Object.entries(this.featuresTimes)) {\n this.createFeature(featureName, options);\n }\n }\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 const url = new URL(\"/v1/sdk/feature/usages\", this.getBaseUrl());\n\n fetch(url.toString(), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n publicKey: this.options.publicKey,\n privateKey: this.options.privateKey,\n usages: this.featuresUsage,\n }),\n }).catch((e) => console.error(\"Feature Usage Sync:\", e));\n }\n}\n"],"names":["_a"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
class l{constructor(e,t){this.opts=e,this.loader=t,this.inited=!1,this.pollingIntervalTimer=null,this.syncIntervalTimer=null,this.featuresTimes={},this.featuresFlags={},this.featuresUsage=[],this.options={apiUrl:"https://api.flipflag.dev",pollingInterval:3e4,syncInterval:9e4,...e}}async init(){if(this.loader){const e=await this.loader.load();e&&this.applyYamlConfig(e)}await this.getFeaturesFlags(),await this.syncFeaturesTimes(),this.pollingIntervalTimer=setInterval(()=>{this.getFeaturesFlags()},this.options.pollingInterval),this.syncIntervalTimer=setInterval(()=>{this.syncFeaturesTimes(),this.syncFeaturesUsage()},this.options.syncInterval),this.inited=!0}destroy(){this.inited=!1,this.pollingIntervalTimer&&clearInterval(this.pollingIntervalTimer),this.syncIntervalTimer&&clearInterval(this.syncIntervalTimer),this.featuresTimes={},this.featuresFlags={},this.featuresUsage=[]}isEnabled(e){const t=this.featuresFlags[e];return t?(this.upsertFeaturesUsage(e),t.enabled):(this.createFeature(e,{times:[]}),!1)}declareFromObject(e){this.applyYamlConfig(e)}async sync(){await this.syncFeaturesTimes(),await this.syncFeaturesUsage()}applyYamlConfig(e){var t;for(const[s,a]of Object.entries(e)){const r=((t=a?.times)!=null?t:[]).map(i=>{var n;return{email:e[s].contributor,start:i.started,end:(n=i.finished)!=null?n:null}});for(const i of r){if(Number.isNaN(Date.parse(i.start)))throw new Error(`FlipFlag: invalid "started" date in ${s}: ${i.start}`);if(i.end!==null&&Number.isNaN(Date.parse(String(i.end))))throw new Error(`FlipFlag: invalid "finished" date in ${s}: ${i.end}`)}this.featuresTimes[s]={times:r}}}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})}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 createFeature(e,t){if(!this.options.privateKey)return null;const s=new URL("/v1/sdk/feature",this.getBaseUrl());fetch(s.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))}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=new URL("/v1/sdk/feature/flags",this.getBaseUrl());e.searchParams.append("publicKey",this.options.publicKey);const t=await fetch(e.toString(),{method:"GET",headers:{"Content-Type":"application/json"}});if(!t.ok&&!this.inited){const s=await t.text();throw new Error(`Failed to get features: ${t.status} - ${s}`)}this.featuresFlags=await t.json()}catch(e){console.error("Get list features flag:",e)}}async syncFeaturesTimes(){if(!this.options.privateKey)return null;for(const[e,t]of Object.entries(this.featuresTimes))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=new URL("/v1/sdk/feature/usages",this.getBaseUrl());fetch(e.toString(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({publicKey:this.options.publicKey,privateKey:this.options.privateKey,usages:this.featuresUsage})}).catch(t=>console.error("Feature Usage Sync:",t))}}export{l as F};
|
|
2
|
+
//# sourceMappingURL=flipflag-core-BiEpOSVM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flipflag-core-BiEpOSVM.js","sources":["../src/core/flipflag-core.ts"],"sourcesContent":["import {\n FlipFlagYaml,\n IDeclareFeatureOptions,\n IDeclareFeatureTime,\n IFeatureFlag,\n IFeatureFlagUsage,\n IManagerOptions,\n} from \"../types/provider\";\nimport { ConfigLoader } from \"../platform/config-loader\";\n\nexport class FlipFlagCore {\n private inited = false;\n private pollingIntervalTimer: any = null;\n private syncIntervalTimer: any = null;\n\n protected options: Partial<IManagerOptions>;\n private featuresTimes: Record<string, IDeclareFeatureOptions> = {};\n private featuresFlags: Record<string, IFeatureFlag> = {};\n private featuresUsage: IFeatureFlagUsage[] = [];\n\n constructor(\n protected readonly opts: IManagerOptions,\n private readonly loader?: ConfigLoader,\n ) {\n this.options = {\n apiUrl: \"https://api.flipflag.dev\",\n pollingInterval: 30_000,\n syncInterval: 90_000,\n ...opts,\n };\n }\n\n public async init() {\n if (this.loader) {\n const yamlDoc = await this.loader.load();\n if (yamlDoc) this.applyYamlConfig(yamlDoc);\n }\n\n await this.getFeaturesFlags();\n await this.syncFeaturesTimes();\n\n this.pollingIntervalTimer = setInterval(() => {\n this.getFeaturesFlags();\n }, this.options.pollingInterval);\n\n this.syncIntervalTimer = setInterval(() => {\n this.syncFeaturesTimes();\n this.syncFeaturesUsage();\n }, this.options.syncInterval);\n\n this.inited = true;\n }\n\n public destroy() {\n this.inited = false;\n if (this.pollingIntervalTimer) clearInterval(this.pollingIntervalTimer);\n if (this.syncIntervalTimer) clearInterval(this.syncIntervalTimer);\n this.featuresTimes = {};\n this.featuresFlags = {};\n this.featuresUsage = [];\n }\n\n public isEnabled(featureName: string) {\n const feature = this.featuresFlags[featureName];\n if (!feature) {\n this.createFeature(featureName, { times: [] });\n return false;\n }\n this.upsertFeaturesUsage(featureName);\n return feature.enabled;\n }\n\n public declareFromObject(doc: FlipFlagYaml) {\n this.applyYamlConfig(doc);\n }\n\n public async sync() {\n await this.syncFeaturesTimes();\n await this.syncFeaturesUsage();\n }\n\n private applyYamlConfig(doc: FlipFlagYaml) {\n for (const [featureName, cfg] of Object.entries(doc)) {\n const times = (cfg?.times ?? []).map((t) => ({\n email: doc[featureName].contributor,\n start: t.started,\n end: t.finished ?? null,\n })) as IDeclareFeatureTime[];\n\n for (const t of times) {\n if (Number.isNaN(Date.parse(t.start))) {\n throw new Error(\n `FlipFlag: invalid \"started\" date in ${featureName}: ${t.start}`,\n );\n }\n if (t.end !== null && Number.isNaN(Date.parse(String(t.end)))) {\n throw new Error(\n `FlipFlag: invalid \"finished\" date in ${featureName}: ${t.end}`,\n );\n }\n }\n\n this.featuresTimes[featureName] = { times };\n }\n }\n\n private upsertFeaturesUsage(featureName: string) {\n const existing = this.featuresUsage.find(\n (u) => u.featureName === featureName,\n );\n if (existing) {\n existing.usedAt = new Date();\n return;\n }\n this.featuresUsage.push({ featureName, usedAt: new Date() });\n }\n\n private getBaseUrl() {\n if (this.options.apiUrl) return this.options.apiUrl.replace(/\\/+$/, \"\");\n throw new Error(\n \"Base API URL is not configured. Please provide apiUrl in the SDK options.\",\n );\n }\n\n private async createFeature(\n featureName: string,\n options: IDeclareFeatureOptions,\n ) {\n if (!this.options.privateKey) return null;\n\n const url = new URL(\"/v1/sdk/feature\", this.getBaseUrl());\n fetch(url.toString(), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n featureName,\n privateKey: this.options.privateKey,\n ...options,\n }),\n }).catch((e) => console.error(\"Create Feature:\", e));\n }\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 url = new URL(\"/v1/sdk/feature/flags\", this.getBaseUrl());\n url.searchParams.append(\"publicKey\", this.options.publicKey);\n\n const res = await fetch(url.toString(), {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" },\n });\n if (!res.ok && !this.inited) {\n const errorText = await res.text();\n throw new Error(`Failed to get features: ${res.status} - ${errorText}`);\n }\n\n this.featuresFlags = await res.json();\n } catch (e) {\n console.error(\"Get list features flag:\", e);\n }\n }\n\n private async syncFeaturesTimes() {\n if (!this.options.privateKey) return null;\n for (const [featureName, options] of Object.entries(this.featuresTimes)) {\n this.createFeature(featureName, options);\n }\n }\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 const url = new URL(\"/v1/sdk/feature/usages\", this.getBaseUrl());\n\n fetch(url.toString(), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n publicKey: this.options.publicKey,\n privateKey: this.options.privateKey,\n usages: this.featuresUsage,\n }),\n }).catch((e) => console.error(\"Feature Usage Sync:\", e));\n }\n}\n"],"names":["FlipFlagCore","opts","loader","yamlDoc","featureName","feature","doc","_a","cfg","times","t","existing","u","options","url","e","res","errorText"],"mappings":"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"}
|
package/dist/node.d.ts
CHANGED
package/dist/node.js
CHANGED
package/dist/node.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{F as s}from"./flipflag-core-
|
|
1
|
+
import{F as s}from"./flipflag-core-BiEpOSVM.js";import*as c from"node:fs/promises";import*as p from"node:path";import*as f from"js-yaml";class g{constructor(r){this.options=r}async load(){var r,t,e;const l=(r=this.options.configPath)!=null?r:p.resolve(process.cwd(),".flipflag.yml");let n;try{n=await c.readFile(l,"utf8")}catch(o){if(o?.code==="ENOENT"&&this.options.ignoreMissingConfig)return null;throw new Error(`FlipFlag: cannot read config at ${l}: ${(t=o?.message)!=null?t:o}`)}let a;try{a=f.load(n)}catch(o){throw new Error(`FlipFlag: invalid YAML in ${l}: ${(e=o?.message)!=null?e:o}`)}return!a||typeof a!="object"||Array.isArray(a)?(console.warn("FlipFlag: YAML root must be an object (mapping featureName -> config)"),null):a}}class u extends s{constructor(r){super(r,new g(r))}}export{u as FlipFlag};
|
|
2
2
|
//# sourceMappingURL=node.min.js.map
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flipflag-core-BNqlFhCW.js","sources":["../src/core/flipflag-core.ts"],"sourcesContent":["import {\n FlipFlagYaml,\n IDeclareFeatureOptions,\n IDeclareFeatureTime,\n IFeatureFlag,\n IFeatureFlagUsage,\n IManagerOptions,\n} from \"../types/provider\";\nimport { ConfigLoader } from \"../platform/config-loader\";\n\nexport class FlipFlagCore {\n private inited = false;\n private interval: any = null;\n\n protected options: Partial<IManagerOptions>;\n private featuresTimes: Record<string, IDeclareFeatureOptions> = {};\n private featuresFlags: Record<string, IFeatureFlag> = {};\n private featuresUsage: IFeatureFlagUsage[] = [];\n\n constructor(\n protected readonly opts: IManagerOptions,\n private readonly loader?: ConfigLoader,\n ) {\n this.options = {\n apiUrl: \"https://api.flipflag.dev\",\n pollingInterval: 30_000,\n ...opts,\n };\n }\n\n public async init() {\n if (this.loader) {\n const yamlDoc = await this.loader.load();\n if (yamlDoc) this.applyYamlConfig(yamlDoc);\n }\n\n await this.getFeaturesFlags();\n await this.syncFeaturesTimes();\n\n this.interval = setInterval(() => {\n this.getFeaturesFlags();\n this.syncFeaturesTimes();\n this.syncFeaturesUsage();\n }, this.options.pollingInterval);\n\n this.inited = true;\n }\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 public isEnabled(featureName: string) {\n const feature = this.featuresFlags[featureName];\n if (!feature) {\n this.createFeature(featureName, { times: [] });\n return false;\n }\n this.upsertFeaturesUsage(featureName);\n return feature.enabled;\n }\n\n public declareFromObject(doc: FlipFlagYaml) {\n this.applyYamlConfig(doc);\n }\n\n private applyYamlConfig(doc: FlipFlagYaml) {\n for (const [featureName, cfg] of Object.entries(doc)) {\n const times = (cfg?.times ?? []).map((t) => ({\n email: doc[featureName].contributor,\n start: t.started,\n end: t.finished ?? null,\n })) as IDeclareFeatureTime[];\n\n for (const t of times) {\n if (Number.isNaN(Date.parse(t.start))) {\n throw new Error(\n `FlipFlag: invalid \"started\" date in ${featureName}: ${t.start}`,\n );\n }\n if (t.end !== null && Number.isNaN(Date.parse(String(t.end)))) {\n throw new Error(\n `FlipFlag: invalid \"finished\" date in ${featureName}: ${t.end}`,\n );\n }\n }\n\n this.featuresTimes[featureName] = { times };\n }\n }\n\n private upsertFeaturesUsage(featureName: string) {\n const existing = this.featuresUsage.find(\n (u) => u.featureName === featureName,\n );\n if (existing) {\n existing.usedAt = new Date();\n return;\n }\n this.featuresUsage.push({ featureName, usedAt: new Date() });\n }\n\n private getBaseUrl() {\n if (this.options.apiUrl) return this.options.apiUrl.replace(/\\/+$/, \"\");\n throw new Error(\n \"Base API URL is not configured. Please provide apiUrl in the SDK options.\",\n );\n }\n\n private async createFeature(\n featureName: string,\n options: IDeclareFeatureOptions,\n ) {\n if (!this.options.privateKey) return null;\n\n const url = new URL(\"/v1/sdk/feature\", this.getBaseUrl());\n fetch(url.toString(), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n featureName,\n privateKey: this.options.privateKey,\n ...options,\n }),\n }).catch((e) => console.error(\"Create Feature:\", e));\n }\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 url = new URL(\"/v1/sdk/feature/flags\", this.getBaseUrl());\n url.searchParams.append(\"publicKey\", this.options.publicKey);\n\n const res = await fetch(url.toString(), {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" },\n });\n if (!res.ok && !this.inited) {\n const errorText = await res.text();\n throw new Error(`Failed to get features: ${res.status} - ${errorText}`);\n }\n\n this.featuresFlags = await res.json();\n } catch (e) {\n console.error(\"Get list features flag:\", e);\n }\n }\n\n private async syncFeaturesTimes() {\n if (!this.options.privateKey) return null;\n for (const [featureName, options] of Object.entries(this.featuresTimes)) {\n this.createFeature(featureName, options);\n }\n }\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 const url = new URL(\"/v1/sdk/feature/usages\", this.getBaseUrl());\n\n fetch(url.toString(), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n publicKey: this.options.publicKey,\n privateKey: this.options.privateKey,\n usages: this.featuresUsage,\n }),\n }).catch((e) => console.error(\"Feature Usage Sync:\", e));\n }\n}\n"],"names":["_a"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
class o{constructor(e,t){this.opts=e,this.loader=t,this.inited=!1,this.interval=null,this.featuresTimes={},this.featuresFlags={},this.featuresUsage=[],this.options={apiUrl:"https://api.flipflag.dev",pollingInterval:3e4,...e}}async init(){if(this.loader){const e=await this.loader.load();e&&this.applyYamlConfig(e)}await this.getFeaturesFlags(),await this.syncFeaturesTimes(),this.interval=setInterval(()=>{this.getFeaturesFlags(),this.syncFeaturesTimes(),this.syncFeaturesUsage()},this.options.pollingInterval),this.inited=!0}destroy(){this.inited=!1,this.interval&&clearInterval(this.interval),this.featuresTimes={},this.featuresFlags={},this.featuresUsage=[]}isEnabled(e){const t=this.featuresFlags[e];return t?(this.upsertFeaturesUsage(e),t.enabled):(this.createFeature(e,{times:[]}),!1)}declareFromObject(e){this.applyYamlConfig(e)}applyYamlConfig(e){var t;for(const[s,a]of Object.entries(e)){const r=((t=a?.times)!=null?t:[]).map(i=>{var n;return{email:e[s].contributor,start:i.started,end:(n=i.finished)!=null?n:null}});for(const i of r){if(Number.isNaN(Date.parse(i.start)))throw new Error(`FlipFlag: invalid "started" date in ${s}: ${i.start}`);if(i.end!==null&&Number.isNaN(Date.parse(String(i.end))))throw new Error(`FlipFlag: invalid "finished" date in ${s}: ${i.end}`)}this.featuresTimes[s]={times:r}}}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})}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 createFeature(e,t){if(!this.options.privateKey)return null;const s=new URL("/v1/sdk/feature",this.getBaseUrl());fetch(s.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))}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=new URL("/v1/sdk/feature/flags",this.getBaseUrl());e.searchParams.append("publicKey",this.options.publicKey);const t=await fetch(e.toString(),{method:"GET",headers:{"Content-Type":"application/json"}});if(!t.ok&&!this.inited){const s=await t.text();throw new Error(`Failed to get features: ${t.status} - ${s}`)}this.featuresFlags=await t.json()}catch(e){console.error("Get list features flag:",e)}}async syncFeaturesTimes(){if(!this.options.privateKey)return null;for(const[e,t]of Object.entries(this.featuresTimes))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=new URL("/v1/sdk/feature/usages",this.getBaseUrl());fetch(e.toString(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({publicKey:this.options.publicKey,privateKey:this.options.privateKey,usages:this.featuresUsage})}).catch(t=>console.error("Feature Usage Sync:",t))}}export{o as F};
|
|
2
|
-
//# sourceMappingURL=flipflag-core-DHCsP2TB.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flipflag-core-DHCsP2TB.js","sources":["../src/core/flipflag-core.ts"],"sourcesContent":["import {\n FlipFlagYaml,\n IDeclareFeatureOptions,\n IDeclareFeatureTime,\n IFeatureFlag,\n IFeatureFlagUsage,\n IManagerOptions,\n} from \"../types/provider\";\nimport { ConfigLoader } from \"../platform/config-loader\";\n\nexport class FlipFlagCore {\n private inited = false;\n private interval: any = null;\n\n protected options: Partial<IManagerOptions>;\n private featuresTimes: Record<string, IDeclareFeatureOptions> = {};\n private featuresFlags: Record<string, IFeatureFlag> = {};\n private featuresUsage: IFeatureFlagUsage[] = [];\n\n constructor(\n protected readonly opts: IManagerOptions,\n private readonly loader?: ConfigLoader,\n ) {\n this.options = {\n apiUrl: \"https://api.flipflag.dev\",\n pollingInterval: 30_000,\n ...opts,\n };\n }\n\n public async init() {\n if (this.loader) {\n const yamlDoc = await this.loader.load();\n if (yamlDoc) this.applyYamlConfig(yamlDoc);\n }\n\n await this.getFeaturesFlags();\n await this.syncFeaturesTimes();\n\n this.interval = setInterval(() => {\n this.getFeaturesFlags();\n this.syncFeaturesTimes();\n this.syncFeaturesUsage();\n }, this.options.pollingInterval);\n\n this.inited = true;\n }\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 public isEnabled(featureName: string) {\n const feature = this.featuresFlags[featureName];\n if (!feature) {\n this.createFeature(featureName, { times: [] });\n return false;\n }\n this.upsertFeaturesUsage(featureName);\n return feature.enabled;\n }\n\n public declareFromObject(doc: FlipFlagYaml) {\n this.applyYamlConfig(doc);\n }\n\n private applyYamlConfig(doc: FlipFlagYaml) {\n for (const [featureName, cfg] of Object.entries(doc)) {\n const times = (cfg?.times ?? []).map((t) => ({\n email: doc[featureName].contributor,\n start: t.started,\n end: t.finished ?? null,\n })) as IDeclareFeatureTime[];\n\n for (const t of times) {\n if (Number.isNaN(Date.parse(t.start))) {\n throw new Error(\n `FlipFlag: invalid \"started\" date in ${featureName}: ${t.start}`,\n );\n }\n if (t.end !== null && Number.isNaN(Date.parse(String(t.end)))) {\n throw new Error(\n `FlipFlag: invalid \"finished\" date in ${featureName}: ${t.end}`,\n );\n }\n }\n\n this.featuresTimes[featureName] = { times };\n }\n }\n\n private upsertFeaturesUsage(featureName: string) {\n const existing = this.featuresUsage.find(\n (u) => u.featureName === featureName,\n );\n if (existing) {\n existing.usedAt = new Date();\n return;\n }\n this.featuresUsage.push({ featureName, usedAt: new Date() });\n }\n\n private getBaseUrl() {\n if (this.options.apiUrl) return this.options.apiUrl.replace(/\\/+$/, \"\");\n throw new Error(\n \"Base API URL is not configured. Please provide apiUrl in the SDK options.\",\n );\n }\n\n private async createFeature(\n featureName: string,\n options: IDeclareFeatureOptions,\n ) {\n if (!this.options.privateKey) return null;\n\n const url = new URL(\"/v1/sdk/feature\", this.getBaseUrl());\n fetch(url.toString(), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n featureName,\n privateKey: this.options.privateKey,\n ...options,\n }),\n }).catch((e) => console.error(\"Create Feature:\", e));\n }\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 url = new URL(\"/v1/sdk/feature/flags\", this.getBaseUrl());\n url.searchParams.append(\"publicKey\", this.options.publicKey);\n\n const res = await fetch(url.toString(), {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" },\n });\n if (!res.ok && !this.inited) {\n const errorText = await res.text();\n throw new Error(`Failed to get features: ${res.status} - ${errorText}`);\n }\n\n this.featuresFlags = await res.json();\n } catch (e) {\n console.error(\"Get list features flag:\", e);\n }\n }\n\n private async syncFeaturesTimes() {\n if (!this.options.privateKey) return null;\n for (const [featureName, options] of Object.entries(this.featuresTimes)) {\n this.createFeature(featureName, options);\n }\n }\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 const url = new URL(\"/v1/sdk/feature/usages\", this.getBaseUrl());\n\n fetch(url.toString(), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n publicKey: this.options.publicKey,\n privateKey: this.options.privateKey,\n usages: this.featuresUsage,\n }),\n }).catch((e) => console.error(\"Feature Usage Sync:\", e));\n }\n}\n"],"names":["FlipFlagCore","opts","loader","yamlDoc","featureName","feature","doc","_a","cfg","times","t","existing","u","options","url","e","res","errorText"],"mappings":"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"}
|