@cyberismo/data-handler 0.0.14 → 0.0.16

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 (280) hide show
  1. package/dist/card-metadata-updater.js +8 -4
  2. package/dist/card-metadata-updater.js.map +1 -1
  3. package/dist/command-handler.d.ts +4 -0
  4. package/dist/command-handler.js +29 -19
  5. package/dist/command-handler.js.map +1 -1
  6. package/dist/command-manager.d.ts +25 -2
  7. package/dist/command-manager.js +30 -5
  8. package/dist/command-manager.js.map +1 -1
  9. package/dist/commands/create.d.ts +1 -1
  10. package/dist/commands/create.js +45 -93
  11. package/dist/commands/create.js.map +1 -1
  12. package/dist/commands/edit.d.ts +1 -15
  13. package/dist/commands/edit.js +15 -89
  14. package/dist/commands/edit.js.map +1 -1
  15. package/dist/commands/export.d.ts +11 -2
  16. package/dist/commands/export.js +58 -58
  17. package/dist/commands/export.js.map +1 -1
  18. package/dist/commands/import.d.ts +9 -1
  19. package/dist/commands/import.js +17 -11
  20. package/dist/commands/import.js.map +1 -1
  21. package/dist/commands/move.d.ts +1 -2
  22. package/dist/commands/move.js +107 -146
  23. package/dist/commands/move.js.map +1 -1
  24. package/dist/commands/remove.d.ts +8 -1
  25. package/dist/commands/remove.js +17 -48
  26. package/dist/commands/remove.js.map +1 -1
  27. package/dist/commands/rename.d.ts +4 -9
  28. package/dist/commands/rename.js +34 -108
  29. package/dist/commands/rename.js.map +1 -1
  30. package/dist/commands/show.d.ts +22 -34
  31. package/dist/commands/show.js +103 -151
  32. package/dist/commands/show.js.map +1 -1
  33. package/dist/commands/transition.d.ts +9 -2
  34. package/dist/commands/transition.js +49 -44
  35. package/dist/commands/transition.js.map +1 -1
  36. package/dist/commands/update.d.ts +18 -12
  37. package/dist/commands/update.js +34 -18
  38. package/dist/commands/update.js.map +1 -1
  39. package/dist/commands/validate.d.ts +18 -10
  40. package/dist/commands/validate.js +101 -47
  41. package/dist/commands/validate.js.map +1 -1
  42. package/dist/containers/card-container.d.ts +87 -24
  43. package/dist/containers/card-container.js +183 -279
  44. package/dist/containers/card-container.js.map +1 -1
  45. package/dist/containers/project/calculation-engine.d.ts +13 -4
  46. package/dist/containers/project/calculation-engine.js +79 -77
  47. package/dist/containers/project/calculation-engine.js.map +1 -1
  48. package/dist/containers/project/card-cache.d.ts +146 -0
  49. package/dist/containers/project/card-cache.js +411 -0
  50. package/dist/containers/project/card-cache.js.map +1 -0
  51. package/dist/containers/project/project-paths.d.ts +5 -4
  52. package/dist/containers/project/project-paths.js +16 -12
  53. package/dist/containers/project/project-paths.js.map +1 -1
  54. package/dist/containers/project/resource-cache.d.ts +169 -0
  55. package/dist/containers/project/resource-cache.js +507 -0
  56. package/dist/containers/project/resource-cache.js.map +1 -0
  57. package/dist/containers/project/resource-handler.d.ts +129 -0
  58. package/dist/containers/project/resource-handler.js +206 -0
  59. package/dist/containers/project/resource-handler.js.map +1 -0
  60. package/dist/containers/project.d.ts +114 -195
  61. package/dist/containers/project.js +425 -535
  62. package/dist/containers/project.js.map +1 -1
  63. package/dist/containers/template.d.ts +22 -32
  64. package/dist/containers/template.js +113 -115
  65. package/dist/containers/template.js.map +1 -1
  66. package/dist/index.d.ts +1 -0
  67. package/dist/index.js +1 -0
  68. package/dist/index.js.map +1 -1
  69. package/dist/interfaces/folder-content-interfaces.d.ts +7 -4
  70. package/dist/interfaces/folder-content-interfaces.js +3 -3
  71. package/dist/interfaces/folder-content-interfaces.js.map +1 -1
  72. package/dist/interfaces/macros.d.ts +1 -0
  73. package/dist/interfaces/macros.js +1 -1
  74. package/dist/interfaces/macros.js.map +1 -1
  75. package/dist/interfaces/project-interfaces.d.ts +7 -5
  76. package/dist/interfaces/project-interfaces.js.map +1 -1
  77. package/dist/interfaces/resource-interfaces.d.ts +25 -22
  78. package/dist/interfaces/resource-interfaces.js +3 -0
  79. package/dist/interfaces/resource-interfaces.js.map +1 -1
  80. package/dist/macros/common.d.ts +10 -10
  81. package/dist/macros/createCards/index.d.ts +0 -13
  82. package/dist/macros/createCards/index.js.map +1 -1
  83. package/dist/macros/createCards/types.d.ts +44 -0
  84. package/dist/macros/createCards/types.js +15 -0
  85. package/dist/macros/createCards/types.js.map +1 -0
  86. package/dist/macros/graph/index.d.ts +2 -6
  87. package/dist/macros/graph/index.js +14 -28
  88. package/dist/macros/graph/index.js.map +1 -1
  89. package/dist/macros/graph/types.d.ts +23 -0
  90. package/dist/macros/graph/types.js +15 -0
  91. package/dist/macros/graph/types.js.map +1 -0
  92. package/dist/macros/image/index.d.ts +8 -16
  93. package/dist/macros/image/index.js +36 -33
  94. package/dist/macros/image/index.js.map +1 -1
  95. package/dist/macros/image/types.d.ts +38 -0
  96. package/dist/macros/image/types.js +15 -0
  97. package/dist/macros/image/types.js.map +1 -0
  98. package/dist/macros/include/index.d.ts +1 -6
  99. package/dist/macros/include/index.js +4 -7
  100. package/dist/macros/include/index.js.map +1 -1
  101. package/dist/macros/include/types.d.ts +31 -0
  102. package/dist/macros/include/types.js +15 -0
  103. package/dist/macros/include/types.js.map +1 -0
  104. package/dist/macros/index.d.ts +1 -1
  105. package/dist/macros/index.js +2 -2
  106. package/dist/macros/index.js.map +1 -1
  107. package/dist/macros/percentage/index.d.ts +0 -6
  108. package/dist/macros/percentage/index.js.map +1 -1
  109. package/dist/macros/percentage/types.d.ts +31 -0
  110. package/dist/macros/percentage/types.js +15 -0
  111. package/dist/macros/percentage/types.js.map +1 -0
  112. package/dist/macros/report/index.d.ts +0 -3
  113. package/dist/macros/report/index.js +3 -6
  114. package/dist/macros/report/index.js.map +1 -1
  115. package/dist/macros/report/types.d.ts +19 -0
  116. package/dist/macros/report/types.js +15 -0
  117. package/dist/macros/report/types.js.map +1 -0
  118. package/dist/macros/scoreCard/index.d.ts +0 -6
  119. package/dist/macros/scoreCard/index.js.map +1 -1
  120. package/dist/macros/scoreCard/types.d.ts +31 -0
  121. package/dist/macros/scoreCard/types.js +15 -0
  122. package/dist/macros/scoreCard/types.js.map +1 -0
  123. package/dist/macros/types.d.ts +25 -0
  124. package/dist/macros/types.js +2 -0
  125. package/dist/macros/types.js.map +1 -0
  126. package/dist/macros/vega/index.d.ts +0 -4
  127. package/dist/macros/vega/index.js.map +1 -1
  128. package/dist/macros/vega/types.d.ts +20 -0
  129. package/dist/macros/vega/types.js +2 -0
  130. package/dist/macros/vega/types.js.map +1 -0
  131. package/dist/macros/vegalite/index.d.ts +0 -4
  132. package/dist/macros/vegalite/index.js.map +1 -1
  133. package/dist/macros/vegalite/types.d.ts +20 -0
  134. package/dist/macros/vegalite/types.js +15 -0
  135. package/dist/macros/vegalite/types.js.map +1 -0
  136. package/dist/macros/xref/index.d.ts +0 -3
  137. package/dist/macros/xref/index.js +5 -14
  138. package/dist/macros/xref/index.js.map +1 -1
  139. package/dist/macros/xref/types.d.ts +19 -0
  140. package/dist/macros/xref/types.js +15 -0
  141. package/dist/macros/xref/types.js.map +1 -0
  142. package/dist/module-manager.d.ts +16 -3
  143. package/dist/module-manager.js +55 -23
  144. package/dist/module-manager.js.map +1 -1
  145. package/dist/project-settings.d.ts +16 -3
  146. package/dist/project-settings.js +79 -14
  147. package/dist/project-settings.js.map +1 -1
  148. package/dist/resources/calculation-resource.d.ts +6 -33
  149. package/dist/resources/calculation-resource.js +11 -60
  150. package/dist/resources/calculation-resource.js.map +1 -1
  151. package/dist/resources/card-type-resource.d.ts +10 -22
  152. package/dist/resources/card-type-resource.js +46 -66
  153. package/dist/resources/card-type-resource.js.map +1 -1
  154. package/dist/resources/create-defaults.d.ts +3 -2
  155. package/dist/resources/create-defaults.js +3 -2
  156. package/dist/resources/create-defaults.js.map +1 -1
  157. package/dist/resources/field-type-resource.d.ts +8 -22
  158. package/dist/resources/field-type-resource.js +35 -60
  159. package/dist/resources/field-type-resource.js.map +1 -1
  160. package/dist/resources/file-resource.d.ts +14 -35
  161. package/dist/resources/file-resource.js +22 -301
  162. package/dist/resources/file-resource.js.map +1 -1
  163. package/dist/resources/folder-resource.d.ts +44 -66
  164. package/dist/resources/folder-resource.js +102 -149
  165. package/dist/resources/folder-resource.js.map +1 -1
  166. package/dist/resources/graph-model-resource.d.ts +9 -34
  167. package/dist/resources/graph-model-resource.js +18 -64
  168. package/dist/resources/graph-model-resource.js.map +1 -1
  169. package/dist/resources/graph-view-resource.d.ts +9 -29
  170. package/dist/resources/graph-view-resource.js +13 -48
  171. package/dist/resources/graph-view-resource.js.map +1 -1
  172. package/dist/resources/link-type-resource.d.ts +9 -23
  173. package/dist/resources/link-type-resource.js +11 -33
  174. package/dist/resources/link-type-resource.js.map +1 -1
  175. package/dist/resources/report-resource.d.ts +10 -23
  176. package/dist/resources/report-resource.js +20 -67
  177. package/dist/resources/report-resource.js.map +1 -1
  178. package/dist/resources/resource-object.d.ts +143 -23
  179. package/dist/resources/resource-object.js +369 -48
  180. package/dist/resources/resource-object.js.map +1 -1
  181. package/dist/resources/template-resource.d.ts +10 -17
  182. package/dist/resources/template-resource.js +19 -27
  183. package/dist/resources/template-resource.js.map +1 -1
  184. package/dist/resources/workflow-resource.d.ts +9 -25
  185. package/dist/resources/workflow-resource.js +25 -55
  186. package/dist/resources/workflow-resource.js.map +1 -1
  187. package/dist/utils/card-utils.d.ts +69 -19
  188. package/dist/utils/card-utils.js +179 -30
  189. package/dist/utils/card-utils.js.map +1 -1
  190. package/dist/utils/clingo-fact-builder.d.ts +25 -14
  191. package/dist/utils/clingo-fact-builder.js +27 -5
  192. package/dist/utils/clingo-fact-builder.js.map +1 -1
  193. package/dist/utils/clingo-facts.js +14 -7
  194. package/dist/utils/clingo-facts.js.map +1 -1
  195. package/dist/utils/clingo-parser.js +1 -1
  196. package/dist/utils/clingo-parser.js.map +1 -1
  197. package/dist/utils/constants.d.ts +2 -0
  198. package/dist/utils/constants.js +4 -0
  199. package/dist/utils/constants.js.map +1 -1
  200. package/dist/utils/csv.js +1 -1
  201. package/dist/utils/csv.js.map +1 -1
  202. package/dist/utils/resource-utils.d.ts +1 -0
  203. package/dist/utils/resource-utils.js +2 -1
  204. package/dist/utils/resource-utils.js.map +1 -1
  205. package/package.json +11 -11
  206. package/src/card-metadata-updater.ts +9 -7
  207. package/src/command-handler.ts +35 -23
  208. package/src/command-manager.ts +32 -19
  209. package/src/commands/create.ts +59 -160
  210. package/src/commands/edit.ts +16 -132
  211. package/src/commands/export.ts +71 -81
  212. package/src/commands/import.ts +26 -18
  213. package/src/commands/move.ts +143 -179
  214. package/src/commands/remove.ts +20 -59
  215. package/src/commands/rename.ts +45 -156
  216. package/src/commands/show.ts +153 -211
  217. package/src/commands/transition.ts +53 -58
  218. package/src/commands/update.ts +44 -23
  219. package/src/commands/validate.ts +108 -82
  220. package/src/containers/card-container.ts +200 -360
  221. package/src/containers/project/calculation-engine.ts +81 -105
  222. package/src/containers/project/card-cache.ts +497 -0
  223. package/src/containers/project/project-paths.ts +21 -13
  224. package/src/containers/project/resource-cache.ts +648 -0
  225. package/src/containers/project/resource-handler.ts +265 -0
  226. package/src/containers/project.ts +551 -693
  227. package/src/containers/template.ts +129 -142
  228. package/src/index.ts +1 -0
  229. package/src/interfaces/folder-content-interfaces.ts +14 -7
  230. package/src/interfaces/macros.ts +2 -0
  231. package/src/interfaces/project-interfaces.ts +14 -7
  232. package/src/interfaces/resource-interfaces.ts +30 -27
  233. package/src/macros/createCards/index.ts +1 -12
  234. package/src/macros/createCards/types.ts +46 -0
  235. package/src/macros/graph/index.ts +27 -52
  236. package/src/macros/graph/types.ts +24 -0
  237. package/src/macros/image/index.ts +50 -61
  238. package/src/macros/image/types.ts +39 -0
  239. package/src/macros/include/index.ts +6 -15
  240. package/src/macros/include/types.ts +32 -0
  241. package/src/macros/index.ts +2 -2
  242. package/src/macros/percentage/index.ts +1 -7
  243. package/src/macros/percentage/types.ts +32 -0
  244. package/src/macros/report/index.ts +4 -13
  245. package/src/macros/report/types.ts +20 -0
  246. package/src/macros/scoreCard/index.ts +1 -7
  247. package/src/macros/scoreCard/types.ts +32 -0
  248. package/src/macros/types.ts +48 -0
  249. package/src/macros/vega/index.ts +1 -4
  250. package/src/macros/vega/types.ts +21 -0
  251. package/src/macros/vegalite/index.ts +1 -4
  252. package/src/macros/vegalite/types.ts +22 -0
  253. package/src/macros/xref/index.ts +6 -20
  254. package/src/macros/xref/types.ts +20 -0
  255. package/src/module-manager.ts +79 -22
  256. package/src/project-settings.ts +84 -15
  257. package/src/resources/calculation-resource.ts +21 -91
  258. package/src/resources/card-type-resource.ts +74 -109
  259. package/src/resources/create-defaults.ts +3 -2
  260. package/src/resources/field-type-resource.ts +61 -104
  261. package/src/resources/file-resource.ts +33 -441
  262. package/src/resources/folder-resource.ts +130 -207
  263. package/src/resources/graph-model-resource.ts +36 -95
  264. package/src/resources/graph-view-resource.ts +28 -70
  265. package/src/resources/link-type-resource.ts +23 -53
  266. package/src/resources/report-resource.ts +34 -96
  267. package/src/resources/resource-object.ts +511 -66
  268. package/src/resources/template-resource.ts +32 -44
  269. package/src/resources/workflow-resource.ts +42 -85
  270. package/src/utils/card-utils.ts +217 -31
  271. package/src/utils/clingo-fact-builder.ts +28 -16
  272. package/src/utils/clingo-facts.ts +16 -7
  273. package/src/utils/clingo-parser.ts +1 -1
  274. package/src/utils/constants.ts +6 -0
  275. package/src/utils/csv.ts +1 -1
  276. package/src/utils/resource-utils.ts +2 -1
  277. package/dist/containers/project/resource-collector.d.ts +0 -87
  278. package/dist/containers/project/resource-collector.js +0 -337
  279. package/dist/containers/project/resource-collector.js.map +0 -1
  280. package/src/containers/project/resource-collector.ts +0 -396
