@cyberismo/data-handler 0.0.17 → 0.0.19

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.
Files changed (112) hide show
  1. package/dist/command-handler.d.ts +2 -0
  2. package/dist/command-handler.js +26 -2
  3. package/dist/command-handler.js.map +1 -1
  4. package/dist/command-manager.d.ts +2 -0
  5. package/dist/command-manager.js +3 -0
  6. package/dist/command-manager.js.map +1 -1
  7. package/dist/commands/create.d.ts +3 -1
  8. package/dist/commands/create.js +10 -1
  9. package/dist/commands/create.js.map +1 -1
  10. package/dist/commands/migrate.d.ts +33 -0
  11. package/dist/commands/migrate.js +66 -0
  12. package/dist/commands/migrate.js.map +1 -0
  13. package/dist/containers/project/card-cache.js +13 -1
  14. package/dist/containers/project/card-cache.js.map +1 -1
  15. package/dist/containers/project/project-paths.d.ts +1 -0
  16. package/dist/containers/project/project-paths.js +5 -2
  17. package/dist/containers/project/project-paths.js.map +1 -1
  18. package/dist/containers/project.d.ts +10 -0
  19. package/dist/containers/project.js +39 -2
  20. package/dist/containers/project.js.map +1 -1
  21. package/dist/containers/template.js +2 -0
  22. package/dist/containers/template.js.map +1 -1
  23. package/dist/interfaces/command-options.d.ts +6 -1
  24. package/dist/interfaces/project-interfaces.d.ts +4 -0
  25. package/dist/interfaces/project-interfaces.js.map +1 -1
  26. package/dist/migrations/index.d.ts +14 -0
  27. package/dist/migrations/index.js +14 -0
  28. package/dist/migrations/index.js.map +1 -0
  29. package/dist/migrations/migration-executor.d.ts +79 -0
  30. package/dist/migrations/migration-executor.js +312 -0
  31. package/dist/migrations/migration-executor.js.map +1 -0
  32. package/dist/migrations/migration-worker.d.ts +13 -0
  33. package/dist/migrations/migration-worker.js +156 -0
  34. package/dist/migrations/migration-worker.js.map +1 -0
  35. package/dist/migrations/worker-executor.d.ts +24 -0
  36. package/dist/migrations/worker-executor.js +157 -0
  37. package/dist/migrations/worker-executor.js.map +1 -0
  38. package/dist/project-settings.d.ts +2 -0
  39. package/dist/project-settings.js +7 -0
  40. package/dist/project-settings.js.map +1 -1
  41. package/dist/resources/calculation-resource.d.ts +9 -0
  42. package/dist/resources/calculation-resource.js +13 -2
  43. package/dist/resources/calculation-resource.js.map +1 -1
  44. package/dist/resources/card-type-resource.d.ts +12 -3
  45. package/dist/resources/card-type-resource.js +73 -91
  46. package/dist/resources/card-type-resource.js.map +1 -1
  47. package/dist/resources/field-type-resource.d.ts +10 -1
  48. package/dist/resources/field-type-resource.js +62 -61
  49. package/dist/resources/field-type-resource.js.map +1 -1
  50. package/dist/resources/file-resource.d.ts +27 -2
  51. package/dist/resources/file-resource.js +46 -8
  52. package/dist/resources/file-resource.js.map +1 -1
  53. package/dist/resources/graph-model-resource.d.ts +5 -0
  54. package/dist/resources/graph-model-resource.js +6 -0
  55. package/dist/resources/graph-model-resource.js.map +1 -1
  56. package/dist/resources/graph-view-resource.d.ts +5 -0
  57. package/dist/resources/graph-view-resource.js +6 -0
  58. package/dist/resources/graph-view-resource.js.map +1 -1
  59. package/dist/resources/link-type-resource.d.ts +11 -1
  60. package/dist/resources/link-type-resource.js +54 -30
  61. package/dist/resources/link-type-resource.js.map +1 -1
  62. package/dist/resources/report-resource.d.ts +6 -1
  63. package/dist/resources/report-resource.js +7 -1
  64. package/dist/resources/report-resource.js.map +1 -1
  65. package/dist/resources/resource-object.d.ts +22 -7
  66. package/dist/resources/resource-object.js +44 -15
  67. package/dist/resources/resource-object.js.map +1 -1
  68. package/dist/resources/template-resource.d.ts +5 -1
  69. package/dist/resources/template-resource.js +11 -27
  70. package/dist/resources/template-resource.js.map +1 -1
  71. package/dist/resources/workflow-resource.d.ts +7 -3
  72. package/dist/resources/workflow-resource.js +90 -82
  73. package/dist/resources/workflow-resource.js.map +1 -1
  74. package/dist/utils/card-utils.d.ts +1 -1
  75. package/dist/utils/common-utils.d.ts +8 -0
  76. package/dist/utils/common-utils.js +14 -0
  77. package/dist/utils/common-utils.js.map +1 -1
  78. package/dist/utils/file-utils.d.ts +15 -3
  79. package/dist/utils/file-utils.js +48 -9
  80. package/dist/utils/file-utils.js.map +1 -1
  81. package/dist/utils/json.js +2 -2
  82. package/dist/utils/json.js.map +1 -1
  83. package/package.json +5 -3
  84. package/src/command-handler.ts +38 -1
  85. package/src/command-manager.ts +3 -0
  86. package/src/commands/create.ts +11 -0
  87. package/src/commands/migrate.ts +88 -0
  88. package/src/containers/project/card-cache.ts +18 -1
  89. package/src/containers/project/project-paths.ts +6 -2
  90. package/src/containers/project.ts +66 -1
  91. package/src/containers/template.ts +5 -0
  92. package/src/interfaces/command-options.ts +8 -0
  93. package/src/interfaces/project-interfaces.ts +4 -0
  94. package/src/migrations/index.ts +20 -0
  95. package/src/migrations/migration-executor.ts +478 -0
  96. package/src/migrations/migration-worker.ts +190 -0
  97. package/src/migrations/worker-executor.ts +185 -0
  98. package/src/project-settings.ts +7 -0
  99. package/src/resources/calculation-resource.ts +13 -2
  100. package/src/resources/card-type-resource.ts +101 -114
  101. package/src/resources/field-type-resource.ts +78 -71
  102. package/src/resources/file-resource.ts +68 -9
  103. package/src/resources/graph-model-resource.ts +6 -0
  104. package/src/resources/graph-view-resource.ts +6 -0
  105. package/src/resources/link-type-resource.ts +66 -36
  106. package/src/resources/report-resource.ts +7 -1
  107. package/src/resources/resource-object.ts +57 -18
  108. package/src/resources/template-resource.ts +12 -27
  109. package/src/resources/workflow-resource.ts +119 -100
  110. package/src/utils/common-utils.ts +15 -0
  111. package/src/utils/file-utils.ts +56 -12
  112. package/src/utils/json.ts +2 -6
