@zedtech/zedkit-flags 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 zedtech-fr
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,9 @@
1
- # Temporary Holding Version
1
+ # @zedtech/zedkit-flags
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Thin helpers around [OpenFeature](https://openfeature.dev/) for typed registries, in-memory and JSON providers, server `getFlag`, React `useFlag`, and `localStorage` overrides for local dev.
4
+
5
+ See [CATALOG.md](./CATALOG.md) for exports and examples.
6
+
7
+ ## Original work
8
+
9
+ Original work by the same author.
@@ -0,0 +1,4 @@
1
+ import { type FlagValue } from "./memory.js";
2
+ export declare function parseFlagsJson(raw: string | undefined | null): Record<string, FlagValue>;
3
+ export declare function loadFlagsFromEnv(env?: Record<string, string | undefined>, envVar?: string): Record<string, FlagValue>;
4
+ //# sourceMappingURL=env-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-json.d.ts","sourceRoot":"","sources":["../src/env-json.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAK7C,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAYxF;AAED,wBAAgB,gBAAgB,CAC9B,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,EACrD,MAAM,SAAsB,GAC3B,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAE3B"}
@@ -0,0 +1,21 @@
1
+ import { tryCatch } from "@zedtech/zedkit-core";
2
+ const FLAG_VALUE = (value) => typeof value === "boolean" || typeof value === "string" || typeof value === "number";
3
+ export function parseFlagsJson(raw) {
4
+ const trimmed = raw?.trim();
5
+ if (!trimmed)
6
+ return {};
7
+ const parsed = tryCatch(() => JSON.parse(trimmed));
8
+ if (!parsed.ok || typeof parsed.value !== "object" || parsed.value === null || Array.isArray(parsed.value)) {
9
+ return {};
10
+ }
11
+ const out = {};
12
+ for (const [key, value] of Object.entries(parsed.value)) {
13
+ if (FLAG_VALUE(value))
14
+ out[key] = value;
15
+ }
16
+ return out;
17
+ }
18
+ export function loadFlagsFromEnv(env = process.env, envVar = "ZEDKIT_FLAGS_JSON") {
19
+ return parseFlagsJson(env[envVar]);
20
+ }
21
+ //# sourceMappingURL=env-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-json.js","sourceRoot":"","sources":["../src/env-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAIhD,MAAM,UAAU,GAAG,CAAC,KAAc,EAAsB,EAAE,CACxD,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC;AAEvF,MAAM,UAAU,cAAc,CAAC,GAA8B;IAC3D,MAAM,OAAO,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAY,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3G,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,GAAG,GAA8B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,IAAI,UAAU,CAAC,KAAK,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC1C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,MAA0C,OAAO,CAAC,GAAG,EACrD,MAAM,GAAG,mBAAmB;IAE5B,OAAO,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Client } from "@openfeature/server-sdk";
2
+ import type { FlagRegistry } from "./registry.js";
3
+ import type { FlagValue } from "./memory.js";
4
+ export declare function getFlag<T extends Record<string, FlagValue>, K extends keyof T & string>(client: Client, registry: FlagRegistry<T>, key: K): Promise<T[K]>;
5
+ //# sourceMappingURL=get-flag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-flag.d.ts","sourceRoot":"","sources":["../src/get-flag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,wBAAsB,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAC3F,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EACzB,GAAG,EAAE,CAAC,GACL,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CASf"}
@@ -0,0 +1,11 @@
1
+ export async function getFlag(client, registry, key) {
2
+ const defaultValue = registry.flags[key];
3
+ if (typeof defaultValue === "boolean") {
4
+ return (await client.getBooleanValue(key, defaultValue));
5
+ }
6
+ if (typeof defaultValue === "string") {
7
+ return (await client.getStringValue(key, defaultValue));
8
+ }
9
+ return (await client.getNumberValue(key, defaultValue));
10
+ }
11
+ //# sourceMappingURL=get-flag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-flag.js","sourceRoot":"","sources":["../src/get-flag.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,MAAc,EACd,QAAyB,EACzB,GAAM;IAEN,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,OAAO,YAAY,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,CAAC,MAAM,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,YAAY,CAAC,CAAS,CAAC;IACnE,CAAC;IACD,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO,CAAC,MAAM,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,YAAY,CAAC,CAAS,CAAC;IAClE,CAAC;IACD,OAAO,CAAC,MAAM,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,YAAsB,CAAC,CAAS,CAAC;AAC5E,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { OpenFeature, TypedInMemoryProvider } from "@openfeature/server-sdk";
2
+ export type { Client, EvaluationContext, JsonValue, Provider } from "@openfeature/server-sdk";
3
+ export { buildOpenFeatureFlagDefinitions, type FlagValue } from "./memory.js";
4
+ export { createMemoryProvider } from "./server-provider.js";
5
+ export { defineFlagRegistry, mergeFlagValues, type FlagRegistry } from "./registry.js";
6
+ export { memoryProviderFromRegistry } from "./server-registry.js";
7
+ export { getFlag } from "./get-flag.js";
8
+ export { loadFlagsFromEnv, parseFlagsJson } from "./env-json.js";
9
+ export { FLAG_OVERRIDE_STORAGE_KEY, flagOverridesSnapshot, mergeFlagValue, readFlagOverrides, subscribeFlagOverrides, writeFlagOverride, } from "./overrides.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC7E,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAE9F,OAAO,EAAE,+BAA+B,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export { OpenFeature, TypedInMemoryProvider } from "@openfeature/server-sdk";
2
+ export { buildOpenFeatureFlagDefinitions } from "./memory.js";
3
+ export { createMemoryProvider } from "./server-provider.js";
4
+ export { defineFlagRegistry, mergeFlagValues } from "./registry.js";
5
+ export { memoryProviderFromRegistry } from "./server-registry.js";
6
+ export { getFlag } from "./get-flag.js";
7
+ export { loadFlagsFromEnv, parseFlagsJson } from "./env-json.js";
8
+ export { FLAG_OVERRIDE_STORAGE_KEY, flagOverridesSnapshot, mergeFlagValue, readFlagOverrides, subscribeFlagOverrides, writeFlagOverride, } from "./overrides.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAG7E,OAAO,EAAE,+BAA+B,EAAkB,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAqB,MAAM,eAAe,CAAC;AACvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type FlagValue = boolean | string | number;
2
+ export declare function buildOpenFeatureFlagDefinitions(flags: Record<string, FlagValue>): Record<string, unknown>;
3
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAElD,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwBzB"}
package/dist/memory.js ADDED
@@ -0,0 +1,28 @@
1
+ export function buildOpenFeatureFlagDefinitions(flags) {
2
+ const definitions = {};
3
+ for (const [key, value] of Object.entries(flags)) {
4
+ if (typeof value === "boolean") {
5
+ definitions[key] = {
6
+ variants: { on: true, off: false },
7
+ defaultVariant: value ? "on" : "off",
8
+ disabled: false,
9
+ };
10
+ }
11
+ else if (typeof value === "string") {
12
+ definitions[key] = {
13
+ variants: { value },
14
+ defaultVariant: "value",
15
+ disabled: false,
16
+ };
17
+ }
18
+ else {
19
+ definitions[key] = {
20
+ variants: { value },
21
+ defaultVariant: "value",
22
+ disabled: false,
23
+ };
24
+ }
25
+ }
26
+ return definitions;
27
+ }
28
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,+BAA+B,CAC7C,KAAgC;IAEhC,MAAM,WAAW,GAA4B,EAAE,CAAC;IAChD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,WAAW,CAAC,GAAG,CAAC,GAAG;gBACjB,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE;gBAClC,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;gBACpC,QAAQ,EAAE,KAAK;aAChB,CAAC;QACJ,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrC,WAAW,CAAC,GAAG,CAAC,GAAG;gBACjB,QAAQ,EAAE,EAAE,KAAK,EAAE;gBACnB,cAAc,EAAE,OAAO;gBACvB,QAAQ,EAAE,KAAK;aAChB,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,GAAG,CAAC,GAAG;gBACjB,QAAQ,EAAE,EAAE,KAAK,EAAE;gBACnB,cAAc,EAAE,OAAO;gBACvB,QAAQ,EAAE,KAAK;aAChB,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { type FlagValue } from "./memory.js";
2
+ export declare const FLAG_OVERRIDE_STORAGE_KEY = "zedkit-flag-overrides";
3
+ export declare function readFlagOverrides(storage: Pick<Storage, "getItem"> | null | undefined): Record<string, FlagValue>;
4
+ export declare function flagOverridesSnapshot(storage: Pick<Storage, "getItem"> | null | undefined): Record<string, FlagValue>;
5
+ export declare function writeFlagOverride(storage: Storage, flagKey: string, value: FlagValue | null): Record<string, FlagValue>;
6
+ export declare function mergeFlagValue<T extends FlagValue>(flagKey: string, evaluated: T, overrides: Record<string, FlagValue>): T;
7
+ export declare function subscribeFlagOverrides(onStoreChange: () => void): () => void;
8
+ //# sourceMappingURL=overrides.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overrides.d.ts","sourceRoot":"","sources":["../src/overrides.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AASjE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAejH;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAMrH;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,SAAS,GAAG,IAAI,GACtB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAa3B;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAO1H;AAED,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAS5E"}
@@ -0,0 +1,72 @@
1
+ import { tryCatch } from "@zedtech/zedkit-core";
2
+ export const FLAG_OVERRIDE_STORAGE_KEY = "zedkit-flag-overrides";
3
+ let overrideSnapshot = {};
4
+ let overrideSnapshotRaw = "";
5
+ function invalidateOverrideSnapshot() {
6
+ overrideSnapshotRaw = "";
7
+ }
8
+ export function readFlagOverrides(storage) {
9
+ if (!storage)
10
+ return {};
11
+ const raw = storage.getItem(FLAG_OVERRIDE_STORAGE_KEY);
12
+ if (!raw?.trim())
13
+ return {};
14
+ const parsed = tryCatch(() => JSON.parse(raw));
15
+ if (!parsed.ok || typeof parsed.value !== "object" || parsed.value === null || Array.isArray(parsed.value)) {
16
+ return {};
17
+ }
18
+ const out = {};
19
+ for (const [key, value] of Object.entries(parsed.value)) {
20
+ if (typeof value === "boolean" || typeof value === "string" || typeof value === "number") {
21
+ out[key] = value;
22
+ }
23
+ }
24
+ return out;
25
+ }
26
+ export function flagOverridesSnapshot(storage) {
27
+ const raw = storage?.getItem(FLAG_OVERRIDE_STORAGE_KEY) ?? "";
28
+ if (raw === overrideSnapshotRaw)
29
+ return overrideSnapshot;
30
+ overrideSnapshotRaw = raw;
31
+ overrideSnapshot = readFlagOverrides(storage);
32
+ return overrideSnapshot;
33
+ }
34
+ export function writeFlagOverride(storage, flagKey, value) {
35
+ const current = readFlagOverrides(storage);
36
+ if (value === null) {
37
+ delete current[flagKey];
38
+ }
39
+ else {
40
+ current[flagKey] = value;
41
+ }
42
+ storage.setItem(FLAG_OVERRIDE_STORAGE_KEY, JSON.stringify(current));
43
+ invalidateOverrideSnapshot();
44
+ if (typeof globalThis.dispatchEvent === "function") {
45
+ globalThis.dispatchEvent(new Event("zedkit-flag-overrides"));
46
+ }
47
+ return current;
48
+ }
49
+ export function mergeFlagValue(flagKey, evaluated, overrides) {
50
+ if (!(flagKey in overrides))
51
+ return evaluated;
52
+ const override = overrides[flagKey];
53
+ if (typeof evaluated === "boolean" && typeof override === "boolean")
54
+ return override;
55
+ if (typeof evaluated === "string" && typeof override === "string")
56
+ return override;
57
+ if (typeof evaluated === "number" && typeof override === "number")
58
+ return override;
59
+ return evaluated;
60
+ }
61
+ export function subscribeFlagOverrides(onStoreChange) {
62
+ if (typeof globalThis.addEventListener !== "function")
63
+ return () => { };
64
+ const handler = () => onStoreChange();
65
+ globalThis.addEventListener("storage", handler);
66
+ globalThis.addEventListener("zedkit-flag-overrides", handler);
67
+ return () => {
68
+ globalThis.removeEventListener("storage", handler);
69
+ globalThis.removeEventListener("zedkit-flag-overrides", handler);
70
+ };
71
+ }
72
+ //# sourceMappingURL=overrides.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overrides.js","sourceRoot":"","sources":["../src/overrides.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type ReactNode } from "react";
2
+ import { type FlagRegistry } from "./registry.js";
3
+ import { type FlagValue } from "./memory.js";
4
+ export { OpenFeatureProvider, useBooleanFlagValue, useNumberFlagValue, useStringFlagValue } from "@openfeature/react-sdk";
5
+ export { OpenFeature, TypedInMemoryProvider } from "@openfeature/web-sdk";
6
+ export type ZedkitFlagsProviderProps<T extends Record<string, FlagValue>> = {
7
+ registry: FlagRegistry<T>;
8
+ children: ReactNode;
9
+ };
10
+ export declare function ZedkitFlagsProvider<T extends Record<string, FlagValue>>({ registry, children, }: ZedkitFlagsProviderProps<T>): ReactNode;
11
+ export declare function useFlag(flagKey: string, defaultValue: boolean): boolean;
12
+ export { defineFlagRegistry, type FlagRegistry } from "./registry.js";
13
+ export { writeFlagOverride, FLAG_OVERRIDE_STORAGE_KEY } from "./overrides.js";
14
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIrE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC1H,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE1E,MAAM,MAAM,wBAAwB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI;IAC1E,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,EACvE,QAAQ,EACR,QAAQ,GACT,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAAG,SAAS,CAYzC;AAcD,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO,CAIvE;AAED,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/react.js ADDED
@@ -0,0 +1,33 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { OpenFeatureProvider, useBooleanFlagValue } from "@openfeature/react-sdk";
4
+ import { OpenFeature, TypedInMemoryProvider } from "@openfeature/web-sdk";
5
+ import { useEffect, useMemo, useState } from "react";
6
+ import { buildOpenFeatureFlagDefinitions } from "./memory.js";
7
+ import { mergeFlagValue, flagOverridesSnapshot, subscribeFlagOverrides } from "./overrides.js";
8
+ export { OpenFeatureProvider, useBooleanFlagValue, useNumberFlagValue, useStringFlagValue } from "@openfeature/react-sdk";
9
+ export { OpenFeature, TypedInMemoryProvider } from "@openfeature/web-sdk";
10
+ export function ZedkitFlagsProvider({ registry, children, }) {
11
+ const provider = useMemo(() => new TypedInMemoryProvider(buildOpenFeatureFlagDefinitions(registry.flags)), [registry]);
12
+ useEffect(() => {
13
+ OpenFeature.setProvider(provider);
14
+ }, [provider]);
15
+ return _jsx(OpenFeatureProvider, { children: children });
16
+ }
17
+ function useFlagOverrides() {
18
+ const [overrides, setOverrides] = useState(() => flagOverridesSnapshot(typeof localStorage === "undefined" ? null : localStorage));
19
+ useEffect(() => {
20
+ return subscribeFlagOverrides(() => {
21
+ setOverrides(flagOverridesSnapshot(typeof localStorage === "undefined" ? null : localStorage));
22
+ });
23
+ }, []);
24
+ return overrides;
25
+ }
26
+ export function useFlag(flagKey, defaultValue) {
27
+ const evaluated = useBooleanFlagValue(flagKey, defaultValue);
28
+ const overrides = useFlagOverrides();
29
+ return mergeFlagValue(flagKey, evaluated, overrides);
30
+ }
31
+ export { defineFlagRegistry } from "./registry.js";
32
+ export { writeFlagOverride, FLAG_OVERRIDE_STORAGE_KEY } from "./overrides.js";
33
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAErE,OAAO,EAAE,+BAA+B,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAI/F,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC1H,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAO1E,MAAM,UAAU,mBAAmB,CAAsC,EACvE,QAAQ,EACR,QAAQ,GACoB;IAC5B,MAAM,QAAQ,GAAG,OAAO,CACtB,GAAG,EAAE,CACH,IAAI,qBAAqB,CACvB,+BAA+B,CAAC,QAAQ,CAAC,KAAK,CAA2D,CAC1G,EACH,CAAC,QAAQ,CAAC,CACX,CAAC;IACF,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IACf,OAAO,KAAC,mBAAmB,cAAE,QAAQ,GAAuB,CAAC;AAC/D,CAAC;AAED,SAAS,gBAAgB;IACvB,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAC9C,qBAAqB,CAAC,OAAO,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CACjF,CAAC;IACF,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,sBAAsB,CAAC,GAAG,EAAE;YACjC,YAAY,CAAC,qBAAqB,CAAC,OAAO,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;QACjG,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IACP,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,YAAqB;IAC5D,MAAM,SAAS,GAAG,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;IACrC,OAAO,cAAc,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AACvD,CAAC;AAED,OAAO,EAAE,kBAAkB,EAAqB,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type FlagValue } from "./memory.js";
2
+ export type FlagRegistry<T extends Record<string, FlagValue>> = {
3
+ flags: T;
4
+ };
5
+ export declare function defineFlagRegistry<const T extends Record<string, FlagValue>>(flags: T): FlagRegistry<T>;
6
+ export declare function mergeFlagValues<T extends Record<string, FlagValue>>(registry: FlagRegistry<T>, overrides: Record<string, FlagValue>): Record<string, FlagValue>;
7
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI;IAC9D,KAAK,EAAE,CAAC,CAAC;CACV,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAEvG;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EACjE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EACzB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GACnC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAE3B"}
@@ -0,0 +1,7 @@
1
+ export function defineFlagRegistry(flags) {
2
+ return { flags };
3
+ }
4
+ export function mergeFlagValues(registry, overrides) {
5
+ return { ...registry.flags, ...overrides };
6
+ }
7
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,kBAAkB,CAA4C,KAAQ;IACpF,OAAO,EAAE,KAAK,EAAE,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,QAAyB,EACzB,SAAoC;IAEpC,OAAO,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,SAAS,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { TypedInMemoryProvider } from "@openfeature/server-sdk";
2
+ import { type FlagValue } from "./memory.js";
3
+ export declare function createMemoryProvider(flags: Record<string, FlagValue>): TypedInMemoryProvider<Record<string, Record<string, boolean> | Record<string, string> | Record<string, number> | Record<string, import("@openfeature/server-sdk").JsonValue>>>;
4
+ //# sourceMappingURL=server-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-provider.d.ts","sourceRoot":"","sources":["../src/server-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAmC,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE9E,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,kLAIpE"}
@@ -0,0 +1,6 @@
1
+ import { TypedInMemoryProvider } from "@openfeature/server-sdk";
2
+ import { buildOpenFeatureFlagDefinitions } from "./memory.js";
3
+ export function createMemoryProvider(flags) {
4
+ return new TypedInMemoryProvider(buildOpenFeatureFlagDefinitions(flags));
5
+ }
6
+ //# sourceMappingURL=server-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-provider.js","sourceRoot":"","sources":["../src/server-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,+BAA+B,EAAkB,MAAM,aAAa,CAAC;AAE9E,MAAM,UAAU,oBAAoB,CAAC,KAAgC;IACnE,OAAO,IAAI,qBAAqB,CAC9B,+BAA+B,CAAC,KAAK,CAA2D,CACjG,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type FlagRegistry } from "./registry.js";
2
+ import { type FlagValue } from "./memory.js";
3
+ export declare function memoryProviderFromRegistry<T extends Record<string, FlagValue>>(registry: FlagRegistry<T>): import("@openfeature/server-sdk").TypedInMemoryProvider<Record<string, Record<string, boolean> | Record<string, string> | Record<string, number> | Record<string, import("@openfeature/server-sdk").JsonValue>>>;
4
+ //# sourceMappingURL=server-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-registry.d.ts","sourceRoot":"","sources":["../src/server-registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,oNAExG"}
@@ -0,0 +1,5 @@
1
+ import { createMemoryProvider } from "./server-provider.js";
2
+ export function memoryProviderFromRegistry(registry) {
3
+ return createMemoryProvider(registry.flags);
4
+ }
5
+ //# sourceMappingURL=server-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-registry.js","sourceRoot":"","sources":["../src/server-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAI5D,MAAM,UAAU,0BAA0B,CAAsC,QAAyB;IACvG,OAAO,oBAAoB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC9C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,88 @@
1
1
  {
2
2
  "name": "@zedtech/zedkit-flags",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
4
+ "publishConfig": {
5
+ "access": "public",
6
+ "registry": "https://registry.npmjs.org/"
7
+ },
8
+ "description": "Typed flag registry, server evaluation, React hooks, JSON/env providers, and local override storage for dev. Original work by the same author.",
9
+ "keywords": [
10
+ "feature-flags",
11
+ "openfeature",
12
+ "react",
13
+ "typescript",
14
+ "server"
15
+ ],
16
+ "homepage": "https://github.com/zedtech-fr/zedkit/tree/main/packages/flags",
17
+ "bugs": {
18
+ "url": "https://github.com/zedtech-fr/zedkit/issues"
19
+ },
20
+ "license": "MIT",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/zedtech-fr/zedkit",
24
+ "directory": "packages/flags"
25
+ },
26
+ "type": "module",
27
+ "sideEffects": false,
28
+ "imports": {
29
+ "#*": "./src/*"
30
+ },
31
+ "main": "./dist/index.js",
32
+ "types": "./dist/index.d.ts",
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/index.d.ts",
36
+ "import": "./dist/index.js"
37
+ },
38
+ "./react": {
39
+ "types": "./dist/react.d.ts",
40
+ "import": "./dist/react.js"
41
+ },
42
+ "./package.json": "./package.json"
43
+ },
44
+ "files": [
45
+ "dist"
46
+ ],
47
+ "peerDependencies": {
48
+ "@openfeature/react-sdk": "1.4.1",
49
+ "@openfeature/server-sdk": "1.23.0",
50
+ "@openfeature/web-sdk": "1.10.0",
51
+ "react": "19.3.1"
52
+ },
53
+ "peerDependenciesMeta": {
54
+ "@openfeature/react-sdk": {
55
+ "optional": true
56
+ },
57
+ "@openfeature/web-sdk": {
58
+ "optional": true
59
+ },
60
+ "react": {
61
+ "optional": true
62
+ }
63
+ },
64
+ "dependencies": {
65
+ "@zedtech/zedkit-core": "0.2.0"
66
+ },
67
+ "devDependencies": {
68
+ "@openfeature/react-sdk": "1.4.1",
69
+ "@openfeature/server-sdk": "1.23.0",
70
+ "@openfeature/web-sdk": "1.10.0",
71
+ "@testing-library/react": "16.3.3",
72
+ "@testing-library/user-event": "14.6.8",
73
+ "@types/node": "26.6.5",
74
+ "@types/react": "19.3.0",
75
+ "jsdom": "30.1.3",
76
+ "react": "19.3.1",
77
+ "react-dom": "19.3.1",
78
+ "typescript": "5.9.3",
79
+ "vitest": "5.0.5",
80
+ "@zedtech/zedkit-quality": "0.4.0"
81
+ },
82
+ "scripts": {
83
+ "build": "tsc -p tsconfig.json",
84
+ "test": "vitest run",
85
+ "typecheck": "tsc --noEmit -p tsconfig.tests.json",
86
+ "lint": "eslint src tests"
87
+ }
6
88
  }