@trackunit/react-core-hooks 1.12.50-alpha-c496ead6241.0 → 1.12.51

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/index.cjs.js CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  var reactCoreContextsApi = require('@trackunit/react-core-contexts-api');
4
4
  var react = require('react');
5
- var esToolkit = require('es-toolkit');
6
5
  var irisAppRuntimeCore = require('@trackunit/iris-app-runtime-core');
7
6
 
8
7
  /**
@@ -380,88 +379,64 @@ const useModalDialogContext = () => {
380
379
  return modalDialogContext;
381
380
  };
382
381
 
383
- const isMultipleCriteriaOneOf = (options) => typeof options === "object" && "oneOf" in options;
384
- const isMultipleCriteriaRequireAll = (options) => typeof options === "object" && "requireAll" in options;
385
- const resolveAccess = async (context, options) => {
386
- if (isMultipleCriteriaOneOf(options) && isMultipleCriteriaRequireAll(options)) {
387
- throw new Error("Multiple criteria are not allowed, use one of or require all - not both");
388
- }
389
- if (isMultipleCriteriaOneOf(options)) {
390
- const results = await Promise.all(options.oneOf.map(option => context.hasAccessTo(option)));
391
- return results.some(Boolean);
392
- }
393
- if (isMultipleCriteriaRequireAll(options)) {
394
- const results = await Promise.all(options.requireAll.map(option => context.hasAccessTo(option)));
395
- return results.every(Boolean);
396
- }
397
- return context.hasAccessTo(options);
382
+ const isMultipleCriteriaOneOf = (options) => {
383
+ return typeof options === "object" && "oneOf" in options;
398
384
  };
399
- const INITIAL_STATE = {
400
- status: "loading",
401
- hasAccess: undefined,
402
- error: undefined,
403
- };
404
- const accessReducer = (_state, action) => {
405
- switch (action.type) {
406
- case "FETCH_START":
407
- return INITIAL_STATE;
408
- case "FETCH_SUCCESS":
409
- return { status: "success", hasAccess: action.hasAccess, error: undefined };
410
- case "FETCH_ERROR":
411
- return { status: "error", hasAccess: undefined, error: action.error };
412
- default:
413
- throw new Error(`${action} is not a known action`);
414
- }
385
+ const isMultipleCriteriaRequireAll = (options) => {
386
+ return typeof options === "object" && "requireAll" in options;
415
387
  };
416
388
  /**
417
- * Hook to check if the current user has access to a navigation target.
418
- * Useful for conditionally rendering links based on user permissions.
389
+ * This is a hook to use the hasAccessTo in host.
390
+ * You can use this to ensure the page you link to is available for the user to see.
419
391
  *
420
392
  * @requires NavigationContext
421
393
  * @example
422
394
  * import { useHasAccessTo } from "@trackunit/react-core-hooks";
423
395
  * useHasAccessTo({ assetId: assetInfo?.assetId, page: "movement" })
424
- * @see {@link NavigationRuntimeApi}
425
- * @see {@link HasAccessToOptions}
396
+ * @see (@link NavigationRuntimeApi)
397
+ * @see (@link HasAccessToOptions)
398
+ * @see (@link HasAccessToOptions.assetId)
399
+ * @see (@link HasAccessToOptions.page)
400
+ * @see (@link HasAccessToOptions.siteId)
401
+ * @see (@link NavigationRuntimeApi)
426
402
  */
