@cyberismo/data-handler 0.0.12 → 0.0.14

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 (130) hide show
  1. package/dist/command-handler.d.ts +24 -42
  2. package/dist/command-handler.js +33 -26
  3. package/dist/command-handler.js.map +1 -1
  4. package/dist/commands/create.d.ts +3 -3
  5. package/dist/commands/create.js +7 -22
  6. package/dist/commands/create.js.map +1 -1
  7. package/dist/commands/edit.d.ts +12 -11
  8. package/dist/commands/edit.js +41 -16
  9. package/dist/commands/edit.js.map +1 -1
  10. package/dist/commands/fetch.js +2 -1
  11. package/dist/commands/fetch.js.map +1 -1
  12. package/dist/commands/import.js +2 -2
  13. package/dist/commands/import.js.map +1 -1
  14. package/dist/commands/remove.js +6 -5
  15. package/dist/commands/remove.js.map +1 -1
  16. package/dist/commands/rename.d.ts +1 -0
  17. package/dist/commands/rename.js +11 -0
  18. package/dist/commands/rename.js.map +1 -1
  19. package/dist/commands/show.d.ts +4 -0
  20. package/dist/commands/show.js +6 -12
  21. package/dist/commands/show.js.map +1 -1
  22. package/dist/commands/update.d.ts +11 -1
  23. package/dist/commands/update.js +14 -2
  24. package/dist/commands/update.js.map +1 -1
  25. package/dist/commands/validate.d.ts +2 -1
  26. package/dist/commands/validate.js +4 -3
  27. package/dist/commands/validate.js.map +1 -1
  28. package/dist/containers/card-container.js +1 -1
  29. package/dist/containers/card-container.js.map +1 -1
  30. package/dist/containers/project/calculation-engine.js +18 -18
  31. package/dist/containers/project/calculation-engine.js.map +1 -1
  32. package/dist/containers/project.d.ts +2 -1
  33. package/dist/containers/project.js +5 -1
  34. package/dist/containers/project.js.map +1 -1
  35. package/dist/index.d.ts +4 -2
  36. package/dist/index.js.map +1 -1
  37. package/dist/interfaces/command-options.d.ts +81 -0
  38. package/dist/interfaces/command-options.js +14 -0
  39. package/dist/interfaces/command-options.js.map +1 -0
  40. package/dist/interfaces/folder-content-interfaces.d.ts +56 -0
  41. package/dist/interfaces/folder-content-interfaces.js +47 -0
  42. package/dist/interfaces/folder-content-interfaces.js.map +1 -0
  43. package/dist/interfaces/project-interfaces.d.ts +11 -9
  44. package/dist/interfaces/project-interfaces.js +10 -8
  45. package/dist/interfaces/project-interfaces.js.map +1 -1
  46. package/dist/interfaces/resource-interfaces.d.ts +37 -10
  47. package/dist/interfaces/resource-interfaces.js.map +1 -1
  48. package/dist/macros/report/index.js +4 -4
  49. package/dist/macros/report/index.js.map +1 -1
  50. package/dist/resources/calculation-resource.d.ts +71 -0
  51. package/dist/resources/calculation-resource.js +130 -0
  52. package/dist/resources/calculation-resource.js.map +1 -0
  53. package/dist/resources/card-type-resource.js +11 -5
  54. package/dist/resources/card-type-resource.js.map +1 -1
  55. package/dist/resources/create-defaults.d.ts +13 -6
  56. package/dist/resources/create-defaults.js +19 -5
  57. package/dist/resources/create-defaults.js.map +1 -1
  58. package/dist/resources/field-type-resource.js +1 -1
  59. package/dist/resources/field-type-resource.js.map +1 -1
  60. package/dist/resources/file-resource.js +9 -3
  61. package/dist/resources/file-resource.js.map +1 -1
  62. package/dist/resources/folder-resource.d.ts +38 -10
  63. package/dist/resources/folder-resource.js +108 -12
  64. package/dist/resources/folder-resource.js.map +1 -1
  65. package/dist/resources/graph-model-resource.d.ts +7 -4
  66. package/dist/resources/graph-model-resource.js +12 -25
  67. package/dist/resources/graph-model-resource.js.map +1 -1
  68. package/dist/resources/graph-view-resource.d.ts +7 -4
  69. package/dist/resources/graph-view-resource.js +12 -26
  70. package/dist/resources/graph-view-resource.js.map +1 -1
  71. package/dist/resources/link-type-resource.js +1 -1
  72. package/dist/resources/link-type-resource.js.map +1 -1
  73. package/dist/resources/report-resource.d.ts +14 -10
  74. package/dist/resources/report-resource.js +41 -45
  75. package/dist/resources/report-resource.js.map +1 -1
  76. package/dist/resources/resource-object.d.ts +7 -0
  77. package/dist/resources/resource-object.js +14 -2
  78. package/dist/resources/resource-object.js.map +1 -1
  79. package/dist/resources/template-resource.d.ts +5 -1
  80. package/dist/resources/template-resource.js +12 -7
  81. package/dist/resources/template-resource.js.map +1 -1
  82. package/dist/resources/workflow-resource.js +6 -0
  83. package/dist/resources/workflow-resource.js.map +1 -1
  84. package/dist/utils/constants.js +1 -0
  85. package/dist/utils/constants.js.map +1 -1
  86. package/dist/utils/error-utils.d.ts +34 -0
  87. package/dist/utils/error-utils.js +56 -0
  88. package/dist/utils/error-utils.js.map +1 -0
  89. package/dist/utils/log-utils.d.ts +0 -27
  90. package/dist/utils/log-utils.js +0 -58
  91. package/dist/utils/log-utils.js.map +1 -1
  92. package/dist/utils/user-preferences.js +6 -3
  93. package/dist/utils/user-preferences.js.map +1 -1
  94. package/package.json +9 -7
  95. package/src/command-handler.ts +74 -59
  96. package/src/commands/create.ts +10 -28
  97. package/src/commands/edit.ts +51 -26
  98. package/src/commands/fetch.ts +2 -1
  99. package/src/commands/import.ts +2 -0
  100. package/src/commands/remove.ts +3 -2
  101. package/src/commands/rename.ts +20 -0
  102. package/src/commands/show.ts +5 -13
  103. package/src/commands/update.ts +20 -2
  104. package/src/commands/validate.ts +7 -3
  105. package/src/containers/card-container.ts +1 -1
  106. package/src/containers/project/calculation-engine.ts +23 -23
  107. package/src/containers/project.ts +4 -1
  108. package/src/index.ts +36 -2
  109. package/src/interfaces/command-options.ts +144 -0
  110. package/src/interfaces/folder-content-interfaces.ts +81 -0
  111. package/src/interfaces/project-interfaces.ts +12 -9
  112. package/src/interfaces/resource-interfaces.ts +51 -12
  113. package/src/macros/report/index.ts +4 -4
  114. package/src/resources/calculation-resource.ts +171 -0
  115. package/src/resources/card-type-resource.ts +12 -6
  116. package/src/resources/create-defaults.ts +21 -5
  117. package/src/resources/field-type-resource.ts +1 -1
  118. package/src/resources/file-resource.ts +9 -3
  119. package/src/resources/folder-resource.ts +150 -20
  120. package/src/resources/graph-model-resource.ts +16 -27
  121. package/src/resources/graph-view-resource.ts +16 -28
  122. package/src/resources/link-type-resource.ts +1 -1
  123. package/src/resources/report-resource.ts +60 -62
  124. package/src/resources/resource-object.ts +30 -7
  125. package/src/resources/template-resource.ts +12 -7
  126. package/src/resources/workflow-resource.ts +4 -0
  127. package/src/utils/constants.ts +1 -0
  128. package/src/utils/error-utils.ts +62 -0
  129. package/src/utils/log-utils.ts +0 -68
  130. package/src/utils/user-preferences.ts +7 -3
