@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
@@ -0,0 +1,81 @@
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.
7
+ This program is distributed in the hope that it will be useful, but WITHOUT
8
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9
+ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
10
+ details. 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
+ import type { Schema } from 'jsonschema';
15
+
16
+ // All file mappings for lookup (filename -> property name)
17
+ export const ALL_FILE_MAPPINGS = {
18
+ 'calculation.lp': 'calculation',
19
+ 'index.adoc.hbs': 'contentTemplate',
20
+ 'model.lp': 'model',
21
+ 'parameterSchema.json': 'schema',
22
+ 'query.lp.hbs': 'queryTemplate',
23
+ 'view.lp.hbs': 'viewTemplate',
24
+ } as const;
25
+
26
+ // Reverse mappings from property names to filenames
27
+ export const REVERSE_FILE_MAPPINGS = {
28
+ calculation: 'calculation.lp',
29
+ contentTemplate: 'index.adoc.hbs',
30
+ model: 'model.lp',
31
+ queryTemplate: 'query.lp.hbs',
32
+ schema: 'parameterSchema.json',
33
+ viewTemplate: 'view.lp.hbs',
34
+ } as const;
35
+
36
+ // Union type of all valid content property names
37
+ export type ContentPropertyName = keyof typeof REVERSE_FILE_MAPPINGS;
38
+
39
+ // Content interface for Calculation resources
40
+ export interface CalculationContent {
41
+ calculation: string;
42
+ }
43
+
44
+ // Content interface for Graph Model resources
45
+ export interface GraphModelContent {
46
+ model?: string;
47
+ }
48
+
49
+ // Content interface for Graph View resources
50
+ export interface GraphViewContent {
51
+ viewTemplate?: string;
52
+ }
53
+
54
+ // Content interface for Report resources
55
+ export interface ReportContent {
56
+ contentTemplate: string;
57
+ queryTemplate: string;
58
+ schema?: Schema;
59
+ }
60
+
61
+ /**
62
+ * Get filename with property name
63
+ * @param propertyName Property name.
64
+ * @returns filename that matches property name
65
+ */
66
+ export function filename(propertyName: string): string | undefined {
67
+ return REVERSE_FILE_MAPPINGS[
68
+ propertyName as keyof typeof REVERSE_FILE_MAPPINGS
69
+ ];
70
+ }
71
+
72
+ /**
73
+ * Get property name for a filename
74
+ * @param filename Filename.
75
+ * @returns property name that matches filename
76
+ */
77
+ export function propertyName(
78
+ filename: string,
79
+ ): ContentPropertyName | undefined {
80
+ return ALL_FILE_MAPPINGS[filename as keyof typeof ALL_FILE_MAPPINGS];
81
+ }
@@ -1,13 +1,15 @@
1
1
  /**
2
- Cyberismo
3
- Copyright © Cyberismo Ltd and contributors 2024
4
-
5
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
6
-
7
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
8
-
9
- You should have received a copy of the GNU Affero General Public
10
- License along with this program. If not, see <https://www.gnu.org/licenses/>.
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2024
4
+
5
+ This program is free software: you can redistribute it and/or modify it under
6
+ the terms of the GNU Affero General Public License version 3 as published by
7
+ the Free Software Foundation. This program is distributed in the hope that it
8
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
9
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
+ See the GNU Affero General Public License for more details.
11
+ You should have received a copy of the GNU Affero General Public
12
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
11
13
  */
12
14
 
13
15
  import type { Link, TemplateConfiguration } from './resource-interfaces.js';
