runid-lys 0.2.0 → 0.3.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/CHANGELOG.md CHANGED
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.0] - 2026-03-07
11
+
12
+ ### Added
13
+
14
+ - `ClientProvider` for managing current client ID selection (locked for client users, selectable for admins)
15
+ - `useClientId` hook exposing `clientId`, `setClientId`, and `isLocked`
16
+ - Batched URL update mechanism in `UrlQueriesProvider` via `queueMicrotask` to prevent race conditions
17
+
18
+ ### Fixed
19
+
20
+ - TypeScript errors in `ConnectedUserProvider` (generic types on `useMutation` calls)
21
+ - TypeScript error in test-utils mock user (`lastValidationRequestAt` type)
22
+
10
23
  ## [0.2.0] - 2026-02-25
11
24
 
12
25
  ### Added
@@ -3,9 +3,9 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
5
  import * as React from "react";
6
- import React__default, { createContext, useContext, useMemo, useState, useCallback, useEffect, useRef, useReducer, forwardRef, Suspense, useImperativeHandle } from "react";
6
+ import React__default, { createContext, useContext, useMemo, useState, useCallback, useRef, useEffect, useReducer, forwardRef, Suspense, useImperativeHandle } from "react";
7
7
  import { C as ChatbotContext, b as ConnectedUserContext, a as useConnectedUserInfo } from "./hooks-CvhFUowR.js";
8
- import { useSearchParams } from "react-router-dom";
8
+ import { useSearchParams, useLocation } from "react-router-dom";
9
9
  import { usePreloadedQuery, useFragment, useMutation, useQueryLoader } from "react-relay";
10
10
  import { IntlProvider, useIntl } from "react-intl";
11
11
  import { c as clearRelayCache } from "./RelayEnvironment-D880U9SM.js";
@@ -207,17 +207,29 @@ const UrlQueriesProvider = ({ children }) => {
207
207
  });
208
208
  setSearchParams(newSearchParams);
209
209
  }, [stagedParams, setSearchParams]);
