ffdev 0.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/dist/bar/index.d.ts +22 -0
- package/dist/bar/index.d.ts.map +1 -0
- package/dist/core/flag-def.d.ts +17 -0
- package/dist/core/flag-def.d.ts.map +1 -0
- package/dist/core/local-source.d.ts +9 -0
- package/dist/core/local-source.d.ts.map +1 -0
- package/dist/core/query-source.d.ts +9 -0
- package/dist/core/query-source.d.ts.map +1 -0
- package/dist/core/remote-source.d.ts +11 -0
- package/dist/core/remote-source.d.ts.map +1 -0
- package/dist/core/resolver.d.ts +4 -0
- package/dist/core/resolver.d.ts.map +1 -0
- package/dist/core/source.d.ts +11 -0
- package/dist/core/source.d.ts.map +1 -0
- package/dist/core/store.d.ts +16 -0
- package/dist/core/store.d.ts.map +1 -0
- package/dist/create-ffdev-B2ww_7Y1.js +170 -0
- package/dist/entries/react-headless.d.ts +5 -0
- package/dist/entries/react-headless.d.ts.map +1 -0
- package/dist/entries/react-headless.js +8 -0
- package/dist/entries/react.d.ts +16 -0
- package/dist/entries/react.d.ts.map +1 -0
- package/dist/entries/react.js +56 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/react/create-ffdev.d.ts +34 -0
- package/dist/react/create-ffdev.d.ts.map +1 -0
- package/dist/react/create-ffdev.test.d.ts +2 -0
- package/dist/react/create-ffdev.test.d.ts.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FlagDef } from '../core/flag-def.js';
|
|
2
|
+
import { Store } from '../core/store.js';
|
|
3
|
+
export declare const BAR_SENTINEL = "__FFDEV_BAR_SENTINEL__";
|
|
4
|
+
export interface BarController {
|
|
5
|
+
mount(): void;
|
|
6
|
+
unmount(): void;
|
|
7
|
+
}
|
|
8
|
+
export declare function mountBar(isDev?: boolean): BarController;
|
|
9
|
+
declare global {
|
|
10
|
+
interface Window {
|
|
11
|
+
__FFDEV__?: {
|
|
12
|
+
open(): void;
|
|
13
|
+
close(): void;
|
|
14
|
+
setFlag(name: string, value: unknown): void;
|
|
15
|
+
getFlags(): Record<string, unknown>;
|
|
16
|
+
status(): string;
|
|
17
|
+
refetchRemote(): Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export declare function attachGlobalApi(store: Store, defs: Record<string, FlagDef<unknown>>, bar: BarController): void;
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bar/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,eAAO,MAAM,YAAY,2BAA2B,CAAC;AAErD,MAAM,WAAW,aAAa;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,OAAO,IAAI,IAAI,CAAC;CAChB;AAED,wBAAgB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,aAAa,CA4BvD;AAED,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,MAAM;QACf,SAAS,CAAC,EAAE;YACX,IAAI,IAAI,IAAI,CAAC;YACb,KAAK,IAAI,IAAI,CAAC;YACd,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;YAC5C,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACpC,MAAM,IAAI,MAAM,CAAC;YACjB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;SAC/B,CAAC;KACF;CACD;AAED,wBAAgB,eAAe,CAC9B,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,EACtC,GAAG,EAAE,aAAa,GAChB,IAAI,CA6BN"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface FlagDef<V> {
|
|
2
|
+
readonly kind: 'boolean' | 'enum';
|
|
3
|
+
readonly defaultValue: V;
|
|
4
|
+
validate(value: unknown): value is V;
|
|
5
|
+
}
|
|
6
|
+
declare function booleanFlag(opts: {
|
|
7
|
+
default: boolean;
|
|
8
|
+
}): FlagDef<boolean>;
|
|
9
|
+
declare function enumFlag<const T extends readonly string[]>(variants: T, opts: {
|
|
10
|
+
default: T[number];
|
|
11
|
+
}): FlagDef<T[number]>;
|
|
12
|
+
export declare const flag: {
|
|
13
|
+
readonly boolean: typeof booleanFlag;
|
|
14
|
+
readonly enum: typeof enumFlag;
|
|
15
|
+
};
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=flag-def.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag-def.d.ts","sourceRoot":"","sources":["../../src/core/flag-def.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO,CAAC,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC;CACrC;AAED,iBAAS,WAAW,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAQjE;AAED,iBAAS,QAAQ,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,EAClD,QAAQ,EAAE,CAAC,EACX,IAAI,EAAE;IAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;CAAE,GAC1B,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CASpB;AAED,eAAO,MAAM,IAAI;;;CAGP,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Source } from './source.js';
|
|
2
|
+
export declare class LocalSource implements Source {
|
|
3
|
+
private readonly prefix;
|
|
4
|
+
constructor(namespace: string);
|
|
5
|
+
read(flagName: string): unknown | undefined;
|
|
6
|
+
write(flagName: string, value: unknown | undefined): void;
|
|
7
|
+
subscribe(listener: () => void): () => void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=local-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-source.d.ts","sourceRoot":"","sources":["../../src/core/local-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,qBAAa,WAAY,YAAW,MAAM;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,SAAS,EAAE,MAAM;IAI7B,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAU3C,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI;IASzD,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;CAS3C"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FlagDef } from './flag-def.js';
|
|
2
|
+
import { Source } from './source.js';
|
|
3
|
+
export declare class QuerySource implements Source {
|
|
4
|
+
private namespace;
|
|
5
|
+
private getSearchParams;
|
|
6
|
+
constructor(namespace: string, getSearchParams: () => URLSearchParams);
|
|
7
|
+
read(flagName: string, def: FlagDef<unknown>): unknown | undefined;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=query-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-source.d.ts","sourceRoot":"","sources":["../../src/core/query-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,qBAAa,WAAY,YAAW,MAAM;IAExC,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,eAAe;gBADf,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,eAAe;IAG/C,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS;CAmBlE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FlagDef } from './flag-def.js';
|
|
2
|
+
import { Source } from './source.js';
|
|
3
|
+
export type RemoteConfig = string | (() => Promise<Record<string, unknown>>);
|
|
4
|
+
export declare class RemoteSource implements Source {
|
|
5
|
+
private cache;
|
|
6
|
+
private fetcher;
|
|
7
|
+
constructor(config: RemoteConfig);
|
|
8
|
+
read(flagName: string, _def: FlagDef<unknown>): unknown | undefined;
|
|
9
|
+
fetch(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=remote-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-source.d.ts","sourceRoot":"","sources":["../../src/core/remote-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAE7E,qBAAa,YAAa,YAAW,MAAM;IAC1C,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,OAAO,CAAyC;gBAE5C,MAAM,EAAE,YAAY;IAWhC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS;IAI7D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/core/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,wBAAgB,OAAO,CAAC,CAAC,EACxB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EACf,OAAO,EAAE,SAAS,MAAM,EAAE,GACxB,CAAC,CAQH"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FlagDef } from './flag-def.js';
|
|
2
|
+
export interface Source {
|
|
3
|
+
read(flagName: string, def: FlagDef<unknown>): unknown | undefined;
|
|
4
|
+
subscribe?(listener: () => void): () => void;
|
|
5
|
+
}
|
|
6
|
+
export declare class DefaultSource implements Source {
|
|
7
|
+
private defs;
|
|
8
|
+
constructor(defs: Record<string, FlagDef<unknown>>);
|
|
9
|
+
read(flagName: string): unknown | undefined;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/core/source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,WAAW,MAAM;IACtB,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS,CAAC;IACnE,SAAS,CAAC,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAC7C;AAED,qBAAa,aAAc,YAAW,MAAM;IAC/B,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAE1D,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;CAI3C"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FlagDef } from './flag-def.js';
|
|
2
|
+
import { LocalSource } from './local-source.js';
|
|
3
|
+
import { RemoteSource } from './remote-source.js';
|
|
4
|
+
import { Source } from './source.js';
|
|
5
|
+
export type Status = 'idle' | 'loading' | 'ready' | 'error';
|
|
6
|
+
export interface Store {
|
|
7
|
+
getSnapshot(): Record<string, unknown>;
|
|
8
|
+
getFlagSnapshot(flagName: string): unknown;
|
|
9
|
+
subscribe(listener: () => void): () => void;
|
|
10
|
+
getStatus(): Status;
|
|
11
|
+
notify(): void;
|
|
12
|
+
setLocal(flagName: string, value: unknown | undefined): void;
|
|
13
|
+
refetchRemote(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare function createStore(defs: Record<string, FlagDef<unknown>>, sources: readonly Source[], localSource?: LocalSource, remote?: RemoteSource): Store;
|
|
16
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/core/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE5D,MAAM,WAAW,KAAK;IACrB,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3C,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5C,SAAS,IAAI,MAAM,CAAC;IACpB,MAAM,IAAI,IAAI,CAAC;IACf,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IAC7D,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,wBAAgB,WAAW,CAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,EACtC,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,WAAW,CAAC,EAAE,WAAW,EACzB,MAAM,CAAC,EAAE,YAAY,GACnB,KAAK,CA6EP"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
var y = Object.defineProperty;
|
|
2
|
+
var F = (r, e, t) => e in r ? y(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
|
|
3
|
+
var S = (r, e, t) => F(r, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
import { useSyncExternalStore as g } from "react";
|
|
5
|
+
import { QuerySource as x } from "./index.js";
|
|
6
|
+
class L {
|
|
7
|
+
constructor(e) {
|
|
8
|
+
S(this, "prefix");
|
|
9
|
+
this.prefix = `${e}:`;
|
|
10
|
+
}
|
|
11
|
+
read(e) {
|
|
12
|
+
const t = localStorage.getItem(this.prefix + e);
|
|
13
|
+
if (t !== null)
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(t);
|
|
16
|
+
} catch {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
write(e, t) {
|
|
21
|
+
const n = this.prefix + e;
|
|
22
|
+
t === void 0 ? localStorage.removeItem(n) : localStorage.setItem(n, JSON.stringify(t));
|
|
23
|
+
}
|
|
24
|
+
subscribe(e) {
|
|
25
|
+
const t = (n) => {
|
|
26
|
+
var c;
|
|
27
|
+
(c = n.key) != null && c.startsWith(this.prefix) && e();
|
|
28
|
+
};
|
|
29
|
+
return window.addEventListener("storage", t), () => window.removeEventListener("storage", t);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
class P {
|
|
33
|
+
constructor(e) {
|
|
34
|
+
S(this, "cache");
|
|
35
|
+
S(this, "fetcher");
|
|
36
|
+
this.fetcher = typeof e == "string" ? () => fetch(e).then((t) => {
|
|
37
|
+
if (!t.ok) throw new Error(`HTTP ${t.status}`);
|
|
38
|
+
return t.json();
|
|
39
|
+
}) : e;
|
|
40
|
+
}
|
|
41
|
+
read(e, t) {
|
|
42
|
+
var n;
|
|
43
|
+
return (n = this.cache) == null ? void 0 : n[e];
|
|
44
|
+
}
|
|
45
|
+
async fetch() {
|
|
46
|
+
this.cache = void 0;
|
|
47
|
+
const e = await this.fetcher();
|
|
48
|
+
this.cache = e;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
class R {
|
|
52
|
+
constructor(e) {
|
|
53
|
+
this.defs = e;
|
|
54
|
+
}
|
|
55
|
+
read(e) {
|
|
56
|
+
const t = this.defs[e];
|
|
57
|
+
return t == null ? void 0 : t.defaultValue;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function k(r, e, t) {
|
|
61
|
+
for (const n of t) {
|
|
62
|
+
const c = n.read(r, e);
|
|
63
|
+
if (c !== void 0 && e.validate(c))
|
|
64
|
+
return c;
|
|
65
|
+
}
|
|
66
|
+
return e.defaultValue;
|
|
67
|
+
}
|
|
68
|
+
function D(r, e, t, n) {
|
|
69
|
+
const c = /* @__PURE__ */ new Set();
|
|
70
|
+
let h = l();
|
|
71
|
+
const u = { ...h };
|
|
72
|
+
let f = n ? "loading" : "idle";
|
|
73
|
+
function l() {
|
|
74
|
+
const s = {};
|
|
75
|
+
for (const o of Object.keys(r))
|
|
76
|
+
s[o] = k(o, r[o], e);
|
|
77
|
+
return s;
|
|
78
|
+
}
|
|
79
|
+
function i() {
|
|
80
|
+
const s = l();
|
|
81
|
+
for (const o of Object.keys(s))
|
|
82
|
+
s[o] !== u[o] && (u[o] = s[o]);
|
|
83
|
+
h = s;
|
|
84
|
+
for (const o of c)
|
|
85
|
+
o();
|
|
86
|
+
}
|
|
87
|
+
function d(s) {
|
|
88
|
+
return s.fetch().then(
|
|
89
|
+
() => {
|
|
90
|
+
f = "ready", i();
|
|
91
|
+
},
|
|
92
|
+
(o) => {
|
|
93
|
+
console.warn("[ffdev] Remote fetch failed:", o), f = "error", i();
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
n && d(n);
|
|
98
|
+
function a() {
|
|
99
|
+
return n ? (f = "loading", i(), d(n)) : Promise.resolve();
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
getSnapshot() {
|
|
103
|
+
return h;
|
|
104
|
+
},
|
|
105
|
+
getFlagSnapshot(s) {
|
|
106
|
+
return u[s];
|
|
107
|
+
},
|
|
108
|
+
subscribe(s) {
|
|
109
|
+
return c.add(s), () => {
|
|
110
|
+
c.delete(s);
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
getStatus() {
|
|
114
|
+
return f;
|
|
115
|
+
},
|
|
116
|
+
notify: i,
|
|
117
|
+
setLocal(s, o) {
|
|
118
|
+
t && (t.write(s, o), i());
|
|
119
|
+
},
|
|
120
|
+
refetchRemote: a
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const E = () => new URL(window.location.href).searchParams;
|
|
124
|
+
function I(r, e) {
|
|
125
|
+
const { flags: t } = r, n = r.namespace ?? "ffdev", { remote: c } = r, h = (e == null ? void 0 : e.getSearchParams) ?? E, u = new L(n), f = new x(n, h), l = c ? new P(c) : void 0, i = new R(t), d = [
|
|
126
|
+
f,
|
|
127
|
+
u,
|
|
128
|
+
...l ? [l] : [],
|
|
129
|
+
i
|
|
130
|
+
], a = D(t, d, u, l);
|
|
131
|
+
u.subscribe(() => a.notify());
|
|
132
|
+
function s(m) {
|
|
133
|
+
return g(
|
|
134
|
+
a.subscribe,
|
|
135
|
+
() => a.getFlagSnapshot(m)
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
function o() {
|
|
139
|
+
return g(
|
|
140
|
+
a.subscribe,
|
|
141
|
+
() => a.getSnapshot()
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
function w(m, b) {
|
|
145
|
+
a.setLocal(m, b);
|
|
146
|
+
}
|
|
147
|
+
function p() {
|
|
148
|
+
return g(a.subscribe, () => a.getStatus());
|
|
149
|
+
}
|
|
150
|
+
function v() {
|
|
151
|
+
return a.refetchRemote();
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
useFlag: s,
|
|
155
|
+
useFlags: o,
|
|
156
|
+
setFlag: w,
|
|
157
|
+
useFFDevStatus: p,
|
|
158
|
+
refetchRemote: v,
|
|
159
|
+
store: a,
|
|
160
|
+
defs: t
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function N(r, e) {
|
|
164
|
+
const { store: t, defs: n, ...c } = I(r, e);
|
|
165
|
+
return c;
|
|
166
|
+
}
|
|
167
|
+
export {
|
|
168
|
+
I as a,
|
|
169
|
+
N as c
|
|
170
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { defineConfig, flag, QuerySource } from '../index.js';
|
|
2
|
+
export type { FlagDef, Source } from '../index.js';
|
|
3
|
+
export { createFFDev } from '../react/create-ffdev.js';
|
|
4
|
+
export type { FFDevOptions } from '../react/create-ffdev.js';
|
|
5
|
+
//# sourceMappingURL=react-headless.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-headless.d.ts","sourceRoot":"","sources":["../../src/entries/react-headless.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC9D,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BAR_SENTINEL, mountBar } from '../bar/index.js';
|
|
2
|
+
import { FFDevConfig, FFDevOptions } from '../react/create-ffdev.js';
|
|
3
|
+
export { defineConfig, flag, QuerySource } from '../index.js';
|
|
4
|
+
export type { FlagDef, Source } from '../index.js';
|
|
5
|
+
export type { FFDevOptions };
|
|
6
|
+
export { BAR_SENTINEL, mountBar };
|
|
7
|
+
export declare function createFFDev<C extends FFDevConfig>(config: C, options?: FFDevOptions): {
|
|
8
|
+
useFlag: <K extends keyof C["flags"] & string>(name: K) => C["flags"][K] extends infer T ? T extends C["flags"][K] ? T extends import('./react.js').FlagDef<infer V> ? V : never : never : never;
|
|
9
|
+
useFlags: () => C["flags"] extends infer T extends {
|
|
10
|
+
[x: string]: import('./react.js').FlagDef<unknown>;
|
|
11
|
+
} ? { [K in keyof T]: T[K] extends infer T_1 ? T_1 extends T[K] ? T_1 extends import('./react.js').FlagDef<infer V> ? V : never : never : never; } : never;
|
|
12
|
+
setFlag: <K extends keyof C["flags"] & string>(name: K, value: (C["flags"][K] extends infer T ? T extends C["flags"][K] ? T extends import('./react.js').FlagDef<infer V> ? V : never : never : never) | undefined) => void;
|
|
13
|
+
useFFDevStatus: () => import('../core/store.js').Status;
|
|
14
|
+
refetchRemote: () => Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/entries/react.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC9D,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAmB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,YAAY,EAEjB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,YAAY,EAAE,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;AAElC,wBAAgB,WAAW,CAAC,CAAC,SAAS,WAAW,EAChD,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,YAAY;;;;;;;;EAMtB"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { QuerySource as _, defineConfig as m, flag as v } from "../index.js";
|
|
2
|
+
import { a as f } from "../create-ffdev-B2ww_7Y1.js";
|
|
3
|
+
const c = "__FFDEV_BAR_SENTINEL__";
|
|
4
|
+
function i(n) {
|
|
5
|
+
const r = n ?? (typeof process < "u" ? process.env.NODE_ENV !== "production" : !0);
|
|
6
|
+
let t = null;
|
|
7
|
+
function e() {
|
|
8
|
+
t || (t = document.createElement("div"), t.setAttribute("data-ffdev-bar", c), t.textContent = "ffdev bar [stub]", document.body.appendChild(t));
|
|
9
|
+
}
|
|
10
|
+
function o() {
|
|
11
|
+
t && (t.remove(), t = null);
|
|
12
|
+
}
|
|
13
|
+
return r && e(), { mount: e, unmount: o };
|
|
14
|
+
}
|
|
15
|
+
function a(n, r, t) {
|
|
16
|
+
window.__FFDEV__ = {
|
|
17
|
+
open() {
|
|
18
|
+
t.mount();
|
|
19
|
+
},
|
|
20
|
+
close() {
|
|
21
|
+
t.unmount();
|
|
22
|
+
},
|
|
23
|
+
setFlag(e, o) {
|
|
24
|
+
if (!(e in r)) {
|
|
25
|
+
console.warn(`[ffdev] Unknown flag: "${e}"`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (o !== void 0 && !r[e].validate(o)) {
|
|
29
|
+
console.warn(`[ffdev] Invalid value for flag "${e}":`, o);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
n.setLocal(e, o);
|
|
33
|
+
},
|
|
34
|
+
getFlags() {
|
|
35
|
+
return n.getSnapshot();
|
|
36
|
+
},
|
|
37
|
+
status() {
|
|
38
|
+
return n.getStatus();
|
|
39
|
+
},
|
|
40
|
+
refetchRemote() {
|
|
41
|
+
return n.refetchRemote();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function l(n, r) {
|
|
46
|
+
const { store: t, defs: e, ...o } = f(n, r), u = i();
|
|
47
|
+
return a(t, e, u), o;
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
c as BAR_SENTINEL,
|
|
51
|
+
_ as QuerySource,
|
|
52
|
+
l as createFFDev,
|
|
53
|
+
m as defineConfig,
|
|
54
|
+
v as flag,
|
|
55
|
+
i as mountBar
|
|
56
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FlagDef } from './core/flag-def.js';
|
|
2
|
+
import { RemoteConfig } from './core/remote-source.js';
|
|
3
|
+
export { flag } from './core/flag-def.js';
|
|
4
|
+
export type { FlagDef } from './core/flag-def.js';
|
|
5
|
+
export type { Source } from './core/source.js';
|
|
6
|
+
export { QuerySource } from './core/query-source.js';
|
|
7
|
+
interface FFDevConfig {
|
|
8
|
+
namespace?: string;
|
|
9
|
+
remote?: RemoteConfig;
|
|
10
|
+
flags: Record<string, FlagDef<unknown>>;
|
|
11
|
+
}
|
|
12
|
+
export declare function defineConfig<C extends FFDevConfig>(config: C): C;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,YAAY,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,YAAY,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,UAAU,WAAW;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;CACxC;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAEhE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
function u(t) {
|
|
2
|
+
return {
|
|
3
|
+
kind: "boolean",
|
|
4
|
+
defaultValue: t.default,
|
|
5
|
+
validate(e) {
|
|
6
|
+
return typeof e == "boolean";
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function i(t, e) {
|
|
11
|
+
const n = new Set(t);
|
|
12
|
+
return {
|
|
13
|
+
kind: "enum",
|
|
14
|
+
defaultValue: e.default,
|
|
15
|
+
validate(a) {
|
|
16
|
+
return typeof a == "string" && n.has(a);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const l = {
|
|
21
|
+
boolean: u,
|
|
22
|
+
enum: i
|
|
23
|
+
};
|
|
24
|
+
class s {
|
|
25
|
+
constructor(e, n) {
|
|
26
|
+
this.namespace = e, this.getSearchParams = n;
|
|
27
|
+
}
|
|
28
|
+
read(e, n) {
|
|
29
|
+
const a = this.getSearchParams(), o = `${this.namespace}.${e}`, r = a.get(o);
|
|
30
|
+
if (r !== null) {
|
|
31
|
+
if (n.kind === "boolean")
|
|
32
|
+
return r === "true" ? !0 : r === "false" ? !1 : void 0;
|
|
33
|
+
if (n.kind === "enum")
|
|
34
|
+
return n.validate(r) ? r : void 0;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function f(t) {
|
|
39
|
+
return t;
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
s as QuerySource,
|
|
43
|
+
f as defineConfig,
|
|
44
|
+
l as flag
|
|
45
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { FlagDef } from '../core/flag-def.js';
|
|
2
|
+
import { RemoteConfig } from '../core/remote-source.js';
|
|
3
|
+
import { Status } from '../core/store.js';
|
|
4
|
+
type FlagsConfig = Record<string, FlagDef<unknown>>;
|
|
5
|
+
type FlagValue<F> = F extends FlagDef<infer V> ? V : never;
|
|
6
|
+
type FlagsSnapshot<F extends FlagsConfig> = {
|
|
7
|
+
[K in keyof F]: FlagValue<F[K]>;
|
|
8
|
+
};
|
|
9
|
+
export interface FFDevConfig {
|
|
10
|
+
namespace?: string;
|
|
11
|
+
remote?: RemoteConfig;
|
|
12
|
+
flags: FlagsConfig;
|
|
13
|
+
}
|
|
14
|
+
export interface FFDevOptions {
|
|
15
|
+
getSearchParams?: () => URLSearchParams;
|
|
16
|
+
}
|
|
17
|
+
export declare function createFFDevInternal<C extends FFDevConfig>(config: C, options?: FFDevOptions): {
|
|
18
|
+
useFlag: <K extends keyof C["flags"] & string>(name: K) => FlagValue<C["flags"][K]>;
|
|
19
|
+
useFlags: () => FlagsSnapshot<C["flags"]>;
|
|
20
|
+
setFlag: <K extends keyof C["flags"] & string>(name: K, value: FlagValue<C["flags"][K]> | undefined) => void;
|
|
21
|
+
useFFDevStatus: () => Status;
|
|
22
|
+
refetchRemote: () => Promise<void>;
|
|
23
|
+
store: import('../core/store.js').Store;
|
|
24
|
+
defs: FlagsConfig;
|
|
25
|
+
};
|
|
26
|
+
export declare function createFFDev<C extends FFDevConfig>(config: C, options?: FFDevOptions): {
|
|
27
|
+
useFlag: <K extends keyof C["flags"] & string>(name: K) => FlagValue<C["flags"][K]>;
|
|
28
|
+
useFlags: () => FlagsSnapshot<C["flags"]>;
|
|
29
|
+
setFlag: <K extends keyof C["flags"] & string>(name: K, value: FlagValue<C["flags"][K]> | undefined) => void;
|
|
30
|
+
useFFDevStatus: () => Status;
|
|
31
|
+
refetchRemote: () => Promise<void>;
|
|
32
|
+
};
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=create-ffdev.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-ffdev.d.ts","sourceRoot":"","sources":["../../src/react/create-ffdev.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,KAAK,MAAM,EAAe,MAAM,kBAAkB,CAAC;AAE5D,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AAEpD,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE3D,KAAK,aAAa,CAAC,CAAC,SAAS,WAAW,IAAI;KAC1C,CAAC,IAAI,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC/B,CAAC;AAEF,MAAM,WAAW,WAAW;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,WAAW,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B,eAAe,CAAC,EAAE,MAAM,eAAe,CAAC;CACxC;AAKD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,WAAW,EACxD,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,YAAY;cAsBL,CAAC,SAAS,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,MAAM,QAC7C,CAAC,KACL,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;oBAON,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;cAO7B,CAAC,SAAS,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,MAAM,QAC7C,CAAC,SACA,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,KACzC,IAAI;0BAIoB,MAAM;yBAIP,OAAO,CAAC,IAAI,CAAC;;;EAavC;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,WAAW,EAChD,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,YAAY;cA5CL,CAAC;;cAgBD,CAAC,6FAGf,IAAI;0BAIoB,MAAM;yBAIP,OAAO,CAAC,IAAI,CAAC;EAqBvC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-ffdev.test.d.ts","sourceRoot":"","sources":["../../src/react/create-ffdev.test.tsx"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ffdev",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./react": {
|
|
16
|
+
"types": "./dist/entries/react.d.ts",
|
|
17
|
+
"import": "./dist/entries/react.js"
|
|
18
|
+
},
|
|
19
|
+
"./react/headless": {
|
|
20
|
+
"types": "./dist/entries/react-headless.d.ts",
|
|
21
|
+
"import": "./dist/entries/react-headless.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "vite build",
|
|
29
|
+
"typecheck": "tsc --noEmit"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"react": ">=18.0.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/react": "^19.2.14",
|
|
36
|
+
"react": "^19.1.0",
|
|
37
|
+
"vite": "^6.3.5",
|
|
38
|
+
"vite-plugin-dts": "^4.5.4"
|
|
39
|
+
}
|
|
40
|
+
}
|