@ops-ai/electron-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.
@@ -0,0 +1,141 @@
1
+ import { useMemo, useState, useEffect, useCallback } from 'react';
2
+ import { jsx, Fragment } from 'react/jsx-runtime';
3
+
4
+ // src/react/Feature.tsx
5
+
6
+ // src/renderer/index.ts
7
+ function tryBridge() {
8
+ if (typeof window === "undefined" || !window.toggly) {
9
+ return null;
10
+ }
11
+ return window.toggly;
12
+ }
13
+ function isFeatureOn(key, entityContext, kind) {
14
+ const bridge = tryBridge();
15
+ if (!bridge) {
16
+ return false;
17
+ }
18
+ return bridge.isFeatureOn(key, entityContext, kind);
19
+ }
20
+ function evaluateFeatureGate(keys, requirement, negate, entityContext, kind) {
21
+ const bridge = tryBridge();
22
+ if (!bridge) {
23
+ return negate ?? false;
24
+ }
25
+ return bridge.evaluateFeatureGate(keys, requirement, negate, entityContext, kind);
26
+ }
27
+ function onFlagsUpdated(callback) {
28
+ const bridge = tryBridge();
29
+ if (!bridge) {
30
+ return () => void 0;
31
+ }
32
+ return bridge.onFlagsUpdated(callback);
33
+ }
34
+ function Feature({
35
+ featureKey,
36
+ featureKeys = [],
37
+ requirement = "all",
38
+ negate = false,
39
+ context,
40
+ contextKind,
41
+ children,
42
+ loading = null
43
+ }) {
44
+ const gate = useMemo(() => {
45
+ if (featureKey) {
46
+ return [featureKey, ...featureKeys];
47
+ }
48
+ return [...featureKeys];
49
+ }, [featureKey, featureKeys]);
50
+ const [shouldShow, setShouldShow] = useState(null);
51
+ useEffect(() => {
52
+ const evaluate = () => {
53
+ if (gate.length === 0) {
54
+ setShouldShow(!negate);
55
+ return;
56
+ }
57
+ try {
58
+ setShouldShow(
59
+ evaluateFeatureGate(gate, requirement, negate, context, contextKind)
60
+ );
61
+ } catch {
62
+ setShouldShow(false);
63
+ }
64
+ };
65
+ evaluate();
66
+ return onFlagsUpdated(() => evaluate());
67
+ }, [gate.join(","), requirement, negate, context, contextKind]);
68
+ if (shouldShow === null) {
69
+ return loading ? /* @__PURE__ */ jsx(Fragment, { children: loading }) : null;
70
+ }
71
+ return shouldShow ? /* @__PURE__ */ jsx(Fragment, { children }) : null;
72
+ }
73
+ function useFeatureFlag(featureKey, options = {}) {
74
+ const { negate = false, defaultValue = false, context, contextKind } = options;
75
+ return useFeatureGate(featureKey ? [featureKey] : [], {
76
+ requirement: "all",
77
+ negate,
78
+ defaultValue,
79
+ context,
80
+ contextKind
81
+ });
82
+ }
83
+ function useFeatureGate(featureKeys, options = {}) {
84
+ const {
85
+ requirement = "all",
86
+ negate = false,
87
+ defaultValue = false,
88
+ context,
89
+ contextKind
90
+ } = options;
91
+ const keysKey = useMemo(() => featureKeys.join("\0"), [featureKeys]);
92
+ const stableKeys = useMemo(() => [...featureKeys], [keysKey]);
93
+ const evaluate = useCallback(() => {
94
+ if (stableKeys.length === 0) {
95
+ return !negate;
96
+ }
97
+ try {
98
+ return evaluateFeatureGate(
99
+ stableKeys,
100
+ requirement,
101
+ negate,
102
+ context,
103
+ contextKind
104
+ );
105
+ } catch {
106
+ return defaultValue;
107
+ }
108
+ }, [stableKeys, keysKey, requirement, negate, defaultValue, context, contextKind]);
109
+ const [isEnabled, setIsEnabled] = useState(() => {
110
+ try {
111
+ return evaluate();
112
+ } catch {
113
+ return defaultValue;
114
+ }
115
+ });
116
+ const refresh = useCallback(() => {
117
+ setIsEnabled(evaluate());
118
+ }, [evaluate]);
119
+ useEffect(() => {
120
+ refresh();
121
+ return onFlagsUpdated(() => {
122
+ refresh();
123
+ });
124
+ }, [refresh]);
125
+ return { isEnabled, refresh };
126
+ }
127
+ function readFeatureFlag(featureKey, options = {}) {
128
+ const { negate = false, defaultValue = false, context, contextKind } = options;
129
+ try {
130
+ if (negate) {
131
+ return !isFeatureOn(featureKey, context, contextKind);
132
+ }
133
+ return isFeatureOn(featureKey, context, contextKind);
134
+ } catch {
135
+ return defaultValue;
136
+ }
137
+ }
138
+
139
+ export { Feature, readFeatureFlag, useFeatureFlag, useFeatureGate };
140
+ //# sourceMappingURL=index.js.map
141
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/renderer/index.ts","../../src/react/Feature.tsx","../../src/react/useFeatureFlag.ts"],"names":["useMemo","useState","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n EntityContextInput,\n FeatureFlagsSnapshot,\n FeatureRequirement,\n SetContextInput,\n TogglyBridge,\n} from '../types.js'\n\nfunction tryBridge(): TogglyBridge | null {\n if (typeof window === 'undefined' || !window.toggly) {\n return null\n }\n return window.toggly\n}\n\nexport function isFeatureOn(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return false\n }\n return bridge.isFeatureOn(key, entityContext, kind)\n}\n\nexport function isFeatureOff(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return true\n }\n return bridge.isFeatureOff(key, entityContext, kind)\n}\n\nexport function evaluateFeatureGate(\n keys: string[],\n requirement?: FeatureRequirement | string,\n negate?: boolean,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return negate ?? false\n }\n return bridge.evaluateFeatureGate(keys, requirement, negate, entityContext, kind)\n}\n\nexport function getFlags(): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.getFlags()\n}\n\nexport function setContext(context: SetContextInput): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.setContext(context)\n}\n\nexport function clearContext(): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.clearContext()\n}\n\nexport function onFlagsUpdated(\n callback: (flags: FeatureFlagsSnapshot) => void,\n): () => void {\n const bridge = tryBridge()\n if (!bridge) {\n return () => undefined\n }\n return bridge.onFlagsUpdated(callback)\n}\n\nexport type { TogglyBridge, FeatureFlagsSnapshot, FeatureRequirement, SetContextInput }\n","import React, { useEffect, useMemo, useState, type ReactNode } from 'react'\nimport { evaluateFeatureGate, onFlagsUpdated } from '../renderer/index.js'\nimport type { EntityContextInput, FeatureRequirement } from '../types.js'\n\nexport interface FeatureProps {\n featureKey?: string\n featureKeys?: string[]\n requirement?: FeatureRequirement | string\n negate?: boolean\n context?: EntityContextInput\n contextKind?: string\n children?: ReactNode\n /** Content while evaluating (optional). */\n loading?: ReactNode\n}\n\n/**\n * Conditionally render children based on feature flags (Flutter-like DX).\n */\nexport function Feature({\n featureKey,\n featureKeys = [],\n requirement = 'all',\n negate = false,\n context,\n contextKind,\n children,\n loading = null,\n}: FeatureProps): React.ReactElement | null {\n const gate = useMemo(() => {\n if (featureKey) {\n return [featureKey, ...featureKeys]\n }\n return [...featureKeys]\n }, [featureKey, featureKeys])\n\n const [shouldShow, setShouldShow] = useState<boolean | null>(null)\n\n useEffect(() => {\n const evaluate = () => {\n if (gate.length === 0) {\n setShouldShow(!negate)\n return\n }\n try {\n setShouldShow(\n evaluateFeatureGate(gate, requirement, negate, context, contextKind),\n )\n } catch {\n setShouldShow(false)\n }\n }\n\n evaluate()\n return onFlagsUpdated(() => evaluate())\n }, [gate.join(','), requirement, negate, context, contextKind])\n\n if (shouldShow === null) {\n return loading ? <>{loading}</> : null\n }\n\n return shouldShow ? <>{children}</> : null\n}\n\nexport default Feature\n","import { useCallback, useEffect, useMemo, useState } from 'react'\nimport {\n evaluateFeatureGate,\n isFeatureOn,\n onFlagsUpdated,\n} from '../renderer/index.js'\nimport type { EntityContextInput, FeatureRequirement } from '../types.js'\n\nexport interface UseFeatureFlagOptions {\n defaultValue?: boolean\n negate?: boolean\n context?: EntityContextInput\n contextKind?: string\n}\n\nexport interface UseFeatureFlagResult {\n isEnabled: boolean\n refresh: () => void\n}\n\nexport interface UseFeatureGateOptions extends UseFeatureFlagOptions {\n requirement?: FeatureRequirement | string\n}\n\nexport function useFeatureFlag(\n featureKey: string,\n options: UseFeatureFlagOptions = {},\n): UseFeatureFlagResult {\n const { negate = false, defaultValue = false, context, contextKind } = options\n return useFeatureGate(featureKey ? [featureKey] : [], {\n requirement: 'all',\n negate,\n defaultValue,\n context,\n contextKind,\n })\n}\n\nexport function useFeatureGate(\n featureKeys: string[],\n options: UseFeatureGateOptions = {},\n): UseFeatureFlagResult {\n const {\n requirement = 'all',\n negate = false,\n defaultValue = false,\n context,\n contextKind,\n } = options\n const keysKey = useMemo(() => featureKeys.join('\\0'), [featureKeys])\n const stableKeys = useMemo(() => [...featureKeys], [keysKey])\n\n const evaluate = useCallback((): boolean => {\n if (stableKeys.length === 0) {\n return !negate\n }\n try {\n return evaluateFeatureGate(\n stableKeys,\n requirement,\n negate,\n context,\n contextKind,\n )\n } catch {\n return defaultValue\n }\n }, [stableKeys, keysKey, requirement, negate, defaultValue, context, contextKind])\n\n const [isEnabled, setIsEnabled] = useState<boolean>(() => {\n try {\n return evaluate()\n } catch {\n return defaultValue\n }\n })\n\n const refresh = useCallback(() => {\n setIsEnabled(evaluate())\n }, [evaluate])\n\n useEffect(() => {\n refresh()\n return onFlagsUpdated(() => {\n refresh()\n })\n }, [refresh])\n\n return { isEnabled, refresh }\n}\n\n/** Sync helper for non-hook callers. */\nexport function readFeatureFlag(\n featureKey: string,\n options: UseFeatureFlagOptions = {},\n): boolean {\n const { negate = false, defaultValue = false, context, contextKind } = options\n try {\n if (negate) {\n return !isFeatureOn(featureKey, context, contextKind)\n }\n return isFeatureOn(featureKey, context, contextKind)\n } catch {\n return defaultValue\n }\n}\n"]}
@@ -0,0 +1,80 @@
1
+ 'use strict';
2
+
3
+ // src/renderer/index.ts
4
+ function tryBridge() {
5
+ if (typeof window === "undefined" || !window.toggly) {
6
+ return null;
7
+ }
8
+ return window.toggly;
9
+ }
10
+ function isFeatureOn(key, entityContext, kind) {
11
+ const bridge = tryBridge();
12
+ if (!bridge) {
13
+ return false;
14
+ }
15
+ return bridge.isFeatureOn(key, entityContext, kind);
16
+ }
17
+ function isFeatureOff(key, entityContext, kind) {
18
+ const bridge = tryBridge();
19
+ if (!bridge) {
20
+ return true;
21
+ }
22
+ return bridge.isFeatureOff(key, entityContext, kind);
23
+ }
24
+ function evaluateFeatureGate(keys, requirement, negate, entityContext, kind) {
25
+ const bridge = tryBridge();
26
+ if (!bridge) {
27
+ return negate ?? false;
28
+ }
29
+ return bridge.evaluateFeatureGate(keys, requirement, negate, entityContext, kind);
30
+ }
31
+ function getFlags() {
32
+ const bridge = tryBridge();
33
+ if (!bridge) {
34
+ return Promise.reject(
35
+ new Error(
36
+ "window.toggly is not available. Call exposeToggly() from your preload script."
37
+ )
38
+ );
39
+ }
40
+ return bridge.getFlags();
41
+ }
42
+ function setContext(context) {
43
+ const bridge = tryBridge();
44
+ if (!bridge) {
45
+ return Promise.reject(
46
+ new Error(
47
+ "window.toggly is not available. Call exposeToggly() from your preload script."
48
+ )
49
+ );
50
+ }
51
+ return bridge.setContext(context);
52
+ }
53
+ function clearContext() {
54
+ const bridge = tryBridge();
55
+ if (!bridge) {
56
+ return Promise.reject(
57
+ new Error(
58
+ "window.toggly is not available. Call exposeToggly() from your preload script."
59
+ )
60
+ );
61
+ }
62
+ return bridge.clearContext();
63
+ }
64
+ function onFlagsUpdated(callback) {
65
+ const bridge = tryBridge();
66
+ if (!bridge) {
67
+ return () => void 0;
68
+ }
69
+ return bridge.onFlagsUpdated(callback);
70
+ }
71
+
72
+ exports.clearContext = clearContext;
73
+ exports.evaluateFeatureGate = evaluateFeatureGate;
74
+ exports.getFlags = getFlags;
75
+ exports.isFeatureOff = isFeatureOff;
76
+ exports.isFeatureOn = isFeatureOn;
77
+ exports.onFlagsUpdated = onFlagsUpdated;
78
+ exports.setContext = setContext;
79
+ //# sourceMappingURL=index.cjs.map
80
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/renderer/index.ts"],"names":[],"mappings":";;;AAQA,SAAS,SAAA,GAAiC;AACxC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,MAAA,EAAQ;AACnD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA,CAAO,MAAA;AAChB;AAEO,SAAS,WAAA,CACd,GAAA,EACA,aAAA,EACA,IAAA,EACS;AACT,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA,CAAO,WAAA,CAAY,GAAA,EAAK,aAAA,EAAe,IAAI,CAAA;AACpD;AAEO,SAAS,YAAA,CACd,GAAA,EACA,aAAA,EACA,IAAA,EACS;AACT,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA,CAAO,YAAA,CAAa,GAAA,EAAK,aAAA,EAAe,IAAI,CAAA;AACrD;AAEO,SAAS,mBAAA,CACd,IAAA,EACA,WAAA,EACA,MAAA,EACA,eACA,IAAA,EACS;AACT,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,MAAA,IAAU,KAAA;AAAA,EACnB;AACA,EAAA,OAAO,OAAO,mBAAA,CAAoB,IAAA,EAAM,WAAA,EAAa,MAAA,EAAQ,eAAe,IAAI,CAAA;AAClF;AAEO,SAAS,QAAA,GAA0C;AACxD,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,MACb,IAAI,KAAA;AAAA,QACF;AAAA;AACF,KACF;AAAA,EACF;AACA,EAAA,OAAO,OAAO,QAAA,EAAS;AACzB;AAEO,SAAS,WAAW,OAAA,EAAyD;AAClF,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,MACb,IAAI,KAAA;AAAA,QACF;AAAA;AACF,KACF;AAAA,EACF;AACA,EAAA,OAAO,MAAA,CAAO,WAAW,OAAO,CAAA;AAClC;AAEO,SAAS,YAAA,GAA8C;AAC5D,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,MACb,IAAI,KAAA;AAAA,QACF;AAAA;AACF,KACF;AAAA,EACF;AACA,EAAA,OAAO,OAAO,YAAA,EAAa;AAC7B;AAEO,SAAS,eACd,QAAA,EACY;AACZ,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,MAAM,MAAA;AAAA,EACf;AACA,EAAA,OAAO,MAAA,CAAO,eAAe,QAAQ,CAAA;AACvC","file":"index.cjs","sourcesContent":["import type {\n EntityContextInput,\n FeatureFlagsSnapshot,\n FeatureRequirement,\n SetContextInput,\n TogglyBridge,\n} from '../types.js'\n\nfunction tryBridge(): TogglyBridge | null {\n if (typeof window === 'undefined' || !window.toggly) {\n return null\n }\n return window.toggly\n}\n\nexport function isFeatureOn(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return false\n }\n return bridge.isFeatureOn(key, entityContext, kind)\n}\n\nexport function isFeatureOff(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return true\n }\n return bridge.isFeatureOff(key, entityContext, kind)\n}\n\nexport function evaluateFeatureGate(\n keys: string[],\n requirement?: FeatureRequirement | string,\n negate?: boolean,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return negate ?? false\n }\n return bridge.evaluateFeatureGate(keys, requirement, negate, entityContext, kind)\n}\n\nexport function getFlags(): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.getFlags()\n}\n\nexport function setContext(context: SetContextInput): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.setContext(context)\n}\n\nexport function clearContext(): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.clearContext()\n}\n\nexport function onFlagsUpdated(\n callback: (flags: FeatureFlagsSnapshot) => void,\n): () => void {\n const bridge = tryBridge()\n if (!bridge) {\n return () => undefined\n }\n return bridge.onFlagsUpdated(callback)\n}\n\nexport type { TogglyBridge, FeatureFlagsSnapshot, FeatureRequirement, SetContextInput }\n"]}
@@ -0,0 +1,13 @@
1
+ import { a as FeatureFlagsSnapshot, F as FeatureRequirement, E as EntityContextInput, S as SetContextInput } from '../types-BbMSwQVV.cjs';
2
+ export { b as TogglyBridge } from '../types-BbMSwQVV.cjs';
3
+ import '@ops-ai/toggly-hooks-types';
4
+
5
+ declare function isFeatureOn(key: string, entityContext?: EntityContextInput, kind?: string): boolean;
6
+ declare function isFeatureOff(key: string, entityContext?: EntityContextInput, kind?: string): boolean;
7
+ declare function evaluateFeatureGate(keys: string[], requirement?: FeatureRequirement | string, negate?: boolean, entityContext?: EntityContextInput, kind?: string): boolean;
8
+ declare function getFlags(): Promise<FeatureFlagsSnapshot>;
9
+ declare function setContext(context: SetContextInput): Promise<FeatureFlagsSnapshot>;
10
+ declare function clearContext(): Promise<FeatureFlagsSnapshot>;
11
+ declare function onFlagsUpdated(callback: (flags: FeatureFlagsSnapshot) => void): () => void;
12
+
13
+ export { FeatureFlagsSnapshot, FeatureRequirement, SetContextInput, clearContext, evaluateFeatureGate, getFlags, isFeatureOff, isFeatureOn, onFlagsUpdated, setContext };
@@ -0,0 +1,13 @@
1
+ import { a as FeatureFlagsSnapshot, F as FeatureRequirement, E as EntityContextInput, S as SetContextInput } from '../types-BbMSwQVV.js';
2
+ export { b as TogglyBridge } from '../types-BbMSwQVV.js';
3
+ import '@ops-ai/toggly-hooks-types';
4
+
5
+ declare function isFeatureOn(key: string, entityContext?: EntityContextInput, kind?: string): boolean;
6
+ declare function isFeatureOff(key: string, entityContext?: EntityContextInput, kind?: string): boolean;
7
+ declare function evaluateFeatureGate(keys: string[], requirement?: FeatureRequirement | string, negate?: boolean, entityContext?: EntityContextInput, kind?: string): boolean;
8
+ declare function getFlags(): Promise<FeatureFlagsSnapshot>;
9
+ declare function setContext(context: SetContextInput): Promise<FeatureFlagsSnapshot>;
10
+ declare function clearContext(): Promise<FeatureFlagsSnapshot>;
11
+ declare function onFlagsUpdated(callback: (flags: FeatureFlagsSnapshot) => void): () => void;
12
+
13
+ export { FeatureFlagsSnapshot, FeatureRequirement, SetContextInput, clearContext, evaluateFeatureGate, getFlags, isFeatureOff, isFeatureOn, onFlagsUpdated, setContext };
@@ -0,0 +1,72 @@
1
+ // src/renderer/index.ts
2
+ function tryBridge() {
3
+ if (typeof window === "undefined" || !window.toggly) {
4
+ return null;
5
+ }
6
+ return window.toggly;
7
+ }
8
+ function isFeatureOn(key, entityContext, kind) {
9
+ const bridge = tryBridge();
10
+ if (!bridge) {
11
+ return false;
12
+ }
13
+ return bridge.isFeatureOn(key, entityContext, kind);
14
+ }
15
+ function isFeatureOff(key, entityContext, kind) {
16
+ const bridge = tryBridge();
17
+ if (!bridge) {
18
+ return true;
19
+ }
20
+ return bridge.isFeatureOff(key, entityContext, kind);
21
+ }
22
+ function evaluateFeatureGate(keys, requirement, negate, entityContext, kind) {
23
+ const bridge = tryBridge();
24
+ if (!bridge) {
25
+ return negate ?? false;
26
+ }
27
+ return bridge.evaluateFeatureGate(keys, requirement, negate, entityContext, kind);
28
+ }
29
+ function getFlags() {
30
+ const bridge = tryBridge();
31
+ if (!bridge) {
32
+ return Promise.reject(
33
+ new Error(
34
+ "window.toggly is not available. Call exposeToggly() from your preload script."
35
+ )
36
+ );
37
+ }
38
+ return bridge.getFlags();
39
+ }
40
+ function setContext(context) {
41
+ const bridge = tryBridge();
42
+ if (!bridge) {
43
+ return Promise.reject(
44
+ new Error(
45
+ "window.toggly is not available. Call exposeToggly() from your preload script."
46
+ )
47
+ );
48
+ }
49
+ return bridge.setContext(context);
50
+ }
51
+ function clearContext() {
52
+ const bridge = tryBridge();
53
+ if (!bridge) {
54
+ return Promise.reject(
55
+ new Error(
56
+ "window.toggly is not available. Call exposeToggly() from your preload script."
57
+ )
58
+ );
59
+ }
60
+ return bridge.clearContext();
61
+ }
62
+ function onFlagsUpdated(callback) {
63
+ const bridge = tryBridge();
64
+ if (!bridge) {
65
+ return () => void 0;
66
+ }
67
+ return bridge.onFlagsUpdated(callback);
68
+ }
69
+
70
+ export { clearContext, evaluateFeatureGate, getFlags, isFeatureOff, isFeatureOn, onFlagsUpdated, setContext };
71
+ //# sourceMappingURL=index.js.map
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/renderer/index.ts"],"names":[],"mappings":";AAQA,SAAS,SAAA,GAAiC;AACxC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,CAAC,OAAO,MAAA,EAAQ;AACnD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA,CAAO,MAAA;AAChB;AAEO,SAAS,WAAA,CACd,GAAA,EACA,aAAA,EACA,IAAA,EACS;AACT,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA,CAAO,WAAA,CAAY,GAAA,EAAK,aAAA,EAAe,IAAI,CAAA;AACpD;AAEO,SAAS,YAAA,CACd,GAAA,EACA,aAAA,EACA,IAAA,EACS;AACT,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA,CAAO,YAAA,CAAa,GAAA,EAAK,aAAA,EAAe,IAAI,CAAA;AACrD;AAEO,SAAS,mBAAA,CACd,IAAA,EACA,WAAA,EACA,MAAA,EACA,eACA,IAAA,EACS;AACT,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,MAAA,IAAU,KAAA;AAAA,EACnB;AACA,EAAA,OAAO,OAAO,mBAAA,CAAoB,IAAA,EAAM,WAAA,EAAa,MAAA,EAAQ,eAAe,IAAI,CAAA;AAClF;AAEO,SAAS,QAAA,GAA0C;AACxD,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,MACb,IAAI,KAAA;AAAA,QACF;AAAA;AACF,KACF;AAAA,EACF;AACA,EAAA,OAAO,OAAO,QAAA,EAAS;AACzB;AAEO,SAAS,WAAW,OAAA,EAAyD;AAClF,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,MACb,IAAI,KAAA;AAAA,QACF;AAAA;AACF,KACF;AAAA,EACF;AACA,EAAA,OAAO,MAAA,CAAO,WAAW,OAAO,CAAA;AAClC;AAEO,SAAS,YAAA,GAA8C;AAC5D,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,MACb,IAAI,KAAA;AAAA,QACF;AAAA;AACF,KACF;AAAA,EACF;AACA,EAAA,OAAO,OAAO,YAAA,EAAa;AAC7B;AAEO,SAAS,eACd,QAAA,EACY;AACZ,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,MAAM,MAAA;AAAA,EACf;AACA,EAAA,OAAO,MAAA,CAAO,eAAe,QAAQ,CAAA;AACvC","file":"index.js","sourcesContent":["import type {\n EntityContextInput,\n FeatureFlagsSnapshot,\n FeatureRequirement,\n SetContextInput,\n TogglyBridge,\n} from '../types.js'\n\nfunction tryBridge(): TogglyBridge | null {\n if (typeof window === 'undefined' || !window.toggly) {\n return null\n }\n return window.toggly\n}\n\nexport function isFeatureOn(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return false\n }\n return bridge.isFeatureOn(key, entityContext, kind)\n}\n\nexport function isFeatureOff(\n key: string,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return true\n }\n return bridge.isFeatureOff(key, entityContext, kind)\n}\n\nexport function evaluateFeatureGate(\n keys: string[],\n requirement?: FeatureRequirement | string,\n negate?: boolean,\n entityContext?: EntityContextInput,\n kind?: string,\n): boolean {\n const bridge = tryBridge()\n if (!bridge) {\n return negate ?? false\n }\n return bridge.evaluateFeatureGate(keys, requirement, negate, entityContext, kind)\n}\n\nexport function getFlags(): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.getFlags()\n}\n\nexport function setContext(context: SetContextInput): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.setContext(context)\n}\n\nexport function clearContext(): Promise<FeatureFlagsSnapshot> {\n const bridge = tryBridge()\n if (!bridge) {\n return Promise.reject(\n new Error(\n 'window.toggly is not available. Call exposeToggly() from your preload script.',\n ),\n )\n }\n return bridge.clearContext()\n}\n\nexport function onFlagsUpdated(\n callback: (flags: FeatureFlagsSnapshot) => void,\n): () => void {\n const bridge = tryBridge()\n if (!bridge) {\n return () => undefined\n }\n return bridge.onFlagsUpdated(callback)\n}\n\nexport type { TogglyBridge, FeatureFlagsSnapshot, FeatureRequirement, SetContextInput }\n"]}
@@ -0,0 +1,47 @@
1
+ import { TogglyEntityContext, Hook } from '@ops-ai/toggly-hooks-types';
2
+
3
+ type FeatureRequirement = 'all' | 'any';
4
+ interface TogglyElectronConfig {
5
+ appKey?: string;
6
+ environment?: string;
7
+ baseURI?: string;
8
+ flagDefaults?: Record<string, boolean>;
9
+ identity?: string;
10
+ groups?: string[];
11
+ claims?: Record<string, string>;
12
+ verifySignatures?: boolean;
13
+ allowedKeyIds?: string[];
14
+ maxSignatureAgeSeconds?: number | null;
15
+ enableLiveUpdates?: boolean;
16
+ /** Required — typically `app.getPath('userData')`. */
17
+ userDataPath: string;
18
+ connectTimeout?: number;
19
+ featureFlagsRefreshInterval?: number;
20
+ isDebug?: boolean;
21
+ onError?: (message: string, error?: unknown) => void;
22
+ fetch?: typeof fetch;
23
+ hooks?: Hook[];
24
+ }
25
+ interface SetContextInput {
26
+ identity?: string;
27
+ groups?: string[];
28
+ claims?: Record<string, string>;
29
+ }
30
+ type FeatureFlagsSnapshot = Record<string, boolean>;
31
+ type EntityContextInput = TogglyEntityContext | Record<string, unknown> | null | undefined;
32
+ interface TogglyBridge {
33
+ isFeatureOn(key: string, entityContext?: EntityContextInput, kind?: string): boolean;
34
+ isFeatureOff(key: string, entityContext?: EntityContextInput, kind?: string): boolean;
35
+ evaluateFeatureGate(keys: string[], requirement?: FeatureRequirement | string, negate?: boolean, entityContext?: EntityContextInput, kind?: string): boolean;
36
+ getFlags(): Promise<FeatureFlagsSnapshot>;
37
+ setContext(context: SetContextInput): Promise<FeatureFlagsSnapshot>;
38
+ clearContext(): Promise<FeatureFlagsSnapshot>;
39
+ onFlagsUpdated(callback: (flags: FeatureFlagsSnapshot) => void): () => void;
40
+ }
41
+ declare global {
42
+ interface Window {
43
+ toggly?: TogglyBridge;
44
+ }
45
+ }
46
+
47
+ export type { EntityContextInput as E, FeatureRequirement as F, SetContextInput as S, TogglyElectronConfig as T, FeatureFlagsSnapshot as a, TogglyBridge as b };
@@ -0,0 +1,47 @@
1
+ import { TogglyEntityContext, Hook } from '@ops-ai/toggly-hooks-types';
2
+
3
+ type FeatureRequirement = 'all' | 'any';
4
+ interface TogglyElectronConfig {
5
+ appKey?: string;
6
+ environment?: string;
7
+ baseURI?: string;
8
+ flagDefaults?: Record<string, boolean>;
9
+ identity?: string;
10
+ groups?: string[];
11
+ claims?: Record<string, string>;
12
+ verifySignatures?: boolean;
13
+ allowedKeyIds?: string[];
14
+ maxSignatureAgeSeconds?: number | null;
15
+ enableLiveUpdates?: boolean;
16
+ /** Required — typically `app.getPath('userData')`. */
17
+ userDataPath: string;
18
+ connectTimeout?: number;
19
+ featureFlagsRefreshInterval?: number;
20
+ isDebug?: boolean;
21
+ onError?: (message: string, error?: unknown) => void;
22
+ fetch?: typeof fetch;
23
+ hooks?: Hook[];
24
+ }
25
+ interface SetContextInput {
26
+ identity?: string;
27
+ groups?: string[];
28
+ claims?: Record<string, string>;
29
+ }
30
+ type FeatureFlagsSnapshot = Record<string, boolean>;
31
+ type EntityContextInput = TogglyEntityContext | Record<string, unknown> | null | undefined;
32
+ interface TogglyBridge {
33
+ isFeatureOn(key: string, entityContext?: EntityContextInput, kind?: string): boolean;
34
+ isFeatureOff(key: string, entityContext?: EntityContextInput, kind?: string): boolean;
35
+ evaluateFeatureGate(keys: string[], requirement?: FeatureRequirement | string, negate?: boolean, entityContext?: EntityContextInput, kind?: string): boolean;
36
+ getFlags(): Promise<FeatureFlagsSnapshot>;
37
+ setContext(context: SetContextInput): Promise<FeatureFlagsSnapshot>;
38
+ clearContext(): Promise<FeatureFlagsSnapshot>;
39
+ onFlagsUpdated(callback: (flags: FeatureFlagsSnapshot) => void): () => void;
40
+ }
41
+ declare global {
42
+ interface Window {
43
+ toggly?: TogglyBridge;
44
+ }
45
+ }
46
+
47
+ export type { EntityContextInput as E, FeatureRequirement as F, SetContextInput as S, TogglyElectronConfig as T, FeatureFlagsSnapshot as a, TogglyBridge as b };
package/package.json ADDED
@@ -0,0 +1,132 @@
1
+ {
2
+ "name": "@ops-ai/electron-feature-flags-toggly",
3
+ "version": "1.0.0",
4
+ "description": "Toggly feature flags SDK for Electron — main-process evaluated-signed client with Flutter-like renderer DX",
5
+ "keywords": [
6
+ "feature-flags",
7
+ "feature-toggles",
8
+ "toggly",
9
+ "electron",
10
+ "desktop",
11
+ "feature-management",
12
+ "experimentation"
13
+ ],
14
+ "author": "Toggly <support@toggly.io>",
15
+ "license": "MIT",
16
+ "homepage": "https://docs.toggly.io/sdks/electron",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/ops-ai/Toggly.FeatureManagement.git",
20
+ "directory": "Toggly.FeatureManagement.Electron"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/ops-ai/Toggly.FeatureManagement/issues"
24
+ },
25
+ "type": "module",
26
+ "main": "./dist/index.cjs",
27
+ "module": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "import": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/index.d.cts",
37
+ "default": "./dist/index.cjs"
38
+ }
39
+ },
40
+ "./main": {
41
+ "import": {
42
+ "types": "./dist/main/index.d.ts",
43
+ "default": "./dist/main/index.js"
44
+ },
45
+ "require": {
46
+ "types": "./dist/main/index.d.cts",
47
+ "default": "./dist/main/index.cjs"
48
+ }
49
+ },
50
+ "./preload": {
51
+ "import": {
52
+ "types": "./dist/preload/index.d.ts",
53
+ "default": "./dist/preload/index.js"
54
+ },
55
+ "require": {
56
+ "types": "./dist/preload/index.d.cts",
57
+ "default": "./dist/preload/index.cjs"
58
+ }
59
+ },
60
+ "./renderer": {
61
+ "import": {
62
+ "types": "./dist/renderer/index.d.ts",
63
+ "default": "./dist/renderer/index.js"
64
+ },
65
+ "require": {
66
+ "types": "./dist/renderer/index.d.cts",
67
+ "default": "./dist/renderer/index.cjs"
68
+ }
69
+ },
70
+ "./react": {
71
+ "import": {
72
+ "types": "./dist/react/index.d.ts",
73
+ "default": "./dist/react/index.js"
74
+ },
75
+ "require": {
76
+ "types": "./dist/react/index.d.cts",
77
+ "default": "./dist/react/index.cjs"
78
+ }
79
+ }
80
+ },
81
+ "files": [
82
+ "dist",
83
+ "README.md",
84
+ "LICENSE",
85
+ "CHANGELOG.md"
86
+ ],
87
+ "scripts": {
88
+ "build": "tsup",
89
+ "dev": "tsup --watch",
90
+ "clean": "rm -rf dist",
91
+ "typecheck": "tsc --noEmit",
92
+ "test": "vitest run",
93
+ "test:watch": "vitest",
94
+ "test:coverage": "vitest run --coverage"
95
+ },
96
+ "dependencies": {
97
+ "@ops-ai/toggly-hooks-types": "^1.4.3",
98
+ "@ops-ai/toggly-local-gates": "^1.0.1",
99
+ "@ops-ai/toggly-signed-defs": "^1.2.3",
100
+ "ws": "^8.0.0"
101
+ },
102
+ "peerDependencies": {
103
+ "electron": ">=28",
104
+ "react": ">=18"
105
+ },
106
+ "peerDependenciesMeta": {
107
+ "react": {
108
+ "optional": true
109
+ },
110
+ "electron": {
111
+ "optional": true
112
+ }
113
+ },
114
+ "devDependencies": {
115
+ "@types/node": "^20.17.12",
116
+ "@types/react": "^18.3.18",
117
+ "@types/ws": "^8.0.0",
118
+ "@vitest/coverage-v8": "^3.0.4",
119
+ "electron": "^28.3.3",
120
+ "react": "^18.3.1",
121
+ "tsup": "^8.3.5",
122
+ "typescript": "^5.7.3",
123
+ "vitest": "^3.0.4"
124
+ },
125
+ "engines": {
126
+ "node": ">=18.0.0"
127
+ },
128
+ "publishConfig": {
129
+ "access": "public",
130
+ "provenance": true
131
+ }
132
+ }