@cyberismo/data-handler 0.0.14 → 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 (240) 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 +10 -16
  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.js +13 -59
  9. package/dist/commands/create.js.map +1 -1
  10. package/dist/commands/edit.d.ts +1 -15
  11. package/dist/commands/edit.js +15 -89
  12. package/dist/commands/edit.js.map +1 -1
  13. package/dist/commands/export.js +4 -17
  14. package/dist/commands/export.js.map +1 -1
  15. package/dist/commands/import.js +3 -5
  16. package/dist/commands/import.js.map +1 -1
  17. package/dist/commands/move.d.ts +1 -2
  18. package/dist/commands/move.js +108 -146
  19. package/dist/commands/move.js.map +1 -1
  20. package/dist/commands/remove.js +9 -44
  21. package/dist/commands/remove.js.map +1 -1
  22. package/dist/commands/rename.js +2 -7
  23. package/dist/commands/rename.js.map +1 -1
  24. package/dist/commands/show.d.ts +7 -25
  25. package/dist/commands/show.js +38 -102
  26. package/dist/commands/show.js.map +1 -1
  27. package/dist/commands/transition.js +27 -30
  28. package/dist/commands/transition.js.map +1 -1
  29. package/dist/commands/update.d.ts +5 -3
  30. package/dist/commands/update.js +19 -5
  31. package/dist/commands/update.js.map +1 -1
  32. package/dist/commands/validate.d.ts +3 -3
  33. package/dist/commands/validate.js +19 -26
  34. package/dist/commands/validate.js.map +1 -1
  35. package/dist/containers/card-container.d.ts +87 -24
  36. package/dist/containers/card-container.js +183 -279
  37. package/dist/containers/card-container.js.map +1 -1
  38. package/dist/containers/project/calculation-engine.d.ts +6 -0
  39. package/dist/containers/project/calculation-engine.js +19 -12
  40. package/dist/containers/project/calculation-engine.js.map +1 -1
  41. package/dist/containers/project/card-cache.d.ts +146 -0
  42. package/dist/containers/project/card-cache.js +411 -0
  43. package/dist/containers/project/card-cache.js.map +1 -0
  44. package/dist/containers/project/resource-collector.d.ts +24 -1
  45. package/dist/containers/project/resource-collector.js +8 -1
  46. package/dist/containers/project/resource-collector.js.map +1 -1
  47. package/dist/containers/project.d.ts +117 -83
  48. package/dist/containers/project.js +418 -252
  49. package/dist/containers/project.js.map +1 -1
  50. package/dist/containers/template.d.ts +15 -31
  51. package/dist/containers/template.js +97 -104
  52. package/dist/containers/template.js.map +1 -1
  53. package/dist/index.d.ts +1 -0
  54. package/dist/index.js +1 -0
  55. package/dist/index.js.map +1 -1
  56. package/dist/interfaces/folder-content-interfaces.d.ts +2 -1
  57. package/dist/interfaces/folder-content-interfaces.js.map +1 -1
  58. package/dist/interfaces/macros.d.ts +1 -0
  59. package/dist/interfaces/macros.js +1 -1
  60. package/dist/interfaces/macros.js.map +1 -1
  61. package/dist/interfaces/project-interfaces.d.ts +5 -1
  62. package/dist/interfaces/project-interfaces.js.map +1 -1
  63. package/dist/interfaces/resource-interfaces.d.ts +11 -21
  64. package/dist/interfaces/resource-interfaces.js +3 -0
  65. package/dist/interfaces/resource-interfaces.js.map +1 -1
  66. package/dist/macros/common.d.ts +10 -10
  67. package/dist/macros/createCards/index.d.ts +0 -13
  68. package/dist/macros/createCards/index.js.map +1 -1
  69. package/dist/macros/createCards/types.d.ts +44 -0
  70. package/dist/macros/createCards/types.js +15 -0
  71. package/dist/macros/createCards/types.js.map +1 -0
  72. package/dist/macros/graph/index.d.ts +2 -6
  73. package/dist/macros/graph/index.js +2 -2
  74. package/dist/macros/graph/index.js.map +1 -1
  75. package/dist/macros/graph/types.d.ts +23 -0
  76. package/dist/macros/graph/types.js +15 -0
  77. package/dist/macros/graph/types.js.map +1 -0
  78. package/dist/macros/image/index.d.ts +8 -16
  79. package/dist/macros/image/index.js +36 -33
  80. package/dist/macros/image/index.js.map +1 -1
  81. package/dist/macros/image/types.d.ts +38 -0
  82. package/dist/macros/image/types.js +15 -0
  83. package/dist/macros/image/types.js.map +1 -0
  84. package/dist/macros/include/index.d.ts +1 -6
  85. package/dist/macros/include/index.js +4 -7
  86. package/dist/macros/include/index.js.map +1 -1
  87. package/dist/macros/include/types.d.ts +31 -0
  88. package/dist/macros/include/types.js +15 -0
  89. package/dist/macros/include/types.js.map +1 -0
  90. package/dist/macros/percentage/index.d.ts +0 -6
  91. package/dist/macros/percentage/index.js.map +1 -1
  92. package/dist/macros/percentage/types.d.ts +31 -0
  93. package/dist/macros/percentage/types.js +15 -0
  94. package/dist/macros/percentage/types.js.map +1 -0
  95. package/dist/macros/report/index.d.ts +0 -3
  96. package/dist/macros/report/index.js.map +1 -1
  97. package/dist/macros/report/types.d.ts +19 -0
  98. package/dist/macros/report/types.js +15 -0
  99. package/dist/macros/report/types.js.map +1 -0
  100. package/dist/macros/scoreCard/index.d.ts +0 -6
  101. package/dist/macros/scoreCard/index.js.map +1 -1
  102. package/dist/macros/scoreCard/types.d.ts +31 -0
  103. package/dist/macros/scoreCard/types.js +15 -0
  104. package/dist/macros/scoreCard/types.js.map +1 -0
  105. package/dist/macros/types.d.ts +25 -0
  106. package/dist/macros/types.js +2 -0
  107. package/dist/macros/types.js.map +1 -0
  108. package/dist/macros/vega/index.d.ts +0 -4
  109. package/dist/macros/vega/index.js.map +1 -1
  110. package/dist/macros/vega/types.d.ts +20 -0
  111. package/dist/macros/vega/types.js +2 -0
  112. package/dist/macros/vega/types.js.map +1 -0
  113. package/dist/macros/vegalite/index.d.ts +0 -4
  114. package/dist/macros/vegalite/index.js.map +1 -1
  115. package/dist/macros/vegalite/types.d.ts +20 -0
  116. package/dist/macros/vegalite/types.js +15 -0
  117. package/dist/macros/vegalite/types.js.map +1 -0
  118. package/dist/macros/xref/index.d.ts +0 -3
  119. package/dist/macros/xref/index.js +5 -14
  120. package/dist/macros/xref/index.js.map +1 -1
  121. package/dist/macros/xref/types.d.ts +19 -0
  122. package/dist/macros/xref/types.js +15 -0
  123. package/dist/macros/xref/types.js.map +1 -0
  124. package/dist/module-manager.js +4 -4
  125. package/dist/module-manager.js.map +1 -1
  126. package/dist/project-settings.js.map +1 -1
  127. package/dist/resources/calculation-resource.d.ts +4 -32
  128. package/dist/resources/calculation-resource.js +0 -55
  129. package/dist/resources/calculation-resource.js.map +1 -1
  130. package/dist/resources/card-type-resource.d.ts +4 -21
  131. package/dist/resources/card-type-resource.js +13 -44
  132. package/dist/resources/card-type-resource.js.map +1 -1
  133. package/dist/resources/field-type-resource.d.ts +4 -21
  134. package/dist/resources/field-type-resource.js +14 -38
  135. package/dist/resources/field-type-resource.js.map +1 -1
  136. package/dist/resources/file-resource.d.ts +12 -29
  137. package/dist/resources/file-resource.js +19 -293
  138. package/dist/resources/file-resource.js.map +1 -1
  139. package/dist/resources/folder-resource.d.ts +31 -50
  140. package/dist/resources/folder-resource.js +68 -96
  141. package/dist/resources/folder-resource.js.map +1 -1
  142. package/dist/resources/graph-model-resource.d.ts +5 -33
  143. package/dist/resources/graph-model-resource.js +8 -61
  144. package/dist/resources/graph-model-resource.js.map +1 -1
  145. package/dist/resources/graph-view-resource.d.ts +5 -28
  146. package/dist/resources/graph-view-resource.js +6 -45
  147. package/dist/resources/graph-view-resource.js.map +1 -1
  148. package/dist/resources/link-type-resource.d.ts +4 -21
  149. package/dist/resources/link-type-resource.js +6 -31
  150. package/dist/resources/link-type-resource.js.map +1 -1
  151. package/dist/resources/report-resource.d.ts +5 -17
  152. package/dist/resources/report-resource.js +6 -44
  153. package/dist/resources/report-resource.js.map +1 -1
  154. package/dist/resources/resource-object.d.ts +58 -23
  155. package/dist/resources/resource-object.js +293 -24
  156. package/dist/resources/resource-object.js.map +1 -1
  157. package/dist/resources/template-resource.d.ts +4 -15
  158. package/dist/resources/template-resource.js +10 -25
  159. package/dist/resources/template-resource.js.map +1 -1
  160. package/dist/resources/workflow-resource.d.ts +4 -23
  161. package/dist/resources/workflow-resource.js +12 -38
  162. package/dist/resources/workflow-resource.js.map +1 -1
  163. package/dist/utils/card-utils.d.ts +69 -19
  164. package/dist/utils/card-utils.js +179 -30
  165. package/dist/utils/card-utils.js.map +1 -1
  166. package/dist/utils/clingo-facts.js +11 -3
  167. package/dist/utils/clingo-facts.js.map +1 -1
  168. package/dist/utils/clingo-parser.js +1 -1
  169. package/dist/utils/clingo-parser.js.map +1 -1
  170. package/dist/utils/constants.d.ts +2 -0
  171. package/dist/utils/constants.js +4 -0
  172. package/dist/utils/constants.js.map +1 -1
  173. package/dist/utils/csv.js +1 -1
  174. package/dist/utils/csv.js.map +1 -1
  175. package/package.json +5 -5
  176. package/src/card-metadata-updater.ts +3 -5
  177. package/src/command-handler.ts +11 -18
  178. package/src/command-manager.ts +4 -3
  179. package/src/commands/create.ts +17 -83
  180. package/src/commands/edit.ts +16 -132
  181. package/src/commands/export.ts +8 -29
  182. package/src/commands/import.ts +4 -6
  183. package/src/commands/move.ts +144 -179
  184. package/src/commands/remove.ts +9 -52
  185. package/src/commands/rename.ts +2 -7
  186. package/src/commands/show.ts +50 -143
  187. package/src/commands/transition.ts +30 -33
  188. package/src/commands/update.ts +27 -9
  189. package/src/commands/validate.ts +21 -36
  190. package/src/containers/card-container.ts +200 -360
  191. package/src/containers/project/calculation-engine.ts +21 -13
  192. package/src/containers/project/card-cache.ts +497 -0
  193. package/src/containers/project/resource-collector.ts +9 -1
  194. package/src/containers/project.ts +529 -327
  195. package/src/containers/template.ts +109 -127
  196. package/src/index.ts +1 -0
  197. package/src/interfaces/folder-content-interfaces.ts +7 -1
  198. package/src/interfaces/macros.ts +2 -0
  199. package/src/interfaces/project-interfaces.ts +7 -1
  200. package/src/interfaces/resource-interfaces.ts +12 -24
  201. package/src/macros/createCards/index.ts +1 -12
  202. package/src/macros/createCards/types.ts +46 -0
  203. package/src/macros/graph/index.ts +3 -7
  204. package/src/macros/graph/types.ts +24 -0
  205. package/src/macros/image/index.ts +50 -61
  206. package/src/macros/image/types.ts +39 -0
  207. package/src/macros/include/index.ts +6 -15
  208. package/src/macros/include/types.ts +32 -0
  209. package/src/macros/percentage/index.ts +1 -7
  210. package/src/macros/percentage/types.ts +32 -0
  211. package/src/macros/report/index.ts +1 -4
  212. package/src/macros/report/types.ts +20 -0
  213. package/src/macros/scoreCard/index.ts +1 -7
  214. package/src/macros/scoreCard/types.ts +32 -0
  215. package/src/macros/types.ts +48 -0
  216. package/src/macros/vega/index.ts +1 -4
  217. package/src/macros/vega/types.ts +21 -0
  218. package/src/macros/vegalite/index.ts +1 -4
  219. package/src/macros/vegalite/types.ts +22 -0
  220. package/src/macros/xref/index.ts +6 -20
  221. package/src/macros/xref/types.ts +20 -0
  222. package/src/module-manager.ts +5 -5
  223. package/src/project-settings.ts +1 -1
  224. package/src/resources/calculation-resource.ts +6 -76
  225. package/src/resources/card-type-resource.ts +24 -59
  226. package/src/resources/field-type-resource.ts +22 -51
  227. package/src/resources/file-resource.ts +27 -409
  228. package/src/resources/folder-resource.ts +98 -124
  229. package/src/resources/graph-model-resource.ts +17 -74
  230. package/src/resources/graph-view-resource.ts +14 -54
  231. package/src/resources/link-type-resource.ts +13 -40
  232. package/src/resources/report-resource.ts +17 -57
  233. package/src/resources/resource-object.ts +435 -32
  234. package/src/resources/template-resource.ts +16 -29
  235. package/src/resources/workflow-resource.ts +26 -50
  236. package/src/utils/card-utils.ts +217 -31
  237. package/src/utils/clingo-facts.ts +13 -3
  238. package/src/utils/clingo-parser.ts +1 -1
  239. package/src/utils/constants.ts +6 -0
  240. package/src/utils/csv.ts +1 -1
