@trackunit/react-core-hooks 1.15.11 → 1.15.12
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 +98 -0
- package/index.esm.js +98 -1
- package/package.json +5 -4
- package/src/index.d.ts +1 -0
- package/src/utilities/useSettingsUtils.d.ts +68 -0
package/index.cjs.js
CHANGED
|
@@ -4,6 +4,7 @@ var reactCoreContextsApi = require('@trackunit/react-core-contexts-api');
|
|
|
4
4
|
var react = require('react');
|
|
5
5
|
var esToolkit = require('es-toolkit');
|
|
6
6
|
var irisAppRuntimeCore = require('@trackunit/iris-app-runtime-core');
|
|
7
|
+
var zod = require('zod');
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Hook to get the analytics context.
|
|
@@ -1050,6 +1051,102 @@ const useUserPermission = (requiredPermission) => {
|
|
|
1050
1051
|
}, [permissions, requiredPermission]);
|
|
1051
1052
|
};
|
|
1052
1053
|
|
|
1054
|
+
/**
|
|
1055
|
+
* Zod pipeline that parses a non-empty JSON string into an unknown value.
|
|
1056
|
+
* Handles double-encoded JSON by attempting a second parse when the first
|
|
1057
|
+
* result is still a string. Returns a Zod issue (rather than throwing)
|
|
1058
|
+
* when the input is not valid JSON.
|
|
1059
|
+
*/
|
|
1060
|
+
const jsonParsePipeline = zod.z
|
|
1061
|
+
.string()
|
|
1062
|
+
.min(1)
|
|
1063
|
+
.transform((str, ctx) => {
|
|
1064
|
+
let parsed;
|
|
1065
|
+
try {
|
|
1066
|
+
parsed = JSON.parse(str);
|
|
1067
|
+
}
|
|
1068
|
+
catch {
|
|
1069
|
+
ctx.addIssue({
|
|
1070
|
+
code: zod.z.ZodIssueCode.custom,
|
|
1071
|
+
message: "Invalid JSON string",
|
|
1072
|
+
});
|
|
1073
|
+
return zod.z.NEVER;
|
|
1074
|
+
}
|
|
1075
|
+
if (typeof parsed === "string") {
|
|
1076
|
+
try {
|
|
1077
|
+
parsed = JSON.parse(parsed);
|
|
1078
|
+
}
|
|
1079
|
+
catch {
|
|
1080
|
+
// Not double-encoded, keep the first-level parse
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
return parsed;
|
|
1084
|
+
});
|
|
1085
|
+
/**
|
|
1086
|
+
* Zod pipeline that validates a non-null value and converts it to a JSON string.
|
|
1087
|
+
* Strings are returned as-is; all other values go through `JSON.stringify`.
|
|
1088
|
+
* Non-serialisable values (e.g. circular references) produce a Zod issue
|
|
1089
|
+
* instead of throwing.
|
|
1090
|
+
*/
|
|
1091
|
+
const stringifySchema = zod.z
|
|
1092
|
+
.unknown()
|
|
1093
|
+
.refine((val) => val !== null && val !== undefined)
|
|
1094
|
+
.transform((val, ctx) => {
|
|
1095
|
+
if (typeof val === "string") {
|
|
1096
|
+
return val;
|
|
1097
|
+
}
|
|
1098
|
+
try {
|
|
1099
|
+
return JSON.stringify(val);
|
|
1100
|
+
}
|
|
1101
|
+
catch {
|
|
1102
|
+
ctx.addIssue({
|
|
1103
|
+
code: zod.z.ZodIssueCode.custom,
|
|
1104
|
+
message: "Value is not serializable to JSON",
|
|
1105
|
+
});
|
|
1106
|
+
return zod.z.NEVER;
|
|
1107
|
+
}
|
|
1108
|
+
})
|
|
1109
|
+
.pipe(zod.z.string());
|
|
1110
|
+
/**
|
|
1111
|
+
* Hook providing safe JSON parsing and stringification utilities with Zod validation.
|
|
1112
|
+
*
|
|
1113
|
+
* Returns stable callbacks for:
|
|
1114
|
+
* - `safeParse` - Parse JSON and validate against a schema
|
|
1115
|
+
* - `isJSON` - Check if a string is valid JSON
|
|
1116
|
+
* - `safeStringify` - Convert a value to JSON string
|
|
1117
|
+
*
|
|
1118
|
+
* @example
|
|
1119
|
+
* ```ts
|
|
1120
|
+
* const { safeParse, safeStringify, isJSON } = useSettingsUtils();
|
|
1121
|
+
*
|
|
1122
|
+
* const data = safeParse(rawJson, mySchema);
|
|
1123
|
+
* const json = safeStringify(myObject);
|
|
1124
|
+
* const valid = isJSON(someString);
|
|
1125
|
+
* ```
|
|
1126
|
+
*/
|
|
1127
|
+
const useSettingsUtils = () => {
|
|
1128
|
+
const safeParse = react.useCallback((jsonString, schema) => {
|
|
1129
|
+
if (!jsonString) {
|
|
1130
|
+
return null;
|
|
1131
|
+
}
|
|
1132
|
+
const jsonResult = jsonParsePipeline.pipe(schema).safeParse(jsonString);
|
|
1133
|
+
if (jsonResult.success) {
|
|
1134
|
+
return jsonResult.data;
|
|
1135
|
+
}
|
|
1136
|
+
const rawResult = schema.safeParse(jsonString);
|
|
1137
|
+
return rawResult.success ? rawResult.data : null;
|
|
1138
|
+
}, []);
|
|
1139
|
+
const isJSON = react.useCallback((jsonString) => {
|
|
1140
|
+
const result = jsonParsePipeline.safeParse(jsonString);
|
|
1141
|
+
return result.success && result.data !== null;
|
|
1142
|
+
}, []);
|
|
1143
|
+
const safeStringify = react.useCallback((value) => {
|
|
1144
|
+
const result = stringifySchema.safeParse(value);
|
|
1145
|
+
return result.success ? result.data : null;
|
|
1146
|
+
}, []);
|
|
1147
|
+
return react.useMemo(() => ({ safeParse, isJSON, safeStringify }), [safeParse, isJSON, safeStringify]);
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1053
1150
|
/**
|
|
1054
1151
|
* This is a hook to use the WidgetConfigProvider.
|
|
1055
1152
|
*
|
|
@@ -1205,6 +1302,7 @@ exports.useIrisAppName = useIrisAppName;
|
|
|
1205
1302
|
exports.useModalDialogContext = useModalDialogContext;
|
|
1206
1303
|
exports.useNavigateInHost = useNavigateInHost;
|
|
1207
1304
|
exports.useOemBrandingContext = useOemBrandingContext;
|
|
1305
|
+
exports.useSettingsUtils = useSettingsUtils;
|
|
1208
1306
|
exports.useSiteRuntime = useSiteRuntime;
|
|
1209
1307
|
exports.useTimeRange = useTimeRange;
|
|
1210
1308
|
exports.useToast = useToast;
|
package/index.esm.js
CHANGED
|
@@ -2,6 +2,7 @@ import { AnalyticsContext, AssetSortingContext, ConfirmationDialogContext, Envir
|
|
|
2
2
|
import { useContext, useMemo, useState, useCallback, useEffect, useReducer, useRef } from 'react';
|
|
3
3
|
import { isEqual } from 'es-toolkit';
|
|
4
4
|
import { AssetRuntime, CustomerRuntime, EventRuntime, ParamsRuntime, SiteRuntime, WidgetConfigRuntime } from '@trackunit/iris-app-runtime-core';
|
|
5
|
+
import { z } from 'zod';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Hook to get the analytics context.
|
|
@@ -1048,6 +1049,102 @@ const useUserPermission = (requiredPermission) => {
|
|
|
1048
1049
|
}, [permissions, requiredPermission]);
|
|
1049
1050
|
};
|
|
1050
1051
|
|
|
1052
|
+
/**
|
|
1053
|
+
* Zod pipeline that parses a non-empty JSON string into an unknown value.
|
|
1054
|
+
* Handles double-encoded JSON by attempting a second parse when the first
|
|
1055
|
+
* result is still a string. Returns a Zod issue (rather than throwing)
|
|
1056
|
+
* when the input is not valid JSON.
|
|
1057
|
+
*/
|
|
1058
|
+
const jsonParsePipeline = z
|
|
1059
|
+
.string()
|
|
1060
|
+
.min(1)
|
|
1061
|
+
.transform((str, ctx) => {
|
|
1062
|
+
let parsed;
|
|
1063
|
+
try {
|
|
1064
|
+
parsed = JSON.parse(str);
|
|
1065
|
+
}
|
|
1066
|
+
catch {
|
|
1067
|
+
ctx.addIssue({
|
|
1068
|
+
code: z.ZodIssueCode.custom,
|
|
1069
|
+
message: "Invalid JSON string",
|
|
1070
|
+
});
|
|
1071
|
+
return z.NEVER;
|
|
1072
|
+
}
|
|
1073
|
+
if (typeof parsed === "string") {
|
|
1074
|
+
try {
|
|
1075
|
+
parsed = JSON.parse(parsed);
|
|
1076
|
+
}
|
|
1077
|
+
catch {
|
|
1078
|
+
// Not double-encoded, keep the first-level parse
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
return parsed;
|
|
1082
|
+
});
|
|
1083
|
+
/**
|
|
1084
|
+
* Zod pipeline that validates a non-null value and converts it to a JSON string.
|
|
1085
|
+
* Strings are returned as-is; all other values go through `JSON.stringify`.
|
|
1086
|
+
* Non-serialisable values (e.g. circular references) produce a Zod issue
|
|
1087
|
+
* instead of throwing.
|
|
1088
|
+
*/
|
|
1089
|
+
const stringifySchema = z
|
|
1090
|
+
.unknown()
|
|
1091
|
+
.refine((val) => val !== null && val !== undefined)
|
|
1092
|
+
.transform((val, ctx) => {
|
|
1093
|
+
if (typeof val === "string") {
|
|
1094
|
+
return val;
|
|
1095
|
+
}
|
|
1096
|
+
try {
|
|
1097
|
+
return JSON.stringify(val);
|
|
1098
|
+
}
|
|
1099
|
+
catch {
|
|
1100
|
+
ctx.addIssue({
|
|
1101
|
+
code: z.ZodIssueCode.custom,
|
|
1102
|
+
message: "Value is not serializable to JSON",
|
|
1103
|
+
});
|
|
1104
|
+
return z.NEVER;
|
|
1105
|
+
}
|
|
1106
|
+
})
|
|
1107
|
+
.pipe(z.string());
|
|
1108
|
+
/**
|
|
1109
|
+
* Hook providing safe JSON parsing and stringification utilities with Zod validation.
|
|
1110
|
+
*
|
|
1111
|
+
* Returns stable callbacks for:
|
|
1112
|
+
* - `safeParse` - Parse JSON and validate against a schema
|
|
1113
|
+
* - `isJSON` - Check if a string is valid JSON
|
|
1114
|
+
* - `safeStringify` - Convert a value to JSON string
|
|
1115
|
+
*
|
|
1116
|
+
* @example
|
|
1117
|
+
* ```ts
|
|
1118
|
+
* const { safeParse, safeStringify, isJSON } = useSettingsUtils();
|
|
1119
|
+
*
|
|
1120
|
+
* const data = safeParse(rawJson, mySchema);
|
|
1121
|
+
* const json = safeStringify(myObject);
|
|
1122
|
+
* const valid = isJSON(someString);
|
|
1123
|
+
* ```
|
|
1124
|
+
*/
|
|
1125
|
+
const useSettingsUtils = () => {
|
|
1126
|
+
const safeParse = useCallback((jsonString, schema) => {
|
|
1127
|
+
if (!jsonString) {
|
|
1128
|
+
return null;
|
|
1129
|
+
}
|
|
1130
|
+
const jsonResult = jsonParsePipeline.pipe(schema).safeParse(jsonString);
|
|
1131
|
+
if (jsonResult.success) {
|
|
1132
|
+
return jsonResult.data;
|
|
1133
|
+
}
|
|
1134
|
+
const rawResult = schema.safeParse(jsonString);
|
|
1135
|
+
return rawResult.success ? rawResult.data : null;
|
|
1136
|
+
}, []);
|
|
1137
|
+
const isJSON = useCallback((jsonString) => {
|
|
1138
|
+
const result = jsonParsePipeline.safeParse(jsonString);
|
|
1139
|
+
return result.success && result.data !== null;
|
|
1140
|
+
}, []);
|
|
1141
|
+
const safeStringify = useCallback((value) => {
|
|
1142
|
+
const result = stringifySchema.safeParse(value);
|
|
1143
|
+
return result.success ? result.data : null;
|
|
1144
|
+
}, []);
|
|
1145
|
+
return useMemo(() => ({ safeParse, isJSON, safeStringify }), [safeParse, isJSON, safeStringify]);
|
|
1146
|
+
};
|
|
1147
|
+
|
|
1051
1148
|
/**
|
|
1052
1149
|
* This is a hook to use the WidgetConfigProvider.
|
|
1053
1150
|
*
|
|
@@ -1174,4 +1271,4 @@ const useWidgetConfig = () => {
|
|
|
1174
1271
|
return result;
|
|
1175
1272
|
};
|
|
1176
1273
|
|
|
1177
|
-
export { fetchAssetBlobUrl, useAnalytics, useAssetRuntime, useAssetSorting, useConfirmationDialog, useCurrentUser, useCurrentUserFavoriteAdvancedSensors, useCurrentUserFavoriteInsights, useCurrentUserLanguage, useCurrentUserSystemOfMeasurement, useCurrentUserTimeZonePreference, useCustomerRuntime, useEnvironment, useErrorHandler, useErrorHandlerOrNull, useEventRuntime, useExportDataContext, useFeatureBranchQueryString, useFeatureFlags, useFilterBarContext, useGeolocation, useHasAccessTo, useImageUploader, useIrisAppId, useIrisAppImage, useIrisAppName, useModalDialogContext, useNavigateInHost, useOemBrandingContext, useSiteRuntime, useTimeRange, useToast, useToken, useUserPermission, useUserSubscription, useWidgetConfig, useWidgetConfigAsync };
|
|
1274
|
+
export { fetchAssetBlobUrl, useAnalytics, useAssetRuntime, useAssetSorting, useConfirmationDialog, useCurrentUser, useCurrentUserFavoriteAdvancedSensors, useCurrentUserFavoriteInsights, useCurrentUserLanguage, useCurrentUserSystemOfMeasurement, useCurrentUserTimeZonePreference, useCustomerRuntime, useEnvironment, useErrorHandler, useErrorHandlerOrNull, useEventRuntime, useExportDataContext, useFeatureBranchQueryString, useFeatureFlags, useFilterBarContext, useGeolocation, useHasAccessTo, useImageUploader, useIrisAppId, useIrisAppImage, useIrisAppName, useModalDialogContext, useNavigateInHost, useOemBrandingContext, useSettingsUtils, useSiteRuntime, useTimeRange, useToast, useToken, useUserPermission, useUserSubscription, useWidgetConfig, useWidgetConfigAsync };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-core-hooks",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.12",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"es-toolkit": "^1.39.10",
|
|
11
|
-
"@trackunit/iris-app-runtime-core": "1.15.
|
|
12
|
-
"@trackunit/iris-app-runtime-core-api": "1.14.
|
|
13
|
-
"@trackunit/react-core-contexts-api": "1.15.
|
|
11
|
+
"@trackunit/iris-app-runtime-core": "1.15.11",
|
|
12
|
+
"@trackunit/iris-app-runtime-core-api": "1.14.11",
|
|
13
|
+
"@trackunit/react-core-contexts-api": "1.15.11",
|
|
14
|
+
"zod": "^3.25.76"
|
|
14
15
|
},
|
|
15
16
|
"peerDependencies": {
|
|
16
17
|
"react": "^19.0.0"
|
package/src/index.d.ts
CHANGED
|
@@ -27,4 +27,5 @@ export * from "./useFeatureBranchQueryString";
|
|
|
27
27
|
export * from "./user/useCurrentUser";
|
|
28
28
|
export * from "./user/useCurrentUserPreference";
|
|
29
29
|
export * from "./user/useUserPermission";
|
|
30
|
+
export * from "./utilities/useSettingsUtils";
|
|
30
31
|
export * from "./widgetConfig/useWidgetConfig";
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export interface SettingsUtils {
|
|
3
|
+
/**
|
|
4
|
+
* Safely parses a JSON string and validates the result against a Zod schema.
|
|
5
|
+
* Returns the validated value when parsing and validation succeed, otherwise `null`.
|
|
6
|
+
* The return type is inferred from the schema — no type assertions needed.
|
|
7
|
+
*
|
|
8
|
+
* @param jsonString - The JSON string to parse, or `null`.
|
|
9
|
+
* @param schema - A Zod schema that describes the expected shape of the parsed value.
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const result = safeParse('{"name":"Ada"}', z.object({ name: z.string() }));
|
|
13
|
+
* // result: { name: "Ada" }
|
|
14
|
+
*
|
|
15
|
+
* const num = safeParse("42", z.number());
|
|
16
|
+
* // num: 42
|
|
17
|
+
*
|
|
18
|
+
* const miss = safeParse('{"a":1}', z.object({ b: z.string() }));
|
|
19
|
+
* // miss: null
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
safeParse: <TValue>(jsonString: string | null, schema: z.ZodType<TValue>) => TValue | null;
|
|
23
|
+
/**
|
|
24
|
+
* Checks whether a string is valid, non-null JSON.
|
|
25
|
+
*
|
|
26
|
+
* Returns `false` for the JSON literal `"null"` to match the legacy behaviour
|
|
27
|
+
* where `JSON.parse(str) !== null` was required.
|
|
28
|
+
*
|
|
29
|
+
* @param jsonString - The string to test.
|
|
30
|
+
* @returns `true` when the string can be parsed as non-null JSON.
|
|
31
|
+
*/
|
|
32
|
+
isJSON: (jsonString: string) => boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Safely converts a value to a JSON string using a Zod validation pipeline.
|
|
35
|
+
*
|
|
36
|
+
* - Returns the value unchanged if it is already a string.
|
|
37
|
+
* - Returns `null` for `null` / `undefined` or if serialisation fails
|
|
38
|
+
* (e.g. circular references).
|
|
39
|
+
*
|
|
40
|
+
* @param value - The value to stringify.
|
|
41
|
+
* @returns The JSON string representation, or `null` on failure.
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* safeStringify({ a: 1 }) // '{"a":1}'
|
|
45
|
+
* safeStringify("hello") // "hello"
|
|
46
|
+
* safeStringify(null) // null
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
safeStringify: (value: unknown) => string | null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Hook providing safe JSON parsing and stringification utilities with Zod validation.
|
|
53
|
+
*
|
|
54
|
+
* Returns stable callbacks for:
|
|
55
|
+
* - `safeParse` - Parse JSON and validate against a schema
|
|
56
|
+
* - `isJSON` - Check if a string is valid JSON
|
|
57
|
+
* - `safeStringify` - Convert a value to JSON string
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* const { safeParse, safeStringify, isJSON } = useSettingsUtils();
|
|
62
|
+
*
|
|
63
|
+
* const data = safeParse(rawJson, mySchema);
|
|
64
|
+
* const json = safeStringify(myObject);
|
|
65
|
+
* const valid = isJSON(someString);
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare const useSettingsUtils: () => SettingsUtils;
|