@arcanejs/react-toolkit 0.13.0 → 0.14.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/dist/data.d.mts CHANGED
@@ -17,6 +17,8 @@ type DataFileUsage = WithPathChange & {
17
17
  * this will be relative to the current working directory.
18
18
  */
19
19
  path: string;
20
+ /** Callback that will be called if any error occurs during loading or saving the file */
21
+ onError?: (error: ArcaneDataFileError) => void;
20
22
  };
21
23
  type ProviderProps = DataFileUsage & {
22
24
  children: ReactNode;
@@ -93,10 +95,18 @@ type DataState<T> = {
93
95
  status: 'ready';
94
96
  data: T;
95
97
  });
98
+ type DataFileOperation = 'load' | 'save' | 'usage';
99
+ declare class ArcaneDataFileError extends Error {
100
+ readonly operation: DataFileOperation;
101
+ readonly path: string | null;
102
+ constructor(message: string, operation: DataFileOperation, path: string | null, cause?: unknown);
103
+ }
104
+ type ErrorListener = (error: ArcaneDataFileError) => void;
96
105
  type UseDataFileCoreProps<T> = WithPathChange & {
97
106
  schema: ZodType<T>;
98
107
  defaultValue: T;
99
108
  path: string;
109
+ onError?: (error: ArcaneDataFileError) => void;
100
110
  };