@@ -12,7 +12,7 @@
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';
@@ -20,22 +20,21 @@ 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,20 +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
- resourceNameToString,
51
- } from '../utils/resource-utils.js';
46
+ import { type ResourceName, resourceName } from '../utils/resource-utils.js';
52
47
  import { TemplateResource } from '../resources/template-resource.js';
53
48
  import { UserPreferences } from '../utils/user-preferences.js';
54
49
 
55
50
  import ReportMacro from '../macros/report/index.js';
56
51
  import TaskQueue from '../macros/task-queue.js';
57
52
  import { evaluateMacros } from '../macros/index.js';
58
- import { FolderResource } from '../resources/folder-resource.js';
59
53
  import { readJsonFile } from '../utils/json.js';
60
54
  import { getChildLogger } from '../utils/log-utils.js';
55
+ import { buildCardHierarchy } from '../utils/card-utils.js';
61
56
 
62
57
  /**
63
58
  * Show command.
@@ -94,28 +89,13 @@ export class Show {
94
89
  if (card.metadata?.labels) {
95
90
  labels.push(...card.metadata.labels);
96
91
  }
97
- // Recursively collect labels from subcards, if they exist
98
- if (card.children) {
99
- labels.push(...this.collectLabels(card.children));
100
- }
101
92
  return labels;
102
93
  }, []);
103
94
  };
104
95
 
105
96
  // Returns attachment details
106
- private async getAttachment(cardKey: string, filename: string) {
107
- const details = {
108
- content: false,
109
- metadata: true,
110
- children: false,
111
- parent: false,
112
- attachments: true,
113
- };
114
- const card = await this.project.cardDetailsById(cardKey, details);
115
- if (card === undefined) {
116
- throw new Error(`Card '${cardKey}' does not exist in the project`);
117
- }
118
-
97
+ private getAttachment(cardKey: string, filename: string) {
98
+ const card = this.project.findCard(cardKey);
119
99
  const attachment =
120
100
  card.attachments?.find((a) => a.fileName === filename) ?? undefined;
121
101
  return attachment;
@@ -141,17 +121,20 @@ export class Show {
141
121
  * @returns all template cards in a project.
142
122
  */
