@cyberismo/data-handler 0.0.13 → 0.0.15

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 (262) hide show
  1. package/dist/card-metadata-updater.js +1 -3
  2. package/dist/card-metadata-updater.js.map +1 -1
  3. package/dist/command-handler.js +13 -17
  4. package/dist/command-handler.js.map +1 -1
  5. package/dist/command-manager.d.ts +1 -1
  6. package/dist/command-manager.js +4 -3
  7. package/dist/command-manager.js.map +1 -1
  8. package/dist/commands/create.d.ts +3 -3
  9. package/dist/commands/create.js +20 -81
  10. package/dist/commands/create.js.map +1 -1
  11. package/dist/commands/edit.d.ts +12 -25
  12. package/dist/commands/edit.js +25 -74
  13. package/dist/commands/edit.js.map +1 -1
  14. package/dist/commands/export.js +4 -17
  15. package/dist/commands/export.js.map +1 -1
  16. package/dist/commands/fetch.js +2 -1
  17. package/dist/commands/fetch.js.map +1 -1
  18. package/dist/commands/import.js +3 -5
  19. package/dist/commands/import.js.map +1 -1
  20. package/dist/commands/move.d.ts +1 -2
  21. package/dist/commands/move.js +108 -146
  22. package/dist/commands/move.js.map +1 -1
  23. package/dist/commands/remove.js +15 -49
  24. package/dist/commands/remove.js.map +1 -1
  25. package/dist/commands/rename.d.ts +1 -0
  26. package/dist/commands/rename.js +13 -7
  27. package/dist/commands/rename.js.map +1 -1
  28. package/dist/commands/show.d.ts +7 -25
  29. package/dist/commands/show.js +39 -113
  30. package/dist/commands/show.js.map +1 -1
  31. package/dist/commands/transition.js +27 -30
  32. package/dist/commands/transition.js.map +1 -1
  33. package/dist/commands/update.d.ts +5 -3
  34. package/dist/commands/update.js +19 -5
  35. package/dist/commands/update.js.map +1 -1
  36. package/dist/commands/validate.d.ts +3 -3
  37. package/dist/commands/validate.js +20 -27
  38. package/dist/commands/validate.js.map +1 -1
  39. package/dist/containers/card-container.d.ts +87 -24
  40. package/dist/containers/card-container.js +183 -279
  41. package/dist/containers/card-container.js.map +1 -1
  42. package/dist/containers/project/calculation-engine.d.ts +6 -0
  43. package/dist/containers/project/calculation-engine.js +36 -29
  44. package/dist/containers/project/calculation-engine.js.map +1 -1
  45. package/dist/containers/project/card-cache.d.ts +146 -0
  46. package/dist/containers/project/card-cache.js +411 -0
  47. package/dist/containers/project/card-cache.js.map +1 -0
  48. package/dist/containers/project/resource-collector.d.ts +24 -1
  49. package/dist/containers/project/resource-collector.js +8 -1
  50. package/dist/containers/project/resource-collector.js.map +1 -1
  51. package/dist/containers/project.d.ts +119 -84
  52. package/dist/containers/project.js +423 -253
  53. package/dist/containers/project.js.map +1 -1
  54. package/dist/containers/template.d.ts +15 -31
  55. package/dist/containers/template.js +97 -104
  56. package/dist/containers/template.js.map +1 -1
  57. package/dist/index.d.ts +1 -0
  58. package/dist/index.js +1 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/interfaces/folder-content-interfaces.d.ts +12 -5
  61. package/dist/interfaces/folder-content-interfaces.js +5 -3
  62. package/dist/interfaces/folder-content-interfaces.js.map +1 -1
  63. package/dist/interfaces/macros.d.ts +1 -0
  64. package/dist/interfaces/macros.js +1 -1
  65. package/dist/interfaces/macros.js.map +1 -1
  66. package/dist/interfaces/project-interfaces.d.ts +16 -10
  67. package/dist/interfaces/project-interfaces.js +10 -8
  68. package/dist/interfaces/project-interfaces.js.map +1 -1
  69. package/dist/interfaces/resource-interfaces.d.ts +21 -22
  70. package/dist/interfaces/resource-interfaces.js +3 -0
  71. package/dist/interfaces/resource-interfaces.js.map +1 -1
  72. package/dist/macros/common.d.ts +10 -10
  73. package/dist/macros/createCards/index.d.ts +0 -13
  74. package/dist/macros/createCards/index.js.map +1 -1
  75. package/dist/macros/createCards/types.d.ts +44 -0
  76. package/dist/macros/createCards/types.js +15 -0
  77. package/dist/macros/createCards/types.js.map +1 -0
  78. package/dist/macros/graph/index.d.ts +2 -6
  79. package/dist/macros/graph/index.js +2 -2
  80. package/dist/macros/graph/index.js.map +1 -1
  81. package/dist/macros/graph/types.d.ts +23 -0
  82. package/dist/macros/graph/types.js +15 -0
  83. package/dist/macros/graph/types.js.map +1 -0
  84. package/dist/macros/image/index.d.ts +8 -16
  85. package/dist/macros/image/index.js +36 -33
  86. package/dist/macros/image/index.js.map +1 -1
  87. package/dist/macros/image/types.d.ts +38 -0
  88. package/dist/macros/image/types.js +15 -0
  89. package/dist/macros/image/types.js.map +1 -0
  90. package/dist/macros/include/index.d.ts +1 -6
  91. package/dist/macros/include/index.js +4 -7
  92. package/dist/macros/include/index.js.map +1 -1
  93. package/dist/macros/include/types.d.ts +31 -0
  94. package/dist/macros/include/types.js +15 -0
  95. package/dist/macros/include/types.js.map +1 -0
  96. package/dist/macros/percentage/index.d.ts +0 -6
  97. package/dist/macros/percentage/index.js.map +1 -1
  98. package/dist/macros/percentage/types.d.ts +31 -0
  99. package/dist/macros/percentage/types.js +15 -0
  100. package/dist/macros/percentage/types.js.map +1 -0
  101. package/dist/macros/report/index.d.ts +0 -3
  102. package/dist/macros/report/index.js.map +1 -1
  103. package/dist/macros/report/types.d.ts +19 -0
  104. package/dist/macros/report/types.js +15 -0
  105. package/dist/macros/report/types.js.map +1 -0
  106. package/dist/macros/scoreCard/index.d.ts +0 -6
  107. package/dist/macros/scoreCard/index.js.map +1 -1
  108. package/dist/macros/scoreCard/types.d.ts +31 -0
  109. package/dist/macros/scoreCard/types.js +15 -0
  110. package/dist/macros/scoreCard/types.js.map +1 -0
  111. package/dist/macros/types.d.ts +25 -0
  112. package/dist/macros/types.js +2 -0
  113. package/dist/macros/types.js.map +1 -0
  114. package/dist/macros/vega/index.d.ts +0 -4
  115. package/dist/macros/vega/index.js.map +1 -1
  116. package/dist/macros/vega/types.d.ts +20 -0
  117. package/dist/macros/vega/types.js +2 -0
  118. package/dist/macros/vega/types.js.map +1 -0
  119. package/dist/macros/vegalite/index.d.ts +0 -4
  120. package/dist/macros/vegalite/index.js.map +1 -1
  121. package/dist/macros/vegalite/types.d.ts +20 -0
  122. package/dist/macros/vegalite/types.js +15 -0
  123. package/dist/macros/vegalite/types.js.map +1 -0
  124. package/dist/macros/xref/index.d.ts +0 -3
  125. package/dist/macros/xref/index.js +5 -14
  126. package/dist/macros/xref/index.js.map +1 -1
  127. package/dist/macros/xref/types.d.ts +19 -0
  128. package/dist/macros/xref/types.js +15 -0
  129. package/dist/macros/xref/types.js.map +1 -0
  130. package/dist/module-manager.js +4 -4
  131. package/dist/module-manager.js.map +1 -1
  132. package/dist/project-settings.js.map +1 -1
  133. package/dist/resources/calculation-resource.d.ts +43 -0
  134. package/dist/resources/calculation-resource.js +75 -0
  135. package/dist/resources/calculation-resource.js.map +1 -0
  136. package/dist/resources/card-type-resource.d.ts +4 -21
  137. package/dist/resources/card-type-resource.js +13 -44
  138. package/dist/resources/card-type-resource.js.map +1 -1
  139. package/dist/resources/create-defaults.d.ts +13 -6
  140. package/dist/resources/create-defaults.js +19 -5
  141. package/dist/resources/create-defaults.js.map +1 -1
  142. package/dist/resources/field-type-resource.d.ts +4 -21
  143. package/dist/resources/field-type-resource.js +14 -38
  144. package/dist/resources/field-type-resource.js.map +1 -1
  145. package/dist/resources/file-resource.d.ts +12 -29
  146. package/dist/resources/file-resource.js +19 -287
  147. package/dist/resources/file-resource.js.map +1 -1
  148. package/dist/resources/folder-resource.d.ts +32 -51
  149. package/dist/resources/folder-resource.js +68 -96
  150. package/dist/resources/folder-resource.js.map +1 -1
  151. package/dist/resources/graph-model-resource.d.ts +5 -33
  152. package/dist/resources/graph-model-resource.js +8 -61
  153. package/dist/resources/graph-model-resource.js.map +1 -1
  154. package/dist/resources/graph-view-resource.d.ts +5 -28
  155. package/dist/resources/graph-view-resource.js +6 -45
  156. package/dist/resources/graph-view-resource.js.map +1 -1
  157. package/dist/resources/link-type-resource.d.ts +4 -21
  158. package/dist/resources/link-type-resource.js +6 -31
  159. package/dist/resources/link-type-resource.js.map +1 -1
  160. package/dist/resources/report-resource.d.ts +5 -17
  161. package/dist/resources/report-resource.js +6 -44
  162. package/dist/resources/report-resource.js.map +1 -1
  163. package/dist/resources/resource-object.d.ts +58 -23
  164. package/dist/resources/resource-object.js +307 -26
  165. package/dist/resources/resource-object.js.map +1 -1
  166. package/dist/resources/template-resource.d.ts +4 -15
  167. package/dist/resources/template-resource.js +10 -25
  168. package/dist/resources/template-resource.js.map +1 -1
  169. package/dist/resources/workflow-resource.d.ts +4 -23
  170. package/dist/resources/workflow-resource.js +12 -38
  171. package/dist/resources/workflow-resource.js.map +1 -1
  172. package/dist/utils/card-utils.d.ts +69 -19
  173. package/dist/utils/card-utils.js +179 -30
  174. package/dist/utils/card-utils.js.map +1 -1
  175. package/dist/utils/clingo-facts.js +11 -3
  176. package/dist/utils/clingo-facts.js.map +1 -1
  177. package/dist/utils/clingo-parser.js +1 -1
  178. package/dist/utils/clingo-parser.js.map +1 -1
  179. package/dist/utils/constants.d.ts +2 -0
  180. package/dist/utils/constants.js +5 -0
  181. package/dist/utils/constants.js.map +1 -1
  182. package/dist/utils/csv.js +1 -1
  183. package/dist/utils/csv.js.map +1 -1
  184. package/dist/utils/error-utils.d.ts +34 -0
  185. package/dist/utils/error-utils.js +56 -0
  186. package/dist/utils/error-utils.js.map +1 -0
  187. package/dist/utils/log-utils.d.ts +0 -27
  188. package/dist/utils/log-utils.js +0 -58
  189. package/dist/utils/log-utils.js.map +1 -1
  190. package/dist/utils/user-preferences.js +6 -3
  191. package/dist/utils/user-preferences.js.map +1 -1
  192. package/package.json +5 -5
  193. package/src/card-metadata-updater.ts +3 -5
  194. package/src/command-handler.ts +14 -19
  195. package/src/command-manager.ts +4 -3
  196. package/src/commands/create.ts +28 -112
  197. package/src/commands/edit.ts +27 -118
  198. package/src/commands/export.ts +8 -29
  199. package/src/commands/fetch.ts +2 -1
  200. package/src/commands/import.ts +4 -6
  201. package/src/commands/move.ts +144 -179
  202. package/src/commands/remove.ts +12 -54
  203. package/src/commands/rename.ts +22 -7
  204. package/src/commands/show.ts +51 -156
  205. package/src/commands/transition.ts +30 -33
  206. package/src/commands/update.ts +27 -9
  207. package/src/commands/validate.ts +22 -37
  208. package/src/containers/card-container.ts +200 -360
  209. package/src/containers/project/calculation-engine.ts +43 -33
  210. package/src/containers/project/card-cache.ts +497 -0
  211. package/src/containers/project/resource-collector.ts +9 -1
  212. package/src/containers/project.ts +533 -328
  213. package/src/containers/template.ts +109 -127
  214. package/src/index.ts +1 -0
  215. package/src/interfaces/folder-content-interfaces.ts +23 -5
  216. package/src/interfaces/macros.ts +2 -0
  217. package/src/interfaces/project-interfaces.ts +19 -10
  218. package/src/interfaces/resource-interfaces.ts +22 -24
  219. package/src/macros/createCards/index.ts +1 -12
  220. package/src/macros/createCards/types.ts +46 -0
  221. package/src/macros/graph/index.ts +3 -7
  222. package/src/macros/graph/types.ts +24 -0
  223. package/src/macros/image/index.ts +50 -61
  224. package/src/macros/image/types.ts +39 -0
  225. package/src/macros/include/index.ts +6 -15
  226. package/src/macros/include/types.ts +32 -0
  227. package/src/macros/percentage/index.ts +1 -7
  228. package/src/macros/percentage/types.ts +32 -0
  229. package/src/macros/report/index.ts +1 -4
  230. package/src/macros/report/types.ts +20 -0
  231. package/src/macros/scoreCard/index.ts +1 -7
  232. package/src/macros/scoreCard/types.ts +32 -0
  233. package/src/macros/types.ts +48 -0
  234. package/src/macros/vega/index.ts +1 -4
  235. package/src/macros/vega/types.ts +21 -0
  236. package/src/macros/vegalite/index.ts +1 -4
  237. package/src/macros/vegalite/types.ts +22 -0
  238. package/src/macros/xref/index.ts +6 -20
  239. package/src/macros/xref/types.ts +20 -0
  240. package/src/module-manager.ts +5 -5
  241. package/src/project-settings.ts +1 -1
  242. package/src/resources/calculation-resource.ts +101 -0
  243. package/src/resources/card-type-resource.ts +24 -59
  244. package/src/resources/create-defaults.ts +21 -5
  245. package/src/resources/field-type-resource.ts +22 -51
  246. package/src/resources/file-resource.ts +27 -403
  247. package/src/resources/folder-resource.ts +99 -125
  248. package/src/resources/graph-model-resource.ts +17 -74
  249. package/src/resources/graph-view-resource.ts +14 -54
  250. package/src/resources/link-type-resource.ts +13 -40
  251. package/src/resources/report-resource.ts +17 -57
  252. package/src/resources/resource-object.ts +454 -39
  253. package/src/resources/template-resource.ts +16 -29
  254. package/src/resources/workflow-resource.ts +26 -50
  255. package/src/utils/card-utils.ts +217 -31
  256. package/src/utils/clingo-facts.ts +13 -3
  257. package/src/utils/clingo-parser.ts +1 -1
  258. package/src/utils/constants.ts +7 -0
  259. package/src/utils/csv.ts +1 -1
  260. package/src/utils/error-utils.ts +62 -0
  261. package/src/utils/log-utils.ts +0 -68
  262. package/src/utils/user-preferences.ts +7 -3
