@ops-ai/react-router-toggly 1.2.0 → 1.5.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/CHANGELOG.md +38 -0
- package/dist/client.cjs +106 -22
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +5 -2
- package/dist/client.d.ts +5 -2
- package/dist/client.js +108 -24
- package/dist/client.js.map +1 -1
- package/dist/server.cjs +94 -48
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +86 -48
- package/dist/server.js.map +1 -1
- package/dist/telemetry/grpc.cjs +1 -1
- package/dist/telemetry/grpc.cjs.map +1 -1
- package/dist/telemetry/grpc.js +1 -1
- package/dist/telemetry/grpc.js.map +1 -1
- package/package.json +4 -3
- package/proto/usage.proto +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
|
+
## 1.5.1
|
|
2
|
+
|
|
3
|
+
2026-10-15
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- After `dispose()`, `use()` and `captureCheck()` no longer create an
|
|
7
|
+
unmanaged reporter or attach leftover lifecycle listeners [OPS-1758].
|
|
8
|
+
|
|
9
|
+
## 1.5.0
|
|
10
|
+
|
|
11
|
+
2026-10-11
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- `use()` for timed feature usage scopes (attempt, duration, errors) via `@ops-ai/toggly-client-telemetry` [OPS-1758].
|
|
15
|
+
|
|
1
16
|
# Changelog
|
|
2
17
|
|
|
18
|
+
## [1.4.0] - 2026-10-11
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- Usage scope metrics on `VariantStats` (`errorCount`, `durationSumMs`,
|
|
22
|
+
`errorDurationSumMs`) and batcher APIs `recordUsageError`, `recordUsageDuration`,
|
|
23
|
+
`recordUsageScopeOutcome` (proto fields 5–7).
|
|
24
|
+
|
|
25
|
+
## [1.3.1] - 2026-10-11
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- Only call `useRouteLoaderData` when `routeId` is set and use `useInRouterContext` so SSR and non-data-router apps hydrate from `fallbackContext` / `TogglyScript` without invoking data-router hooks [OPS-1756].
|
|
29
|
+
|
|
30
|
+
## [1.3.0] - 2026-10-04
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
- Server export of `createSegmentMembershipClient` for Backend-key targeting-list updates.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
## [1.2.1] - 2026-09-27
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
- Keep `RouterTogglyProvider` hook order stable when route selection changes while retaining loader and fallback context hydration [OPS-1451].
|
|
40
|
+
- Surface invalid React Router context errors to the application's Error Boundary instead of intercepting loader hooks [OPS-1451].
|
|
3
41
|
|
|
4
42
|
## [1.2.0] - 2026-09-26
|
|
5
43
|
|
package/dist/client.cjs
CHANGED
|
@@ -186,6 +186,7 @@ function createBrowserTelemetry(config) {
|
|
|
186
186
|
}
|
|
187
187
|
};
|
|
188
188
|
const getReporter = () => {
|
|
189
|
+
if (disposed) return void 0;
|
|
189
190
|
if (!reporter) {
|
|
190
191
|
reporter = togglyClientTelemetry.createTelemetryReporter({
|
|
191
192
|
appKey: config.appKey,
|
|
@@ -207,6 +208,7 @@ function createBrowserTelemetry(config) {
|
|
|
207
208
|
};
|
|
208
209
|
function replay(entry) {
|
|
209
210
|
const target = getReporter();
|
|
211
|
+
if (!target) return;
|
|
210
212
|
target.setContext(entry.context);
|
|
211
213
|
if (entry.kind === "feature") {
|
|
212
214
|
const methods = ["recordCheck", "recordUsage", "recordView"];
|
|
@@ -274,6 +276,28 @@ function createBrowserTelemetry(config) {
|
|
|
274
276
|
}
|
|
275
277
|
const api = {
|
|
276
278
|
recordUsage: (key, variant = "enabled") => feature(key, variant, 1),
|
|
279
|
+
use: (key, fn, variant = "enabled") => {
|
|
280
|
+
if (!usage || disposed) {
|
|
281
|
+
return togglyClientTelemetry.runFeatureUsageScope(
|
|
282
|
+
{ recordAttempt: () => {
|
|
283
|
+
}, recordSuccessDuration: () => {
|
|
284
|
+
}, recordFailure: () => {
|
|
285
|
+
} },
|
|
286
|
+
fn
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
const target = getReporter();
|
|
290
|
+
if (!target) {
|
|
291
|
+
return togglyClientTelemetry.runFeatureUsageScope(
|
|
292
|
+
{ recordAttempt: () => {
|
|
293
|
+
}, recordSuccessDuration: () => {
|
|
294
|
+
}, recordFailure: () => {
|
|
295
|
+
} },
|
|
296
|
+
fn
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
return target.use(key, fn, variant);
|
|
300
|
+
},
|
|
277
301
|
recordView: (key, variant = "enabled") => feature(key, variant, 2),
|
|
278
302
|
incrementCounter: (key, value = 1) => event({ partition, context, key, kind: "counter", values: [value] }),
|
|
279
303
|
setGauge: (key, value) => event({ partition, context, key, kind: "gauge", values: [value] }),
|
|
@@ -293,7 +317,10 @@ function createBrowserTelemetry(config) {
|
|
|
293
317
|
if (disposed || !usage) return () => {
|
|
294
318
|
};
|
|
295
319
|
if (active) {
|
|
296
|
-
const
|
|
320
|
+
const target = getReporter();
|
|
321
|
+
if (!target) return () => {
|
|
322
|
+
};
|
|
323
|
+
const record = target.captureCheck();
|
|
297
324
|
return (key, result) => record(key, checkVariantLabel(result));
|
|
298
325
|
}
|
|
299
326
|
const attribution = context;
|
|
@@ -320,7 +347,7 @@ function createBrowserTelemetry(config) {
|
|
|
320
347
|
|
|
321
348
|
// src/client/sdk-identity.ts
|
|
322
349
|
var SDK_ID = "react-router";
|
|
323
|
-
var SDK_VERSION = "1.
|
|
350
|
+
var SDK_VERSION = "1.5.0";
|
|
324
351
|
function appendSdkQueryParams(params) {
|
|
325
352
|
params.set("sdk", SDK_ID);
|
|
326
353
|
params.set("sdkVersion", SDK_VERSION);
|
|
@@ -1053,40 +1080,97 @@ function FeatureGate({
|
|
|
1053
1080
|
const enabled = useFeatureGate(featureKeys, requirement, negate, context, contextKind);
|
|
1054
1081
|
return enabled ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }) : null;
|
|
1055
1082
|
}
|
|
1056
|
-
function
|
|
1083
|
+
function resolveServerContext(data, fallbackContext) {
|
|
1084
|
+
const serverContext = data?.[TOGGLY_LOADER_KEY];
|
|
1085
|
+
return serverContext ?? fallbackContext;
|
|
1086
|
+
}
|
|
1087
|
+
function buildMergedConfig(config, serverContext) {
|
|
1088
|
+
return config ?? (serverContext ? {
|
|
1089
|
+
appKey: serverContext.appKey,
|
|
1090
|
+
environment: serverContext.environment
|
|
1091
|
+
} : void 0);
|
|
1092
|
+
}
|
|
1093
|
+
function RouterTogglyProviderInner({
|
|
1094
|
+
children,
|
|
1095
|
+
serverContext,
|
|
1096
|
+
config,
|
|
1097
|
+
...props
|
|
1098
|
+
}) {
|
|
1099
|
+
const mergedConfig = buildMergedConfig(config, serverContext);
|
|
1100
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TogglyProvider, { serverContext, config: mergedConfig, ...props, children });
|
|
1101
|
+
}
|
|
1102
|
+
function RouterTogglyProviderWithData({
|
|
1103
|
+
children,
|
|
1104
|
+
data,
|
|
1105
|
+
fallbackContext,
|
|
1106
|
+
config,
|
|
1107
|
+
...props
|
|
1108
|
+
}) {
|
|
1109
|
+
const serverContext = resolveServerContext(data, fallbackContext);
|
|
1110
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RouterTogglyProviderInner, { serverContext, config, ...props, children });
|
|
1111
|
+
}
|
|
1112
|
+
function RouterTogglyProviderFromRoute({
|
|
1057
1113
|
children,
|
|
1058
1114
|
routeId,
|
|
1059
1115
|
fallbackContext,
|
|
1060
1116
|
config,
|
|
1061
1117
|
...props
|
|
1062
1118
|
}) {
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1119
|
+
const routeData = reactRouter.useRouteLoaderData(routeId);
|
|
1120
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1121
|
+
RouterTogglyProviderWithData,
|
|
1122
|
+
{
|
|
1123
|
+
data: routeData,
|
|
1124
|
+
fallbackContext,
|
|
1125
|
+
config,
|
|
1126
|
+
...props,
|
|
1127
|
+
children
|
|
1071
1128
|
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
function RouterTogglyProviderFromLoader({
|
|
1132
|
+
children,
|
|
1133
|
+
fallbackContext,
|
|
1134
|
+
config,
|
|
1135
|
+
...props
|
|
1136
|
+
}) {
|
|
1137
|
+
const loaderData = reactRouter.useLoaderData();
|
|
1080
1138
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1081
|
-
|
|
1139
|
+
RouterTogglyProviderWithData,
|
|
1082
1140
|
{
|
|
1083
|
-
|
|
1084
|
-
|
|
1141
|
+
data: loaderData,
|
|
1142
|
+
fallbackContext,
|
|
1143
|
+
config,
|
|
1085
1144
|
...props,
|
|
1086
1145
|
children
|
|
1087
1146
|
}
|
|
1088
1147
|
);
|
|
1089
1148
|
}
|
|
1149
|
+
function RouterTogglyProviderStatic({
|
|
1150
|
+
children,
|
|
1151
|
+
fallbackContext,
|
|
1152
|
+
config,
|
|
1153
|
+
...props
|
|
1154
|
+
}) {
|
|
1155
|
+
const serverContext = fallbackContext ?? getWindowTogglyData();
|
|
1156
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RouterTogglyProviderInner, { serverContext, config, ...props, children });
|
|
1157
|
+
}
|
|
1158
|
+
function RouterTogglyProvider({
|
|
1159
|
+
children,
|
|
1160
|
+
routeId,
|
|
1161
|
+
fallbackContext,
|
|
1162
|
+
config,
|
|
1163
|
+
...props
|
|
1164
|
+
}) {
|
|
1165
|
+
const inRouter = reactRouter.useInRouterContext();
|
|
1166
|
+
if (routeId && inRouter) {
|
|
1167
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RouterTogglyProviderFromRoute, { routeId, fallbackContext, config, ...props, children });
|
|
1168
|
+
}
|
|
1169
|
+
if (inRouter) {
|
|
1170
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RouterTogglyProviderFromLoader, { fallbackContext, config, ...props, children });
|
|
1171
|
+
}
|
|
1172
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RouterTogglyProviderStatic, { fallbackContext, config, ...props, children });
|
|
1173
|
+
}
|
|
1090
1174
|
function useTogglyLoaderData() {
|
|
1091
1175
|
const loaderData = reactRouter.useLoaderData();
|
|
1092
1176
|
return {
|