@faststats/react 0.1.9 → 0.2.1
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.d.ts +15 -2
- package/dist/index.js +84 -2
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConsentMode, WebAnalyticsOptions, reportError } from "@faststats/web";
|
|
1
|
+
import { ConsentMode, FeatureFlagEvaluation, WebAnalyticsOptions, reportError } from "@faststats/web";
|
|
2
2
|
|
|
3
3
|
//#region src/analytics.d.ts
|
|
4
4
|
type AnalyticsProps = WebAnalyticsOptions;
|
|
@@ -18,4 +18,17 @@ declare function useConsentMode(): (mode: ConsentMode) => void;
|
|
|
18
18
|
declare function useOptIn(): () => void;
|
|
19
19
|
declare function useOptOut(): () => void;
|
|
20
20
|
//#endregion
|
|
21
|
-
|
|
21
|
+
//#region src/use-flag.d.ts
|
|
22
|
+
type UseFlagOptions = {
|
|
23
|
+
attributes?: Record<string, unknown>;
|
|
24
|
+
externalId?: string;
|
|
25
|
+
skip?: boolean;
|
|
26
|
+
};
|
|
27
|
+
type UseFlagResult = FeatureFlagEvaluation & {
|
|
28
|
+
isLoading: boolean;
|
|
29
|
+
error: Error | null;
|
|
30
|
+
refetch: () => void;
|
|
31
|
+
};
|
|
32
|
+
declare function useFlag(flagKey: string, options?: UseFlagOptions): UseFlagResult;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { Analytics, type UseFlagOptions, type UseFlagResult, reportError, useConsentMode, useEvent, useFlag, useIdentify, useLogout, useOptIn, useOptOut, useTrack };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { WebAnalytics, getInstance, reportError } from "@faststats/web";
|
|
3
|
-
import { useEffect, useRef } from "react";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
4
4
|
//#region src/instance.ts
|
|
5
5
|
let instance = null;
|
|
6
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
7
|
+
function subscribeToInstance(onStoreChange) {
|
|
8
|
+
listeners.add(onStoreChange);
|
|
9
|
+
return () => {
|
|
10
|
+
listeners.delete(onStoreChange);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function getInstanceSnapshot() {
|
|
14
|
+
return instance;
|
|
15
|
+
}
|
|
6
16
|
function setInstance(wa) {
|
|
7
17
|
instance = wa;
|
|
18
|
+
for (const l of listeners) l();
|
|
8
19
|
}
|
|
9
20
|
//#endregion
|
|
10
21
|
//#region src/analytics.tsx
|
|
@@ -81,4 +92,75 @@ function useOptOut() {
|
|
|
81
92
|
};
|
|
82
93
|
}
|
|
83
94
|
//#endregion
|
|
84
|
-
|
|
95
|
+
//#region src/use-flag.ts
|
|
96
|
+
const defaultEvaluation = { enabled: false };
|
|
97
|
+
function stableSerialize(attributes) {
|
|
98
|
+
if (!attributes) return "";
|
|
99
|
+
const keys = Object.keys(attributes).sort();
|
|
100
|
+
const obj = {};
|
|
101
|
+
for (const k of keys) obj[k] = attributes[k];
|
|
102
|
+
return JSON.stringify(obj);
|
|
103
|
+
}
|
|
104
|
+
function useFlag(flagKey, options) {
|
|
105
|
+
const wa = useSyncExternalStore(subscribeToInstance, getInstanceSnapshot, () => null);
|
|
106
|
+
const attributes = options?.attributes;
|
|
107
|
+
const externalId = options?.externalId;
|
|
108
|
+
const skip = options?.skip ?? false;
|
|
109
|
+
const attrKey = useMemo(() => stableSerialize(attributes), [attributes]);
|
|
110
|
+
const [refetchCount, setRefetchCount] = useState(0);
|
|
111
|
+
const [evaluation, setEvaluation] = useState(defaultEvaluation);
|
|
112
|
+
const [isLoading, setIsLoading] = useState(!skip);
|
|
113
|
+
const [error, setError] = useState(null);
|
|
114
|
+
const refetch = useCallback(() => setRefetchCount((n) => n + 1), []);
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
if (skip || typeof window === "undefined") {
|
|
117
|
+
setIsLoading(false);
|
|
118
|
+
setEvaluation(defaultEvaluation);
|
|
119
|
+
setError(null);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (!wa) {
|
|
123
|
+
setIsLoading(false);
|
|
124
|
+
setEvaluation(defaultEvaluation);
|
|
125
|
+
setError(null);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const ac = new AbortController();
|
|
129
|
+
setIsLoading(true);
|
|
130
|
+
setError(null);
|
|
131
|
+
const requestAttributes = attrKey ? JSON.parse(attrKey) : void 0;
|
|
132
|
+
wa.checkFeatureFlag(flagKey, requestAttributes, {
|
|
133
|
+
externalId,
|
|
134
|
+
signal: ac.signal
|
|
135
|
+
}).then((result) => {
|
|
136
|
+
if (ac.signal.aborted) return;
|
|
137
|
+
setEvaluation(result);
|
|
138
|
+
setIsLoading(false);
|
|
139
|
+
}).catch((e) => {
|
|
140
|
+
if (ac.signal.aborted) return;
|
|
141
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
142
|
+
if (err.name === "AbortError") return;
|
|
143
|
+
setError(err);
|
|
144
|
+
setEvaluation(defaultEvaluation);
|
|
145
|
+
setIsLoading(false);
|
|
146
|
+
});
|
|
147
|
+
return () => {
|
|
148
|
+
ac.abort();
|
|
149
|
+
};
|
|
150
|
+
}, [
|
|
151
|
+
wa,
|
|
152
|
+
flagKey,
|
|
153
|
+
externalId,
|
|
154
|
+
skip,
|
|
155
|
+
attrKey,
|
|
156
|
+
refetchCount
|
|
157
|
+
]);
|
|
158
|
+
return {
|
|
159
|
+
...evaluation,
|
|
160
|
+
isLoading,
|
|
161
|
+
error,
|
|
162
|
+
refetch
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
//#endregion
|
|
166
|
+
export { Analytics, reportError, useConsentMode, useEvent, useFlag, useIdentify, useLogout, useOptIn, useOptOut, useTrack };
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"type": "git",
|
|
5
5
|
"url": "https://github.com/faststats-dev/web-analytics.git"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.1
|
|
7
|
+
"version": "0.2.1",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "./dist/index.js",
|
|
10
10
|
"module": "./dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"react": ">=18"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@faststats/web": "^0.1
|
|
34
|
+
"@faststats/web": "^0.2.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/react": "^19.0.0",
|