427
403
  const useHasAccessTo = (options) => {
428
404
  const context = react.useContext(reactCoreContextsApi.NavigationContext);
429
- const [stableOptions, setStableOptions] = react.useState(options);
430
- const [state, dispatch] = react.useReducer(accessReducer, INITIAL_STATE);
431
- if (!esToolkit.isEqual(stableOptions, options)) {
432
- setStableOptions(options);
405
+ if (!context) {
406
+ throw new Error("useHasAccessTo must be used within an NavigationContext");
433
407
  }
408
+ const [hasAccess, setHasAccess] = react.useState();
409
+ const [loading, setLoading] = react.useState(true);
410
+ const [error, setError] = react.useState();
434
411
  react.useEffect(() => {
435
- if (!context)
436
- return;
437
- let cancelled = false;
438
- dispatch({ type: "FETCH_START" });
439
- const checkAccess = async () => {
412
+ async function checkAccess() {
440
413
  try {
441
- const accessResult = await resolveAccess(context, stableOptions);
442
- if (!cancelled) {
443
- dispatch({ type: "FETCH_SUCCESS", hasAccess: accessResult });
414
+ if (isMultipleCriteriaOneOf(options) && isMultipleCriteriaRequireAll(options)) {
415
+ throw new Error("Multiple criteria are not allowed, use one of or require all - not both");
416
+ }
417
+ if (isMultipleCriteriaOneOf(options)) {
418
+ const doHaveAccess = await Promise.all(options.oneOf.map(option => context?.hasAccessTo(option)));
419
+ setHasAccess(doHaveAccess.some(access => access));
420
+ }
421
+ else if (isMultipleCriteriaRequireAll(options)) {
422
+ const doHaveAccess = await Promise.all(options.requireAll.map(option => context?.hasAccessTo(option)));
423
+ setHasAccess(doHaveAccess.every(access => access));
424
+ }
425
+ else {
426
+ const doHaveAccess = await context?.hasAccessTo(options);
427
+ setHasAccess(doHaveAccess);
444
428
  }
445
429
  }
446
430
  catch (e) {
447
- if (!cancelled) {
448
- dispatch({ type: "FETCH_ERROR", error: new Error("Failed to check access", { cause: e }) });
449
- }
431
+ setError(new Error("Failed to check access", { cause: e }));
450
432
  }
451
- };
433
+ finally {
434
+ setLoading(false);
435
+ }
436
+ }
452
437
  void checkAccess();
453
- return () => {
454
- cancelled = true;
455
- };
456
- }, [context, stableOptions]);
457
- if (!context) {
458
- throw new Error("useHasAccessTo must be used within a NavigationContext");
459
- }
460
- return react.useMemo(() => ({
461
- hasAccess: state.hasAccess,
462
- loading: state.status === "loading",
463
- error: state.error,
464
- }), [state]);
438
+ }, [context, options]);
439
+ return react.useMemo(() => ({ hasAccess, loading, error }), [hasAccess, loading, error]);
465
440
  };
466
441
 