@@ -39,6 +39,11 @@ export class TemplateResource extends FolderResource<TemplateMetadata, never> {
39
39
  private cardsFolder = '';
40
40
  private cardsSchema = super.contentSchemaContent('cardBaseSchema');
41
41
 
42
+ /**
43
+ * Creates an instance of TemplateResource
44
+ * @param project Project to use
45
+ * @param name Resource name
46
+ */
42
47
  constructor(project: Project, name: ResourceName) {
43
48
  super(project, name, 'templates');
44
49
 
@@ -63,6 +68,7 @@ export class TemplateResource extends FolderResource<TemplateMetadata, never> {
63
68
  await Promise.all([
64
69
  super.updateHandleBars(existingName, this.content.name),
65
70
  super.updateCalculations(existingName, this.content.name),
71
+ super.updateCardContentReferences(existingName, this.content.name),
66
72
  ]);
67
73
  await this.write();
68
74
  }
@@ -70,7 +76,6 @@ export class TemplateResource extends FolderResource<TemplateMetadata, never> {
70
76
  /**
71
77
  * Sets new metadata into the template object.
72
78
  * @param newContent metadata content for the template.
73
- * @throws if 'newContent' is not valid.
74
79
  */
75
80
  public async create(newContent?: TemplateMetadata) {
76
81
  if (!newContent) {
@@ -140,35 +145,15 @@ export class TemplateResource extends FolderResource<TemplateMetadata, never> {
140
145
  updateKey: UpdateKey<K>,
141
146
  op: Operation<Type>,
142
147
  ) {
143
- const { key } = updateKey;
144
- const nameChange = key === 'name';
145
- const existingName = this.content.name;
146
-
147
- // Only call super.update for keys that base class supports
148
- if (key === 'name' || key === 'displayName' || key === 'description') {
149
- await super.update(updateKey, op);
150
- }
151
-
152
- const content = structuredClone(this.content);
153
-
154
- if (key === 'name') {
155
- content.name = super.handleScalar(op) as string;
156
- } else if (key === 'displayName') {
157
- content.displayName = super.handleScalar(op) as string;
158
- } else if (key === 'description') {
159
- content.description = super.handleScalar(op) as string;
160
- } else if (key === 'category') {
148
+ if (updateKey.key === 'category') {
149
+ const content = structuredClone(this.content);
161
150
  content.category = super.handleScalar(op) as string;
162
- } else {
163
- throw new Error(`Unknown property '${key}' for Template`);
164
- }
165
151
 
166
- await super.postUpdate(content, updateKey, op);
167
-
168
- // Renaming this template causes that references to its name must be updated.
169
- if (nameChange) {
170
- await this.onNameChange(existingName);
152
+ await super.postUpdate(content, updateKey, op);
153
+ return;
171
154
  }
155
+
156
+ await super.update(updateKey, op);
172
157
  }
173
158
 
174
159
  /**
@@ -36,6 +36,11 @@ import type { ResourceName } from '../utils/resource-utils.js';
36
36
  * Workflow resource class.
37
37
  */
38
38
  export class WorkflowResource extends FileResource<Workflow> {
39
+ /**
40
+ * Creates an instance of WorkflowResource
41
+ * @param project Project to use
42
+ * @param name Resource name
43
+ */
39
44
  constructor(project: Project, name: ResourceName) {
40
45
  super(project, name, 'workflows');
41
46
 
@@ -49,17 +54,24 @@ export class WorkflowResource extends FileResource<Workflow> {
49
54
  const promises: Promise<Card[]>[] = [];
50
55
  for (const cardType of cardTypes) {
51
56
  if (cardType.data?.workflow === resourceNameToString(this.resourceName)) {
52
- promises.push(this.collectCards(cardType.data.name));
57
+ promises.push(
58
+ this.collectCards(
59
+ cardType.data.name,
60
+ (card, cardTypeName) => card.metadata?.cardType === cardTypeName,
61
+ ),
62
+ );
53
63
  }
54
64
  }
55
65
  return (await Promise.all(promises)).flat();
56
66
  }
57
67
 
58
68
  // When resource name changes.
59
- private async handleNameChange(existingName: string) {
69
+ protected async onNameChange(existingName: string) {
60
70
  await Promise.all([
61
71
  super.updateHandleBars(existingName, this.content.name),
62
72
  super.updateCalculations(existingName, this.content.name),
73
+ super.updateCardContentReferences(existingName, this.content.name),
74
+ this.updateCardTypes(existingName),
63
75
  ]);
64
76
  // Finally, write updated content.
65
77
  await this.write();
@@ -131,6 +143,11 @@ export class WorkflowResource extends FileResource<Workflow> {
131
143
  }
132
144
  }
133
145
 
146
+ // Check if operation is a string operation.
147
+ private isStringOperation(op: Operation<unknown>): op is Operation<string> {
148
+ return typeof op.target === 'string';
149
+ }
150
+
134
151
  // Returns target name irregardless of the type
135
152
  private targetName(op: Operation<WorkflowState | WorkflowTransition>) {
136
153
  const name = op.target.name ? op.target.name : op.target;
@@ -167,11 +184,6 @@ export class WorkflowResource extends FileResource<Workflow> {
167
184
  return op.to;
168
185
  }
169
186
 
170
- // Check if operation is a string operation.
171
- private isStringOperation(op: Operation<unknown>): op is Operation<string> {
172
- return typeof op.target === 'string';
173
- }
174
-
175
187
  // Update card states when state is changed
176
188
  private async updateCardStates(oldState: string, newState: string) {
177
189
  const cards = await this.collectCardsUsingWorkflow();
@@ -193,19 +205,21 @@ export class WorkflowResource extends FileResource<Workflow> {
193
205
  to: this.content.name,
194
206
  } as ChangeOperation<string>;
195
207
  for (const cardType of cardTypes) {
196
- await cardType.update(
197
- {
198
- key: 'workflow',
199
- },
200
- op,
201
- );
208
+ // Only update card types that use this workflow
209
+ if (cardType.data?.workflow === oldName) {
210
+ await cardType.update(
211
+ {
212
+ key: 'workflow',
213
+ },
214
+ op,
215
+ );
216
+ }
202
217
  }
203
218
  }
204
219
 
205
220
  /**
206
221
  * Sets new metadata into the workflow object.
207
222
  * @param newContent metadata content for the workflow.
208
- * @throws if 'newContent' is not valid.
209
223
  */
210
224
  public async create(newContent?: Workflow) {
211
225
  if (!newContent) {
@@ -225,7 +239,7 @@ export class WorkflowResource extends FileResource<Workflow> {
225
239
  public async rename(newName: ResourceName) {
226
240
  const existingName = this.content.name;
227
241
  await super.rename(newName);
228
- return this.handleNameChange(existingName);
242
+ return this.onNameChange(existingName);
229
243
  }
230
244
 
231
245
  /**
@@ -239,101 +253,106 @@ export class WorkflowResource extends FileResource<Workflow> {
239
253
  op: Operation<Type>,
240
254
  ) {
241
255
  const { key } = updateKey;
242
- const nameChange = key === 'name';
243
- const existingName = this.content.name;
244
256
 
245
- await super.update(updateKey, op);
246
-
247
- const content = structuredClone(this.content) as Workflow;
248
-
249
- if (key === 'name') {
250
- content.name = super.handleScalar(op) as string;
251
- } else if (key === 'displayName') {
252
- content.displayName = super.handleScalar(op) as string;
253
- } else if (key === 'description') {
254
- content.description = super.handleScalar(op) as string;
255
- } else if (key === 'states') {
256
- content.states = super.handleArray(
257
- op,
258
- key,
259
- content.states as Type[],
260
- ) as WorkflowState[];
261
- } else if (key === 'transitions') {
262
- content.transitions = super.handleArray(
263
- op,
264
- key,
265
- content.transitions as WorkflowTransition[] as Type[],
266
- ) as WorkflowTransition[];
257
+ if (key === 'name' || key === 'displayName' || key === 'description') {
258
+ await super.update(updateKey, op);
267
259
  } else {
268
- throw new Error(`Unknown property '${key}' for Workflow`);
269
- }
270
-
271
- // If workflow transition is removed, then above call to 'handleArray' is all that is needed.
272
-
273
- if (key === 'transitions' && op.name === 'change') {
274
- // If workflow transition is changed, update to full object and change the content.
275
- let changeOp: ChangeOperation<WorkflowTransition>;
276
- if (this.isStringOperation(op)) {
277
- const targetTransition = (this.content as Workflow).transitions.find(
278
- (transition) => transition.name === op.target,
279
- )!;
280
- changeOp = {
281
- name: 'change',
282
- target: targetTransition as WorkflowTransition,
283
- to: {
284
- name: op.to,
285
- toState: targetTransition.toState,
286
- fromState: targetTransition.fromState,
287
- },
288
- };
289
- } else {
290
- changeOp = op as ChangeOperation<WorkflowTransition>;
260
+ const content = structuredClone(this.content) as Workflow;
261
+
262
+ // Validate state change operations before processing
263
+ if (key === 'states' && op.name === 'change') {
264
+ const changeOp = op as ChangeOperation<WorkflowState>;
265
+ if (
266
+ changeOp.to.name === undefined ||
267
+ changeOp.to.category === undefined
268
+ ) {
269
+ const stateName =
270
+ changeOp.target['name' as keyof typeof changeOp.target] ||
271
+ changeOp.target;
272
+ throw new Error(
273
+ `Cannot change state '${stateName}' for workflow '${this.content.name}'.
274
+ Updated state must have 'name' and 'category' properties.`,
275
+ );
276
+ }
291
277
  }
292
- const newTransition = await this.transitionObject(changeOp);
293
- content.transitions = content.transitions.map((item) =>
294
- item.name == newTransition.name ? newTransition : item,
295
- );
296
- }
297
278
 
298
- if (key === 'states' && op.name === 'remove') {
299
- // If workflow state is removed, remove all transitions "to" and "from" this state.
300
- let removeOp: RemoveOperation<WorkflowState>;
301
- if (this.isStringOperation(op)) {
302
- const toBeRemovedState = this.content.states.find(
303
- (state) => state.name === op.target,
304
- );
305
- removeOp = {
306
- name: 'remove',
307
- target: toBeRemovedState as WorkflowState,
308
- };
279
+ if (key === 'states') {
280
+ content.states = super.handleArray(
281
+ op,
282
+ key,
283
+ content.states as Type[],
284
+ ) as WorkflowState[];
285
+ } else if (key === 'transitions') {
286
+ content.transitions = super.handleArray(
287
+ op,
288
+ key,
289
+ content.transitions as WorkflowTransition[] as Type[],
290
+ ) as WorkflowTransition[];
309
291
  } else {
310
- removeOp = op as RemoveOperation<WorkflowState>;
292
+ throw new Error(`Unknown property '${key}' for Workflow`);
311
293
  }
312
- await this.handleStateRemoval(removeOp);
313
- } else if (key === 'states' && op.name === 'change') {
314
- // If workflow state is renamed, replace all transitions "to" and "from" the old state with new state.
315
- let changeOp: ChangeOperation<WorkflowState>;
316
- if (this.isStringOperation(op)) {
317
- const toBeChangedState = this.content.states.find(
318
- (state) => state.name === op.target,
294
+
295
+ // If workflow transition is removed, then above call to 'handleArray' is all that is needed.
296
+
297
+ if (key === 'transitions' && op.name === 'change') {
298
+ // If workflow transition is changed, update to full object and change the content.
299
+ let changeOp: ChangeOperation<WorkflowTransition>;
300
+ if (this.isStringOperation(op)) {
301
+ const targetTransition = (this.content as Workflow).transitions.find(
302
+ (transition) => transition.name === op.target,
303
+ )!;
304
+ changeOp = {
305
+ name: 'change',
306
+ target: targetTransition as WorkflowTransition,
307
+ to: {
308
+ name: op.to,
309
+ toState: targetTransition.toState,
310
+ fromState: targetTransition.fromState,
311
+ },
312
+ };
313
+ } else {
314
+ changeOp = op as ChangeOperation<WorkflowTransition>;
315
+ }
316
+ const newTransition = await this.transitionObject(changeOp);
317
+ content.transitions = content.transitions.map((item) =>
318
+ item.name == newTransition.name ? newTransition : item,
319
319
  );
320
- changeOp = {
321
- name: 'change',
322
- target: toBeChangedState as WorkflowState,
323
- to: { name: op.to },
324
- };
325
- } else {
326
- changeOp = op as ChangeOperation<WorkflowState>;
327
320
  }
328
- await this.handleStateChange(changeOp);
329
- }
330
321
 
331
- await super.postUpdate(content, updateKey, op);
322
+ if (key === 'states' && op.name === 'remove') {
323
+ // If workflow state is removed, remove all transitions "to" and "from" this state.
324
+ let removeOp: RemoveOperation<WorkflowState>;
325
+ if (this.isStringOperation(op)) {
326
+ const toBeRemovedState = this.content.states.find(
327
+ (state) => state.name === op.target,
328
+ );
329
+ removeOp = {
330
+ name: 'remove',
331
+ target: toBeRemovedState as WorkflowState,
332
+ };
333
+ } else {
334
+ removeOp = op as RemoveOperation<WorkflowState>;
335
+ }
336
+ await this.handleStateRemoval(removeOp);
337
+ } else if (key === 'states' && op.name === 'change') {
338
+ // If workflow state is renamed, replace all transitions "to" and "from" the old state with new state.
339
+ let changeOp: ChangeOperation<WorkflowState>;
340
+ if (this.isStringOperation(op)) {
341
+ const toBeChangedState = this.content.states.find(
342
+ (state) => state.name === op.target,
343
+ );
344
+ changeOp = {
345
+ name: 'change',
346
+ target: toBeChangedState as WorkflowState,
347
+ to: { name: op.to },
348
+ };
349
+ } else {
350
+ changeOp = op as ChangeOperation<WorkflowState>;
351
+ }
352
+ await this.handleStateChange(changeOp);
353
+ }
332
354
 
333
- // Renaming this workflow causes that references to its name must be updated.
334
- if (nameChange) {
335
- await this.handleNameChange(existingName);
336
- await this.updateCardTypes(existingName);
355
+ await super.postUpdate(content, updateKey, op);
337
356
  }
338
357
  }
339
358
 
@@ -52,3 +52,18 @@ export function isBigInt(value: string): boolean {
52
52
  return false;
53
53
  }
54
54
  }
55
+
56
+ /**
57
+ * Removes the first occurrence of a value from an array.
58
+ * Modifies the array in place.
59
+ * @param array The array to modify
60
+ * @param value The value to remove
61
+ * @returns The modified array (same reference as input)
62
+ */
63
+ export function removeValue<T>(array: T[], value: T): T[] {
64
+ const index = array.findIndex((element) => element === value);
65
+ if (index !== -1) {
66
+ array.splice(index, 1);
67
+ }
68
+ return array;
69
+ }
@@ -17,6 +17,8 @@ import {
17
17
  mkdir,
18
18
  readdir,
19
19
  rm,
20
+ stat,
21
+ statfs,
20
22
  unlink,
21
23
  writeFile,
22
24
  } from 'node:fs/promises';
@@ -25,19 +27,17 @@ import { dirname, join, sep } from 'node:path';
25
27
  import { homedir } from 'node:os';
26
28
 
27
29
  /**
28
- * Works like the writeFile method, but ensures that the directory exists
29
- * There is only one difference: This method only supports a string as the filePath
30
+ * Get available disk space for a given path.
31
+ * @param path Path to check
32
+ * @returns Available space in bytes
30
33
  */
31
- export async function writeFileSafe(
32
- filePath: string,
33
- data: Parameters<typeof writeFile>[1],
34
- options?: Parameters<typeof writeFile>[2],
35
- ) {
36
- const dir = dirname(filePath);
37
- await mkdir(dir, {
38
- recursive: true,
39
- });
40
- return writeFile(filePath, data, options);
34
+ export async function availableSpace(path: string): Promise<number> {
35
+ try {
36
+ const stats = await statfs(path);
37
+ return stats.bavail * stats.bsize;
38
+ } catch (error) {
39
+ throw new Error(`Failed to check available disk space: ${error}`);
40
+ }
41
41
  }
42
42
 
43
43
  /**
@@ -87,6 +87,34 @@ export async function deleteFile(path: string): Promise<boolean> {
87
87
  return true;
88
88
  }
89
89
 
90
+ /**
91
+ * Calculate the total size of a directory recursively.
92
+ * @param dirPath Path to directory
93
+ * @returns Size in bytes
94
+ */
95
+ export async function folderSize(dirPath: string): Promise<number> {
96
+ let size = 0;
97
+
98
+ try {
99
+ const entries = await readdir(dirPath, { withFileTypes: true });
100
+
101
+ for (const entry of entries) {
102
+ const fullPath = join(dirPath, entry.name);
103
+
104
+ if (entry.isDirectory()) {
105
+ size += await folderSize(fullPath);
106
+ } else if (entry.isFile()) {
107
+ const stats = await stat(fullPath);
108
+ size += stats.size;
109
+ }
110
+ }
111
+ } catch {
112
+ // Ignore permission errors or missing directories
113
+ }
114
+
115
+ return size;
116
+ }
117
+
90
118
  /**
91
119
  * Removes extension from filename.
92
120
  * @param filename Filename
@@ -180,3 +208,19 @@ export function resolveTilde(filePath: string): string {
180
208
  * Path separator RE.
181
209
  */
182
210
  export const sepRegex = /[/\\]/;
211
+
212
+ /**
213
+ * Works like the writeFile method, but ensures that the directory exists
214
+ * There is only one difference: This method only supports a string as the filePath
215
+ */
216
+ export async function writeFileSafe(
217
+ filePath: string,
218
+ data: Parameters<typeof writeFile>[1],
219
+ options?: Parameters<typeof writeFile>[2],
220
+ ) {
221
+ const dir = dirname(filePath);
222
+ await mkdir(dir, {
223
+ recursive: true,
224
+ });
225
+ return writeFile(filePath, data, options);
226
+ }
package/src/utils/json.ts CHANGED
@@ -28,9 +28,7 @@ export function readJsonFileSync(file: string) {
28
28
  return returnValue;
29
29
  } catch (error) {
30
30
  if (error instanceof Error) {
31
- throw new Error(
32
- `Error while handling JSON file '${file}' : ${error.message}`,
33
- );
31
+ throw new Error(`Invalid JSON in file '${file}': ${error.message}`);
34
32
  }
35
33
  }
36
34
  }
@@ -47,9 +45,7 @@ export async function readJsonFile(file: string) {
47
45
  return JSON.parse(raw);
48
46
  } catch (error) {
49
47
  if (error instanceof Error) {
50
- throw new Error(
51
- `Error while handling JSON file '${file}' : ${error.message}`,
52
- );
48
+ throw new Error(`Invalid JSON in file '${file}': ${error.message}`);
53
49
  }
54
50
  }
55
51
  }