@@ -12,30 +12,29 @@
12
12
  */
13
13
 
14
14
  // node
15
- import { existsSync, readFileSync } from 'node:fs';
15
+ import { readFileSync } from 'node:fs';
16
16
  import { homedir } from 'node:os';
17
17
  import { join, resolve } from 'node:path';
18
18
  import { spawn } from 'node:child_process';
19
- import { readFile, writeFile } from 'node:fs/promises';
19
+ import { writeFile } from 'node:fs/promises';
20
20
 
21
21
  import { MODULE_LIST_FULL_PATH } from './fetch.js';
22
22
 
23
- import mime from 'mime-types';
24
-
25
23
  import type { attachmentPayload } from '../interfaces/request-status-interfaces.js';
26
24
  import type {
27
- CardAttachment,
28
25
  Card,
26
+ CardAttachment,
29
27
  CardListContainer,
30
- ModuleContent,
28
+ CardLocation,
29
+ CardWithChildrenCards,
30
+ Context,
31
+ FetchCardDetails,
32
+ FileContentType,
31
33
  HubSetting,
34
+ ModuleContent,
32
35
  ModuleSettingFromHub,
33
- ProjectFetchCardDetails,
34
36
  ProjectMetadata,
35
37
  Resource,
36
- CardLocation,
37
- Context,
38
- ResourceFolderType,
39
38
  } from '../interfaces/project-interfaces.js';