467
442
  /**
package/index.esm.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { AnalyticsContext, AssetSortingContext, ConfirmationDialogContext, EnvironmentContext, ErrorHandlingContext, ExportDataContext, FeatureFlagContext, FilterBarContext, TokenContext, ModalDialogContext, NavigationContext, OemBrandingContext, UserSubscriptionContext, TimeRangeContext, ToastContext, CurrentUserContext, CurrentUserPreferenceContext, WidgetConfigContext } from '@trackunit/react-core-contexts-api';
2
- import { useContext, useMemo, useState, useCallback, useReducer, useEffect, useRef } from 'react';
3
- import { isEqual } from 'es-toolkit';
2
+ import { useContext, useMemo, useState, useCallback, useEffect, useRef } from 'react';
4
3
  import { AssetRuntime, CustomerRuntime, EventRuntime, ParamsRuntime, SiteRuntime, WidgetConfigRuntime } from '@trackunit/iris-app-runtime-core';
5
4
 
6
5
  /**
@@ -378,88 +377,64 @@ const useModalDialogContext = () => {
378
377
  return modalDialogContext;
379
378
  };
380
379
 
381
- const isMultipleCriteriaOneOf = (options) => typeof options === "object" && "oneOf" in options;
382
- const isMultipleCriteriaRequireAll = (options) => typeof options === "object" && "requireAll" in options;
383
- const resolveAccess = async (context, options) => {
384
- if (isMultipleCriteriaOneOf(options) && isMultipleCriteriaRequireAll(options)) {
385
- throw new Error("Multiple criteria are not allowed, use one of or require all - not both");
386
- }
387
- if (isMultipleCriteriaOneOf(options)) {
388
- const results = await Promise.all(options.oneOf.map(option => context.hasAccessTo(option)));
389
- return results.some(Boolean);
390
- }
391
- if (isMultipleCriteriaRequireAll(options)) {
392
- const results = await Promise.all(options.requireAll.map(option => context.hasAccessTo(option)));
393
- return results.every(Boolean);
394
- }
395
- return context.hasAccessTo(options);
396
- };
397
- const INITIAL_STATE = {
398
- status: "loading",
399
- hasAccess: undefined,
400
- error: undefined,
401
- };
402
- const accessReducer = (_state, action) => {
403
- switch (action.type) {
404
- case "FETCH_START":
405
- return INITIAL_STATE;
406
- case "FETCH_SUCCESS":
407
- return { status: "success", hasAccess: action.hasAccess, error: undefined };
408
- case "FETCH_ERROR":
409
- return { status: "error", hasAccess: undefined, error: action.error };
410
- default:
411
- throw new Error(`${action} is not a known action`);
412
- }
380
+ const isMultipleCriteriaOneOf = (options) => {
381
+ return typeof options === "object" && "oneOf" in options;
382
+ };
383
+ const isMultipleCriteriaRequireAll = (options) => {
384
+ return typeof options === "object" && "requireAll" in options;
413
385
  };
414
386
  /**
415
- * Hook to check if the current user has access to a navigation target.
416
- * Useful for conditionally rendering links based on user permissions.
387
+ * This is a hook to use the hasAccessTo in host.
388
+ * You can use this to ensure the page you link to is available for the user to see.
417
389
  *
418
390
  * @requires NavigationContext
419
391
  * @example
420
392
  * import { useHasAccessTo } from "@trackunit/react-core-hooks";
421
393
  * useHasAccessTo({ assetId: assetInfo?.assetId, page: "movement" })
422
- * @see {@link NavigationRuntimeApi}
423
- * @see {@link HasAccessToOptions}
394
+ * @see (@link NavigationRuntimeApi)
395
+ * @see (@link HasAccessToOptions)
396
+ * @see (@link HasAccessToOptions.assetId)
397
+ * @see (@link HasAccessToOptions.page)
398
+ * @see (@link HasAccessToOptions.siteId)
399
+ * @see (@link NavigationRuntimeApi)
424
400
  */
425
401
  const useHasAccessTo = (options) => {
426
402
  const context = useContext(NavigationContext);
427
- const [stableOptions, setStableOptions] = useState(options);
428
- const [state, dispatch] = useReducer(accessReducer, INITIAL_STATE);
429
- if (!isEqual(stableOptions, options)) {
430
- setStableOptions(options);
403
+ if (!context) {
404
+ throw new Error("useHasAccessTo must be used within an NavigationContext");
431
405
  }
406
+ const [hasAccess, setHasAccess] = useState();
407
+ const [loading, setLoading] = useState(true);
408
+ const [error, setError] = useState();
432
409
  useEffect(() => {
433
- if (!context)
434
- return;
435
- let cancelled = false;
436
- dispatch({ type: "FETCH_START" });
437
- const checkAccess = async () => {
410
+ async function checkAccess() {
438
411
  try {
439
- const accessResult = await resolveAccess(context, stableOptions);
440
- if (!cancelled) {
441
- dispatch({ type: "FETCH_SUCCESS", hasAccess: accessResult });
412
+ if (isMultipleCriteriaOneOf(options) && isMultipleCriteriaRequireAll(options)) {
413
+ throw new Error("Multiple criteria are not allowed, use one of or require all - not both");
414
+ }
415
+ if (isMultipleCriteriaOneOf(options)) {
416
+ const doHaveAccess = await Promise.all(options.oneOf.map(option => context?.hasAccessTo(option)));
417
+ setHasAccess(doHaveAccess.some(access => access));
418
+ }
419
+ else if (isMultipleCriteriaRequireAll(options)) {
420
+ const doHaveAccess = await Promise.all(options.requireAll.map(option => context?.hasAccessTo(option)));
421
+ setHasAccess(doHaveAccess.every(access => access));
422
+ }
423
+ else {
424
+ const doHaveAccess = await context?.hasAccessTo(options);
425
+ setHasAccess(doHaveAccess);
442
426
  }
443
427
  }
444
428
  catch (e) {
445
- if (!cancelled) {
446
- dispatch({ type: "FETCH_ERROR", error: new Error("Failed to check access", { cause: e }) });
447
- }
429
+ setError(new Error("Failed to check access", { cause: e }));
448
430
  }
449
- };
431
+ finally {
432
+ setLoading(false);
433
+ }
434
+ }
450
435
  void checkAccess();
451
- return () => {
452
- cancelled = true;
453
- };
454
- }, [context, stableOptions]);
455
- if (!context) {
456
- throw new Error("useHasAccessTo must be used within a NavigationContext");
457
- }
458
- return useMemo(() => ({
459
- hasAccess: state.hasAccess,
460
- loading: state.status === "loading",
461
- error: state.error,
462
- }), [state]);
436
+ }, [context, options]);
437
+ return useMemo(() => ({ hasAccess, loading, error }), [hasAccess, loading, error]);
463
438
  };