@@ -16,6 +16,8 @@
16
16
  import { readFile, writeFile } from 'node:fs/promises';
17
17
  import { basename, join } from 'node:path';
18
18
 
19
+ import { hasCode } from '../utils/error-utils.js';
20
+
19
21
  import { ArrayHandler } from './array-handler.js';
20
22
  import type {
21
23
  Card,
@@ -67,6 +69,17 @@ export type Operation<T> =
67
69
  | RankOperation<T>
68
70
  | RemoveOperation<T>;
69
71
 
72
+ // Utility mapping from operation name to its concrete operation type
73
+ export type OperationMap<T> = {
74
+ add: AddOperation<T>;
75
+ change: ChangeOperation<T>;
76
+ rank: RankOperation<T>;
77
+ remove: RemoveOperation<T>;
78
+ };
79
+
80
+ // Given an operation name, get the corresponding operation type
81
+ export type OperationFor<T, N extends UpdateOperations> = OperationMap<T>[N];
82
+
70
83
  /**
71
84
  * Abstract class for resources.
72
85
  */
@@ -211,19 +224,29 @@ export class ResourceObject extends AbstractResource {
211
224
  );
212
225
  }
213
226
 
214
- const filename = join(
215
- calculation.path,
216
- basename(calculation.name) + '.lp',
217
- );
227
+ const base = basename(calculation.name);
228
+ const fileNameWithExtension = base.endsWith('.lp')
229
+ ? base
230
+ : base + '.lp';
231
+ const filename = join(calculation.path, fileNameWithExtension);
218
232
 