@@ -205,6 +207,7 @@ export interface ModuleSettingOptions {
205
207
  // Resources that are possible to remove.
206
208
  export type RemovableResourceTypes =
207
209
  | 'attachment'
210
+ | 'calculation'
208
211
  | 'card'
209
212
  | 'cardType'
210
213
  | 'fieldType'
@@ -11,7 +11,12 @@
11
11
  License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
12
  */
13
13
 
14
- import type { Schema } from 'jsonschema';
14
+ import type {
15
+ CalculationContent,
16
+ GraphModelContent,
17
+ GraphViewContent,
18
+ ReportContent,
19
+ } from './folder-content-interfaces.js';
15
20
 
16
21
  /**
17
22
  * Each resource represents a file (or a folder in some cases) with metadata stored
@@ -23,6 +28,15 @@ import type { Schema } from 'jsonschema';
23
28
  export interface CalculationMetadata extends ResourceBaseMetadata {
24
29
  calculation: string;
25
30
  }
31
+ export interface Calculation extends CalculationMetadata {
32
+ content: CalculationContent;
33
+ }
34
+ export type CalculationContentPropertyName = 'calculation';
35
+ export interface CalculationContentUpdateKey {
36
+ key: 'content';
37
+ subKey: CalculationContentPropertyName;
38
+ }
39
+ export type CalculationUpdateKey = string | CalculationContentUpdateKey;
26
40
 
27
41
  // Card type content.
28
42
  export interface CardType extends ResourceBaseMetadata {
@@ -32,6 +46,12 @@ export interface CardType extends ResourceBaseMetadata {
32
46
  optionallyVisibleFields: string[];
33
47
  }
34
48
 
49
+ // Base content update key interface
50
+ export interface ContentUpdateKey {
51
+ key: 'content';
52
+ subKey: string; // Resource-specific types should narrow this
53
+ }
54
+
35
55
  // Custom field
36
56
  // todo: merge with FieldType.
37
57
  export interface CustomField {
@@ -71,19 +91,29 @@ export interface FieldType extends ResourceBaseMetadata {
71
91
  export interface GraphModelMetadata extends ResourceBaseMetadata {
72
92
  category?: string;
73
93
  }
74
-
75
94
  export interface GraphModel extends GraphModelMetadata {
76
- calculationFile: string;
95
+ content: GraphModelContent;
96
+ }
97
+ export type GraphModelContentPropertyName = 'model';
98
+ export interface GraphModelContentUpdateKey {
99
+ key: 'content';
100
+ subKey: GraphModelContentPropertyName;
77
101
  }
102
+ export type GraphModelUpdateKey = string | GraphModelContentUpdateKey;
78
103
 
79
104
  // Graph view content.
80
105
  export interface GraphViewMetadata extends ResourceBaseMetadata {
81
106
  category?: string;
82
107
  }
83
-
108
+ export type GraphViewContentPropertyName = 'viewTemplate';
84
109
  export interface GraphView extends GraphViewMetadata {
85
- handleBarFile: string;
110
+ content: GraphViewContent;
111
+ }
112
+ export interface GraphViewContentUpdateKey {
113
+ key: 'content';
114
+ subKey: GraphViewContentPropertyName;
86
115
  }
116
+ export type GraphViewUpdateKey = string | GraphViewContentUpdateKey;
87
117
 
88
118
  // Link content.
89
119
  export interface Link {
@@ -103,13 +133,20 @@ export interface LinkType extends ResourceBaseMetadata {
103
133
 
104
134
  // Report resource.
105
135
  export interface Report extends ResourceBaseMetadata {
106
- name: string;
107
- metadata: ReportMetadata;
108
- contentTemplate: string;
109
- queryTemplate: string;
110
- schema?: Schema;
136
+ content: ReportContent;
111
137
  }
112
138
 
139
+ // Resource-specific content names
140
+ export type ReportContentPropertyName =
141
+ | 'contentTemplate'
142
+ | 'queryTemplate'
143
+ | 'schema';
144
+ export interface ReportContentUpdateKey {
145
+ key: 'content';
146
+ subKey: ReportContentPropertyName;
147
+ }
148
+ export type ReportUpdateKey = string | ReportContentUpdateKey;
149
+
113
150
  // Metadata for report
114
151
  export interface ReportMetadata extends ResourceBaseMetadata {
115
152
  category: string;
@@ -136,10 +173,9 @@ export type ResourceContent =
136
173
  | Workflow;
137
174
 
138
175
  // Template configuration details.
139
- export interface TemplateConfiguration extends ResourceBaseMetadata {
176
+ export interface TemplateConfiguration extends TemplateMetadata {
140
177
  path: string;
141
178
  numberOfCards: number;
142
- metadata: TemplateMetadata;
143
179
  }
144
180
 
145
181
  // Template configuration content details.
@@ -147,6 +183,9 @@ export interface TemplateMetadata extends ResourceBaseMetadata {
147
183
  category?: string;
148
184
  }
149
185
 
186
+ // Generic update key
187
+ export type UpdateKey = string | ContentUpdateKey;
188
+
150
189
  // Workflow's json file content.
151
190
  export interface Workflow extends ResourceBaseMetadata {
152
191
  states: WorkflowState[];
@@ -45,16 +45,16 @@ class ReportMacro extends BaseMacro {
45
45
 
46
46
  if (!report) throw new Error(`Report ${options.name} does not exist`);
47
47
 
48
- if (report.schema) {
48
+ if (report.content.schema) {
49
49
  validateJson(options, {
50
- schema: report.schema,
50
+ schema: report.content.schema,
51
51
  });
52
52
  }
53
53
  try {
54
54
  return await generateReportContent({
55
55
  calculate: context.project.calculationEngine,
56
- contentTemplate: report.contentTemplate,
57
- queryTemplate: report.queryTemplate,
56
+ contentTemplate: report.content.contentTemplate,
57
+ queryTemplate: report.content.queryTemplate,
58
58
  options: {
59
59
  cardKey: context.cardKey,
60
60
  ...options,
@@ -0,0 +1,171 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2025
4
+
5
+ This program is free software: you can redistribute it and/or modify it under
6
+ the terms of the GNU Affero General Public License version 3 as published by
7
+ the Free Software Foundation. This program is distributed in the hope that it
8
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
9
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
+ See the GNU Affero General Public License for more details.
11
+ You should have received a copy of the GNU Affero General Public
12
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
13
+ */
14
+
15
+ import { join } from 'node:path';
16
+
17
+ import {
18
+ DefaultContent,
19
+ FolderResource,
20
+ resourceNameToString,
21
+ sortCards,
22
+ } from './folder-resource.js';
23
+ import { writeFileSafe } from '../utils/file-utils.js';
24
+
25
+ import type {
26
+ Calculation,
27
+ CalculationMetadata,
28
+ CalculationUpdateKey,
29
+ } from '../interfaces/resource-interfaces.js';
30
+ import type { CalculationContent } from '../interfaces/folder-content-interfaces.js';
31
+ import type {
32
+ Card,
33
+ Operation,
34
+ Project,
35
+ ResourceName,
36
+ } from './file-resource.js';
37
+
38
+ /**
39
+ * Calculation resource class.
40
+ */
41
+ export class CalculationResource extends FolderResource {
42
+ private calculationsFile = 'calculation.lp';
43
+ constructor(project: Project, name: ResourceName) {
44
+ super(project, name, 'calculations');
45
+
46
+ this.contentSchemaId = 'calculationSchema';
47
+ this.contentSchema = super.contentSchemaContent(this.contentSchemaId);
48
+
49
+ this.initialize();
50
+ }
51
+
52
+ // When resource name changes
53
+ protected async onNameChange(existingName: string) {
54
+ await super.updateCalculations(existingName, this.content.name);
55
+ await this.write();
56
+ }
57
+
58
+ /**
59
+ * Creates a new calculation object and file.
60
+ * @param newContent Content for the calculation.
61
+ */
62
+ public async create(newContent?: CalculationMetadata) {
63
+ if (!newContent) {
64
+ newContent = DefaultContent.calculation(
65
+ resourceNameToString(this.resourceName),
66
+ );
67
+ } else {
68
+ await this.validate(newContent);
69
+ }
70
+ await super.create(newContent);
71
+
72
+ const calculationsFile = join(this.internalFolder, this.calculationsFile);
73
+ await writeFileSafe(
74
+ calculationsFile,
75
+ `% add your calculations here for '${this.resourceName.identifier}'`,
76
+ {
77
+ flag: 'wx',
78
+ },
79
+ );
80
+ }
81
+
82
+ /**
83
+ * Returns content data.
84
+ */
85
+ public get data(): CalculationMetadata {
86
+ return super.data as CalculationMetadata;
87
+ }
88
+
89
+ /**
90
+ * Deletes files from disk and clears out the memory resident object.
91
+ */
92
+ public async delete() {
93
+ await super.delete();
94
+ }
95
+
96
+ /**
97
+ * Renames resource metadata file and renames memory resident object 'name'.
98
+ * @param newName New name for the resource.
99
+ */
100
+ public async rename(newName: ResourceName) {
101
+ const existingName = this.content.name;
102
+ await super.rename(newName);
103
+ return this.onNameChange(existingName);
104
+ }
105
+
106
+ /**
107
+ * Shows metadata of the resource.
108
+ * @returns calculation metadata.
109
+ */
110
+ public async show(): Promise<Calculation> {
111
+ const baseData = (await super.show()) as CalculationMetadata;
112
+ const fileContents = await super.contentData();
113
+ const content: CalculationContent = {
114
+ calculation: fileContents.calculation as string,
115
+ };
116
+ return {
117
+ ...baseData,
118
+ content: content,
119
+ };
120
+ }
121
+
122
+ /**
123
+ * Updates calculation resource.
124
+ * @template Type The type of the operation being operated on for the given key.
125
+ * @param key Key to modify
126
+ * @param op Operation to perform on 'key'
127
+ * @example
128
+ * // Update the description
129
+ * await calculation.update('description', { name: 'change', to: 'New description' });
130
+ * await calculation.update({ key: 'content', subKey: 'calculation' }, { name: 'change', to: 'new content' });
131
+ */
132
+ public async update<Type>(key: CalculationUpdateKey, op: Operation<Type>) {
133
+ if (
134
+ typeof key === 'object' &&
135
+ key.key === 'content' &&
136
+ key.subKey === 'calculation'
137
+ ) {
138
+ const calculationContent = super.handleScalar(op) as string;
139
+ await this.updateFile(this.calculationsFile, calculationContent);
140
+ return;
141
+ }
142
+ await super.update(key, op);
143
+ }
144
+
145
+ /**
146
+ * List where calculation resource is used in cards, or other calculation resources.
147
+ * Always returns card key references first, then calculation references.
148
+ *
149
+ * @param cards Optional. Check these cards for usage of this resource. If undefined, will check all cards.
150
+ * @returns array of card keys and calculation filenames that refer this resource.
151
+ */
152
+ public async usage(cards?: Card[]): Promise<string[]> {
153
+ const allCards = cards || (await super.cards());
154
+
155
+ const [cardContentReferences, calculations] = await Promise.all([
156
+ super.usage(allCards),
157
+ super.calculations(),
158
+ ]);
159
+
160
+ const cardReferences = cardContentReferences.sort(sortCards);
161
+ return [...new Set([...cardReferences, ...calculations])];
162
+ }
163
+
164
+ /**
165
+ * Validates the resource. If object is invalid, throws.
166
+ * @param content Content to validate
167
+ */
168
+ public async validate(content?: object) {
169
+ return super.validate(content);
170
+ }
171
+ }
@@ -233,7 +233,10 @@ export class CardTypeResource extends FileResource {
233
233
  }
234
234
 
235
235
  // If value from 'customFields' is removed, remove it also from 'optionallyVisible' and 'alwaysVisible' arrays.
236
- private removeValueFromOtherArrays<Type>(op: Operation<Type>) {
236
+ private removeValueFromOtherArrays<Type>(
237
+ op: Operation<Type>,
238
+ content: CardType,
239
+ ) {
237
240
  // Update target can be a string, or an object. Of object, fetch only 'name'
238
241
  // todo: fetching 'name' or using string as name could be function in resource base class.
239
242
  const target = (op as RemoveOperation<Type>).target as Type;
@@ -242,8 +245,8 @@ export class CardTypeResource extends FileResource {
242
245
  field = { name: target['name' as keyof Type] };
243
246
  }
244
247
  const fieldName = (field ? field.name : target) as string;
245
- this.removeValue(this.data.alwaysVisibleFields, fieldName);
246
- this.removeValue(this.data.optionallyVisibleFields, fieldName);
248
+ this.removeValue(content.alwaysVisibleFields, fieldName);
249
+ this.removeValue(content.optionallyVisibleFields, fieldName);
247
250
  }
248
251
 
249
252
  // Sets content container values to be either '[]' or with proper values.
@@ -481,7 +484,7 @@ export class CardTypeResource extends FileResource {
481
484
  const existingName = this.content.name;
482
485
  await super.update(key, op);
483
486
 
484
- const content = this.content as CardType;
487
+ const content = structuredClone(this.content) as CardType;
485
488
  if (key === 'name') {
486
489
  content.name = super.handleScalar(op) as string;
487
490
  } else if (key === 'alwaysVisibleFields') {
@@ -513,12 +516,15 @@ export class CardTypeResource extends FileResource {
513
516
  content.customFields as Type[],
514
517
  ) as CustomField[];
515
518
  if (op.name === 'remove') {
516
- this.removeValueFromOtherArrays(op);
519
+ this.removeValueFromOtherArrays(op, content);
517
520
  }
521
+ } else if (key === 'description') {
522
+ content.description = super.handleScalar(op) as string;
523
+ } else if (key === 'displayName') {
524
+ content.displayName = super.handleScalar(op) as string;
518
525
  } else {
519
526
  throw new Error(`Unknown property '${key}' for CardType`);
520
527
  }
521
-
522
528
  await super.postUpdate(content, key, op);
523
529
 
524
530
  // Renaming this card type causes that references to its name must be updated.
@@ -1,18 +1,20 @@
1
1
  /**
2
2
  Cyberismo
3
3
  Copyright © Cyberismo Ltd and contributors 2024
4
+
4
5
  This program is free software: you can redistribute it and/or modify it under
5
6
  the terms of the GNU Affero General Public License version 3 as published by
6
- the Free Software Foundation.
7
- This program is distributed in the hope that it will be useful, but WITHOUT
8
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9
- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
10
- details. You should have received a copy of the GNU Affero General Public
7
+ the Free Software Foundation. This program is distributed in the hope that it
8
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
9
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
+ See the GNU Affero General Public License for more details.
11
+ You should have received a copy of the GNU Affero General Public
11
12
  License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
13
  */
13
14
 
14
15
  import type { Card } from '../interfaces/project-interfaces.js';
15
16
  import type {
17
+ CalculationMetadata,
16
18
  CardType,
17
19
  DataType,
18
20
  FieldType,
@@ -70,6 +72,20 @@ export abstract class DefaultContent {
70
72
  );
71
73
  }
72
74
 
75
+ /**
76
+ * Default content for calculation.
77
+ * @param calculationName calculation name
78
+ * @returns Default content for calculation.
79
+ */
80
+ static calculation(calculationName: string): CalculationMetadata {
81
+ return {
82
+ name: calculationName,
83
+ displayName: '',
84
+ description: undefined,
85
+ calculation: 'calculation.lp',
86
+ };
87
+ }
88
+
73
89
  /**
74
90
  * Default content for card type.
75
91
  * @param cardTypeName card type name
@@ -433,7 +433,7 @@ export class FieldTypeResource extends FileResource {
433
433
 
434
434
  await super.update(key, op);
435
435
 
436
- const content = this.content as FieldType;
436
+ const content = structuredClone(this.content) as FieldType;
437
437
  if (key === 'name') {
438
438
  content.name = super.handleScalar(op) as string;
439
439
  } else if (key === 'dataType') {
@@ -30,6 +30,7 @@ import {
30
30
  } from './resource-object.js';
31
31
  import { DefaultContent } from './create-defaults.js';
32
32
  import { deleteFile, pathExists } from '../utils/file-utils.js';
33
+ import { hasCode } from '../utils/error-utils.js';
33
34
  import { Project, ResourcesFrom } from '../containers/project.js';
34
35
  import {
35
36
  readJsonFile,
@@ -242,6 +243,11 @@ export class FileResource extends ResourceObject {
242
243
  references.push(calculation.name);
243
244
  }
244
245
  } catch (error) {
246
+ // Skip files that don't exist (they may have been renamed or deleted)
247
+ if (hasCode(error) && error.code === 'ENOENT') {
248
+ this.logger.warn(`Skipping non-existent file: ${filename}`);
249
+ continue;
250
+ }
245
251
  throw new Error(
246
252
  `Failed to process file ${filename}: ${(error as Error).message}`,
247
253
  );
@@ -397,9 +403,9 @@ export class FileResource extends ResourceObject {
397
403
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
398
404
  _op: Operation<Type>,
399
405
  ): Promise<void> {
400
- const content = this.data;
401
- if (!content) {
402
- throw new Error(`Resource '${this.fileName}' does not exist`);
406
+ if (!this.data) {
407
+ const name = resourceNameToString(this.resourceName);
408
+ throw new Error(`Resource '${name}' does not exist in the project`);
403
409
  }
404
410
  if (this.moduleResource) {
405
411
  throw new Error(`Cannot update module resources`);