210
+ const pendingUpdatesRef = useRef({});
211
+ const flushScheduledRef = useRef(false);
210
212
  const update = useCallback((data) => {
211
- setSearchParams((prev) => {
212
- Object.entries(data).forEach(([key, value]) => {
213
- if (value !== void 0 && value !== null) {
214
- prev.set(key, value.toString());
215
- } else {
216
- prev.delete(key);
217
- }
213
+ Object.assign(pendingUpdatesRef.current, data);
214
+ if (!flushScheduledRef.current) {
215
+ flushScheduledRef.current = true;
216
+ queueMicrotask(() => {
217
+ flushScheduledRef.current = false;
218
+ const pending = { ...pendingUpdatesRef.current };
219
+ pendingUpdatesRef.current = {};
220
+ setSearchParams((prev) => {
221
+ const next = new URLSearchParams(prev);
222
+ Object.entries(pending).forEach(([key, value]) => {
223
+ if (value !== void 0 && value !== null) {
224
+ next.set(key, value.toString());
225
+ } else {
226
+ next.delete(key);
227
+ }
228
+ });
229
+ return next;
230
+ });
218
231
  });
219
- return prev;
220
- });
232
+ }
221
233
  }, [setSearchParams]);
222
234
  useEffect(() => {
223
235
  const newTmpParameters = {};
@@ -2056,6 +2068,68 @@ const LysMutationProvider = forwardRef((props, ref) => {
2056
2068
  }
2057
2069
  );
2058
2070
  });
2071
+ const ClientContext = createContext({
2072
+ clientId: null,
2073
+ setClientId: () => {
2074
+ console.warn("ClientProvider not initialized: setClientId");
2075
+ },
2076
+ isLocked: false
2077
+ });
2078
+ function useClientId() {
2079
+ return useContext(ClientContext);
2080
+ }
2081
+ const SESSION_KEY = "lys_clientId";
2082
+ const URL_PARAM_KEY = "clientId";
2083
+ const ClientProvider = ({ children }) => {
2084
+ const { user } = useConnectedUserInfo();
2085
+ const { update: updateUrl, appliedParams } = useUrlQueries();
2086
+ const location = useLocation();
2087
+ const isLocked = !!(user == null ? void 0 : user.clientId);
2088
+ const prevUserRef = useRef(user);
2089
+ const [selectedClientId, setSelectedClientId] = useState(() => {
2090
+ return appliedParams.get(URL_PARAM_KEY) || sessionStorage.getItem(SESSION_KEY);
2091
+ });
2092
+ useEffect(() => {
2093
+ const wasLoggedIn = prevUserRef.current !== void 0;
2094
+ const isLoggedOut = user === void 0;
2095
+ prevUserRef.current = user;
2096
+ if (wasLoggedIn && isLoggedOut) {
2097
+ sessionStorage.removeItem(SESSION_KEY);
2098
+ setSelectedClientId(null);
2099
+ updateUrl({ [URL_PARAM_KEY]: null });
2100
+ }
2101
+ }, [user, updateUrl]);
2102
+ useEffect(() => {
2103
+ if (isLocked) return;
2104
+ if (selectedClientId) {
2105
+ updateUrl({ [URL_PARAM_KEY]: selectedClientId });
2106
+ } else {
2107
+ updateUrl({ [URL_PARAM_KEY]: null });
2108
+ }
2109
+ }, [selectedClientId, location.pathname, isLocked, updateUrl]);
2110
+ const clientId = useMemo(() => {
2111
+ if (user == null ? void 0 : user.clientId) {
2112
+ return user.clientId;
2113
+ }
2114
+ return selectedClientId;
2115
+ }, [user == null ? void 0 : user.clientId, selectedClientId]);
2116
+ const setClientId = useCallback((id) => {
2117
+ if (isLocked) return;
2118
+ if (id) {
2119
+ sessionStorage.setItem(SESSION_KEY, id);
2120
+ } else {
2121
+ sessionStorage.removeItem(SESSION_KEY);
2122
+ }
2123
+ setSelectedClientId(id);
2124
+ }, [isLocked]);
2125
+ const value = useMemo(() => ({
2126
+ clientId,
2127
+ setClientId,
2128
+ isLocked
2129
+ }), [clientId, setClientId, isLocked]);
2130
+ return /* @__PURE__ */ jsx(ClientContext.Provider, { value, children });
2131
+ };
2132
+ ClientProvider.displayName = "ClientProvider";
2059
2133
  const GRAPHQL_ERROR = "GraphQL Error";
2060
2134
  export {
2061
2135
  AlertMessageProvider as A,
@@ -2069,28 +2143,30 @@ export {
2069
2143
  SignalProvider as S,
2070
2144
  UrlQueriesProvider as U,
2071
2145
  WebserviceAccessProvider as W,
2072
- ConnectedUserFragment as a,
2073
- ConnectedUserProvider as b,
2074
- LysDialogProvider as c,
2075
- LysLoadingContext as d,
2076
- LysMutationProvider as e,
2077
- LysQueryProvider as f,
2078
- useDialogWithUpdates as g,
2079
- useFilterLabels as h,
2080
- useLocale as i,
2081
- useLysDialog as j,
2082
- useLysLoadingFallback as k,
2083
- useLysMutation as l,
2084
- useLysQuery as m,
2085
- usePageContext as n,
2086
- usePermissionCheck as o,
2087
- useRefreshSignal as p,
2088
- useSignal as q,
2089
- useSignalRefresh as r,
2090
- useSignalSubscription as s,
2091
- useUrlQueries as t,
2146
+ ClientProvider as a,
2147
+ ConnectedUserFragment as b,
2148
+ ConnectedUserProvider as c,
2149
+ LysDialogProvider as d,
2150
+ LysLoadingContext as e,
2151
+ LysMutationProvider as f,
2152
+ LysQueryProvider as g,
2153
+ useClientId as h,
2154
+ useDialogWithUpdates as i,
2155
+ useFilterLabels as j,
2156
+ useLocale as k,
2157
+ useLysDialog as l,
2158
+ useLysLoadingFallback as m,
2159
+ useLysMutation as n,
2160
+ useLysQuery as o,
2161
+ usePageContext as p,
2162
+ usePermissionCheck as q,
2163
+ useRefreshSignal as r,
2164
+ useSignal as s,
2165
+ useSignalRefresh as t,
2092
2166
  useAlertMessages as u,
2093
- useWebserviceAccess as v,
2094
- webserviceAccessProviderConfig as w
2167
+ useSignalSubscription as v,
2168
+ useUrlQueries as w,
2169
+ useWebserviceAccess as x,
2170
+ webserviceAccessProviderConfig as y
2095
2171
  };
2096
- //# sourceMappingURL=constants-BnIuKcUZ.js.map
2172
+ //# sourceMappingURL=constants-DEt8avUj.js.map