@vexillo/react-sdk 1.0.5 → 2.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/index.cjs +53 -32
- package/dist/index.d.cts +90 -0
- package/dist/index.d.ts +68 -3
- package/dist/index.mjs +88 -0
- package/package.json +5 -6
- package/dist/index.d.mts +0 -25
- package/dist/index.js +0 -69
package/dist/index.cjs
CHANGED
|
@@ -21,51 +21,71 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
VexilloProvider: () => VexilloProvider,
|
|
24
|
+
fetchFlags: () => fetchFlags,
|
|
24
25
|
useFlag: () => useFlag
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(src_exports);
|
|
27
28
|
|
|
28
29
|
// src/provider.tsx
|
|
29
30
|
var import_react = require("react");
|
|
31
|
+
|
|
32
|
+
// src/fetch-flags.ts
|
|
33
|
+
async function fetchFlags(baseUrl, apiKey) {
|
|
34
|
+
try {
|
|
35
|
+
const res = await fetch(`${baseUrl}/api/flags`, {
|
|
36
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
37
|
+
});
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
console.warn(
|
|
40
|
+
`Vexillo: fetchFlags received status ${res.status} ${res.statusText}. Returning empty flags.`
|
|
41
|
+
);
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
const data = await res.json();
|
|
45
|
+
const map = {};
|
|
46
|
+
for (const f of data.flags) {
|
|
47
|
+
map[f.key] = f.enabled;
|
|
48
|
+
}
|
|
49
|
+
return map;
|
|
50
|
+
} catch (e) {
|
|
51
|
+
console.warn("Vexillo: fetchFlags failed. Returning empty flags.");
|
|
52
|
+
return {};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/provider.tsx
|
|
30
57
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
31
58
|
var VexilloContext = (0, import_react.createContext)(null);
|
|
59
|
+
var clientCache = /* @__PURE__ */ new Map();
|
|
60
|
+
function getOrCreateFlagPromise(baseUrl, apiKey) {
|
|
61
|
+
const key = `${baseUrl}__${apiKey}`;
|
|
62
|
+
if (!clientCache.has(key)) {
|
|
63
|
+
clientCache.set(key, fetchFlags(baseUrl, apiKey));
|
|
64
|
+
}
|
|
65
|
+
return clientCache.get(key);
|
|
66
|
+
}
|
|
32
67
|
function VexilloProvider({
|
|
33
68
|
baseUrl,
|
|
34
69
|
apiKey,
|
|
70
|
+
initialFlags,
|
|
35
71
|
fallbacks = {},
|
|
36
72
|
children
|
|
37
73
|
}) {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const map = {};
|
|
54
|
-
for (const f of data.flags) {
|
|
55
|
-
map[f.key] = f.enabled;
|
|
56
|
-
}
|
|
57
|
-
setFlags(map);
|
|
58
|
-
}).catch((err) => {
|
|
59
|
-
if (cancelled) return;
|
|
60
|
-
setError(
|
|
61
|
-
err instanceof Error ? err : new Error(`Vexillo: unexpected error \u2014 ${String(err)}`)
|
|
62
|
-
);
|
|
63
|
-
});
|
|
64
|
-
return () => {
|
|
65
|
-
cancelled = true;
|
|
66
|
-
};
|
|
67
|
-
}, [apiKey, baseUrl]);
|
|
68
|
-
if (error) throw error;
|
|
74
|
+
const isServer = typeof window === "undefined";
|
|
75
|
+
if (initialFlags) {
|
|
76
|
+
const key = `${baseUrl}__${apiKey}`;
|
|
77
|
+
if (!isServer && !clientCache.has(key)) {
|
|
78
|
+
clientCache.set(key, Promise.resolve(initialFlags));
|
|
79
|
+
}
|
|
80
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VexilloContext.Provider, { value: { flags: initialFlags, fallbacks }, children });
|
|
81
|
+
}
|
|
82
|
+
let flagPromise;
|
|
83
|
+
if (isServer) {
|
|
84
|
+
flagPromise = fetchFlags(baseUrl, apiKey);
|
|
85
|
+
} else {
|
|
86
|
+
flagPromise = getOrCreateFlagPromise(baseUrl, apiKey);
|
|
87
|
+
}
|
|
88
|
+
const flags = (0, import_react.use)(flagPromise);
|
|
69
89
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VexilloContext.Provider, { value: { flags, fallbacks }, children });
|
|
70
90
|
}
|
|
71
91
|
function useVexilloContext() {
|
|
@@ -80,7 +100,7 @@ function useVexilloContext() {
|
|
|
80
100
|
function useFlag(key) {
|
|
81
101
|
var _a;
|
|
82
102
|
const { flags, fallbacks } = useVexilloContext();
|
|
83
|
-
if (
|
|
103
|
+
if (key in flags) {
|
|
84
104
|
return flags[key];
|
|
85
105
|
}
|
|
86
106
|
return (_a = fallbacks[key]) != null ? _a : false;
|
|
@@ -88,5 +108,6 @@ function useFlag(key) {
|
|
|
88
108
|
// Annotate the CommonJS export names for ESM import in node:
|
|
89
109
|
0 && (module.exports = {
|
|
90
110
|
VexilloProvider,
|
|
111
|
+
fetchFlags,
|
|
91
112
|
useFlag
|
|
92
113
|
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
interface VexilloProviderProps {
|
|
4
|
+
/** Base URL of your Vexillo deployment (e.g. "https://vexillo.example.com") */
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
/** SDK API key for the target environment */
|
|
7
|
+
apiKey: string;
|
|
8
|
+
/**
|
|
9
|
+
* Pre-resolved flags from the server.
|
|
10
|
+
*
|
|
11
|
+
* **Required when using `renderToString`** — pass the result of
|
|
12
|
+
* `fetchFlags(baseUrl, apiKey)` here, as `renderToString` does not support
|
|
13
|
+
* Suspense. Without this, the provider will throw during server rendering.
|
|
14
|
+
*
|
|
15
|
+
* Optional for `renderToPipeableStream`, RSC, and SPA — the provider will
|
|
16
|
+
* suspend and fetch flags on its own if omitted.
|
|
17
|
+
*/
|
|
18
|
+
initialFlags?: Record<string, boolean>;
|
|
19
|
+
/** Flag values used as defaults for unknown keys */
|
|
20
|
+
fallbacks?: Record<string, boolean>;
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Provides feature flag values to the React tree via Suspense.
|
|
25
|
+
*
|
|
26
|
+
* The subtree suspends until flags are resolved — wrap with `<Suspense>`
|
|
27
|
+
* to show a loading state.
|
|
28
|
+
*
|
|
29
|
+
* ```tsx
|
|
30
|
+
* <Suspense fallback={<Spinner />}>
|
|
31
|
+
* <VexilloProvider baseUrl="..." apiKey="...">
|
|
32
|
+
* <App />
|
|
33
|
+
* </VexilloProvider>
|
|
34
|
+
* </Suspense>
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* ### SSR with `renderToString`
|
|
38
|
+
* `renderToString` does not support Suspense. Call `fetchFlags` before
|
|
39
|
+
* rendering and pass the result as `initialFlags`:
|
|
40
|
+
* ```ts
|
|
41
|
+
* const flags = await fetchFlags(baseUrl, apiKey);
|
|
42
|
+
* renderToString(<VexilloProvider initialFlags={flags} ...>);
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* ### SSR with `renderToPipeableStream` / RSC
|
|
46
|
+
* `initialFlags` is optional. The provider suspends and streams the resolved
|
|
47
|
+
* flags inline. Pass `initialFlags` to avoid the suspension entirely.
|
|
48
|
+
*/
|
|
49
|
+
declare function VexilloProvider({ baseUrl, apiKey, initialFlags, fallbacks, children, }: VexilloProviderProps): React.ReactElement;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Returns the current boolean value for a feature flag key.
|
|
53
|
+
*
|
|
54
|
+
* - Before the provider's fetch resolves (including SSR), returns the value
|
|
55
|
+
* from `fallbacks`, or `false` if the key is absent.
|
|
56
|
+
* - After the fetch resolves, returns the live value from the API, falling
|
|
57
|
+
* back to `fallbacks[key] ?? false` for keys not present in the response.
|
|
58
|
+
* - Throws if called outside a `<VexilloProvider>`.
|
|
59
|
+
*/
|
|
60
|
+
declare function useFlag(key: string): boolean;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Fetches feature flags from your Vexillo deployment.
|
|
64
|
+
*
|
|
65
|
+
* Use this on the server before rendering to pass resolved flags as
|
|
66
|
+
* `initialFlags` to `<VexilloProvider>`.
|
|
67
|
+
*
|
|
68
|
+
* ## When to use
|
|
69
|
+
*
|
|
70
|
+
* - **`renderToString`** — Suspense is not supported. You MUST call
|
|
71
|
+
* `fetchFlags` before rendering and pass the result as `initialFlags`:
|
|
72
|
+
* ```ts
|
|
73
|
+
* const flags = await fetchFlags(baseUrl, apiKey);
|
|
74
|
+
* renderToString(<VexilloProvider initialFlags={flags} ...>);
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* - **`renderToPipeableStream` / `renderToReadableStream`** — Suspense is
|
|
78
|
+
* supported. `initialFlags` is optional; the provider will suspend and
|
|
79
|
+
* fetch flags inline. You may still pass `initialFlags` to avoid the
|
|
80
|
+
* suspension entirely.
|
|
81
|
+
*
|
|
82
|
+
* - **React Server Components (Next.js App Router)** — call `fetchFlags`
|
|
83
|
+
* in your server component and pass the result as `initialFlags`.
|
|
84
|
+
*
|
|
85
|
+
* - **SPA (no SSR)** — omit `initialFlags`. The provider fetches on the
|
|
86
|
+
* client and suspends until resolved.
|
|
87
|
+
*/
|
|
88
|
+
declare function fetchFlags(baseUrl: string, apiKey: string): Promise<Record<string, boolean>>;
|
|
89
|
+
|
|
90
|
+
export { VexilloProvider, type VexilloProviderProps, fetchFlags, useFlag };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,11 +5,48 @@ interface VexilloProviderProps {
|
|
|
5
5
|
baseUrl: string;
|
|
6
6
|
/** SDK API key for the target environment */
|
|
7
7
|
apiKey: string;
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Pre-resolved flags from the server.
|
|
10
|
+
*
|
|
11
|
+
* **Required when using `renderToString`** — pass the result of
|
|
12
|
+
* `fetchFlags(baseUrl, apiKey)` here, as `renderToString` does not support
|
|
13
|
+
* Suspense. Without this, the provider will throw during server rendering.
|
|
14
|
+
*
|
|
15
|
+
* Optional for `renderToPipeableStream`, RSC, and SPA — the provider will
|
|
16
|
+
* suspend and fetch flags on its own if omitted.
|
|
17
|
+
*/
|
|
18
|
+
initialFlags?: Record<string, boolean>;
|
|
19
|
+
/** Flag values used as defaults for unknown keys */
|
|
9
20
|
fallbacks?: Record<string, boolean>;
|
|
10
21
|
children: ReactNode;
|
|
11
22
|
}
|
|
12
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Provides feature flag values to the React tree via Suspense.
|
|
25
|
+
*
|
|
26
|
+
* The subtree suspends until flags are resolved — wrap with `<Suspense>`
|
|
27
|
+
* to show a loading state.
|
|
28
|
+
*
|
|
29
|
+
* ```tsx
|
|
30
|
+
* <Suspense fallback={<Spinner />}>
|
|
31
|
+
* <VexilloProvider baseUrl="..." apiKey="...">
|
|
32
|
+
* <App />
|
|
33
|
+
* </VexilloProvider>
|
|
34
|
+
* </Suspense>
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* ### SSR with `renderToString`
|
|
38
|
+
* `renderToString` does not support Suspense. Call `fetchFlags` before
|
|
39
|
+
* rendering and pass the result as `initialFlags`:
|
|
40
|
+
* ```ts
|
|
41
|
+
* const flags = await fetchFlags(baseUrl, apiKey);
|
|
42
|
+
* renderToString(<VexilloProvider initialFlags={flags} ...>);
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* ### SSR with `renderToPipeableStream` / RSC
|
|
46
|
+
* `initialFlags` is optional. The provider suspends and streams the resolved
|
|
47
|
+
* flags inline. Pass `initialFlags` to avoid the suspension entirely.
|
|
48
|
+
*/
|
|
49
|
+
declare function VexilloProvider({ baseUrl, apiKey, initialFlags, fallbacks, children, }: VexilloProviderProps): React.ReactElement;
|
|
13
50
|
|
|
14
51
|
/**
|
|
15
52
|
* Returns the current boolean value for a feature flag key.
|
|
@@ -22,4 +59,32 @@ declare function VexilloProvider({ baseUrl, apiKey, fallbacks, children, }: Vexi
|
|
|
22
59
|
*/
|
|
23
60
|
declare function useFlag(key: string): boolean;
|
|
24
61
|
|
|
25
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Fetches feature flags from your Vexillo deployment.
|
|
64
|
+
*
|
|
65
|
+
* Use this on the server before rendering to pass resolved flags as
|
|
66
|
+
* `initialFlags` to `<VexilloProvider>`.
|
|
67
|
+
*
|
|
68
|
+
* ## When to use
|
|
69
|
+
*
|
|
70
|
+
* - **`renderToString`** — Suspense is not supported. You MUST call
|
|
71
|
+
* `fetchFlags` before rendering and pass the result as `initialFlags`:
|
|
72
|
+
* ```ts
|
|
73
|
+
* const flags = await fetchFlags(baseUrl, apiKey);
|
|
74
|
+
* renderToString(<VexilloProvider initialFlags={flags} ...>);
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* - **`renderToPipeableStream` / `renderToReadableStream`** — Suspense is
|
|
78
|
+
* supported. `initialFlags` is optional; the provider will suspend and
|
|
79
|
+
* fetch flags inline. You may still pass `initialFlags` to avoid the
|
|
80
|
+
* suspension entirely.
|
|
81
|
+
*
|
|
82
|
+
* - **React Server Components (Next.js App Router)** — call `fetchFlags`
|
|
83
|
+
* in your server component and pass the result as `initialFlags`.
|
|
84
|
+
*
|
|
85
|
+
* - **SPA (no SSR)** — omit `initialFlags`. The provider fetches on the
|
|
86
|
+
* client and suspends until resolved.
|
|
87
|
+
*/
|
|
88
|
+
declare function fetchFlags(baseUrl: string, apiKey: string): Promise<Record<string, boolean>>;
|
|
89
|
+
|
|
90
|
+
export { VexilloProvider, type VexilloProviderProps, fetchFlags, useFlag };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// src/provider.tsx
|
|
2
|
+
import {
|
|
3
|
+
createContext,
|
|
4
|
+
use,
|
|
5
|
+
useContext
|
|
6
|
+
} from "react";
|
|
7
|
+
|
|
8
|
+
// src/fetch-flags.ts
|
|
9
|
+
async function fetchFlags(baseUrl, apiKey) {
|
|
10
|
+
try {
|
|
11
|
+
const res = await fetch(`${baseUrl}/api/flags`, {
|
|
12
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
13
|
+
});
|
|
14
|
+
if (!res.ok) {
|
|
15
|
+
console.warn(
|
|
16
|
+
`Vexillo: fetchFlags received status ${res.status} ${res.statusText}. Returning empty flags.`
|
|
17
|
+
);
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
const data = await res.json();
|
|
21
|
+
const map = {};
|
|
22
|
+
for (const f of data.flags) {
|
|
23
|
+
map[f.key] = f.enabled;
|
|
24
|
+
}
|
|
25
|
+
return map;
|
|
26
|
+
} catch (e) {
|
|
27
|
+
console.warn("Vexillo: fetchFlags failed. Returning empty flags.");
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/provider.tsx
|
|
33
|
+
import { jsx } from "react/jsx-runtime";
|
|
34
|
+
var VexilloContext = createContext(null);
|
|
35
|
+
var clientCache = /* @__PURE__ */ new Map();
|
|
36
|
+
function getOrCreateFlagPromise(baseUrl, apiKey) {
|
|
37
|
+
const key = `${baseUrl}__${apiKey}`;
|
|
38
|
+
if (!clientCache.has(key)) {
|
|
39
|
+
clientCache.set(key, fetchFlags(baseUrl, apiKey));
|
|
40
|
+
}
|
|
41
|
+
return clientCache.get(key);
|
|
42
|
+
}
|
|
43
|
+
function VexilloProvider({
|
|
44
|
+
baseUrl,
|
|
45
|
+
apiKey,
|
|
46
|
+
initialFlags,
|
|
47
|
+
fallbacks = {},
|
|
48
|
+
children
|
|
49
|
+
}) {
|
|
50
|
+
const isServer = typeof window === "undefined";
|
|
51
|
+
if (initialFlags) {
|
|
52
|
+
const key = `${baseUrl}__${apiKey}`;
|
|
53
|
+
if (!isServer && !clientCache.has(key)) {
|
|
54
|
+
clientCache.set(key, Promise.resolve(initialFlags));
|
|
55
|
+
}
|
|
56
|
+
return /* @__PURE__ */ jsx(VexilloContext.Provider, { value: { flags: initialFlags, fallbacks }, children });
|
|
57
|
+
}
|
|
58
|
+
let flagPromise;
|
|
59
|
+
if (isServer) {
|
|
60
|
+
flagPromise = fetchFlags(baseUrl, apiKey);
|
|
61
|
+
} else {
|
|
62
|
+
flagPromise = getOrCreateFlagPromise(baseUrl, apiKey);
|
|
63
|
+
}
|
|
64
|
+
const flags = use(flagPromise);
|
|
65
|
+
return /* @__PURE__ */ jsx(VexilloContext.Provider, { value: { flags, fallbacks }, children });
|
|
66
|
+
}
|
|
67
|
+
function useVexilloContext() {
|
|
68
|
+
const ctx = useContext(VexilloContext);
|
|
69
|
+
if (ctx === null) {
|
|
70
|
+
throw new Error("useFlag must be called inside a <VexilloProvider>.");
|
|
71
|
+
}
|
|
72
|
+
return ctx;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/use-flag.ts
|
|
76
|
+
function useFlag(key) {
|
|
77
|
+
var _a;
|
|
78
|
+
const { flags, fallbacks } = useVexilloContext();
|
|
79
|
+
if (key in flags) {
|
|
80
|
+
return flags[key];
|
|
81
|
+
}
|
|
82
|
+
return (_a = fallbacks[key]) != null ? _a : false;
|
|
83
|
+
}
|
|
84
|
+
export {
|
|
85
|
+
VexilloProvider,
|
|
86
|
+
fetchFlags,
|
|
87
|
+
useFlag
|
|
88
|
+
};
|
package/package.json
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vexillo/react-sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"license": "MIT",
|
|
5
6
|
"publishConfig": {
|
|
6
7
|
"registry": "https://registry.npmjs.org",
|
|
7
8
|
"access": "public"
|
|
8
9
|
},
|
|
9
|
-
"main": "./dist/index.cjs",
|
|
10
|
-
"module": "./dist/index.js",
|
|
11
10
|
"types": "./dist/index.d.ts",
|
|
12
11
|
"exports": {
|
|
13
12
|
".": {
|
|
14
13
|
"types": "./dist/index.d.ts",
|
|
15
|
-
"import": "./dist/index.
|
|
14
|
+
"import": "./dist/index.mjs",
|
|
16
15
|
"require": "./dist/index.cjs"
|
|
17
16
|
}
|
|
18
17
|
},
|
|
@@ -20,8 +19,8 @@
|
|
|
20
19
|
"dist"
|
|
21
20
|
],
|
|
22
21
|
"peerDependencies": {
|
|
23
|
-
"react": "^
|
|
24
|
-
"react-dom": "^
|
|
22
|
+
"react": "^19",
|
|
23
|
+
"react-dom": "^19"
|
|
25
24
|
},
|
|
26
25
|
"devDependencies": {
|
|
27
26
|
"@testing-library/react": "^16",
|
package/dist/index.d.mts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
interface VexilloProviderProps {
|
|
4
|
-
/** Base URL of your Vexillo deployment (e.g. "https://vexillo.example.com") */
|
|
5
|
-
baseUrl: string;
|
|
6
|
-
/** SDK API key for the target environment */
|
|
7
|
-
apiKey: string;
|
|
8
|
-
/** Flag values used before the fetch resolves and for unknown keys */
|
|
9
|
-
fallbacks?: Record<string, boolean>;
|
|
10
|
-
children: ReactNode;
|
|
11
|
-
}
|
|
12
|
-
declare function VexilloProvider({ baseUrl, apiKey, fallbacks, children, }: VexilloProviderProps): React.ReactElement;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Returns the current boolean value for a feature flag key.
|
|
16
|
-
*
|
|
17
|
-
* - Before the provider's fetch resolves (including SSR), returns the value
|
|
18
|
-
* from `fallbacks`, or `false` if the key is absent.
|
|
19
|
-
* - After the fetch resolves, returns the live value from the API, falling
|
|
20
|
-
* back to `fallbacks[key] ?? false` for keys not present in the response.
|
|
21
|
-
* - Throws if called outside a `<VexilloProvider>`.
|
|
22
|
-
*/
|
|
23
|
-
declare function useFlag(key: string): boolean;
|
|
24
|
-
|
|
25
|
-
export { VexilloProvider, type VexilloProviderProps, useFlag };
|
package/dist/index.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
// src/provider.tsx
|
|
2
|
-
import {
|
|
3
|
-
createContext,
|
|
4
|
-
useContext,
|
|
5
|
-
useEffect,
|
|
6
|
-
useState
|
|
7
|
-
} from "react";
|
|
8
|
-
import { jsx } from "react/jsx-runtime";
|
|
9
|
-
var VexilloContext = createContext(null);
|
|
10
|
-
function VexilloProvider({
|
|
11
|
-
baseUrl,
|
|
12
|
-
apiKey,
|
|
13
|
-
fallbacks = {},
|
|
14
|
-
children
|
|
15
|
-
}) {
|
|
16
|
-
const [flags, setFlags] = useState(null);
|
|
17
|
-
const [error, setError] = useState(null);
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
let cancelled = false;
|
|
20
|
-
fetch(`${baseUrl}/api/flags`, {
|
|
21
|
-
headers: { Authorization: `Bearer ${apiKey}` }
|
|
22
|
-
}).then((res) => {
|
|
23
|
-
if (!res.ok) {
|
|
24
|
-
throw new Error(
|
|
25
|
-
`Vexillo: API responded with status ${res.status} ${res.statusText}`
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
return res.json();
|
|
29
|
-
}).then((data) => {
|
|
30
|
-
if (cancelled) return;
|
|
31
|
-
const map = {};
|
|
32
|
-
for (const f of data.flags) {
|
|
33
|
-
map[f.key] = f.enabled;
|
|
34
|
-
}
|
|
35
|
-
setFlags(map);
|
|
36
|
-
}).catch((err) => {
|
|
37
|
-
if (cancelled) return;
|
|
38
|
-
setError(
|
|
39
|
-
err instanceof Error ? err : new Error(`Vexillo: unexpected error \u2014 ${String(err)}`)
|
|
40
|
-
);
|
|
41
|
-
});
|
|
42
|
-
return () => {
|
|
43
|
-
cancelled = true;
|
|
44
|
-
};
|
|
45
|
-
}, [apiKey, baseUrl]);
|
|
46
|
-
if (error) throw error;
|
|
47
|
-
return /* @__PURE__ */ jsx(VexilloContext.Provider, { value: { flags, fallbacks }, children });
|
|
48
|
-
}
|
|
49
|
-
function useVexilloContext() {
|
|
50
|
-
const ctx = useContext(VexilloContext);
|
|
51
|
-
if (ctx === null) {
|
|
52
|
-
throw new Error("useFlag must be called inside a <VexilloProvider>.");
|
|
53
|
-
}
|
|
54
|
-
return ctx;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// src/use-flag.ts
|
|
58
|
-
function useFlag(key) {
|
|
59
|
-
var _a;
|
|
60
|
-
const { flags, fallbacks } = useVexilloContext();
|
|
61
|
-
if (flags !== null && key in flags) {
|
|
62
|
-
return flags[key];
|
|
63
|
-
}
|
|
64
|
-
return (_a = fallbacks[key]) != null ? _a : false;
|
|
65
|
-
}
|
|
66
|
-
export {
|
|
67
|
-
VexilloProvider,
|
|
68
|
-
useFlag
|
|
69
|
-
};
|