219
233
  try {
220
234
  const content = await readFile(filename, 'utf-8');
221
235
  const updatedContent = content.replaceAll(from, to);
222
236
  await writeFile(filename, updatedContent);
223
237
  } catch (error) {
224
- throw new Error(
225
- `Failed to process file ${filename}: ${(error as Error).message}`,
226
- );
238
+ if (hasCode(error) && error.code === 'ENOENT') {
239
+ // Skip files that don't exist (they may have been renamed or deleted)
240
+ this.getLogger(this.getType).warn(
241
+ `Skipping non-existent file: ${filename}`,
242
+ );
243
+ return;
244
+ }
245
+ if (error instanceof Error) {
246
+ throw new Error(
247
+ `Failed to process file while updating calculation ${filename}: ${error.message}`,
248
+ );
249
+ }
227
250
  }
228
251
  }),
229
252
  );
@@ -57,13 +57,15 @@ export class TemplateResource extends FolderResource {
57
57
  });
58
58
  }
59
59
 
60
- // When resource name changes.
61
- private async handleNameChange(existingName: string) {
60
+ /**
61
+ * Handle name changes for templates
62
+ * @param existingName The previous name before the change
63
+ */
64
+ protected async onNameChange(existingName: string): Promise<void> {
62
65
  await Promise.all([
63
66
  super.updateHandleBars(existingName, this.content.name),
64
67
  super.updateCalculations(existingName, this.content.name),
65
68
  ]);
66
- // Finally, write updated content.
67
69
  await this.write();
68
70
  }
69
71
 
@@ -105,7 +107,7 @@ export class TemplateResource extends FolderResource {
105
107
  public async rename(newName: ResourceName) {
106
108
  const existingName = this.content.name;
107
109
  await super.rename(newName);
108
- return this.handleNameChange(existingName);
110
+ return this.onNameChange(existingName);
109
111
  }
110
112
 
111
113
  /**
@@ -117,8 +119,8 @@ export class TemplateResource extends FolderResource {
117
119
  const container = this.templateObject();
118
120
 
119
121
  return {
120
- metadata: templateMetadata,
121
122
  name: resourceNameToString(this.resourceName),
123
+ category: templateMetadata.category,
122
124
  displayName: templateMetadata.displayName,
123
125
  description: templateMetadata.description,
124
126
  path: this.fileName,
@@ -144,7 +146,10 @@ export class TemplateResource extends FolderResource {
144
146
  const nameChange = key === 'name';
145
147
  const existingName = this.content.name;
146
148
 
147
- await super.update(key, op);
149
+ // Only call super.update for keys that base class supports
150
+ if (key === 'name' || key === 'displayName' || key === 'description') {
151
+ await super.update(key, op);
152
+ }
148
153
 
149
154
  const content = structuredClone(this.content) as TemplateMetadata;
150
155
 
@@ -164,7 +169,7 @@ export class TemplateResource extends FolderResource {
164
169
 
165
170
  // Renaming this template causes that references to its name must be updated.
166
171
  if (nameChange) {
167
- await this.handleNameChange(existingName);
172
+ await this.onNameChange(existingName);
168
173
  }
169
174
  }
170
175
 
@@ -283,6 +283,10 @@ export class WorkflowResource extends FileResource {
283
283
 
284
284
  if (key === 'name') {
285
285
  content.name = super.handleScalar(op) as string;
286
+ } else if (key === 'displayName') {
287
+ content.displayName = super.handleScalar(op) as string;
288
+ } else if (key === 'description') {
289
+ content.description = super.handleScalar(op) as string;
286
290
  } else if (key === 'states') {
287
291
  content.states = super.handleArray(
288
292
  op,
@@ -29,6 +29,7 @@ export const VALID_FOLDER_RESOURCE_FILES = [
29
29
  'parameterSchema.json',
30
30
  'view.lp.hbs',
31
31
  'model.lp',
32
+ 'calculation.lp',
32
33
  ];
33
34
 
34
35
  /**
@@ -0,0 +1,62 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2025
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation. This program is distributed in the hope that it
7
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
+ See the GNU Affero General Public License for more details.
10
+ You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+
14
+ /**
15
+ * Returns error message string from an Error object.
16
+ * @param error Error object
17
+ * @returns Error message.
18
+ */
19
+ export function errorFunction(error: unknown): string {
20
+ if (error instanceof Error) {
21
+ const err: Error = error;
22
+ return errorMessage(`${err.message}`);
23
+ } else if (typeof error === 'string') {
24
+ return errorMessage(`${error}`);
25
+ } else {
26
+ return `errorFunction called without an error object. Actual object is ${JSON.stringify(error)}`;
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Same as 'errorFunction' but can do automatic replacement of the error message string.
32
+ * @param message Error message
33
+ * @param toReplace replacement substring
34
+ * @param replaceWith string that 'toReplace' is replaced with.
35
+ * @returns Modified error message.
36
+ */
37
+ export function errorMessage(
38
+ message: string,
39
+ toReplace?: string,
40
+ replaceWith?: string,
41
+ ): string {
42
+ let errorMessage = message;
43
+ if (toReplace && replaceWith) {
44
+ errorMessage = message.replace(toReplace, replaceWith);
45
+ }
46
+ return `${errorMessage}`;
47
+ }
48
+
49
+ /**
50
+ * Type guard to check if an error object has a code property.
51
+ * @param error The error object to check
52
+ * @returns true if the error has a code property
53
+ */
54
+ export function hasCode(error: unknown): error is Error & { code: string } {
55
+ return (
56
+ error instanceof Error &&
57
+ typeof error === 'object' &&
58
+ error !== null &&
59
+ 'code' in error &&
60
+ typeof error.code === 'string'
61
+ );
62
+ }
@@ -36,71 +36,3 @@ export function getChildLogger(
36
36
  ): Logger {
37
37
  return _logger.child(context, options);
38
38
  }
39
- /**
40
- * Returns error message string from an Error object.
41
- * @param error Error object
42
- * @returns Error message.
43
- */
44
- export function errorFunction(error: unknown): string {
45
- if (error instanceof Error) {
46
- const err: Error = error;
47
- return errorMessage(`${err.message}`);
48
- } else if (typeof error === 'string') {
49
- return errorMessage(`${error}`);
50
- } else {
51
- return `${logError.name} called without an error object. Actual object is ${JSON.stringify(error)}`;
52
- }
53
- }
54
-
55
- /**
56
- * Same as 'errorFunction' but can do automatic replacement fof the error message string.
57
- * @param message Error message
58
- * @param toReplace replacement substring
59
- * @param replaceWith string that 'toReplace' is replaced with.
60
- * @returns Modified error message.
61
- */
62
- export function errorMessage(
63
- message: string,
64
- toReplace?: string,
65
- replaceWith?: string,
66
- ): string {
67
- let errorMessage = message;
68
- if (toReplace && replaceWith) {
69
- errorMessage = message.replace(toReplace, replaceWith);
70
- }
71
- return `${errorMessage}`;
72
- }
73
-
74
- /**
75
- * Logs error from Error object.
76
- * @param error potentially an Error object. When exceptions are raised, they are typically Error objects.
77
- */
78
- export function logError(error: unknown) {
79
- if (error instanceof Error) {
80
- const err: Error = error;
81
- logErrorMessage(`${err.message}`);
82
- } else {
83
- console.error(
84
- `${logError.name} called without an error object. Actual object is ${JSON.stringify(error)}`,
85
- );
86
- }
87
- }
88
-
89
- /**
90
- * Log error message in RED. Certain parts of messages can be replaced.
91
- * This is useful, if including a message from external sources, and want to reduce the verbosity of the message.
92
- * @param message Error message to log.
93
- * @param toReplace String to look for.
94
- * @param replaceWith Replace 'toReplace' with this. Only replaces first instance of 'toReplace'.
95
- */
96
- export function logErrorMessage(
97
- message: string,
98
- toReplace?: string,
99
- replaceWith?: string,
100
- ) {
101
- let errorMessage = message;
102
- if (toReplace && replaceWith) {
103
- errorMessage = message.replace(toReplace, replaceWith);
104
- }
105
- console.error(`${errorMessage}`);
106
- }
@@ -12,6 +12,7 @@
12
12
  import { dirname } from 'node:path';
13
13
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
14
14
 
15
+ import { hasCode } from './error-utils.js';
15
16
  import { formatJson } from './json.js';
16
17
  import { getChildLogger } from '../utils/log-utils.js';
17
18
 
@@ -111,16 +112,19 @@ export class UserPreferences {
111
112
  flag: 'wx',
112
113
  });
113
114
  } catch (error) {
114
- if (error instanceof Error) {
115
- const err = error as NodeJS.ErrnoException;
115
+ if (hasCode(error)) {
116
116
  // If file already exists (EEXIST), that's fine - we'll use the existing file
117
- if (err?.code !== 'EEXIST') {
117
+ if (error.code !== 'EEXIST') {
118
118
  throw new Error(
119
119
  `Error creating preferences file '${this.prefsFilePath}': ${error}`,
120
120
  );
121
121
  } else {
122
122
  this.logger.warn('Preferences file already exists');
123
123
  }
124
+ } else {
125
+ throw new Error(
126
+ `Error creating preferences file '${this.prefsFilePath}': ${error}`,
127
+ );
124
128
  }
125
129
  }
126
130
  }