101
111
  type DataFileCore<T> = {
102
112
  data: DataState<T>;
@@ -106,11 +116,11 @@ type DataFileCore<T> = {
106
116
  /**
107
117
  * Primary hook for & logic for using data files.
108
118
  */
109
- declare function useDataFileCore<T>({ schema, defaultValue, path, onPathChange, }: UseDataFileCoreProps<T>): DataFileCore<T>;
119
+ declare function useDataFileCore<T>({ schema, defaultValue, path, onPathChange, onError, }: UseDataFileCoreProps<T>): DataFileCore<T>;
110
120
  type CreateDataFileDefinitionProps<T extends ZodType> = {
111
121
  schema: T;
112
122
  defaultValue: z.infer<T>;
113
123
  };
114
124
  declare function createDataFileDefinition<T extends ZodType>({ schema, defaultValue, }: CreateDataFileDefinitionProps<T>): DataFileDefinition<z.infer<T>>;
115
125
 
116
- export { type CreateDataFileDefinitionProps, type DataFileContext, type DataFileCore, type DataFileDefinition, type DataFileUpdater, type DataState, type ProviderProps, type UseDataFileCoreProps, createDataFileDefinition, useDataFile, useDataFileContext, useDataFileCore, useDataFileData, useDataFileUpdater };
126
+ export { ArcaneDataFileError, type CreateDataFileDefinitionProps, type DataFileContext, type DataFileCore, type DataFileDefinition, type DataFileOperation, type DataFileUpdater, type DataState, type ErrorListener, type ProviderProps, type UseDataFileCoreProps, createDataFileDefinition, useDataFile, useDataFileContext, useDataFileCore, useDataFileData, useDataFileUpdater };
package/dist/data.d.ts CHANGED
@@ -17,6 +17,8 @@ type DataFileUsage = WithPathChange & {
17
17
  * this will be relative to the current working directory.
18
18
  */
19
19
  path: string;
20
+ /** Callback that will be called if any error occurs during loading or saving the file */
21
+ onError?: (error: ArcaneDataFileError) => void;
20
22
  };
21
23
  type ProviderProps = DataFileUsage & {
22
24
  children: ReactNode;
@@ -93,10 +95,18 @@ type DataState<T> = {
93
95
  status: 'ready';
94
96
  data: T;
95
97
  });
98
+ type DataFileOperation = 'load' | 'save' | 'usage';
99
+ declare class ArcaneDataFileError extends Error {
100
+ readonly operation: DataFileOperation;
101
+ readonly path: string | null;
102
+ constructor(message: string, operation: DataFileOperation, path: string | null, cause?: unknown);
103
+ }
104
+ type ErrorListener = (error: ArcaneDataFileError) => void;
96
105
  type UseDataFileCoreProps<T> = WithPathChange & {
97
106
  schema: ZodType<T>;
98
107
  defaultValue: T;
99
108
  path: string;
109
+ onError?: (error: ArcaneDataFileError) => void;
100
110
  };
101
111
  type DataFileCore<T> = {
102
112
  data: DataState<T>;
@@ -106,11 +116,11 @@ type DataFileCore<T> = {
106
116
  /**
107
117
  * Primary hook for & logic for using data files.
108
118
  */
109
- declare function useDataFileCore<T>({ schema, defaultValue, path, onPathChange, }: UseDataFileCoreProps<T>): DataFileCore<T>;
119
+ declare function useDataFileCore<T>({ schema, defaultValue, path, onPathChange, onError, }: UseDataFileCoreProps<T>): DataFileCore<T>;
110
120
  type CreateDataFileDefinitionProps<T extends ZodType> = {
111
121
  schema: T;
112
122
  defaultValue: z.infer<T>;
113
123
  };
114
124
  declare function createDataFileDefinition<T extends ZodType>({ schema, defaultValue, }: CreateDataFileDefinitionProps<T>): DataFileDefinition<z.infer<T>>;
115
125
 
116
- export { type CreateDataFileDefinitionProps, type DataFileContext, type DataFileCore, type DataFileDefinition, type DataFileUpdater, type DataState, type ProviderProps, type UseDataFileCoreProps, createDataFileDefinition, useDataFile, useDataFileContext, useDataFileCore, useDataFileData, useDataFileUpdater };
126
+ export { ArcaneDataFileError, type CreateDataFileDefinitionProps, type DataFileContext, type DataFileCore, type DataFileDefinition, type DataFileOperation, type DataFileUpdater, type DataState, type ErrorListener, type ProviderProps, type UseDataFileCoreProps, createDataFileDefinition, useDataFile, useDataFileContext, useDataFileCore, useDataFileData, useDataFileUpdater };
package/dist/data.js CHANGED
@@ -27,11 +27,20 @@ function useDataFileContext(dataFile) {
27
27
  function useDataFile(dataFile, usage) {
28
28
  return dataFile.useDataFile(usage);
29
29
  }
30
+ var ArcaneDataFileError = class extends Error {
31
+ constructor(message, operation, path, cause) {
32
+ super(message, { cause });
33
+ this.operation = operation;
34
+ this.path = path;
35
+ this.name = `ArcaneDataFileError(${operation})`;
36
+ }
37
+ };
30
38
  function useDataFileCore({
31
39
  schema,
32
40
  defaultValue,
33
41
  path,
34
- onPathChange = "defaultValue"
42
+ onPathChange = "defaultValue",
43
+ onError
35
44
  }) {
36
45
  const log = _chunkRT2VSMJLjs.useLogger.call(void 0, );
37
46
  const state = _react.useRef.call(void 0, {
@@ -48,9 +57,13 @@ function useDataFileCore({
48
57
  if (!state.current.initialized) {
49
58
  state.current.initialized = true;
50
59
  } else {
51
- throw new Error(
52
- "Cannot change schema or defaultValue after initialization"
60
+ const error = new ArcaneDataFileError(
61
+ "Cannot change schema or defaultValue after initialization",
62
+ "usage",
63
+ null
53
64
  );
65
+ _optionalChain([onError, 'optionalCall', _ => _(error)]);
66
+ throw error;
54
67
  }
55
68
  }, [schema, defaultValue]);
56
69
  const [data, setData] = _react.useState.call(void 0, {
@@ -104,7 +117,14 @@ function useDataFileCore({
104
117
  if (state.current.path === currentPath && state.current.data === currentData) {
105
118
  state.current.state = { state: "saved" };
106
119
  }
107
- } catch (error) {
120
+ } catch (cause) {
121
+ const error = new ArcaneDataFileError(
122
+ `Error saving data file to path: ${currentPath}`,
123
+ "save",
124
+ currentPath,
125
+ cause
126
+ );
127
+ _optionalChain([onError, 'optionalCall', _2 => _2(error)]);
108
128
  if (state.current.path === currentPath && state.current.data === currentData) {
109
129
  state.current.state = { state: "error", error };
110
130
  updateDataFromState();
@@ -140,16 +160,16 @@ function useDataFileCore({
140
160
  state.current.state = { state: "saved" };
141
161
  updateDataFromState();
142
162
  }
143
- }).catch((error) => {
163
+ }).catch((err) => {
144
164
  if (state.current.path !== path) {
145
165
  return;
146
166
  }
147
- if (error.code === "ENOENT") {
167
+ if (err.code === "ENOENT") {
148
168
  const initialData = onPathChange === "transfer" && state.current.previousData !== void 0 ? state.current.previousData : defaultValue;
149
169
  state.current.data = initialData;
150
170
  state.current.lastUpdatedMillis = Date.now();
151
171
  state.current.state = { state: "dirty" };
152
- _optionalChain([log, 'optionalAccess', _ => _.info, 'call', _2 => _2(
172
+ _optionalChain([log, 'optionalAccess', _3 => _3.info, 'call', _4 => _4(
153
173
  "Creating a new file at %s with initial data %o",
154
174
  path,
155
175
  initialData
@@ -158,6 +178,14 @@ function useDataFileCore({
158
178
  updateDataFromState();
159
179
  return;
160
180
  }
181
+ const error = new ArcaneDataFileError(
182
+ `Error loading data file at path: ${path}`,
183
+ "load",
184
+ path,
185
+ err
186
+ );
187
+ _optionalChain([onError, 'optionalCall', _5 => _5(error)]);
188
+ _optionalChain([log, 'optionalAccess', _6 => _6.error, 'call', _7 => _7(error)]);
161
189
  state.current.state = { state: "error", error };
162
190
  updateDataFromState();
163
191
  });
@@ -202,17 +230,25 @@ function createDataFileDefinition({
202
230
  });
203
231
  const useDataFile2 = ({
204
232
  path,
205
- onPathChange
233
+ onPathChange,
234
+ onError
206
235
  }) => useDataFileCore({
207
236
  schema,
208
237
  defaultValue,
209
238
  path,
210
- onPathChange
239
+ onPathChange,
240
+ onError
211
241
  });
212
- const Provider = ({ path, onPathChange, children }) => {
242
+ const Provider = ({
243
+ path,
244
+ onPathChange,
245
+ onError,
246
+ children
247
+ }) => {
213
248
  const { data, updateData, saveData } = useDataFile2({
214
249
  path,
215
- onPathChange
250
+ onPathChange,
251
+ onError
216
252
  });
217
253
  const providedContext = _react.useMemo.call(void 0,
218
254
  () => ({
@@ -243,4 +279,5 @@ function createDataFileDefinition({
243
279
 
244
280
 
245
281
 
246
- exports.createDataFileDefinition = createDataFileDefinition; exports.useDataFile = useDataFile; exports.useDataFileContext = useDataFileContext; exports.useDataFileCore = useDataFileCore; exports.useDataFileData = useDataFileData; exports.useDataFileUpdater = useDataFileUpdater;
282
+
283
+ exports.ArcaneDataFileError = ArcaneDataFileError; exports.createDataFileDefinition = createDataFileDefinition; exports.useDataFile = useDataFile; exports.useDataFileContext = useDataFileContext; exports.useDataFileCore = useDataFileCore; exports.useDataFileData = useDataFileData; exports.useDataFileUpdater = useDataFileUpdater;
package/dist/data.mjs CHANGED
@@ -27,11 +27,20 @@ function useDataFileContext(dataFile) {
27
27
  function useDataFile(dataFile, usage) {
28
28
  return dataFile.useDataFile(usage);
29
29
  }
30
+ var ArcaneDataFileError = class extends Error {
31
+ constructor(message, operation, path, cause) {
32
+ super(message, { cause });
33
+ this.operation = operation;
34
+ this.path = path;
35
+ this.name = `ArcaneDataFileError(${operation})`;
36
+ }
37
+ };
30
38
  function useDataFileCore({
31
39
  schema,
32
40
  defaultValue,
33
41
  path,
34
- onPathChange = "defaultValue"
42
+ onPathChange = "defaultValue",
43
+ onError
35
44
  }) {
36
45
  const log = useLogger();
37
46
  const state = useRef({
@@ -48,9 +57,13 @@ function useDataFileCore({
48
57
  if (!state.current.initialized) {
49
58
  state.current.initialized = true;
50
59
  } else {
51
- throw new Error(
52
- "Cannot change schema or defaultValue after initialization"
60
+ const error = new ArcaneDataFileError(
61
+ "Cannot change schema or defaultValue after initialization",
62
+ "usage",
63
+ null
53
64
  );
65
+ onError?.(error);
66
+ throw error;
54
67
  }
55
68
  }, [schema, defaultValue]);
56
69
  const [data, setData] = useState({
@@ -104,7 +117,14 @@ function useDataFileCore({
104
117
  if (state.current.path === currentPath && state.current.data === currentData) {
105
118
  state.current.state = { state: "saved" };
106
119
  }
107
- } catch (error) {
120
+ } catch (cause) {
121
+ const error = new ArcaneDataFileError(
122
+ `Error saving data file to path: ${currentPath}`,
123
+ "save",
124
+ currentPath,
125
+ cause
126
+ );
127
+ onError?.(error);
108
128
  if (state.current.path === currentPath && state.current.data === currentData) {
109
129
  state.current.state = { state: "error", error };
110
130
  updateDataFromState();
@@ -140,11 +160,11 @@ function useDataFileCore({
140
160
  state.current.state = { state: "saved" };
141
161
  updateDataFromState();
142
162
  }
143
- }).catch((error) => {
163
+ }).catch((err) => {
144
164
  if (state.current.path !== path) {
145
165
  return;
146
166
  }
147
- if (error.code === "ENOENT") {
167
+ if (err.code === "ENOENT") {
148
168
  const initialData = onPathChange === "transfer" && state.current.previousData !== void 0 ? state.current.previousData : defaultValue;
149
169
  state.current.data = initialData;
150
170
  state.current.lastUpdatedMillis = Date.now();
@@ -158,6 +178,14 @@ function useDataFileCore({
158
178
  updateDataFromState();
159
179
  return;
160
180
  }
181
+ const error = new ArcaneDataFileError(
182
+ `Error loading data file at path: ${path}`,
183
+ "load",
184
+ path,
185
+ err
186
+ );
187
+ onError?.(error);
188
+ log?.error(error);
161
189
  state.current.state = { state: "error", error };
162
190
  updateDataFromState();
163
191
  });
@@ -202,17 +230,25 @@ function createDataFileDefinition({
202
230
  });
203
231
  const useDataFile2 = ({
204
232
  path,
205
- onPathChange
233
+ onPathChange,
234
+ onError
206
235
  }) => useDataFileCore({
207
236
  schema,
208
237
  defaultValue,
209
238
  path,
210
- onPathChange
239
+ onPathChange,
240
+ onError
211
241
  });
212
- const Provider = ({ path, onPathChange, children }) => {
242
+ const Provider = ({
243
+ path,
244
+ onPathChange,
245
+ onError,
246
+ children
247
+ }) => {
213
248
  const { data, updateData, saveData } = useDataFile2({
214
249
  path,
215
- onPathChange
250
+ onPathChange,
251
+ onError
216
252
  });
217
253
  const providedContext = useMemo(
218
254
  () => ({
@@ -237,6 +273,7 @@ function createDataFileDefinition({
237
273
  };
238
274
  }
239
275
  export {
276
+ ArcaneDataFileError,
240
277
  createDataFileDefinition,
241
278
  useDataFile,
242
279
  useDataFileContext,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcanejs/react-toolkit",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "private": false,
5
5
  "description": "Build web-accessible control interfaces for your long-running Node.js processes",
6
6
  "keywords": [