@@ -12,15 +12,12 @@
12
12
  */
13
13
 
14
14
  // node
15
- import { join, sep } from 'node:path';
15
+ import { join } from 'node:path';
16
16
 
17
17
  import { ActionGuard } from '../permissions/action-guard.js';
18
18
  import { copyDir, deleteDir } from '../utils/file-utils.js';
19
- import type {
20
- Card,
21
- FetchCardDetails,
22
- } from '../interfaces/project-interfaces.js';
23
- import { type Project, ResourcesFrom } from '../containers/project.js';
19
+ import type { Card } from '../interfaces/project-interfaces.js';
20
+ import type { Project } from '../containers/project.js';
24
21
  import {
25
22
  EMPTY_RANK,
26
23
  FIRST_RANK,
@@ -29,72 +26,47 @@ import {
29
26
  rebalanceRanks,
30
27
  sortItems,
31
28
  } from '../utils/lexorank.js';
32
- import { isTemplateCard } from '../utils/card-utils.js';
33
- import { resourceName } from '../utils/resource-utils.js';
34
- import { TemplateResource } from '../resources/template-resource.js';
29
+ import {
30
+ cardPathParts,
31
+ isModuleCard,
32
+ isTemplateCard,
33
+ } from '../utils/card-utils.js';
35
34
 
36
- // @todo - we should have project wide constants, so that if we need them, only the const value needs to be changed.
37
- const ROOT: string = 'root';
35
+ import { ROOT } from '../utils/constants.js';
38
36
 
39
37
  export class Move {
40
38
  constructor(private project: Project) {}
41
39
 
42
- // Fetches a card (either template or project card).
43
- private async getCard(cardKey: string, options: FetchCardDetails) {
44
- let card: Card | undefined;
45
- const templateCard = await this.project.isTemplateCard(cardKey);
46
- if (templateCard) {
47
- card = (await this.project.allTemplateCards(options)).find(
48
- (card) => card.key === cardKey,
49
- );
50
- } else {
51
- card = await this.project.findSpecificCard(cardKey, options);
52
- }
53
- if (!card) {
54
- throw new Error('Card was not found from the project');
55
- }
56
- return card;
57
- }
58
-
59
40
  // Returns children of a parent card or root cards
60
- private async getSiblings(card: Card) {
41
+ private getSiblings(card: Card): Card[] {
61
42
  const parentCardKey = card.parent || ROOT;
62
43
 
63
44
  // since we don't know if 'root' is templateRoot or cardRoot, we need to check the card
64
45
  if (parentCardKey === ROOT) {
65
46
  if (isTemplateCard(card)) {
66
- const template = this.project.createTemplateObjectFromCard(card);
67
- if (!template) {
68
- throw new Error(
69
- `Cannot find template for the template card '${card.key}'`,
70
- );
71
- }
72
- if (card?.path.includes(`${sep}modules${sep}`)) {
47
+ if (isModuleCard(card)) {
73
48
  throw new Error(`Cannot rank module cards`);
74
49
  }
75
- return template.cards();
50
+ const { template } = cardPathParts(
51
+ this.project.projectPrefix,
52
+ card.path,
53
+ );
54
+ return this.project.templateCards(template);
76
55
  }
77
56
  }
78
57
 
79
58
  let parentCard;
80
59
  if (parentCardKey !== ROOT) {
81
- parentCard = await this.project.findSpecificCard(parentCardKey, {
82
- children: true,
83
- metadata: true,
84
- });
85
- if (!parentCard) {
86
- throw new Error(`Card ${parentCardKey} not found from project`);
87
- }
88
- }
89
-
90
- if (parentCard) {
91
- return parentCard.children || [];
60
+ parentCard = this.project.findCard(parentCardKey);
61
+ return this.project.cardKeysToCards(parentCard.children);
92
62
  }
93
63
 
94
- return this.project.showProjectCards();
64
+ return this.project
65
+ .showProjectCards()
66
+ .filter((item) => item.parent === 'root' || item.parent === '');
95
67
  }
96
68
 
97
- //
69
+ // Rebalances cards
98
70
  private async rebalanceCards(cards: Card[]) {
99
71
  const ranks = rebalanceRanks(cards.length);
100
72
 
@@ -116,7 +88,9 @@ export class Move {
116
88
  const card = cards[i];
117
89
  await this.project.updateCardMetadataKey(card.key, 'rank', ranks[i]);
118
90
  if (card.children && card.children.length > 0) {
119
- await this.rebalanceProjectRecursively(card.children);
91
+ await this.rebalanceProjectRecursively(
92
+ this.project.cardKeysToCards(card.children),
93
+ );
120
94
  }
121
95
  }
122
96
  }
@@ -133,55 +107,55 @@ export class Move {
133
107
  if (source === destination) {
134
108
  throw new Error(`Card cannot be moved to itself`);
135
109
  }
136
- const promiseContainer = [];
137
- promiseContainer.push(this.project.findSpecificCard(source));
138
- if (destination !== ROOT) {
139
- promiseContainer.push(this.project.findSpecificCard(destination));
140
- } else {
141
- const returnObject: Card = {
142
- key: '',
143
- path: this.project.paths.cardRootFolder,
144
- children: [],
145
- attachments: [],
146
- };
147
- promiseContainer.push(Promise.resolve(returnObject));
148
- }
149
- const [sourceCard, destinationCard] = await Promise.all(promiseContainer);
150
-
151
- if (!sourceCard) {
152
- throw new Error(`Card ${source} not found from project`);
153
- }
154
- if (!destinationCard) {
155
- throw new Error(`Card ${destination} not found from project`);
156
- }
157
-
158
- if (destinationCard.path.includes(source)) {
159
- throw new Error(`Card cannot be moved to inside itself`);
110
+ const movingToRoot = destination === ROOT;
111
+ const sourceCard = this.project.findCard(source);
112
+ const destinationCard = !movingToRoot
113
+ ? this.project.findCard(destination)
114
+ : undefined;
115
+
116
+ // Prevent moving card to inside its descendants
117
+ if (destinationCard) {
118
+ const { parents } = cardPathParts(
119
+ this.project.projectPrefix,
120
+ destinationCard.path,
121
+ );
122
+ if (parents.includes(source)) {
123
+ throw new Error(`Card cannot be moved to inside itself`);
124
+ }
160
125
  }
161
126
 
162
127
  // Imported templates cannot be modified.
163
128
  if (
164
- destinationCard.path.includes(`${sep}modules`) ||
165
- sourceCard.path.includes(`${sep}modules${sep}`)
129
+ (destinationCard && isModuleCard(destinationCard)) ||
130
+ isModuleCard(sourceCard)
166
131
  ) {
167
132
  throw new Error(`Cannot modify imported module templates`);
168
133
  }
169
134
 
170
- const bothTemplateCards =
171
- isTemplateCard(sourceCard) && isTemplateCard(destinationCard);
172
- const bothProjectCards =
173
- this.project.hasCard(sourceCard.key) &&
174
- this.project.hasCard(destinationCard.key);
175
- if (!(bothTemplateCards || bothProjectCards)) {
176
- throw new Error(
177
- `Cards cannot be moved from project to template or vice versa`,
178
- );
135
+ // Special handling for moving to root
136
+ if (movingToRoot) {
137
+ if (isTemplateCard(sourceCard)) {
138
+ throw new Error(`Template cards cannot be moved to project root`);
139
+ }
140
+ } else {
141
+ const bothTemplateCards =
142
+ isTemplateCard(sourceCard) &&
143
+ destinationCard &&
144
+ isTemplateCard(destinationCard);
145
+ const bothProjectCards =
146
+ this.project.hasProjectCard(sourceCard.key) &&
147
+ destinationCard &&
148
+ this.project.hasProjectCard(destinationCard.key);
149
+ if (!(bothTemplateCards || bothProjectCards)) {
150
+ throw new Error(
151
+ `Cards cannot be moved from project to template or vice versa`,
152
+ );
153
+ }
179
154
  }
180
155
 
181
- const destinationPath =
182
- destination === ROOT
183
- ? join(this.project.paths.cardRootFolder, sourceCard.key)
184
- : join(destinationCard.path, 'c', sourceCard.key);
156
+ const destinationPath = movingToRoot
157
+ ? join(this.project.paths.cardRootFolder, sourceCard.key)
158
+ : join(destinationCard!.path, 'c', sourceCard.key);
185
159
 
186
160
  // if the card is already in the destination, do nothing
187
161
  if (sourceCard.path === destinationPath) {
@@ -192,20 +166,14 @@ export class Move {
192
166
  const actionGuard = new ActionGuard(this.project.calculationEngine);
193
167
  await actionGuard.checkPermission('move', source);
194
168
 
195
- // rerank the card in the new location
169
+ // re-rank the card in the new location
196
170
  // it will be the last one in the new location
197
171
  let children;
198
- if (destination !== ROOT) {
199
- const parent = await this.project.findSpecificCard(destination, {
200
- children: true,
201
- metadata: true,
202
- });
203
- if (!parent) {
204
- throw new Error(`Parent card ${destination} not found from project`);
205
- }
206
- children = parent.children;
172
+ if (!movingToRoot) {
173
+ const parent = this.project.findCard(destination);
174
+ children = this.project.cardKeysToCards(parent.children);
207
175
  } else {
208
- children = await this.project.showProjectCards();
176
+ children = this.project.showProjectCards();
209
177
  }
210
178
 
211
179
  if (!children) {
@@ -219,9 +187,50 @@ export class Move {
219
187
  lastChild && lastChild.metadata
220
188
  ? getRankAfter(lastChild.metadata.rank)
221
189
  : FIRST_RANK;
222
- await this.project.updateCardMetadataKey(sourceCard.key, 'rank', rank);
190
+
191
+ // First do the file operations, then update metadata
223
192
  await copyDir(sourceCard.path, destinationPath);
224
193
  await deleteDir(sourceCard.path);
194
+
195
+ // Update card with new path, parent, and rank
196
+ sourceCard.path = destinationPath!;
197
+ sourceCard.parent = movingToRoot ? ROOT : destination;
198
+ if (sourceCard.metadata) {
199
+ sourceCard.metadata.rank = rank;
200
+ }
201
+
202
+ // Handle cache update and persistence
203
+ await this.project.updateCard(sourceCard);
204
+ const updatedCard: Card = {
205
+ ...sourceCard,
206
+ path: destinationPath,
207
+ parent: movingToRoot ? ROOT : destination,
208
+ metadata: sourceCard.metadata
209
+ ? {
210
+ ...sourceCard.metadata,
211
+ rank: rank,
212
+ }
213
+ : undefined,
214
+ };
215
+
216
+ // Fetch old parent
217
+ const oldParent = sourceCard.parent;
218
+ let oldParentCard: Card | undefined;
219
+ if (oldParent && oldParent !== ROOT) {
220
+ oldParentCard = this.project.findCard(oldParent);
221
+ }
222
+
223
+ let newParentCard: Card | undefined;
224
+ if (!movingToRoot) {
225
+ newParentCard = this.project.findCard(destination);
226
+ }
227
+
228
+ // Finally, update the project
229
+ await this.project.handleCardMoved(
230
+ updatedCard,
231
+ newParentCard,
232
+ oldParentCard,
233
+ );
225
234
  }
226
235
 
227
236
  /**
@@ -238,17 +247,13 @@ export class Move {
238
247
  return;
239
248
  }
240
249
 
241
- const card = await this.project.findSpecificCard(cardKey, {
242
- metadata: true,
243
- parent: true,
244
- });
245
-
246
- if (!card || !card.parent) {
247
- throw new Error(`Card ${cardKey} not found from project`);
250
+ const card = this.project.findCard(cardKey);
251
+ if (!card.parent) {
252
+ throw new Error(`Parent card ${cardKey} not found from project`);
248
253
  }
249
254
 
250
255
  const children = sortItems(
251
- await this.getSiblings(card),
256
+ this.getSiblings(card),
252
257
  (item) => item.metadata?.rank || EMPTY_RANK,
253
258
  );
254
259
 
@@ -268,29 +273,15 @@ export class Move {
268
273
  * @param beforeCardKey Card key after which the card will be ranked
269
274
  */
270
275
  public async rankCard(cardKey: string, beforeCardKey: string) {
271
- const card = await this.project.findSpecificCard(cardKey, {
272
- metadata: true,
273
- parent: true,
274
- });
275
- if (!card) {
276
- throw new Error(`Card ${cardKey} not found from project`);
277
- }
278
-
279
- const beforeCard = await this.project.findSpecificCard(beforeCardKey, {
280
- metadata: true,
281
- parent: true,
282
- });
283
-
284
- if (!beforeCard) {
285
- throw new Error(`Card ${beforeCardKey} not found from project`);
286
- }
276
+ const card = this.project.findCard(cardKey);
277
+ const beforeCard = this.project.findCard(beforeCardKey);
287
278
 
288
279
  if (beforeCard.parent !== card.parent) {
289
280
  throw new Error(`Cards must be from the same parent`);
290
281
  }
291
282
 
292
283
  const children = sortItems(
293
- await this.getSiblings(beforeCard),
284
+ this.getSiblings(beforeCard),
294
285
  (item) => item.metadata?.rank || EMPTY_RANK,
295
286
  );
296
287
 
@@ -308,11 +299,8 @@ export class Move {
308
299
  );
309
300
  }
310
301
 
311
- if (
312
- children[beforeCardIndex].key === cardKey ||
313
- children[beforeCardIndex + 1]?.key === cardKey
314
- ) {
315
- throw new Error(`Card ${cardKey} is already in the correct position`);
302
+ if (children[beforeCardIndex].key === cardKey) {
303
+ throw new Error(`Card cannot be ranked after itself`);
316
304
  }
317
305
 
318
306
  if (beforeCardIndex === children.length - 1) {
@@ -338,13 +326,9 @@ export class Move {
338
326
  * @param cardKey card key
339
327
  */
340
328
  public async rankFirst(cardKey: string) {
341
- const card = await this.getCard(cardKey, {
342
- metadata: true,
343
- parent: true,
344
- });
345
-
329
+ const card = this.project.findCard(cardKey);
346
330
  const children = sortItems(
347
- await this.getSiblings(card),
331
+ this.getSiblings(card),
348
332
  (item) => item.metadata?.rank || EMPTY_RANK,
349
333
  );
350
334
 
@@ -387,14 +371,13 @@ export class Move {
387
371
  * @param parentCardKey parent card key
388
372
  */
389
373
  public async rebalanceChildren(parentCardKey: string) {
390
- const parentCard = await this.project.findSpecificCard(parentCardKey, {
391
- children: true,
392
- metadata: true,
393
- });
374
+ const parentCard = this.project.findCard(parentCardKey);
394
375
  if (!parentCard || !parentCard.children) {
395
376
  throw new Error(`Card ${parentCardKey} not found from project`);
396
377
  }
397
- await this.rebalanceCards(parentCard.children);
378
+ await this.rebalanceCards(
379
+ this.project.cardKeysToCards(parentCard.children),
380
+ );
398
381
  }
399
382
 
400
383
  /**
@@ -402,47 +385,28 @@ export class Move {
402
385
  * Can be used even if the ranks do not exist
403
386
  */
404
387
  public async rebalanceProject() {
405
- const cards = await this.project.showProjectCards();
388
+ const cards = this.project.showProjectCards();
406
389
 
407
390
  await this.rebalanceProjectRecursively(cards);
408
391
 
409
- // rebalance templates
410
- const templates = await this.project.templates(ResourcesFrom.localOnly);
411
- for (const template of templates) {
412
- const templateResource = new TemplateResource(
413
- this.project,
414
- resourceName(template.name),
415
- );
416
- const templateObject = templateResource.templateObject();
417
-
418
- if (!templateObject) {
419
- throw new Error(`Template '${template.name}' not found`);
420
- }
421
-
422
- const templateCards = await templateObject.cards('', {
423
- parent: true,
424
- metadata: true,
425
- });
426
-
427
- const cardGroups = templateCards.reduce(
428
- (result, card) => {
429
- // template card root cards have a parent(the template itself) so this shouldn't happen
430
- if (!card.parent) {
431
- return result;
432
- }
433
- // if the parent does not exist yet in the result, we create it
434
- if (!result[card.parent]) {
435
- result[card.parent] = [];
436
- }
437
- result[card.parent].push(card);
392
+ const templateCards = this.project.allTemplateCards();
393
+ const cardGroups = templateCards.reduce(
394
+ (result, card) => {
395
+ // template card root cards always have a parent(, thus this shouldn't happen
396
+ if (!card.parent) {
438
397
  return result;
439
- },
440
- {} as Record<string, Card[]>,
441
- );
398
+ }
399
+ if (!result[card.parent]) {
400
+ result[card.parent] = [];
401
+ }
402
+ result[card.parent].push(card);
403
+ return result;
404
+ },
405
+ {} as Record<string, Card[]>,
406
+ );
442
407
 
443
- for (const [, cards] of Object.entries(cardGroups)) {
444
- await this.rebalanceCards(cards);
445
- }
408
+ for (const [, cards] of Object.entries(cardGroups)) {
409
+ await this.rebalanceCards(cards);
446
410
  }
447
411
  }
448
412
  }
@@ -11,23 +11,21 @@
11
11
  License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
12
  */
13
13
 
14
- // node
15
- import { join, sep } from 'node:path';
16
-
17
14
  import { ActionGuard } from '../permissions/action-guard.js';
18
- import { deleteDir, deleteFile } from '../utils/file-utils.js';
15
+ import { isModuleCard } from '../utils/card-utils.js';
19
16
  import { ModuleManager } from '../module-manager.js';
20
- import { Project } from '../containers/project.js';
17
+ import type { Project } from '../containers/project.js';
21
18
  import type { RemovableResourceTypes } from '../interfaces/project-interfaces.js';
22
- import { resourceName } from '../utils/resource-utils.js';
23
-
24
- const MODULES_PATH = `${sep}modules${sep}`;
25
19
 
26
20
  /**
27
21
  * Remove command.
28
22
  */
29
23
  export class Remove {
30
24
  private moduleManager: ModuleManager;
25
+ /**
26
+ * Creates a new instance of Remove command.
27
+ * @param project Project instance to use
28
+ */
31
29
  constructor(private project: Project) {
32
30
  this.moduleManager = new ModuleManager(this.project);
33
31
  }
@@ -53,45 +51,26 @@ export class Remove {
53
51
  throw new Error(`Attachment filename required`);
54
52
  }
55
53
 
56
- const attachmentFolder = await this.project.cardAttachmentFolder(cardKey);
57
-
58
- // Imported templates cannot be modified.
59
- if (attachmentFolder.includes(MODULES_PATH)) {
60
- throw new Error(`Cannot modify imported module`);
61
- }
62
-
63
- // Attachment's reside in 'a' folders.
64
- const success = await deleteFile(join(attachmentFolder, attachment));
65
- if (!success) {
66
- throw new Error('No such file');
67
- }
54
+ return this.project.removeCardAttachment(cardKey, attachment);
68
55
  }
69
56
 
70
57
  // Removes card from project or template
71
58
  private async removeCard(cardKey: string) {
72
- const cardFolder = await this.project.cardFolder(cardKey);
73
- if (!cardFolder) {
74
- throw new Error(`Card '${cardKey}' not found`);
75
- }
59
+ const card = this.project.findCard(cardKey);
76
60
 
77
61
  // Imported templates cannot be modified.
78
- if (cardFolder.includes(MODULES_PATH)) {
62
+ if (isModuleCard(card)) {
79
63
  throw new Error(`Cannot modify imported module`);
80
64
  }
81
65
 
82
66
  // Make sure card can be removed if it's a project card
83
- if (!(await this.project.isTemplateCard(cardKey))) {
67
+ if (this.project.hasProjectCard(cardKey)) {
84
68
  const actionGuard = new ActionGuard(this.project.calculationEngine);
85
69
  await actionGuard.checkPermission('delete', cardKey);
86
70
  }
87
71
 
88
72
  // If card is destination of a link, remove the link.
89
- const allCards = await this.project.cards(
90
- this.project.paths.cardRootFolder,
91
- {
92
- metadata: true,
93
- },
94
- );
73
+ const allCards = this.project.cards(this.project.paths.cardRootFolder);
95
74
  const promiseContainer: Promise<void>[] = [];
96
75
 
97
76
  for (const item of allCards) {
@@ -105,27 +84,14 @@ export class Remove {
105
84
 
106
85
  await Promise.all(promiseContainer);
107
86
 
108
- // Calculations need to be updated before card is removed.
109
- const card = await this.project.findSpecificCard(cardKey, {
110
- metadata: true,
111
- children: true,
112
- content: false,
113
- parent: false,
114
- });
115
- await deleteDir(cardFolder);
116
87
  if (card) {
117
- await this.project.handleDeleteCard(card);
88
+ await this.project.handleCardDeleted(card);
118
89
  }
119
90
  }
120
91
 
121
92
  // removes label from project
122
93
  private async removeLabel(cardKey: string, label: string) {
123
- const card = await this.project.findSpecificCard(cardKey, {
124
- metadata: true,
125
- });
126
- if (!card) {
127
- throw new Error(`Card '${cardKey}' does not exist in the project`);
128
- }
94
+ const card = this.project.findCard(cardKey);
129
95
  let labels = card.metadata?.labels ?? [];
130
96
 
131
97
  if (!label && labels.length !== 1) {
@@ -152,13 +118,7 @@ export class Remove {
152
118
  linkType?: string,
153
119
  linkDescription?: string,
154
120
  ) {
155
- const sourceCard = await this.project.findSpecificCard(sourceCardKey, {
156
- metadata: true,
157
- });
158
- if (!sourceCard) {
159
- throw new Error(`Card '${sourceCardKey}' not found`);
160
- }
161
-
121
+ const sourceCard = this.project.findCard(sourceCardKey);
162
122
  const link = sourceCard.metadata?.links.find(
163
123
  (l) =>
164
124
  l.cardKey === destinationCardKey &&
@@ -195,14 +155,15 @@ export class Remove {
195
155
  * @param rest Additional arguments
196
156
  * @note removing attachment requires card id and attachment filename
197
157
  * @note removing link requires card ids of source card, and optionally link type and link description
158
+ * @throws when removing an attachment, but attachment parameter is missing, or
159
+ * when removing link, some of the mandatory parameters are missing, or
160
+ * when trying to remove unknown type
198
161
  */
199
162
  public async remove(
200
163
  type: RemovableResourceTypes,
201
164
  targetName: string,
202
165
  ...rest: any[] // eslint-disable-line @typescript-eslint/no-explicit-any
203
166
  ) {
204
- const strictNameCheck = true;
205
-
206
167
  if (type === 'attachment' && rest.length !== 1 && !rest[0]) {
207
168
  throw new Error(
208
169
  `Input validation error: must pass argument 'detail' if requesting to remove attachment`,
@@ -220,9 +181,9 @@ export class Remove {
220
181
  );
221
182
  }
222
183
  if (this.projectResource(type)) {
223
- const resource = Project.resourceObject(
224
- this.project,
225
- resourceName(targetName, strictNameCheck),
184
+ const resource = this.project.resources.byType(
185
+ targetName,
186
+ this.project.resources.resourceTypeFromSingularType(type),
226
187
  );
227
188
  return resource?.delete();
228
189
  } else {