@ops-ai/svelte-feature-flags-toggly 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,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024, Cosmin Atomei
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,431 @@
1
+ Lightweight package that provides feature flags support for Svelte applications allowing you to check feature status and enable/disable them easily.
2
+
3
+ Can be used *WITH* or *WITHOUT* [Toggly.io](https://toggly.io).
4
+
5
+ ## What is a Feature Flag
6
+
7
+ A feature flag (or toggle) in software development provides an alternative to maintaining multiple feature branches in source code. A condition within the code enables or disables a feature during runtime.
8
+
9
+ In agile settings the feature flag is used in production, to switch on the feature on demand, for some or all the users. Thus, feature flags make it easier to release often. Advanced roll out strategies such as canary roll out and A/B testing are easier to handle.
10
+
11
+ ## Installation
12
+
13
+ Simply install using NPM to install this package.
14
+
15
+ ```shell
16
+ $ npm i -s @ops-ai/svelte-feature-flags-toggly
17
+ ```
18
+
19
+ ## Basic Usage (with Toggly.io)
20
+
21
+ ### Initialize Toggly
22
+
23
+ Import and initialize Toggly in your main application file (typically `App.svelte` or `main.ts`):
24
+
25
+ ```typescript
26
+ import { createToggly } from '@ops-ai/svelte-feature-flags-toggly'
27
+
28
+ // Initialize with your App Key & Environment name from your Toggly application page
29
+ await createToggly({
30
+ appKey: 'your-app-key', // You can find this in app.toggly.io
31
+ environment: 'your-environment-name', // You can find this in app.toggly.io
32
+ })
33
+ ```
34
+
35
+ ### Using the Feature Component
36
+
37
+ Now you can start using the Feature component anywhere in your application:
38
+
39
+ ```svelte
40
+ <script>
41
+ import { Feature } from '@ops-ai/svelte-feature-flags-toggly'
42
+ </script>
43
+
44
+ <Feature featureKey="firstFeature">
45
+ <p>This feature can be turned on or off.</p>
46
+ </Feature>
47
+ ```
48
+
49
+ ### Feature Component Options
50
+
51
+ You can also check multiple feature keys and make use of the *requirement* (all/any) and *negate* (bool) options (requirement is set to "all" by default).
52
+
53
+ #### Show if all features are on
54
+
55
+ ```svelte
56
+ <Feature featureKeys={['firstFeature', 'secondFeature']}>
57
+ <p>ALL the provided feature keys are TRUE.</p>
58
+ </Feature>
59
+ ```
60
+
61
+ #### Show if any feature is on
62
+
63
+ ```svelte
64
+ <Feature featureKeys={['firstFeature', 'secondFeature']} requirement="any">
65
+ <p>AT LEAST ONE the provided feature keys is TRUE.</p>
66
+ </Feature>
67
+ ```
68
+
69
+ #### Show if features are off (negate)
70
+
71
+ ```svelte
72
+ <Feature featureKeys={['firstFeature', 'secondFeature']} negate={true}>
73
+ <p>NONE of the provided feature keys is TRUE.</p>
74
+ </Feature>
75
+ ```
76
+
77
+ ### Programmatic Feature Checks
78
+
79
+ You can also check features programmatically using the store functions:
80
+
81
+ ```svelte
82
+ <script>
83
+ import { isFeatureOn, isFeatureOff, evaluateFeatureGate } from '@ops-ai/svelte-feature-flags-toggly'
84
+
85
+ let featureEnabled = false
86
+
87
+ async function checkFeature() {
88
+ featureEnabled = await isFeatureOn('myFeature')
89
+ }
90
+
91
+ async function checkMultipleFeatures() {
92
+ const result = await evaluateFeatureGate(['feature1', 'feature2'], 'any', false)
93
+ console.log('Gate result:', result)
94
+ }
95
+ </script>
96
+
97
+ <button on:click={checkFeature}>Check Feature</button>
98
+ {#if featureEnabled}
99
+ <p>Feature is enabled!</p>
100
+ {/if}
101
+ ```
102
+
103
+ ### Using Reactive Stores
104
+
105
+ You can also use Svelte stores for reactive feature flag checks:
106
+
107
+ ```svelte
108
+ <script>
109
+ import { createFeatureStore } from '@ops-ai/svelte-feature-flags-toggly'
110
+
111
+ const myFeature = createFeatureStore('myFeature')
112
+ </script>
113
+
114
+ {#if $myFeature}
115
+ <p>Feature is enabled!</p>
116
+ {/if}
117
+ ```
118
+
119
+ ## Users and Rollouts
120
+
121
+ Using this package with [Toggly](https://toggly.io) allows you to define custom feature rollouts.
122
+
123
+ Custom rollouts offers the ability to show features only to certain groups of users based on various custom rules which you can define in [Toggly](https://app.toggly.io).
124
+
125
+ In case you want to support custom feature rollouts, remember to provide an unique identity string for each user to make sure they get the same feature values on future visits:
126
+
127
+ ```typescript
128
+ await createToggly({
129
+ appKey: 'your-app-key', // You can find this in app.toggly.io
130
+ environment: 'your-environment-name', // You can find this in app.toggly.io
131
+ identity: 'unique-user-identifier', // Use this in case you want to support custom feature rollouts
132
+ })
133
+ ```
134
+
135
+ ## Basic Usage (without Toggly.io)
136
+
137
+ You can also use the Svelte SDK without connecting to Toggly.io by providing feature defaults:
138
+
139
+ ### Initialize with Defaults
140
+
141
+ ```typescript
142
+ import { createToggly } from '@ops-ai/svelte-feature-flags-toggly'
143
+
144
+ const featureDefaults = {
145
+ firstFeature: true,
146
+ secondFeature: false,
147
+ }
148
+
149
+ await createToggly({
150
+ featureDefaults: featureDefaults,
151
+ })
152
+ ```
153
+
154
+ Now you can use the Feature component the same way as with Toggly.io:
155
+
156
+ ```svelte
157
+ <Feature featureKey="firstFeature">
158
+ <p>This feature can be turned on or off.</p>
159
+ </Feature>
160
+ ```
161
+
162
+ ## Configuration Options
163
+
164
+ The `createToggly` function accepts the following options:
165
+
166
+ ```typescript
167
+ interface TogglyOptions {
168
+ baseURI?: string // Base URI for Toggly API (default: 'https://client.toggly.io')
169
+ appKey?: string // Your Toggly app key
170
+ environment?: string // Environment name (default: 'Production')
171
+ identity?: string // User identity for targeting
172
+ featureDefaults?: { [key: string]: boolean } // Default feature values
173
+ showFeatureDuringEvaluation?: boolean // Show feature while evaluating (default: false)
174
+ featureFlagsRefreshInterval?: number // Cache refresh interval in ms (default: 180000)
175
+ }
176
+ ```
177
+
178
+ ## TypeScript Support
179
+
180
+ The Svelte SDK includes full TypeScript support with type definitions:
181
+
182
+ ```typescript
183
+ import {
184
+ Feature,
185
+ createToggly,
186
+ isFeatureOn,
187
+ type TogglyOptions
188
+ } from '@ops-ai/svelte-feature-flags-toggly'
189
+
190
+ const config: TogglyOptions = {
191
+ appKey: 'your-app-key',
192
+ environment: 'Production',
193
+ identity: 'user-123'
194
+ }
195
+
196
+ await createToggly(config)
197
+ ```
198
+
199
+ ## SvelteKit Integration
200
+
201
+ For SvelteKit applications, initialize Toggly in your root layout or a client-side component:
202
+
203
+ ```svelte
204
+ <!-- src/routes/+layout.svelte -->
205
+ <script>
206
+ import { onMount } from 'svelte'
207
+ import { createToggly } from '@ops-ai/svelte-feature-flags-toggly'
208
+
209
+ onMount(async () => {
210
+ await createToggly({
211
+ appKey: 'your-app-key',
212
+ environment: 'Production',
213
+ identity: 'user-123' // Get from session/auth
214
+ })
215
+ })
216
+ </script>
217
+
218
+ <slot />
219
+ ```
220
+
221
+ ## Best Practices
222
+
223
+ 1. **Initialize Once**: Call `createToggly()` once at the root of your app
224
+ 2. **Use Feature Component**: Prefer using the Feature component for declarative feature flag checks
225
+ 3. **Provide User Context**: Include identity for accurate targeting and rollouts
226
+ 4. **Set Feature Defaults**: Provide defaults for offline scenarios or when not using Toggly.io
227
+ 5. **TypeScript**: Take advantage of TypeScript support for better type safety
228
+ 6. **Reactive Stores**: Use `createFeatureStore()` for reactive feature flag checks in your components
229
+
230
+ ## API Reference
231
+
232
+ ### `createToggly(config: TogglyOptions): Promise<void>`
233
+
234
+ Initializes the Toggly service and loads feature flags.
235
+
236
+ ### `<Feature>`
237
+
238
+ Svelte component for conditional rendering based on feature flags.
239
+
240
+ **Props:**
241
+ - `featureKey?: string` - Single feature key to check
242
+ - `featureKeys?: string[]` - Multiple feature keys to check
243
+ - `requirement?: 'all' | 'any'` - Requirement type (default: 'all')
244
+ - `negate?: boolean` - Whether to negate the result (default: false)
245
+
246
+ ### `isFeatureOn(featureKey: string): Promise<boolean>`
247
+
248
+ Check if a feature is enabled.
249
+
250
+ ### `isFeatureOff(featureKey: string): Promise<boolean>`
251
+
252
+ Check if a feature is disabled.
253
+
254
+ ### `evaluateFeatureGate(featureKeys: string[], requirement?: 'all' | 'any', negate?: boolean): Promise<boolean>`
255
+
256
+ Evaluate a feature gate with multiple flags.
257
+
258
+ ### `createFeatureStore(featureKey: string)`
259
+
260
+ Create a reactive Svelte store for a specific feature flag.
261
+
262
+ ## Building the Library
263
+
264
+ If you're contributing to or building this library from source:
265
+
266
+ ### Prerequisites
267
+
268
+ - Node.js 18+ and npm
269
+ - All dependencies installed
270
+
271
+ ### Build Steps
272
+
273
+ 1. **Install dependencies:**
274
+ ```bash
275
+ npm install
276
+ ```
277
+
278
+ 2. **Run type checking:**
279
+ ```bash
280
+ npm run typecheck
281
+ ```
282
+
283
+ 3. **Build the library:**
284
+ ```bash
285
+ npm run build
286
+ ```
287
+
288
+ This will:
289
+ - Compile TypeScript to JavaScript
290
+ - Bundle the library for both ESM and CommonJS formats
291
+ - Generate TypeScript declaration files
292
+ - Output files to the `dist/` directory
293
+
294
+ 4. **Verify the build:**
295
+ ```bash
296
+ ls -la dist/
297
+ ```
298
+
299
+ You should see:
300
+ - `svelte-feature-flags-toggly.es.js` - ES Module build
301
+ - `svelte-feature-flags-toggly.cjs` - CommonJS build
302
+ - `index.js` - Svelte component entry point
303
+ - `types/` - TypeScript declaration files
304
+
305
+ ### Testing the Build Locally
306
+
307
+ You can test the built package locally using npm link:
308
+
309
+ 1. **Link the package:**
310
+ ```bash
311
+ npm link
312
+ ```
313
+
314
+ 2. **In your test project:**
315
+ ```bash
316
+ npm link @ops-ai/svelte-feature-flags-toggly
317
+ ```
318
+
319
+ 3. **Or test with the example app:**
320
+ ```bash
321
+ cd example
322
+ npm install
323
+ npm run dev
324
+ ```
325
+
326
+ ## Publishing to npm
327
+
328
+ ### Prerequisites for Publishing
329
+
330
+ 1. **npm account**: You need an npm account with access to the `@ops-ai` organization
331
+ 2. **Authentication**: You must be logged in to npm:
332
+ ```bash
333
+ npm login
334
+ ```
335
+
336
+ 3. **Organization access**: Ensure you have publish permissions for `@ops-ai` scope
337
+
338
+ ### Publishing Steps
339
+
340
+ 1. **Update version number:**
341
+
342
+ Update the version in `package.json` following [Semantic Versioning](https://semver.org/):
343
+ - **Patch** (1.0.0 → 1.0.1): Bug fixes
344
+ - **Minor** (1.0.0 → 1.1.0): New features (backward compatible)
345
+ - **Major** (1.0.0 → 2.0.0): Breaking changes
346
+
347
+ ```bash
348
+ # Or use npm version command
349
+ npm version patch # for 1.0.0 → 1.0.1
350
+ npm version minor # for 1.0.0 → 1.1.0
351
+ npm version major # for 1.0.0 → 2.0.0
352
+ ```
353
+
354
+ 2. **Update CHANGELOG.md:**
355
+
356
+ Document the changes in `CHANGELOG.md` with the new version number and date.
357
+
358
+ 3. **Build the library:**
359
+ ```bash
360
+ npm run build
361
+ ```
362
+
363
+ 4. **Verify the build output:**
364
+ ```bash
365
+ # Check that dist/ contains all necessary files
366
+ ls -la dist/
367
+ ```
368
+
369
+ 5. **Dry run (optional but recommended):**
370
+ ```bash
371
+ npm publish --dry-run
372
+ ```
373
+
374
+ This shows what would be published without actually publishing.
375
+
376
+ 6. **Publish to npm:**
377
+ ```bash
378
+ npm publish --access public
379
+ ```
380
+
381
+ The `--access public` flag is required for scoped packages (`@ops-ai/...`) to be published publicly.
382
+
383
+ ### Publishing Checklist
384
+
385
+ Before publishing, ensure:
386
+
387
+ - [ ] Version number is updated in `package.json`
388
+ - [ ] `CHANGELOG.md` is updated with new version
389
+ - [ ] All tests pass (if applicable)
390
+ - [ ] Build completes successfully
391
+ - [ ] `dist/` directory contains all expected files
392
+ - [ ] TypeScript declarations are generated correctly
393
+ - [ ] README.md is up to date
394
+ - [ ] License file is present
395
+ - [ ] `.npmignore` excludes source files and examples
396
+
397
+ ### Post-Publishing
398
+
399
+ After successful publication:
400
+
401
+ 1. **Create a git tag:**
402
+ ```bash
403
+ git tag v1.0.0
404
+ git push origin v1.0.0
405
+ ```
406
+
407
+ 2. **Verify on npm:**
408
+ Visit `https://www.npmjs.com/package/@ops-ai/svelte-feature-flags-toggly` to confirm the new version is available.
409
+
410
+ 3. **Update documentation:**
411
+ If this is a major release or includes breaking changes, update the main Toggly documentation.
412
+
413
+ ### Troubleshooting
414
+
415
+ **Error: "You do not have permission to publish"**
416
+ - Ensure you're logged in: `npm whoami`
417
+ - Verify you have access to the `@ops-ai` organization
418
+ - Contact the organization admin for access
419
+
420
+ **Error: "Package name already exists"**
421
+ - Check if the version already exists on npm
422
+ - Increment the version number
423
+
424
+ **Build fails:**
425
+ - Ensure all dependencies are installed: `npm install`
426
+ - Check TypeScript errors: `npm run typecheck`
427
+ - Verify `vite.config.ts` is correctly configured
428
+
429
+ ## Find out more about Toggly.io
430
+
431
+ Visit [our official website](https://toggly.io) or [check out a video overview of our product](https://docs.toggly.io/).
@@ -0,0 +1 @@
1
+ "use strict";var B=Object.defineProperty;var V=(e,t,n)=>t in e?B(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var x=(e,t,n)=>V(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("svelte/store"),H=require("svelte");class U{constructor(t){this._config={baseURI:"https://client.toggly.io",showFeatureDuringEvaluation:!1,featureFlagsRefreshInterval:3*60*1e3},this._features=null,this._loadingFeatures=!1,this._lastFetchTime=0,this.shouldShowFeatureDuringEvaluation=!1,this._loadFeatures=async()=>{this._loadingFeatures&&await new Promise(o=>{const l=()=>{this._loadingFeatures?setTimeout(l,100):o()};l()});const r=Date.now()-this._lastFetchTime,a=this._config.featureFlagsRefreshInterval??3*60*1e3;if(this._features!==null&&r<a)return this._features;if(this._features!==null&&r<a)return this._features;this._loadingFeatures=!0;try{var s=`${this._config.baseURI}/${this._config.appKey}-${this._config.environment}/defs`;this._config.identity&&(s+=`?u=${this._config.identity}`);const o=await fetch(s);this._features=await o.json(),this._lastFetchTime=Date.now()}catch{this._features===null&&(this._features=this._config.featureDefaults??{}),console.warn("Toggly --- Using feature defaults or cached values as features could not be loaded from the Toggly API")}finally{this._loadingFeatures=!1}return this._features},this._featuresLoaded=async()=>this._features??await this._loadFeatures(),this._evaluateFeatureGate=async(n,r="all",a=!1)=>{if(await this._featuresLoaded(),!this._features||Object.keys(this._features).length===0)return!0;var s;return r==="any"?s=n.reduce((o,l)=>o||this._features[l]&&this._features[l]===!0,!1):s=n.reduce((o,l)=>o&&this._features[l]&&this._features[l]===!0,!0),s=a?!s:s,s},this.evaluateFeatureGate=async(n,r="all",a=!1)=>await this._evaluateFeatureGate(n,r,a),this.isFeatureOn=async n=>await this._evaluateFeatureGate([n]),this.isFeatureOff=async n=>await this._evaluateFeatureGate([n],"all",!0),this.refreshFlags=async()=>{this._lastFetchTime=0,await this._loadFeatures()},t.appKey?t.environment||(t.environment="Production",console.warn("Toggly --- Using Production environment as no environment provided when initializing the Toggly")):t.featureDefaults?(this._features=t.featureDefaults??{},console.warn("Toggly --- Using feature defaults as no application key provided when initializing the Toggly")):console.warn("Toggly --- A valid application key is required to connect to your Toggly.io application for evaluating your features."),this._config=Object.assign({},this._config,t),this.shouldShowFeatureDuringEvaluation=this._config.showFeatureDuringEvaluation??!1}}const G=S.writable(null),m=S.writable({});function p(){const e=S.get(G);if(!e)throw new Error("Toggly service not initialized. Call createToggly() first.");return e}function J(e){return S.derived(m,t=>t[e]??!1)}async function Q(e){return await p().isFeatureOn(e)}async function W(e){return await p().isFeatureOff(e)}async function X(e,t="all",n=!1){return await p().evaluateFeatureGate(e,t,n)}function E(){}function Y(e,t){for(const n in t)e[n]=t[n];return e}function A(e){return e()}function q(){return Object.create(null)}function T(e){e.forEach(A)}function C(e){return typeof e=="function"}function Z(e,t){return e!=e?t==t:e!==t||e&&typeof e=="object"||typeof e=="function"}function $(e){return Object.keys(e).length===0}function ee(e,t,n,r){if(e){const a=z(e,t,n,r);return e[0](a)}}function z(e,t,n,r){return e[1]&&r?Y(n.ctx.slice(),e[1](r(t))):n.ctx}function te(e,t,n,r){return e[2],t.dirty}function re(e,t,n,r,a,s){if(a){const o=z(t,n,r,s);e.p(o,a)}}function ne(e){if(e.ctx.length>32){const t=[],n=e.ctx.length/32;for(let r=0;r<n;r++)t[r]=-1;return t}return-1}function ae(e,t,n){e.insertBefore(t,n||null)}function L(e){e.parentNode&&e.parentNode.removeChild(e)}function se(e){return document.createTextNode(e)}function ie(){return se("")}function oe(e){return Array.from(e.childNodes)}let K;function v(e){K=e}const y=[],P=[];let w=[];const N=[],ue=Promise.resolve();let k=!1;function le(){k||(k=!0,ue.then(M))}function I(e){w.push(e)}const O=new Set;let _=0;function M(){if(_!==0)return;const e=K;do{try{for(;_<y.length;){const t=y[_];_++,v(t),fe(t.$$)}}catch(t){throw y.length=0,_=0,t}for(v(null),y.length=0,_=0;P.length;)P.pop()();for(let t=0;t<w.length;t+=1){const n=w[t];O.has(n)||(O.add(n),n())}w.length=0}while(y.length);for(;N.length;)N.pop()();k=!1,O.clear(),v(e)}function fe(e){if(e.fragment!==null){e.update(),T(e.before_update);const t=e.dirty;e.dirty=[-1],e.fragment&&e.fragment.p(e.ctx,t),e.after_update.forEach(I)}}function ce(e){const t=[],n=[];w.forEach(r=>e.indexOf(r)===-1?t.push(r):n.push(r)),n.forEach(r=>r()),w=t}const b=new Set;let g;function he(){g={r:0,c:[],p:g}}function ge(){g.r||T(g.c),g=g.p}function F(e,t){e&&e.i&&(b.delete(e),e.i(t))}function D(e,t,n,r){if(e&&e.o){if(b.has(e))return;b.add(e),g.c.push(()=>{b.delete(e),r&&(n&&e.d(1),r())}),e.o(t)}else r&&r()}function de(e,t,n){const{fragment:r,after_update:a}=e.$$;r&&r.m(t,n),I(()=>{const s=e.$$.on_mount.map(A).filter(C);e.$$.on_destroy?e.$$.on_destroy.push(...s):T(s),e.$$.on_mount=[]}),a.forEach(I)}function _e(e,t){const n=e.$$;n.fragment!==null&&(ce(n.after_update),T(n.on_destroy),n.fragment&&n.fragment.d(t),n.on_destroy=n.fragment=null,n.ctx=[])}function ye(e,t){e.$$.dirty[0]===-1&&(y.push(e),le(),e.$$.dirty.fill(0)),e.$$.dirty[t/31|0]|=1<<t%31}function we(e,t,n,r,a,s,o=null,l=[-1]){const h=K;v(e);const i=e.$$={fragment:null,ctx:[],props:s,update:E,not_equal:a,bound:q(),on_mount:[],on_destroy:[],on_disconnect:[],before_update:[],after_update:[],context:new Map(t.context||(h?h.$$.context:[])),callbacks:q(),dirty:l,skip_bound:!1,root:t.target||h.$$.root};o&&o(i.root);let c=!1;if(i.ctx=n?n(e,t.props||{},(f,u,...d)=>{const j=d.length?d[0]:u;return i.ctx&&a(i.ctx[f],i.ctx[f]=j)&&(!i.skip_bound&&i.bound[f]&&i.bound[f](j),c&&ye(e,f)),u}):[],i.update(),c=!0,T(i.before_update),i.fragment=r?r(i.ctx):!1,t.target){if(t.hydrate){const f=oe(t.target);i.fragment&&i.fragment.l(f),f.forEach(L)}else i.fragment&&i.fragment.c();t.intro&&F(e.$$.fragment),de(e,t.target,t.anchor),M()}v(h)}class me{constructor(){x(this,"$$");x(this,"$$set")}$destroy(){_e(this,1),this.$destroy=E}$on(t,n){if(!C(n))return E;const r=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return r.push(n),()=>{const a=r.indexOf(n);a!==-1&&r.splice(a,1)}}$set(t){this.$$set&&!$(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}}const ve="4";typeof window<"u"&&(window.__svelte||(window.__svelte={v:new Set})).v.add(ve);function R(e){let t;const n=e[7].default,r=ee(n,e,e[6],null);return{c(){r&&r.c()},m(a,s){r&&r.m(a,s),t=!0},p(a,s){r&&r.p&&(!t||s&64)&&re(r,n,a,a[6],t?te(n,a[6],s,null):ne(a[6]),null)},i(a){t||(F(r,a),t=!0)},o(a){D(r,a),t=!1},d(a){r&&r.d(a)}}}function Fe(e){let t,n,r=e[0]&&R(e);return{c(){r&&r.c(),t=ie()},m(a,s){r&&r.m(a,s),ae(a,t,s),n=!0},p(a,[s]){a[0]?r?(r.p(a,s),s&1&&F(r,1)):(r=R(a),r.c(),F(r,1),r.m(t.parentNode,t)):r&&(he(),D(r,1,1,()=>{r=null}),ge())},i(a){n||(F(r),n=!0)},o(a){D(r),n=!1},d(a){a&&L(t),r&&r.d(a)}}}function pe(e,t,n){let{$$slots:r={},$$scope:a}=t,{featureKey:s=void 0}=t,{featureKeys:o=void 0}=t,{requirement:l="all"}=t,{negate:h=!1}=t,i=!1,c=null;async function f(){if(!c)try{n(5,c=p())}catch(d){console.error("Toggly Feature component error:",d),n(0,i=!1);return}n(0,i=c.shouldShowFeatureDuringEvaluation);const u=[];if(s&&u.push(s),o&&u.push(...o),u.length>0&&c)try{n(0,i=await c.evaluateFeatureGate(u,l,h))}catch(d){console.error("Toggly Feature evaluation error:",d),n(0,i=!1)}else n(0,i=!0)}return H.onMount(()=>{f()}),e.$$set=u=>{"featureKey"in u&&n(1,s=u.featureKey),"featureKeys"in u&&n(2,o=u.featureKeys),"requirement"in u&&n(3,l=u.requirement),"negate"in u&&n(4,h=u.negate),"$$scope"in u&&n(6,a=u.$$scope)},e.$$.update=()=>{e.$$.dirty&38&&(c||s||o)&&f()},[i,s,o,l,h,c,a,r]}class Te extends me{constructor(t){super(),we(this,t,pe,Fe,Z,{featureKey:1,featureKeys:2,requirement:3,negate:4})}}async function be(e){const t=new U(e);G.set(t);try{const r=await t._loadFeatures();r&&m.set(r)}catch(r){console.error("Toggly initialization error:",r),m.set({})}const n=e.featureFlagsRefreshInterval??3*60*1e3;n>0&&e.appKey&&setInterval(async()=>{try{await t.refreshFlags();const r=await t._loadFeatures();r&&m.set(r)}catch(r){console.warn("Toggly refresh error:",r)}},n)}exports.Feature=Te;exports.Toggly=U;exports.createFeatureStore=J;exports.createToggly=be;exports.evaluateFeatureGate=X;exports.getTogglyService=p;exports.isFeatureOff=W;exports.isFeatureOn=Q;exports.togglyFlagsStore=m;exports.togglyServiceStore=G;
@@ -0,0 +1,480 @@
1
+ var B = Object.defineProperty;
2
+ var M = (e, t, r) => t in e ? B(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
3
+ var x = (e, t, r) => M(e, typeof t != "symbol" ? t + "" : t, r);
4
+ import { writable as R, get as V, derived as H } from "svelte/store";
5
+ import { onMount as J } from "svelte";
6
+ class Q {
7
+ constructor(t) {
8
+ this._config = {
9
+ baseURI: "https://client.toggly.io",
10
+ showFeatureDuringEvaluation: !1,
11
+ featureFlagsRefreshInterval: 3 * 60 * 1e3
12
+ // 3 minutes
13
+ }, this._features = null, this._loadingFeatures = !1, this._lastFetchTime = 0, this.shouldShowFeatureDuringEvaluation = !1, this._loadFeatures = async () => {
14
+ this._loadingFeatures && await new Promise((o) => {
15
+ const l = () => {
16
+ this._loadingFeatures ? setTimeout(l, 100) : o();
17
+ };
18
+ l();
19
+ });
20
+ const n = Date.now() - this._lastFetchTime, a = this._config.featureFlagsRefreshInterval ?? 3 * 60 * 1e3;
21
+ if (this._features !== null && n < a)
22
+ return this._features;
23
+ if (this._features !== null && n < a)
24
+ return this._features;
25
+ this._loadingFeatures = !0;
26
+ try {
27
+ var s = `${this._config.baseURI}/${this._config.appKey}-${this._config.environment}/defs`;
28
+ this._config.identity && (s += `?u=${this._config.identity}`);
29
+ const o = await fetch(s);
30
+ this._features = await o.json(), this._lastFetchTime = Date.now();
31
+ } catch {
32
+ this._features === null && (this._features = this._config.featureDefaults ?? {}), console.warn(
33
+ "Toggly --- Using feature defaults or cached values as features could not be loaded from the Toggly API"
34
+ );
35
+ } finally {
36
+ this._loadingFeatures = !1;
37
+ }
38
+ return this._features;
39
+ }, this._featuresLoaded = async () => this._features ?? await this._loadFeatures(), this._evaluateFeatureGate = async (r, n = "all", a = !1) => {
40
+ if (await this._featuresLoaded(), !this._features || Object.keys(this._features).length === 0)
41
+ return !0;
42
+ var s;
43
+ return n === "any" ? s = r.reduce((o, l) => o || this._features[l] && this._features[l] === !0, !1) : s = r.reduce((o, l) => o && this._features[l] && this._features[l] === !0, !0), s = a ? !s : s, s;
44
+ }, this.evaluateFeatureGate = async (r, n = "all", a = !1) => await this._evaluateFeatureGate(r, n, a), this.isFeatureOn = async (r) => await this._evaluateFeatureGate([r]), this.isFeatureOff = async (r) => await this._evaluateFeatureGate([r], "all", !0), this.refreshFlags = async () => {
45
+ this._lastFetchTime = 0, await this._loadFeatures();
46
+ }, t.appKey ? t.environment || (t.environment = "Production", console.warn(
47
+ "Toggly --- Using Production environment as no environment provided when initializing the Toggly"
48
+ )) : t.featureDefaults ? (this._features = t.featureDefaults ?? {}, console.warn(
49
+ "Toggly --- Using feature defaults as no application key provided when initializing the Toggly"
50
+ )) : console.warn(
51
+ "Toggly --- A valid application key is required to connect to your Toggly.io application for evaluating your features."
52
+ ), this._config = Object.assign({}, this._config, t), this.shouldShowFeatureDuringEvaluation = this._config.showFeatureDuringEvaluation ?? !1;
53
+ }
54
+ }
55
+ const U = R(null), p = R({});
56
+ function b() {
57
+ const e = V(U);
58
+ if (!e)
59
+ throw new Error("Toggly service not initialized. Call createToggly() first.");
60
+ return e;
61
+ }
62
+ function be(e) {
63
+ return H(p, (t) => t[e] ?? !1);
64
+ }
65
+ async function xe(e) {
66
+ return await b().isFeatureOn(e);
67
+ }
68
+ async function Ee(e) {
69
+ return await b().isFeatureOff(e);
70
+ }
71
+ async function Se(e, t = "all", r = !1) {
72
+ return await b().evaluateFeatureGate(e, t, r);
73
+ }
74
+ function S() {
75
+ }
76
+ function W(e, t) {
77
+ for (const r in t) e[r] = t[r];
78
+ return (
79
+ /** @type {T & S} */
80
+ e
81
+ );
82
+ }
83
+ function q(e) {
84
+ return e();
85
+ }
86
+ function G() {
87
+ return /* @__PURE__ */ Object.create(null);
88
+ }
89
+ function F(e) {
90
+ e.forEach(q);
91
+ }
92
+ function A(e) {
93
+ return typeof e == "function";
94
+ }
95
+ function X(e, t) {
96
+ return e != e ? t == t : e !== t || e && typeof e == "object" || typeof e == "function";
97
+ }
98
+ function Y(e) {
99
+ return Object.keys(e).length === 0;
100
+ }
101
+ function Z(e, t, r, n) {
102
+ if (e) {
103
+ const a = C(e, t, r, n);
104
+ return e[0](a);
105
+ }
106
+ }
107
+ function C(e, t, r, n) {
108
+ return e[1] && n ? W(r.ctx.slice(), e[1](n(t))) : r.ctx;
109
+ }
110
+ function $(e, t, r, n) {
111
+ return e[2], t.dirty;
112
+ }
113
+ function ee(e, t, r, n, a, s) {
114
+ if (a) {
115
+ const o = C(t, r, n, s);
116
+ e.p(o, a);
117
+ }
118
+ }
119
+ function te(e) {
120
+ if (e.ctx.length > 32) {
121
+ const t = [], r = e.ctx.length / 32;
122
+ for (let n = 0; n < r; n++)
123
+ t[n] = -1;
124
+ return t;
125
+ }
126
+ return -1;
127
+ }
128
+ function ne(e, t, r) {
129
+ e.insertBefore(t, r || null);
130
+ }
131
+ function z(e) {
132
+ e.parentNode && e.parentNode.removeChild(e);
133
+ }
134
+ function re(e) {
135
+ return document.createTextNode(e);
136
+ }
137
+ function ae() {
138
+ return re("");
139
+ }
140
+ function se(e) {
141
+ return Array.from(e.childNodes);
142
+ }
143
+ let D;
144
+ function w(e) {
145
+ D = e;
146
+ }
147
+ const y = [], j = [];
148
+ let m = [];
149
+ const N = [], ie = /* @__PURE__ */ Promise.resolve();
150
+ let k = !1;
151
+ function oe() {
152
+ k || (k = !0, ie.then(L));
153
+ }
154
+ function O(e) {
155
+ m.push(e);
156
+ }
157
+ const E = /* @__PURE__ */ new Set();
158
+ let g = 0;
159
+ function L() {
160
+ if (g !== 0)
161
+ return;
162
+ const e = D;
163
+ do {
164
+ try {
165
+ for (; g < y.length; ) {
166
+ const t = y[g];
167
+ g++, w(t), ue(t.$$);
168
+ }
169
+ } catch (t) {
170
+ throw y.length = 0, g = 0, t;
171
+ }
172
+ for (w(null), y.length = 0, g = 0; j.length; ) j.pop()();
173
+ for (let t = 0; t < m.length; t += 1) {
174
+ const r = m[t];
175
+ E.has(r) || (E.add(r), r());
176
+ }
177
+ m.length = 0;
178
+ } while (y.length);
179
+ for (; N.length; )
180
+ N.pop()();
181
+ k = !1, E.clear(), w(e);
182
+ }
183
+ function ue(e) {
184
+ if (e.fragment !== null) {
185
+ e.update(), F(e.before_update);
186
+ const t = e.dirty;
187
+ e.dirty = [-1], e.fragment && e.fragment.p(e.ctx, t), e.after_update.forEach(O);
188
+ }
189
+ }
190
+ function le(e) {
191
+ const t = [], r = [];
192
+ m.forEach((n) => e.indexOf(n) === -1 ? t.push(n) : r.push(n)), r.forEach((n) => n()), m = t;
193
+ }
194
+ const T = /* @__PURE__ */ new Set();
195
+ let d;
196
+ function fe() {
197
+ d = {
198
+ r: 0,
199
+ c: [],
200
+ p: d
201
+ // parent group
202
+ };
203
+ }
204
+ function ce() {
205
+ d.r || F(d.c), d = d.p;
206
+ }
207
+ function v(e, t) {
208
+ e && e.i && (T.delete(e), e.i(t));
209
+ }
210
+ function I(e, t, r, n) {
211
+ if (e && e.o) {
212
+ if (T.has(e)) return;
213
+ T.add(e), d.c.push(() => {
214
+ T.delete(e), n && (r && e.d(1), n());
215
+ }), e.o(t);
216
+ } else n && n();
217
+ }
218
+ function he(e, t, r) {
219
+ const { fragment: n, after_update: a } = e.$$;
220
+ n && n.m(t, r), O(() => {
221
+ const s = e.$$.on_mount.map(q).filter(A);
222
+ e.$$.on_destroy ? e.$$.on_destroy.push(...s) : F(s), e.$$.on_mount = [];
223
+ }), a.forEach(O);
224
+ }
225
+ function de(e, t) {
226
+ const r = e.$$;
227
+ r.fragment !== null && (le(r.after_update), F(r.on_destroy), r.fragment && r.fragment.d(t), r.on_destroy = r.fragment = null, r.ctx = []);
228
+ }
229
+ function _e(e, t) {
230
+ e.$$.dirty[0] === -1 && (y.push(e), oe(), e.$$.dirty.fill(0)), e.$$.dirty[t / 31 | 0] |= 1 << t % 31;
231
+ }
232
+ function ge(e, t, r, n, a, s, o = null, l = [-1]) {
233
+ const h = D;
234
+ w(e);
235
+ const i = e.$$ = {
236
+ fragment: null,
237
+ ctx: [],
238
+ // state
239
+ props: s,
240
+ update: S,
241
+ not_equal: a,
242
+ bound: G(),
243
+ // lifecycle
244
+ on_mount: [],
245
+ on_destroy: [],
246
+ on_disconnect: [],
247
+ before_update: [],
248
+ after_update: [],
249
+ context: new Map(t.context || (h ? h.$$.context : [])),
250
+ // everything else
251
+ callbacks: G(),
252
+ dirty: l,
253
+ skip_bound: !1,
254
+ root: t.target || h.$$.root
255
+ };
256
+ o && o(i.root);
257
+ let c = !1;
258
+ if (i.ctx = r ? r(e, t.props || {}, (f, u, ..._) => {
259
+ const K = _.length ? _[0] : u;
260
+ return i.ctx && a(i.ctx[f], i.ctx[f] = K) && (!i.skip_bound && i.bound[f] && i.bound[f](K), c && _e(e, f)), u;
261
+ }) : [], i.update(), c = !0, F(i.before_update), i.fragment = n ? n(i.ctx) : !1, t.target) {
262
+ if (t.hydrate) {
263
+ const f = se(t.target);
264
+ i.fragment && i.fragment.l(f), f.forEach(z);
265
+ } else
266
+ i.fragment && i.fragment.c();
267
+ t.intro && v(e.$$.fragment), he(e, t.target, t.anchor), L();
268
+ }
269
+ w(h);
270
+ }
271
+ class ye {
272
+ constructor() {
273
+ /**
274
+ * ### PRIVATE API
275
+ *
276
+ * Do not use, may change at any time
277
+ *
278
+ * @type {any}
279
+ */
280
+ x(this, "$$");
281
+ /**
282
+ * ### PRIVATE API
283
+ *
284
+ * Do not use, may change at any time
285
+ *
286
+ * @type {any}
287
+ */
288
+ x(this, "$$set");
289
+ }
290
+ /** @returns {void} */
291
+ $destroy() {
292
+ de(this, 1), this.$destroy = S;
293
+ }
294
+ /**
295
+ * @template {Extract<keyof Events, string>} K
296
+ * @param {K} type
297
+ * @param {((e: Events[K]) => void) | null | undefined} callback
298
+ * @returns {() => void}
299
+ */
300
+ $on(t, r) {
301
+ if (!A(r))
302
+ return S;
303
+ const n = this.$$.callbacks[t] || (this.$$.callbacks[t] = []);
304
+ return n.push(r), () => {
305
+ const a = n.indexOf(r);
306
+ a !== -1 && n.splice(a, 1);
307
+ };
308
+ }
309
+ /**
310
+ * @param {Partial<Props>} props
311
+ * @returns {void}
312
+ */
313
+ $set(t) {
314
+ this.$$set && !Y(t) && (this.$$.skip_bound = !0, this.$$set(t), this.$$.skip_bound = !1);
315
+ }
316
+ }
317
+ const me = "4";
318
+ typeof window < "u" && (window.__svelte || (window.__svelte = { v: /* @__PURE__ */ new Set() })).v.add(me);
319
+ function P(e) {
320
+ let t;
321
+ const r = (
322
+ /*#slots*/
323
+ e[7].default
324
+ ), n = Z(
325
+ r,
326
+ e,
327
+ /*$$scope*/
328
+ e[6],
329
+ null
330
+ );
331
+ return {
332
+ c() {
333
+ n && n.c();
334
+ },
335
+ m(a, s) {
336
+ n && n.m(a, s), t = !0;
337
+ },
338
+ p(a, s) {
339
+ n && n.p && (!t || s & /*$$scope*/
340
+ 64) && ee(
341
+ n,
342
+ r,
343
+ a,
344
+ /*$$scope*/
345
+ a[6],
346
+ t ? $(
347
+ r,
348
+ /*$$scope*/
349
+ a[6],
350
+ s,
351
+ null
352
+ ) : te(
353
+ /*$$scope*/
354
+ a[6]
355
+ ),
356
+ null
357
+ );
358
+ },
359
+ i(a) {
360
+ t || (v(n, a), t = !0);
361
+ },
362
+ o(a) {
363
+ I(n, a), t = !1;
364
+ },
365
+ d(a) {
366
+ n && n.d(a);
367
+ }
368
+ };
369
+ }
370
+ function we(e) {
371
+ let t, r, n = (
372
+ /*shouldShow*/
373
+ e[0] && P(e)
374
+ );
375
+ return {
376
+ c() {
377
+ n && n.c(), t = ae();
378
+ },
379
+ m(a, s) {
380
+ n && n.m(a, s), ne(a, t, s), r = !0;
381
+ },
382
+ p(a, [s]) {
383
+ /*shouldShow*/
384
+ a[0] ? n ? (n.p(a, s), s & /*shouldShow*/
385
+ 1 && v(n, 1)) : (n = P(a), n.c(), v(n, 1), n.m(t.parentNode, t)) : n && (fe(), I(n, 1, 1, () => {
386
+ n = null;
387
+ }), ce());
388
+ },
389
+ i(a) {
390
+ r || (v(n), r = !0);
391
+ },
392
+ o(a) {
393
+ I(n), r = !1;
394
+ },
395
+ d(a) {
396
+ a && z(t), n && n.d(a);
397
+ }
398
+ };
399
+ }
400
+ function ve(e, t, r) {
401
+ let { $$slots: n = {}, $$scope: a } = t, { featureKey: s = void 0 } = t, { featureKeys: o = void 0 } = t, { requirement: l = "all" } = t, { negate: h = !1 } = t, i = !1, c = null;
402
+ async function f() {
403
+ if (!c)
404
+ try {
405
+ r(5, c = b());
406
+ } catch (_) {
407
+ console.error("Toggly Feature component error:", _), r(0, i = !1);
408
+ return;
409
+ }
410
+ r(0, i = c.shouldShowFeatureDuringEvaluation);
411
+ const u = [];
412
+ if (s && u.push(s), o && u.push(...o), u.length > 0 && c)
413
+ try {
414
+ r(0, i = await c.evaluateFeatureGate(u, l, h));
415
+ } catch (_) {
416
+ console.error("Toggly Feature evaluation error:", _), r(0, i = !1);
417
+ }
418
+ else
419
+ r(0, i = !0);
420
+ }
421
+ return J(() => {
422
+ f();
423
+ }), e.$$set = (u) => {
424
+ "featureKey" in u && r(1, s = u.featureKey), "featureKeys" in u && r(2, o = u.featureKeys), "requirement" in u && r(3, l = u.requirement), "negate" in u && r(4, h = u.negate), "$$scope" in u && r(6, a = u.$$scope);
425
+ }, e.$$.update = () => {
426
+ e.$$.dirty & /*toggly, featureKey, featureKeys*/
427
+ 38 && (c || s || o) && f();
428
+ }, [
429
+ i,
430
+ s,
431
+ o,
432
+ l,
433
+ h,
434
+ c,
435
+ a,
436
+ n
437
+ ];
438
+ }
439
+ class ke extends ye {
440
+ constructor(t) {
441
+ super(), ge(this, t, ve, we, X, {
442
+ featureKey: 1,
443
+ featureKeys: 2,
444
+ requirement: 3,
445
+ negate: 4
446
+ });
447
+ }
448
+ }
449
+ async function Oe(e) {
450
+ const t = new Q(e);
451
+ U.set(t);
452
+ try {
453
+ const n = await t._loadFeatures();
454
+ n && p.set(n);
455
+ } catch (n) {
456
+ console.error("Toggly initialization error:", n), p.set({});
457
+ }
458
+ const r = e.featureFlagsRefreshInterval ?? 3 * 60 * 1e3;
459
+ r > 0 && e.appKey && setInterval(async () => {
460
+ try {
461
+ await t.refreshFlags();
462
+ const n = await t._loadFeatures();
463
+ n && p.set(n);
464
+ } catch (n) {
465
+ console.warn("Toggly refresh error:", n);
466
+ }
467
+ }, r);
468
+ }
469
+ export {
470
+ ke as Feature,
471
+ Q as Toggly,
472
+ be as createFeatureStore,
473
+ Oe as createToggly,
474
+ Se as evaluateFeatureGate,
475
+ b as getTogglyService,
476
+ Ee as isFeatureOff,
477
+ xe as isFeatureOn,
478
+ p as togglyFlagsStore,
479
+ U as togglyServiceStore
480
+ };
@@ -0,0 +1,2 @@
1
+ export { default as Feature } from './Feature.svelte';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,7 @@
1
+ export * from './services';
2
+ export * from './stores';
3
+ export * from './components';
4
+ export * from './utils';
5
+ export { default as Feature } from './components/Feature.svelte';
6
+ export { createToggly } from './utils/createToggly';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AAGvB,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './toggly.service';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA"}
@@ -0,0 +1,46 @@
1
+ export interface TogglyOptions {
2
+ baseURI?: string;
3
+ appKey?: string;
4
+ environment?: string;
5
+ identity?: string;
6
+ featureDefaults?: {
7
+ [key: string]: boolean;
8
+ };
9
+ showFeatureDuringEvaluation?: boolean;
10
+ featureFlagsRefreshInterval?: number;
11
+ }
12
+ export interface TogglyService {
13
+ shouldShowFeatureDuringEvaluation: boolean;
14
+ _loadFeatures: () => Promise<{
15
+ [key: string]: boolean;
16
+ } | null>;
17
+ _featuresLoaded: () => Promise<{
18
+ [key: string]: boolean;
19
+ } | null>;
20
+ _evaluateFeatureGate: (gate: string[], requirement: string, negate: boolean) => Promise<boolean>;
21
+ evaluateFeatureGate: (featureKeys: string[], requirement: string, negate: boolean) => Promise<boolean>;
22
+ isFeatureOn: (featureKey: string) => Promise<boolean>;
23
+ isFeatureOff: (featureKey: string) => Promise<boolean>;
24
+ refreshFlags: () => Promise<void>;
25
+ }
26
+ export declare class Toggly implements TogglyService {
27
+ private _config;
28
+ private _features;
29
+ private _loadingFeatures;
30
+ private _lastFetchTime;
31
+ shouldShowFeatureDuringEvaluation: boolean;
32
+ constructor(config: TogglyOptions);
33
+ _loadFeatures: () => Promise<{
34
+ [key: string]: boolean;
35
+ } | null>;
36
+ _featuresLoaded: () => Promise<{
37
+ [key: string]: boolean;
38
+ } | null>;
39
+ _evaluateFeatureGate: (gate: string[], requirement?: string, negate?: boolean) => Promise<boolean>;
40
+ evaluateFeatureGate: (featureKeys: string[], requirement?: string, negate?: boolean) => Promise<boolean>;
41
+ isFeatureOn: (featureKey: string) => Promise<boolean>;
42
+ isFeatureOff: (featureKey: string) => Promise<boolean>;
43
+ refreshFlags: () => Promise<void>;
44
+ }
45
+ export default Toggly;
46
+ //# sourceMappingURL=toggly.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toggly.service.d.ts","sourceRoot":"","sources":["../../../src/services/toggly.service.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,eAAe,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;IAC5C,2BAA2B,CAAC,EAAE,OAAO,CAAA;IACrC,2BAA2B,CAAC,EAAE,MAAM,CAAA;CACrC;AAED,MAAM,WAAW,aAAa;IAC5B,iCAAiC,EAAE,OAAO,CAAA;IAC1C,aAAa,EAAE,MAAM,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IAC/D,eAAe,EAAE,MAAM,OAAO,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IACjE,oBAAoB,EAAE,CACpB,IAAI,EAAE,MAAM,EAAE,EACd,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,OAAO,KACZ,OAAO,CAAC,OAAO,CAAC,CAAA;IACrB,mBAAmB,EAAE,CACnB,WAAW,EAAE,MAAM,EAAE,EACrB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,OAAO,KACZ,OAAO,CAAC,OAAO,CAAC,CAAA;IACrB,WAAW,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACrD,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACtD,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAClC;AAED,qBAAa,MAAO,YAAW,aAAa;IAC1C,OAAO,CAAC,OAAO,CAId;IACD,OAAO,CAAC,SAAS,CAA0C;IAC3D,OAAO,CAAC,gBAAgB,CAAiB;IACzC,OAAO,CAAC,cAAc,CAAY;IAElC,iCAAiC,EAAE,OAAO,CAAQ;gBAEtC,MAAM,EAAE,aAAa;IA2BjC,aAAa;;cAsDZ;IAED,eAAe;;cAEd;IAED,oBAAoB,GAClB,MAAM,MAAM,EAAE,EACd,oBAAmB,EACnB,gBAAc,sBA8Bf;IAED,mBAAmB,GACjB,aAAa,MAAM,EAAE,EACrB,oBAAmB,EACnB,gBAAc,sBAGf;IAED,WAAW,GAAU,YAAY,MAAM,sBAEtC;IAED,YAAY,GAAU,YAAY,MAAM,sBAEvC;IAED,YAAY,QAAa,OAAO,CAAC,IAAI,CAAC,CAGrC;CACF;AAED,eAAe,MAAM,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './toggly.store';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/stores/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA"}
@@ -0,0 +1,43 @@
1
+ import type { TogglyService } from '../services/toggly.service';
2
+ /**
3
+ * Store for the Toggly service instance
4
+ */
5
+ export declare const togglyServiceStore: import("svelte/store").Writable<TogglyService | null>;
6
+ /**
7
+ * Store for feature flags (key-value pairs)
8
+ */
9
+ export declare const togglyFlagsStore: import("svelte/store").Writable<{
10
+ [key: string]: boolean;
11
+ }>;
12
+ /**
13
+ * Get the Toggly service instance from the store
14
+ * @throws Error if service is not initialized
15
+ */
16
+ export declare function getTogglyService(): TogglyService;
17
+ /**
18
+ * Create a derived store for a specific feature flag
19
+ * @param featureKey - The feature flag key
20
+ * @returns A derived store that returns the boolean value of the feature flag
21
+ */
22
+ export declare function createFeatureStore(featureKey: string): import("svelte/store").Readable<boolean>;
23
+ /**
24
+ * Check if a feature is enabled
25
+ * @param featureKey - The feature flag key
26
+ * @returns Promise resolving to true if feature is enabled
27
+ */
28
+ export declare function isFeatureOn(featureKey: string): Promise<boolean>;
29
+ /**
30
+ * Check if a feature is disabled
31
+ * @param featureKey - The feature flag key
32
+ * @returns Promise resolving to true if feature is disabled
33
+ */
34
+ export declare function isFeatureOff(featureKey: string): Promise<boolean>;
35
+ /**
36
+ * Evaluate a feature gate (multiple features with requirement and negate)
37
+ * @param featureKeys - Array of feature flag keys
38
+ * @param requirement - 'all' or 'any' (default: 'all')
39
+ * @param negate - Whether to negate the result (default: false)
40
+ * @returns Promise resolving to the evaluation result
41
+ */
42
+ export declare function evaluateFeatureGate(featureKeys: string[], requirement?: 'all' | 'any', negate?: boolean): Promise<boolean>;
43
+ //# sourceMappingURL=toggly.store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toggly.store.d.ts","sourceRoot":"","sources":["../../../src/stores/toggly.store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAE/D;;GAEG;AACH,eAAO,MAAM,kBAAkB,uDAAuC,CAAA;AAEtE;;GAEG;AACH,eAAO,MAAM,gBAAgB;;EAA2C,CAAA;AAExE;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAMhD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,4CAEpD;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGtE;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGvE;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EAAE,EACrB,WAAW,GAAE,KAAK,GAAG,KAAa,EAClC,MAAM,GAAE,OAAe,GACtB,OAAO,CAAC,OAAO,CAAC,CAGlB"}
@@ -0,0 +1,22 @@
1
+ import { type TogglyOptions } from '../services/toggly.service';
2
+ /**
3
+ * Initialize Toggly with the provided configuration
4
+ * This function sets up the Toggly service and loads feature flags
5
+ *
6
+ * @param config - Toggly configuration options
7
+ * @returns Promise that resolves when initialization is complete
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { createToggly } from '@ops-ai/svelte-feature-flags-toggly'
12
+ *
13
+ * await createToggly({
14
+ * appKey: 'your-app-key',
15
+ * environment: 'Production',
16
+ * identity: 'user-123'
17
+ * })
18
+ * ```
19
+ */
20
+ export declare function createToggly(config: TogglyOptions): Promise<void>;
21
+ export default createToggly;
22
+ //# sourceMappingURL=createToggly.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createToggly.d.ts","sourceRoot":"","sources":["../../../src/utils/createToggly.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAGvE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAiCvE;AAED,eAAe,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './createToggly';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@ops-ai/svelte-feature-flags-toggly",
3
+ "version": "1.0.0",
4
+ "description": "Provides feature flags support for Svelte applications allowing you to enable and disable features easily. Can be used with or without Toggly.io.",
5
+ "type": "module",
6
+ "main": "./dist/svelte-feature-flags-toggly.cjs",
7
+ "module": "./dist/svelte-feature-flags-toggly.es.js",
8
+ "svelte": "./dist/index.js",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/svelte-feature-flags-toggly.es.js",
12
+ "require": "./dist/svelte-feature-flags-toggly.cjs",
13
+ "svelte": "./dist/index.js"
14
+ },
15
+ "./package.json": "./package.json"
16
+ },
17
+ "types": "./dist/types/index.d.ts",
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "scripts": {
22
+ "dev": "vite",
23
+ "build": "vite build && tsc --emitDeclarationOnly --outDir dist/types",
24
+ "prepublishOnly": "npm run build",
25
+ "check": "svelte-check --tsconfig ./tsconfig.json",
26
+ "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
27
+ "test": "vitest",
28
+ "typecheck": "svelte-check --tsconfig ./tsconfig.json"
29
+ },
30
+ "keywords": [
31
+ "svelte",
32
+ "feature-flags",
33
+ "feature-toggles",
34
+ "toggly",
35
+ "ab-testing"
36
+ ],
37
+ "author": {
38
+ "name": "Cosmin Atomei",
39
+ "email": "cosmin.atomei@gmail.com"
40
+ },
41
+ "license": "BSD-3-Clause",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/ops-ai/Toggly.FeatureManagement.git",
45
+ "directory": "Toggly.FeatureManagement/Toggly.FeatureManagement.Svelte/svelte-feature-flags-toggly"
46
+ },
47
+ "bugs": {
48
+ "url": "https://github.com/ops-ai/Toggly.FeatureManagement/issues"
49
+ },
50
+ "homepage": "https://github.com/ops-ai/Toggly.FeatureManagement/tree/develop/Toggly.FeatureManagement/Toggly.FeatureManagement.Svelte/svelte-feature-flags-toggly#readme",
51
+ "peerDependencies": {
52
+ "svelte": "^4.0.0 || ^5.0.0"
53
+ },
54
+ "devDependencies": {
55
+ "@sveltejs/vite-plugin-svelte": "^3.0.0",
56
+ "@types/node": "^20.0.0",
57
+ "svelte": "^4.2.0",
58
+ "svelte-check": "^3.6.0",
59
+ "typescript": "^5.0.0",
60
+ "vite": "^5.0.0",
61
+ "vitest": "^1.0.0"
62
+ }
63
+ }