143
123
  public async showAllTemplateCards(): Promise<
144
- { name: string; cards: Card[] }[]
124
+ { name: string; cards: CardWithChildrenCards[] }[]
145
125
  > {
146
126
  return Promise.all(
147
- (await this.project.templates()).map(async (template) => {
127
+ (await this.project.templates()).map((template) => {
148
128
  const templateResource = new TemplateResource(
149
129
  this.project,
150
130
  resourceName(template.name),
151
131
  );
132
+ const cards = templateResource.templateObject().listCards();
133
+ const buildCards = buildCardHierarchy(cards);
134
+
152
135
  return {
153
136
  name: template.name,
154
- cards: await templateResource.templateObject().showTemplateCards(),
137
+ cards: buildCards,
155
138
  };
156
139
  }),
157
140
  );
@@ -162,20 +145,8 @@ export class Show {
162
145
  * @returns array of card attachments
163
146
  */
164
147
  public async showAttachments(): Promise<CardAttachment[]> {
165
- const attachments: CardAttachment[] = await this.project.attachments();
166
- const templateAttachments: CardAttachment[] = [];
167
- const templates = await this.project.templates();
168
- for (const template of templates) {
169
- const templateResource = new TemplateResource(
170
- this.project,
171
- resourceName(template.name),
172
- );
173
- const templateObject = templateResource.templateObject();
174
- if (templateObject) {
175
- templateAttachments.push(...(await templateObject.attachments()));
176
- }
177
- }
178
-
148
+ const attachments = this.project.attachments();
149
+ const templateAttachments = await this.project.attachmentsFromTemplates();
179
150
  attachments.push(...templateAttachments);
180
151
  return attachments;
181
152
  }
@@ -186,32 +157,22 @@ export class Show {
186
157
  * @param filename attachment filename
187
158
  * @returns attachment details
188
159
  */
189
- public async showAttachment(
190
- cardKey: string,
191
- filename: string,
192
- ): Promise<attachmentPayload> {
160
+ public showAttachment(cardKey: string, filename: string): attachmentPayload {
193
161
  if (!cardKey) {
194
162
  throw new Error(`Mandatory parameter 'cardKey' missing`);
195
163
  }
196
164
 
197
- const attachment = await this.getAttachment(cardKey, filename);
198
-
199
- let attachmentPath: string = '';
200
- if (attachment) {
201
- attachmentPath = `${attachment.path}/${attachment.fileName}`;
202
- }
165
+ const attachment = this.getAttachment(cardKey, filename);
203
166
 
204
- if (!attachment || !existsSync(attachmentPath)) {
167
+ if (!attachment) {
205
168
  throw new Error(`Attachment '${filename}' not found for card ${cardKey}`);
206
- } else {
207
- const fileBuffer = readFileSync(attachmentPath);
208
- let mimeType = mime.lookup(attachmentPath);
209
- if (mimeType === false) {
210
- mimeType = 'application/octet-stream';
211
- }
212
- const payload: attachmentPayload = { fileBuffer, mimeType };
213
- return payload;
214
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;
215
176
  }
216
177
 
217
178
  /**
@@ -226,7 +187,7 @@ export class Show {
226
187
  filename: string,
227
188
  waitDelay: number = 1000,
228
189
  ) {
229
- const attachment = await this.getAttachment(cardKey, filename);
190
+ const attachment = this.getAttachment(cardKey, filename);
230
191
 
231
192
  if (!attachment) {
232
193
  throw new Error(`Attachment '${filename}' not found for card ${cardKey}`);
@@ -273,22 +234,29 @@ export class Show {
273
234
  /**
274
235
  * Shows details of a particular card (template card, or project card)
275
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.
276
- * @param details card details to show
277
237
  * @param cardKey card key to find
238
+ * @param contentType Content format in which content is to be shown
278
239
  * @returns card details
279
240
  */
280
- public async showCardDetails(
281
- details: ProjectFetchCardDetails,
241
+ public showCardDetails(
282
242
  cardKey?: string,
283
- ): Promise<Card> {
243
+ contentType?: FileContentType,
244
+ ): Card {
284
245
  if (!cardKey) {
285
246
  throw new Error(`Mandatory parameter 'cardKey' missing`);
286
247
  }
287
- const cardDetails = await this.project.cardDetailsById(cardKey, details);
288
- if (cardDetails === undefined) {
289
- 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;
290
258
  }
291
- return cardDetails;
259
+ return this.project.findCard(cardKey, details);
292
260
  }
293
261
 
294
262
  /**
@@ -329,62 +297,6 @@ export class Show {
329
297
  return results.filter((item) => item);
330
298
  }
331
299
 
332
- /**
333
- * Shows the content of a file in a resource.
334
- * TODO: To be removed
335
- * @deprecated
336
- * @param resourceName Name of the resource.
337
- * @param fileName Name of the file to show.
338
- * @returns the content of the file.
339
- */
340
- public async showFile(
341
- resourceName: ResourceName,
342
- fileName: string,
343
- ): Promise<string> {
344
- const resourceNameStr = resourceNameToString(resourceName);
345
- if (
346
- !(await this.project.resourceExists(
347
- resourceName.type as ResourceFolderType,
348
- resourceNameStr,
349
- ))
350
- ) {
351
- throw new Error(
352
- `Resource '${resourceNameStr}' does not exist in the project`,
353
- );
354
- }
355
- const resource = Project.resourceObject(this.project, resourceName);
356
- if (!(resource instanceof FolderResource)) {
357
- throw new Error(`Resource '${resourceNameStr}' is not a folder resource`);
358
- }
359
- return resource.showFile(fileName);
360
- }
361
-
362
- /**
363
- * Shows all file names in a folder resource.
364
- * TODO: To be removed
365
- * @deprecated
366
- * @param resourceName Name of the resource.
367
- * @returns all file names in the resource.
368
- */
369
- public async showFileNames(resourceName: ResourceName): Promise<string[]> {
370
- const resourceNameStr = resourceNameToString(resourceName);
371
- if (
372
- !(await this.project.resourceExists(
373
- resourceName.type as ResourceFolderType,
374
- resourceNameStr,
375
- ))
376
- ) {
377
- throw new Error(
378
- `Resource '${resourceNameStr}' does not exist in the project`,
379
- );
380
- }
381
- const resource = Project.resourceObject(this.project, resourceName);
382
- if (!(resource instanceof FolderResource)) {
383
- throw new Error(`Resource '${resourceNameStr}' is not a folder resource`);
384
- }
385
- return resource.showFileNames();
386
- }
387
-
388
300
  /**
389
301
  * Shows importable modules.
390
302
  * @param showAll - When true, shows all importable modules, even if they have already been imported
@@ -436,12 +348,9 @@ export class Show {
436
348
  * Returns all unique labels in a project
437
349
  * @returns labels in a list
438
350
  */
439
- public async showLabels(): Promise<string[]> {
440
- const cards = await this.project.showProjectCards();
441
- const templateCards = await this.project.allTemplateCards({
442
- metadata: true,
443
- children: true,
444
- });
351
+ public showLabels(): string[] {
352
+ const cards = this.project.showProjectCards();
353
+ const templateCards = this.project.allTemplateCards();
445
354
 
446
355
  const labels = this.collectLabels([...cards, ...templateCards]);
447
356
  return Array.from(new Set(labels));
@@ -479,12 +388,10 @@ export class Show {
479
388
 
480
389
  /**
481
390
  * Returns all project cards in the project. Cards don't have content and nor metadata.
482
- * @note AppUi uses this method.
483
391
  * @returns array of cards
484
392
  */
485
- public async showProjectCards(): Promise<Card[]> {
486
- const projectCards = await this.project.showProjectCards();
487
- return projectCards;
393
+ public showProjectCards(): Card[] {
394
+ return this.project.showProjectCards();
488
395
  }
489
396
 
490
397
  /**
@@ -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
  }
@@ -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,