40
39
  import type {
41
40
  CardType,
@@ -44,21 +43,16 @@ import type {
44
43
  Workflow,
45
44
  } from '../interfaces/resource-interfaces.js';
46
45
  import { Project, type ResourcesFrom } from '../containers/project.js';
47
- import {
48
- type ResourceName,
49
- resourceName,
50
- resourceNameToPath,
51
- resourceNameToString,
52
- } from '../utils/resource-utils.js';
46
+ import { type ResourceName, resourceName } from '../utils/resource-utils.js';
53
47
  import { TemplateResource } from '../resources/template-resource.js';
54
48
  import { UserPreferences } from '../utils/user-preferences.js';
55
49
 
56
50
  import ReportMacro from '../macros/report/index.js';
57
51
  import TaskQueue from '../macros/task-queue.js';
58
52
  import { evaluateMacros } from '../macros/index.js';
59
- import { FolderResource } from '../resources/folder-resource.js';
60
53
  import { readJsonFile } from '../utils/json.js';
61
54
  import { getChildLogger } from '../utils/log-utils.js';
55
+ import { buildCardHierarchy } from '../utils/card-utils.js';
62
56
 
63
57
  /**
64
58
  * Show command.
@@ -95,28 +89,13 @@ export class Show {
95
89
  if (card.metadata?.labels) {
96
90
  labels.push(...card.metadata.labels);
97
91
  }
98
- // Recursively collect labels from subcards, if they exist
99
- if (card.children) {
100
- labels.push(...this.collectLabels(card.children));
101
- }
102
92
  return labels;
103
93
  }, []);
104
94
  };
105
95
 
106
96
  // Returns attachment details
107
- private async getAttachment(cardKey: string, filename: string) {
108
- const details = {
109
- content: false,
110
- metadata: true,
111
- children: false,
112
- parent: false,
113
- attachments: true,
114
- };
115
- const card = await this.project.cardDetailsById(cardKey, details);
116
- if (card === undefined) {
117
- throw new Error(`Card '${cardKey}' does not exist in the project`);
118
- }
119
-
97
+ private getAttachment(cardKey: string, filename: string) {
98
+ const card = this.project.findCard(cardKey);
120
99
  const attachment =
121
100
  card.attachments?.find((a) => a.fileName === filename) ?? undefined;
122
101
  return attachment;
@@ -142,17 +121,20 @@ export class Show {
142
121
  * @returns all template cards in a project.
143
122
  */
144
123
  public async showAllTemplateCards(): Promise<
145
- { name: string; cards: Card[] }[]
124
+ { name: string; cards: CardWithChildrenCards[] }[]
146
125
  > {
147
126
  return Promise.all(
148
- (await this.project.templates()).map(async (template) => {
127
+ (await this.project.templates()).map((template) => {
149
128
  const templateResource = new TemplateResource(
150
129
  this.project,
151
130
  resourceName(template.name),
152
131
  );
132
+ const cards = templateResource.templateObject().listCards();
133
+ const buildCards = buildCardHierarchy(cards);
134
+
153
135
  return {
154
136
  name: template.name,
155
- cards: await templateResource.templateObject().showTemplateCards(),
137
+ cards: buildCards,
156
138
  };
157
139
  }),
158
140
  );
@@ -163,20 +145,8 @@ export class Show {
163
145
  * @returns array of card attachments
164
146
  */
165
147
  public async showAttachments(): Promise<CardAttachment[]> {
166
- const attachments: CardAttachment[] = await this.project.attachments();
167
- const templateAttachments: CardAttachment[] = [];
168
- const templates = await this.project.templates();
169
- for (const template of templates) {
170
- const templateResource = new TemplateResource(
171
- this.project,
172
- resourceName(template.name),
173
- );
174
- const templateObject = templateResource.templateObject();
175
- if (templateObject) {
176
- templateAttachments.push(...(await templateObject.attachments()));
177
- }
178
- }
179
-
148
+ const attachments = this.project.attachments();
149
+ const templateAttachments = await this.project.attachmentsFromTemplates();
180
150
  attachments.push(...templateAttachments);
181
151
  return attachments;
182
152
  }
@@ -187,32 +157,22 @@ export class Show {
187
157
  * @param filename attachment filename
188
158
  * @returns attachment details
189
159
  */
190
- public async showAttachment(
191
- cardKey: string,
192
- filename: string,
193
- ): Promise<attachmentPayload> {
160
+ public showAttachment(cardKey: string, filename: string): attachmentPayload {
194
161
  if (!cardKey) {
195
162
  throw new Error(`Mandatory parameter 'cardKey' missing`);
196
163
  }
197
164
 
198
- const attachment = await this.getAttachment(cardKey, filename);
165
+ const attachment = this.getAttachment(cardKey, filename);
199
166
 
200
- let attachmentPath: string = '';
201
- if (attachment) {
202
- attachmentPath = `${attachment.path}/${attachment.fileName}`;
203
- }
204
-
205
- if (!attachment || !existsSync(attachmentPath)) {
167
+ if (!attachment) {
206
168
  throw new Error(`Attachment '${filename}' not found for card ${cardKey}`);
207
- } else {
208
- const fileBuffer = readFileSync(attachmentPath);
209
- let mimeType = mime.lookup(attachmentPath);
210
- if (mimeType === false) {
211
- mimeType = 'application/octet-stream';
212
- }
213
- const payload: attachmentPayload = { fileBuffer, mimeType };
214
- return payload;
215
169
  }
170
+
171
+ const attachmentPath = `${attachment.path}/${attachment.fileName}`;
172
+ const fileBuffer = readFileSync(attachmentPath);
173
+ const mimeType = attachment.mimeType || 'application/octet-stream';
174
+ const payload: attachmentPayload = { fileBuffer, mimeType };
175
+ return payload;
216
176
  }
217
177
 
218
178
  /**
@@ -227,7 +187,7 @@ export class Show {
227
187
  filename: string,
228
188
  waitDelay: number = 1000,
229
189
  ) {
230
- const attachment = await this.getAttachment(cardKey, filename);
190
+ const attachment = this.getAttachment(cardKey, filename);
231
191
 
232
192
  if (!attachment) {
233
193
  throw new Error(`Attachment '${filename}' not found for card ${cardKey}`);
@@ -274,22 +234,29 @@ export class Show {
274
234
  /**
275
235
  * Shows details of a particular card (template card, or project card)
276
236
  * @note Note that parameter 'cardKey' is optional due to technical limitations of class calling this class. It must be defined to get valid results.
277
- * @param details card details to show
278
237
  * @param cardKey card key to find
238
+ * @param contentType Content format in which content is to be shown
279
239
  * @returns card details
280
240
  */
281
- public async showCardDetails(
282
- details: ProjectFetchCardDetails,
241
+ public showCardDetails(
283
242
  cardKey?: string,
284
- ): Promise<Card> {
243
+ contentType?: FileContentType,
244
+ ): Card {
285
245
  if (!cardKey) {
286
246
  throw new Error(`Mandatory parameter 'cardKey' missing`);
287
247
  }
288
- const cardDetails = await this.project.cardDetailsById(cardKey, details);
289
- if (cardDetails === undefined) {
290
- throw new Error(`Card '${cardKey}' does not exist in the project`);
248
+ // todo: Make a constant about this
249
+ const details: FetchCardDetails = {
250
+ parent: true,
251
+ metadata: true,
252
+ children: true,
253
+ attachments: true,
254
+ content: true,
255
+ };
256
+ if (contentType) {
257
+ details.contentType = contentType;
291
258
  }
292
- return cardDetails;
259
+ return this.project.findCard(cardKey, details);
293
260
  }
294
261
 
295
262
  /**
@@ -330,62 +297,6 @@ export class Show {
330
297
  return results.filter((item) => item);
331
298
  }
332
299
 
333
- /**
334
- * Shows the content of a file in a resource.
335
- * TODO: To be removed
336
- * @deprecated
337
- * @param resourceName Name of the resource.
338
- * @param fileName Name of the file to show.
339
- * @returns the content of the file.
340
- */
341
- public async showFile(
342
- resourceName: ResourceName,
343
- fileName: string,
344
- ): Promise<string> {
345
- const resourceNameStr = resourceNameToString(resourceName);
346
- if (
347
- !(await this.project.resourceExists(
348
- resourceName.type as ResourceFolderType,
349
- resourceNameStr,
350
- ))
351
- ) {
352
- throw new Error(
353
- `Resource '${resourceNameStr}' does not exist in the project`,
354
- );
355
- }
356
- const resource = Project.resourceObject(this.project, resourceName);
357
- if (!(resource instanceof FolderResource)) {
358
- throw new Error(`Resource '${resourceNameStr}' is not a folder resource`);
359
- }
360
- return resource.showFile(fileName);
361
- }
362
-
363
- /**
364
- * Shows all file names in a folder resource.
365
- * TODO: To be removed
366
- * @deprecated
367
- * @param resourceName Name of the resource.
368
- * @returns all file names in the resource.
369
- */
370
- public async showFileNames(resourceName: ResourceName): Promise<string[]> {
371
- const resourceNameStr = resourceNameToString(resourceName);
372
- if (
373
- !(await this.project.resourceExists(
374
- resourceName.type as ResourceFolderType,
375
- resourceNameStr,
376
- ))
377
- ) {
378
- throw new Error(
379
- `Resource '${resourceNameStr}' does not exist in the project`,
380
- );
381
- }
382
- const resource = Project.resourceObject(this.project, resourceName);
383
- if (!(resource instanceof FolderResource)) {
384
- throw new Error(`Resource '${resourceNameStr}' is not a folder resource`);
385
- }
386
- return resource.showFileNames();
387
- }
388
-
389
300
  /**
390
301
  * Shows importable modules.
391
302
  * @param showAll - When true, shows all importable modules, even if they have already been imported
@@ -437,12 +348,9 @@ export class Show {
437
348
  * Returns all unique labels in a project
438
349
  * @returns labels in a list
439
350
  */
440
- public async showLabels(): Promise<string[]> {
441
- const cards = await this.project.showProjectCards();
442
- const templateCards = await this.project.allTemplateCards({
443
- metadata: true,
444
- children: true,
445
- });
351
+ public showLabels(): string[] {
352
+ const cards = this.project.showProjectCards();
353
+ const templateCards = this.project.allTemplateCards();
446
354
 
447
355
  const labels = this.collectLabels([...cards, ...templateCards]);
448
356
  return Array.from(new Set(labels));
@@ -480,12 +388,10 @@ export class Show {
480
388
 
481
389
  /**
482
390
  * Returns all project cards in the project. Cards don't have content and nor metadata.
483
- * @note AppUi uses this method.
484
391
  * @returns array of cards
485
392
  */
486
- public async showProjectCards(): Promise<Card[]> {
487
- const projectCards = await this.project.showProjectCards();
488
- return projectCards;
393
+ public showProjectCards(): Card[] {
394
+ return this.project.showProjectCards();
489
395
  }
490
396
 
491
397
  /**
@@ -571,17 +477,6 @@ export class Show {
571
477
  name: string,
572
478
  showUse: boolean = false,
573
479
  ): Promise<ResourceContent | undefined> {
574
- // TODO: remove this workaround once calculations are implemented as a resource class
575
- if (resourceName(name).type === 'calculations') {
576
- const nameObj = resourceName(name);
577
- const path = resourceNameToPath(this.project, nameObj, '.lp');
578
- return {
579
- name,
580
- displayName: nameObj.identifier,
581
- calculation: await readFile(path, 'utf-8'),
582
- };
583
- }
584
-
585
480
  const strictNameCheck = true;
586
481
  const resource = Project.resourceObject(
587
482
  this.project,
@@ -29,21 +29,15 @@ export class Transition {
29
29
  * @param transition which transition to do
30
30
  */
31
31
  public async cardTransition(cardKey: string, transition: WorkflowState) {
32
- // Card details
33
- const details = await this.project.cardDetailsById(cardKey, {
34
- metadata: true,
35
- });
36
- if (!details || !details.metadata) {
37
- throw new Error(`Card ${cardKey} does not exist in the project`);
38
- }
32
+ const card = this.project.findCard(cardKey);
39
33
 
40
34
  // Card type
41
- const cardType = await this.project.resource<CardType>(
42
- details.metadata?.cardType,
35
+ const cardType = this.project.resource<CardType>(
36
+ card.metadata?.cardType || '',
43
37
  );
44
38
  if (cardType === undefined) {
45
39
  throw new Error(
46
- `Card's card type '${details.metadata?.cardType}' does not exist in the project`,
40
+ `Card's card type '${card.metadata?.cardType}' does not exist in the project`,
47
41
  );
48
42
  }
49
43
 
@@ -58,13 +52,13 @@ export class Transition {
58
52
  // Check that the state transition can be made "from".
59
53
  const foundFrom = workflow.transitions.find(
60
54
  (item) =>
61
- (details.metadata &&
62
- item.fromState.includes(details.metadata?.workflowState)) ||
55
+ (card.metadata &&
56
+ item.fromState.includes(card.metadata?.workflowState)) ||
63
57
  item.fromState.includes('*'),
64
58
  );
65
59
  if (!foundFrom) {
66
60
  throw new Error(
67
- `Card's workflow '${cardType.workflow}' does not contain transition from card's current state '${details.metadata?.workflowState}'`,
61
+ `Card's workflow '${cardType.workflow}' does not contain transition from card's current state '${card.metadata?.workflowState}'`,
68
62
  );
69
63
  }
70
64
 
@@ -80,36 +74,39 @@ export class Transition {
80
74
 
81
75
  if (
82
76
  !(
83
- found.fromState.includes(details.metadata?.workflowState) ||
77
+ (card.metadata?.workflowState &&
78
+ found.fromState.includes(card.metadata.workflowState)) ||
84
79
  found.fromState.includes('*')
85
80
  )
86
81
  ) {
87
82
  throw new Error(
88
- `Card's workflow '${cardType.workflow}' does not contain state transition from state '${details.metadata?.workflowState}' for '${transition.name}`,
83
+ `Card's workflow '${cardType.workflow}' does not contain state transition from state '${card.metadata?.workflowState}' for '${transition.name}`,
89
84
  );
90
85
  }
91
86
 
92
87
  const actionGuard = new ActionGuard(this.project.calculationEngine);
93
88
  await actionGuard.checkPermission('transition', cardKey, transition.name);
94
89
 
95
- details.metadata.workflowState = found.toState;
96
- details.metadata.lastUpdated = new Date().toISOString();
97
- details.metadata.lastTransitioned = new Date().toISOString();
98
- return this.project
99
- .updateCardMetadata(details, details.metadata)
100
- .then(async () => this.transitionChangesQuery(cardKey, transition.name))
101
- .then(async (queryResult) => {
102
- if (
103
- !queryResult ||
104
- queryResult.at(0) === undefined ||
105
- queryResult.at(0)?.updateFields === undefined
106
- ) {
107
- return;
108
- }
109
- const fieldsToUpdate = queryResult.at(0)!.updateFields;
110
- return CardMetadataUpdater.apply(this.project, fieldsToUpdate);
111
- })
112
- .catch((error) => console.error(error));
90
+ if (card.metadata) {
91
+ card.metadata.workflowState = found.toState;
92
+ card.metadata.lastUpdated = new Date().toISOString();
93
+ card.metadata.lastTransitioned = new Date().toISOString();
94
+ return this.project
95
+ .updateCardMetadata(card, card.metadata)
96
+ .then(async () => this.transitionChangesQuery(cardKey, transition.name))
97
+ .then(async (queryResult) => {
98
+ if (
99
+ !queryResult ||
100
+ queryResult.at(0) === undefined ||
101
+ queryResult.at(0)?.updateFields === undefined
102
+ ) {
103
+ return;
104
+ }
105
+ const fieldsToUpdate = queryResult.at(0)!.updateFields;
106
+ return CardMetadataUpdater.apply(this.project, fieldsToUpdate);
107
+ })
108
+ .catch((error) => console.error(error));
109
+ }
113
110
  }
114
111
 
115
112
  // Wrapper to run onTransition query.
@@ -21,6 +21,7 @@ import type {
21
21
  } from '../resources/resource-object.js';
22
22
  import { Project } from '../containers/project.js';
23
23
  import { resourceName } from '../utils/resource-utils.js';
24
+ import type { UpdateKey } from '../interfaces/resource-interfaces.js';
24
25
 
25
26
  /**
26
27
  * Class that handles 'update' commands.
@@ -32,7 +33,7 @@ export class Update {
32
33
  * Updates single resource property.
33
34
  * @param name Name of the resource to operate on.
34
35
  * @param operation Operation to perform ('add', 'remove', 'change', 'rank')
35
- * @param key Property to change in resource JSON
36
+ * @param key Property to change in resource JSON. If content, content/<property>
36
37
  * @param value Value for 'key'
37
38
  * @param optionalDetail Additional detail needed for some operations. For example, 'update' needs a new value.
38
39
  * @param mappingTable Optional mapping table for workflow state transitions (only used for workflow changes)
@@ -75,26 +76,43 @@ export class Update {
75
76
  ? optionalDetail
76
77
  : undefined;
77
78
  }
79
+ const splitKey = key.split('/');
80
+ if (splitKey.length !== 1 && splitKey.length !== 2) {
81
+ throw new Error(
82
+ `Invalid key format: ${key}. Use 'property' or 'content/<property>'.`,
83
+ );
84
+ }
78
85
 
79
- await this.applyResourceOperation(name, key, op);
86
+ if (splitKey.length === 2 && splitKey[0] !== 'content') {
87
+ throw new Error(
88
+ `Invalid key format: ${key}. When using 'content', always use as 'content/<property>'.`,
89
+ );
90
+ }
91
+ const [parsedKey, subKey] = splitKey;
92
+ if (parsedKey === 'content') {
93
+ await this.applyResourceOperation(name, { key: parsedKey, subKey }, op);
94
+ } else {
95
+ await this.applyResourceOperation(name, { key: parsedKey }, op);
96
+ }
80
97
  }
81
98
 
82
99
  /**
83
100
  * Update single resource property
84
101
  * This is similar to updateValue, but allows the operation to be fully specified
85
102
  * @param name Name of the resource to operate on.
86
- * @param key Property to change in resource JSON
103
+ * @param updateKey Property to change in resource or in resource content.
87
104
  * @param operation The full operation object
88
105
  * @template Type Type of the target of the operation
89
106
  * @template T Type of operation ('add', 'remove', 'change', 'rank')
107
+ * @template K Type of the key to change
90
108
  */
91
- public async applyResourceOperation<Type, T extends UpdateOperations>(
92
- name: string,
93
- key: string,
94
- operation: OperationFor<Type, T>,
95
- ) {
109
+ public async applyResourceOperation<
110
+ Type,
111
+ T extends UpdateOperations,
112
+ K extends string,
113
+ >(name: string, updateKey: UpdateKey<K>, operation: OperationFor<Type, T>) {
96
114
  const resource = Project.resourceObject(this.project, resourceName(name));
97
- await resource?.update(key, operation);
115
+ await resource?.update(updateKey, operation);
98
116
  this.project.collectLocalResources();
99
117
  }
100
118
  }
@@ -36,7 +36,7 @@ import type {
36
36
  ResourceContent,
37
37
  Workflow,
38
38
  } from '../interfaces/resource-interfaces.js';
39
- import { errorFunction } from '../utils/log-utils.js';
39
+ import { errorFunction } from '../utils/error-utils.js';
40
40
  import { isTemplateCard } from '../utils/card-utils.js';
41
41
  import { pathExists } from '../utils/file-utils.js';
42
42
  import { Project } from '../containers/project.js';
@@ -169,21 +169,16 @@ export class Validate {
169
169
 
170
170
  // Puts resource to a local cache if found and returns the resource.
171
171
  // If value is already cached, returns from cache.
172
- private async getAndCacheResource<Type>(
172
+ private getAndCacheResource<Type>(
173
173
  project: Project,
174
174
  cachedValues: Map<string, Type>,
175
175
  valueName: string,
176
- ): Promise<Type | undefined> {
177
- return (
178
- cachedValues.get(valueName) ||
179
- project.resource<Type>(valueName).then((resource) => {
180
- if (!resource) {
181
- return undefined;
182
- }
183
- cachedValues.set(valueName, resource);
184
- return resource;
185
- })
186
- );
176
+ ): Type | undefined {
177
+ const resource = project.resource<Type>(valueName);
178
+ if (resource) {
179
+ cachedValues.set(valueName, resource);
180
+ }
181
+ return resource;
187
182
  }
188
183
 
189
184
  private parseValidatorMessage(errorObject: object[]): string {
@@ -395,7 +390,7 @@ export class Validate {
395
390
  const errors: string[] = [];
396
391
  if (cardType && fieldArray) {
397
392
  const validationPromises = fieldArray.map(async (field) => {
398
- const fieldType = await this.getAndCacheResource(
393
+ const fieldType = this.getAndCacheResource(
399
394
  project,
400
395
  this.validatedFieldTypes,
401
396
  field,
@@ -550,6 +545,7 @@ export class Validate {
550
545
  } else {
551
546
  const errorMsg: string[] = [];
552
547
  const project = projectFn();
548
+ await project.populateCaches();
553
549
 
554
550
  // Then, validate that each 'contentSchema' children as well.
555
551
  const result = await this.readAndValidateContentFiles(
@@ -561,8 +557,8 @@ export class Validate {
561
557
  }
562
558
 
563
559
  // Finally, validate that each card is correct
564
- const cards = await project.cards();
565
- cards.push(...(await project.allTemplateCards()));
560
+ const cards = project.cards();
561
+ cards.push(...project.allTemplateCards());
566
562
 
567
563
  const cardIds = new Map<string, number>();
568
564
 
@@ -574,12 +570,8 @@ export class Validate {
574
570
  }
575
571
 
576
572
  if (card.metadata) {
577
- // validate card's workflow
578
573
  if (!isTemplateCard(card)) {
579
- const validWorkflow = await this.validateWorkflowState(
580
- project,
581
- card,
582
- );
574
+ const validWorkflow = this.validateWorkflowState(project, card);
583
575
  if (validWorkflow.length !== 0) {
584
576
  errorMsg.push(validWorkflow);
585
577
  }
@@ -604,7 +596,7 @@ export class Validate {
604
596
  await evaluateMacros(card.content, {
605
597
  context: 'localApp',
606
598
  mode: 'validate',
607
- project,
599
+ project: project,
608
600
  cardKey: card.key,
609
601
  });
610
602
  }
@@ -673,19 +665,15 @@ export class Validate {
673
665
  * @param prefixes currently used project prefixes
674
666
  * @returns resource name as valid resource name; throws in error cases.
675
667
  */
676
- public async validResourceName(
668
+ public validResourceName(
677
669
  resourceType: ResourceTypes,
678
670
  name: string,
679
671
  prefixes: string[],
680
- ): Promise<string> {
672
+ ): string {
681
673
  const resource = resourceName(name);
682
674
  resource.type = resource.type ? resource.type : resourceType;
683
- // a bit shaky way to ensure that prefix is set; first of the project prefixes should be the actual project prefix.
684
675
  if (resource.prefix === '') {
685
- resource.prefix = prefixes.length > 0 ? prefixes.at(0) || '' : '';
686
- if (resource.prefix === '') {
687
- throw new Error(`Project prefix cannot be empty string`);
688
- }
676
+ throw new Error(`Project prefix cannot be empty string`);
689
677
  }
690
678
  if (!prefixes.includes(resource.prefix)) {
691
679
  throw new Error(
@@ -735,7 +723,7 @@ export class Validate {
735
723
  );
736
724
  }
737
725
 
738
- const cardType = await this.getAndCacheResource(
726
+ const cardType = this.getAndCacheResource(
739
727
  project,
740
728
  this.validatedCardTypes,
741
729
  card.metadata?.cardType,
@@ -836,7 +824,7 @@ export class Validate {
836
824
  * Validates the labels of a card
837
825
  * @param card card to validate. Card must have metadata.
838
826
  */
839
- public async validateCardLabels(card: Card): Promise<string> {
827
+ public validateCardLabels(card: Card): string {
840
828
  const validationErrors: string[] = [];
841
829
  if (!card.metadata) {
842
830
  validationErrors.push(
@@ -870,10 +858,7 @@ export class Validate {
870
858
  * @param card Card object to validate
871
859
  * @returns string containing all validation errors
872
860
  */
873
- public async validateWorkflowState(
874
- project: Project,
875
- card: Card,
876
- ): Promise<string> {
861
+ public validateWorkflowState(project: Project, card: Card): string {
877
862
  const validationErrors: string[] = [];
878
863
 
879
864
  if (!card.metadata) {
@@ -883,7 +868,7 @@ export class Validate {
883
868
  }
884
869
 
885
870
  // Use caches for cardTypes and workflows, to avoid re-reading the same JSON files multiple times.
886
- const cardType = await this.getAndCacheResource(
871
+ const cardType = this.getAndCacheResource(
887
872
  project,
888
873
  this.validatedCardTypes,
889
874
  card.metadata?.cardType || '',
@@ -901,7 +886,7 @@ export class Validate {
901
886
  return validationErrors.join('\n');
902
887
  }
903
888
 
904
- const workflow = await this.getAndCacheResource(
889
+ const workflow = this.getAndCacheResource(
905
890
  project,
906
891
  this.validatedWorkflows,
907
892
  cardType.workflow,