464
439
 
465
440
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-core-hooks",
3
- "version": "1.12.50-alpha-c496ead6241.0",
3
+ "version": "1.12.51",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -8,10 +8,9 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "react": "19.0.0",
11
- "es-toolkit": "^1.39.10",
12
- "@trackunit/iris-app-runtime-core": "1.13.47-alpha-c496ead6241.0",
13
- "@trackunit/iris-app-runtime-core-api": "1.12.45-alpha-c496ead6241.0",
14
- "@trackunit/react-core-contexts-api": "1.13.45-alpha-c496ead6241.0"
11
+ "@trackunit/iris-app-runtime-core": "1.13.48",
12
+ "@trackunit/iris-app-runtime-core-api": "1.12.46",
13
+ "@trackunit/react-core-contexts-api": "1.13.46"
15
14
  },
16
15
  "module": "./index.esm.js",
17
16
  "main": "./index.cjs.js",
@@ -1,26 +1,27 @@
1
- import type { HasAccessToOptions } from "@trackunit/iris-app-runtime-core-api";
2
- export type MultipleCriteriaOneOf = {
3
- readonly oneOf: Array<HasAccessToOptions>;
4
- };
5
- export type MultipleCriteriaRequireAll = {
6
- readonly requireAll: Array<HasAccessToOptions>;
7
- };
8
- type AccessOptions = HasAccessToOptions | MultipleCriteriaOneOf | MultipleCriteriaRequireAll;
9
- type UseHasAccessToResult = {
10
- readonly hasAccess: boolean | undefined;
11
- readonly loading: boolean;
12
- readonly error: Error | undefined;
13
- };
1
+ import { HasAccessToOptions } from "@trackunit/iris-app-runtime-core-api";
2
+ export interface MultipleCriteriaOneOf {
3
+ oneOf: Array<HasAccessToOptions>;
4
+ }
5
+ export interface MultipleCriteriaRequireAll {
6
+ requireAll: Array<HasAccessToOptions>;
7
+ }
14
8
  /**
15
- * Hook to check if the current user has access to a navigation target.
16
- * Useful for conditionally rendering links based on user permissions.
9
+ * This is a hook to use the hasAccessTo in host.
10
+ * You can use this to ensure the page you link to is available for the user to see.
17
11
  *
18
12
  * @requires NavigationContext
19
13
  * @example
20
14
  * import { useHasAccessTo } from "@trackunit/react-core-hooks";
21
15
  * useHasAccessTo({ assetId: assetInfo?.assetId, page: "movement" })
22
- * @see {@link NavigationRuntimeApi}
23
- * @see {@link HasAccessToOptions}
16
+ * @see (@link NavigationRuntimeApi)
17
+ * @see (@link HasAccessToOptions)
18
+ * @see (@link HasAccessToOptions.assetId)
19
+ * @see (@link HasAccessToOptions.page)
20
+ * @see (@link HasAccessToOptions.siteId)
21
+ * @see (@link NavigationRuntimeApi)
24
22
  */
25
- export declare const useHasAccessTo: (options: AccessOptions) => UseHasAccessToResult;
26
- export {};
23
+ export declare const useHasAccessTo: (options: HasAccessToOptions | MultipleCriteriaOneOf | MultipleCriteriaRequireAll) => {
24
+ hasAccess: boolean | undefined;
25
+ loading: boolean;
26
+ error: Error | undefined;
27
+ };