@flipflag/sdk 1.2.0 → 1.3.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 CHANGED
@@ -1,4 +1,4 @@
1
- import { F as FlipFlagCore, I as IManagerOptions, a as FlipFlagYaml } from './flipflag-core-iEJf8R86.js';
1
+ import { F as FlipFlagCore, I as IManagerOptions, a as FlipFlagYaml } from './flipflag-core-v7AUprKd.js';
2
2
 
3
3
  declare class FlipFlag extends FlipFlagCore {
4
4
  constructor(opts: IManagerOptions, initialConfig?: FlipFlagYaml);
package/dist/browser.js CHANGED
@@ -1,4 +1,4 @@
1
- import { F as FlipFlagCore } from './flipflag-core-DJGCcm4t.js';
1
+ import { F as FlipFlagCore } from './flipflag-core-BNqlFhCW.js';
2
2
 
3
3
  class FlipFlag extends FlipFlagCore {
4
4
  constructor(opts, initialConfig) {
@@ -1,2 +1,2 @@
1
- import{F as s}from"./flipflag-core-AolmW7Kv.js";class o extends s{constructor(e,r){super(e),r&&this.declareFromObject(r)}}export{o as FlipFlag};
1
+ import{F as s}from"./flipflag-core-DHCsP2TB.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
@@ -7,7 +7,11 @@ class FlipFlagCore {
7
7
  this.featuresTimes = {};
8
8
  this.featuresFlags = {};
9
9
  this.featuresUsage = [];
10
- this.options = { apiUrl: "https://api.flipflag.dev", ...opts };
10
+ this.options = {
11
+ apiUrl: "https://api.flipflag.dev",
12
+ pollingInterval: 3e4,
13
+ ...opts
14
+ };
11
15
  }
12
16
  async init() {
13
17
  if (this.loader) {
@@ -20,7 +24,7 @@ class FlipFlagCore {
20
24
  this.getFeaturesFlags();
21
25
  this.syncFeaturesTimes();
22
26
  this.syncFeaturesUsage();
23
- }, 1e4);
27
+ }, this.options.pollingInterval);
24
28
  this.inited = true;
25
29
  }
26
30
  destroy() {
@@ -145,4 +149,4 @@ class FlipFlagCore {
145
149
  }
146
150
 
147
151
  export { FlipFlagCore as F };
148
- //# sourceMappingURL=flipflag-core-DJGCcm4t.js.map
152
+ //# sourceMappingURL=flipflag-core-BNqlFhCW.js.map
@@ -0,0 +1 @@
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":"AAUO,MAAM,YAAA,CAAa;AAAA,EASxB,WAAA,CACqB,MACF,MAAA,EACjB;AAFmB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACF,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAVnB,IAAA,IAAA,CAAQ,MAAA,GAAS,KAAA;AACjB,IAAA,IAAA,CAAQ,QAAA,GAAgB,IAAA;AAGxB,IAAA,IAAA,CAAQ,gBAAwD,EAAC;AACjE,IAAA,IAAA,CAAQ,gBAA8C,EAAC;AACvD,IAAA,IAAA,CAAQ,gBAAqC,EAAC;AAM5C,IAAA,IAAA,CAAK,OAAA,GAAU;AAAA,MACb,MAAA,EAAQ,0BAAA;AAAA,MACR,eAAA,EAAiB,GAAA;AAAA,MACjB,GAAG;AAAA,KACL;AAAA,EACF;AAAA,EAEA,MAAa,IAAA,GAAO;AAClB,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,MAAA,CAAO,IAAA,EAAK;AACvC,MAAA,IAAI,OAAA,EAAS,IAAA,CAAK,eAAA,CAAgB,OAAO,CAAA;AAAA,IAC3C;AAEA,IAAA,MAAM,KAAK,gBAAA,EAAiB;AAC5B,IAAA,MAAM,KAAK,iBAAA,EAAkB;AAE7B,IAAA,IAAA,CAAK,QAAA,GAAW,YAAY,MAAM;AAChC,MAAA,IAAA,CAAK,gBAAA,EAAiB;AACtB,MAAA,IAAA,CAAK,iBAAA,EAAkB;AACvB,MAAA,IAAA,CAAK,iBAAA,EAAkB;AAAA,IACzB,CAAA,EAAG,IAAA,CAAK,OAAA,CAAQ,eAAe,CAAA;AAE/B,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AAAA,EAChB;AAAA,EAEO,OAAA,GAAU;AACf,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,IAAA,IAAI,IAAA,CAAK,QAAA,EAAU,aAAA,CAAc,IAAA,CAAK,QAAQ,CAAA;AAC9C,IAAA,IAAA,CAAK,gBAAgB,EAAC;AACtB,IAAA,IAAA,CAAK,gBAAgB,EAAC;AACtB,IAAA,IAAA,CAAK,gBAAgB,EAAC;AAAA,EACxB;AAAA,EAEO,UAAU,WAAA,EAAqB;AACpC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,aAAA,CAAc,WAAW,CAAA;AAC9C,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,IAAA,CAAK,cAAc,WAAA,EAAa,EAAE,KAAA,EAAO,IAAI,CAAA;AAC7C,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,IAAA,CAAK,oBAAoB,WAAW,CAAA;AACpC,IAAA,OAAO,OAAA,CAAQ,OAAA;AAAA,EACjB;AAAA,EAEO,kBAAkB,GAAA,EAAmB;AAC1C,IAAA,IAAA,CAAK,gBAAgB,GAAG,CAAA;AAAA,EAC1B;AAAA,EAEQ,gBAAgB,GAAA,EAAmB;AAtE7C,IAAA,IAAA,EAAA;AAuEI,IAAA,KAAA,MAAW,CAAC,WAAA,EAAa,GAAG,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AACpD,MAAA,MAAM,KAAA,GAAA,CAAA,CAAS,gCAAK,KAAA,KAAL,IAAA,GAAA,EAAA,GAAc,EAAC,EAAG,GAAA,CAAI,CAAC,CAAA,KAAG;AAxE/C,QAAA,IAAAA,GAAAA;AAwEmD,QAAA,OAAA;AAAA,UAC3C,KAAA,EAAO,GAAA,CAAI,WAAW,CAAA,CAAE,WAAA;AAAA,UACxB,OAAO,CAAA,CAAE,OAAA;AAAA,UACT,GAAA,EAAA,CAAKA,GAAAA,GAAA,CAAA,CAAE,QAAA,KAAF,OAAAA,GAAAA,GAAc;AAAA,SACrB;AAAA,MAAA,CAAE,CAAA;AAEF,MAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,QAAA,IAAI,OAAO,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA,CAAE,KAAK,CAAC,CAAA,EAAG;AACrC,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,CAAA,oCAAA,EAAuC,WAAW,CAAA,EAAA,EAAK,CAAA,CAAE,KAAK,CAAA;AAAA,WAChE;AAAA,QACF;AACA,QAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,CAAA,CAAE,GAAG,CAAC,CAAC,CAAA,EAAG;AAC7D,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,CAAA,qCAAA,EAAwC,WAAW,CAAA,EAAA,EAAK,CAAA,CAAE,GAAG,CAAA;AAAA,WAC/D;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAA,CAAK,aAAA,CAAc,WAAW,CAAA,GAAI,EAAE,KAAA,EAAM;AAAA,IAC5C;AAAA,EACF;AAAA,EAEQ,oBAAoB,WAAA,EAAqB;AAC/C,IAAA,MAAM,QAAA,GAAW,KAAK,aAAA,CAAc,IAAA;AAAA,MAClC,CAAC,CAAA,KAAM,CAAA,CAAE,WAAA,KAAgB;AAAA,KAC3B;AACA,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,QAAA,CAAS,MAAA,uBAAa,IAAA,EAAK;AAC3B,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,aAAA,CAAc,KAAK,EAAE,WAAA,EAAa,wBAAQ,IAAI,IAAA,IAAQ,CAAA;AAAA,EAC7D;AAAA,EAEQ,UAAA,GAAa;AACnB,IAAA,IAAI,IAAA,CAAK,QAAQ,MAAA,EAAQ,OAAO,KAAK,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AACtE,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAAA,EAEA,MAAc,aAAA,CACZ,WAAA,EACA,OAAA,EACA;AACA,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,OAAO,IAAA;AAErC,IAAA,MAAM,MAAM,IAAI,GAAA,CAAI,iBAAA,EAAmB,IAAA,CAAK,YAAY,CAAA;AACxD,IAAA,KAAA,CAAM,GAAA,CAAI,UAAS,EAAG;AAAA,MACpB,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,WAAA;AAAA,QACA,UAAA,EAAY,KAAK,OAAA,CAAQ,UAAA;AAAA,QACzB,GAAG;AAAA,OACJ;AAAA,KACF,EAAE,KAAA,CAAM,CAAC,MAAM,OAAA,CAAQ,KAAA,CAAM,iBAAA,EAAmB,CAAC,CAAC,CAAA;AAAA,EACrD;AAAA,EAEA,MAAc,gBAAA,GAAmB;AAC/B,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW;AAC3B,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,MAAM,IAAI,GAAA,CAAI,uBAAA,EAAyB,IAAA,CAAK,YAAY,CAAA;AAC9D,MAAA,GAAA,CAAI,YAAA,CAAa,MAAA,CAAO,WAAA,EAAa,IAAA,CAAK,QAAQ,SAAS,CAAA;AAE3D,MAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAA,CAAI,UAAS,EAAG;AAAA,QACtC,MAAA,EAAQ,KAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA;AAAmB,OAC/C,CAAA;AACD,MAAA,IAAI,CAAC,GAAA,CAAI,EAAA,IAAM,CAAC,KAAK,MAAA,EAAQ;AAC3B,QAAA,MAAM,SAAA,GAAY,MAAM,GAAA,CAAI,IAAA,EAAK;AACjC,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,IAAI,MAAM,CAAA,GAAA,EAAM,SAAS,CAAA,CAAE,CAAA;AAAA,MACxE;AAEA,MAAA,IAAA,CAAK,aAAA,GAAgB,MAAM,GAAA,CAAI,IAAA,EAAK;AAAA,IACtC,SAAS,CAAA,EAAG;AACV,MAAA,OAAA,CAAQ,KAAA,CAAM,2BAA2B,CAAC,CAAA;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAc,iBAAA,GAAoB;AAChC,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,OAAO,IAAA;AACrC,IAAA,KAAA,MAAW,CAAC,aAAa,OAAO,CAAA,IAAK,OAAO,OAAA,CAAQ,IAAA,CAAK,aAAa,CAAA,EAAG;AACvE,MAAA,IAAA,CAAK,aAAA,CAAc,aAAa,OAAO,CAAA;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,MAAc,iBAAA,GAAoB;AAChC,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW;AAC3B,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,MAAM,MAAM,IAAI,GAAA,CAAI,wBAAA,EAA0B,IAAA,CAAK,YAAY,CAAA;AAE/D,IAAA,KAAA,CAAM,GAAA,CAAI,UAAS,EAAG;AAAA,MACpB,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,SAAA,EAAW,KAAK,OAAA,CAAQ,SAAA;AAAA,QACxB,UAAA,EAAY,KAAK,OAAA,CAAQ,UAAA;AAAA,QACzB,QAAQ,IAAA,CAAK;AAAA,OACd;AAAA,KACF,EAAE,KAAA,CAAM,CAAC,MAAM,OAAA,CAAQ,KAAA,CAAM,qBAAA,EAAuB,CAAC,CAAC,CAAA;AAAA,EACzD;AACF;;;;"}
@@ -0,0 +1,2 @@
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
@@ -0,0 +1 @@
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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"}
@@ -12,6 +12,11 @@ interface IManagerOptions {
12
12
  * Default: true
13
13
  */
14
14
  ignoreMissingConfig?: boolean;
15
+ /**
16
+ * Polling interval in milliseconds.
17
+ * Default: 30000 (30 seconds)
18
+ */
19
+ pollingInterval?: number;
15
20
  }
16
21
  type YamlTime = {
17
22
  started: string;
package/dist/node.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { F as FlipFlagCore, I as IManagerOptions } from './flipflag-core-iEJf8R86.js';
1
+ import { F as FlipFlagCore, I as IManagerOptions } from './flipflag-core-v7AUprKd.js';
2
2
 
3
3
  declare class FlipFlag extends FlipFlagCore {
4
4
  constructor(opts: IManagerOptions);
package/dist/node.js CHANGED
@@ -1,4 +1,4 @@
1
- import { F as FlipFlagCore } from './flipflag-core-DJGCcm4t.js';
1
+ import { F as FlipFlagCore } from './flipflag-core-BNqlFhCW.js';
2
2
  import * as fs from 'node:fs/promises';
3
3
  import * as path from 'node:path';
4
4
  import * as yaml from 'js-yaml';
package/dist/node.min.js CHANGED
@@ -1,2 +1,2 @@
1
- import{F as s}from"./flipflag-core-AolmW7Kv.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};
1
+ import{F as s}from"./flipflag-core-DHCsP2TB.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,6 +1,6 @@
1
1
  {
2
2
  "name": "@flipflag/sdk",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "description": "A lightweight client-side SDK for working with FlipFlag",
6
6
  "exports": {
@@ -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",...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()},1e4),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-AolmW7Kv.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"flipflag-core-AolmW7Kv.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 = { apiUrl: \"https://api.flipflag.dev\", ...opts };\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 }, 10_000);\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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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"flipflag-core-DJGCcm4t.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 = { apiUrl: \"https://api.flipflag.dev\", ...opts };\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 }, 10_000);\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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"}