@cyberismo/data-handler 0.0.21 → 0.0.22

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 (166) hide show
  1. package/dist/command-handler.js +13 -24
  2. package/dist/command-handler.js.map +1 -1
  3. package/dist/command-manager.d.ts +21 -6
  4. package/dist/command-manager.js +34 -32
  5. package/dist/command-manager.js.map +1 -1
  6. package/dist/commands/calculate.js +101 -46
  7. package/dist/commands/calculate.js.map +1 -1
  8. package/dist/commands/create.js +417 -328
  9. package/dist/commands/create.js.map +1 -1
  10. package/dist/commands/edit.js +117 -68
  11. package/dist/commands/edit.js.map +1 -1
  12. package/dist/commands/export.js +301 -252
  13. package/dist/commands/export.js.map +1 -1
  14. package/dist/commands/fetch.js +205 -156
  15. package/dist/commands/fetch.js.map +1 -1
  16. package/dist/commands/import.js +189 -134
  17. package/dist/commands/import.js.map +1 -1
  18. package/dist/commands/migrate.js +91 -45
  19. package/dist/commands/migrate.js.map +1 -1
  20. package/dist/commands/move.js +347 -267
  21. package/dist/commands/move.js.map +1 -1
  22. package/dist/commands/remove.d.ts +1 -0
  23. package/dist/commands/remove.js +202 -135
  24. package/dist/commands/remove.js.map +1 -1
  25. package/dist/commands/rename.js +233 -187
  26. package/dist/commands/rename.js.map +1 -1
  27. package/dist/commands/show.d.ts +8 -8
  28. package/dist/commands/show.js +477 -372
  29. package/dist/commands/show.js.map +1 -1
  30. package/dist/commands/transition.js +119 -73
  31. package/dist/commands/transition.js.map +1 -1
  32. package/dist/commands/update.js +8 -3
  33. package/dist/commands/update.js.map +1 -1
  34. package/dist/commands/validate.js +1 -1
  35. package/dist/commands/validate.js.map +1 -1
  36. package/dist/containers/project/calculation-engine.js +0 -1
  37. package/dist/containers/project/calculation-engine.js.map +1 -1
  38. package/dist/containers/project/card-cache.js +1 -1
  39. package/dist/containers/project/card-cache.js.map +1 -1
  40. package/dist/containers/project.d.ts +16 -0
  41. package/dist/containers/project.js +59 -1
  42. package/dist/containers/project.js.map +1 -1
  43. package/dist/containers/template.js +1 -1
  44. package/dist/containers/template.js.map +1 -1
  45. package/dist/interfaces/command-options.d.ts +1 -0
  46. package/dist/interfaces/resource-interfaces.d.ts +5 -12
  47. package/dist/interfaces/resource-interfaces.js.map +1 -1
  48. package/dist/macros/base-macro.js +1 -1
  49. package/dist/macros/base-macro.js.map +1 -1
  50. package/dist/macros/graph/index.js +3 -1
  51. package/dist/macros/graph/index.js.map +1 -1
  52. package/dist/macros/index.js +3 -1
  53. package/dist/macros/index.js.map +1 -1
  54. package/dist/macros/report/index.js +1 -1
  55. package/dist/macros/report/index.js.map +1 -1
  56. package/dist/module-manager.js +5 -3
  57. package/dist/module-manager.js.map +1 -1
  58. package/dist/project-settings.js +2 -2
  59. package/dist/project-settings.js.map +1 -1
  60. package/dist/resources/card-type-resource.js +1 -1
  61. package/dist/resources/card-type-resource.js.map +1 -1
  62. package/dist/resources/create-defaults.js +0 -1
  63. package/dist/resources/create-defaults.js.map +1 -1
  64. package/dist/resources/field-type-resource.js +2 -5
  65. package/dist/resources/field-type-resource.js.map +1 -1
  66. package/dist/resources/file-resource.js +4 -1
  67. package/dist/resources/file-resource.js.map +1 -1
  68. package/dist/resources/folder-resource.d.ts +1 -1
  69. package/dist/resources/folder-resource.js +4 -1
  70. package/dist/resources/folder-resource.js.map +1 -1
  71. package/dist/resources/graph-model-resource.d.ts +1 -8
  72. package/dist/resources/graph-model-resource.js +0 -14
  73. package/dist/resources/graph-model-resource.js.map +1 -1
  74. package/dist/resources/graph-view-resource.d.ts +1 -8
  75. package/dist/resources/graph-view-resource.js +0 -14
  76. package/dist/resources/graph-view-resource.js.map +1 -1
  77. package/dist/resources/link-type-resource.js +1 -1
  78. package/dist/resources/link-type-resource.js.map +1 -1
  79. package/dist/resources/report-resource.d.ts +1 -8
  80. package/dist/resources/report-resource.js +0 -14
  81. package/dist/resources/report-resource.js.map +1 -1
  82. package/dist/resources/resource-object.d.ts +11 -1
  83. package/dist/resources/resource-object.js +19 -2
  84. package/dist/resources/resource-object.js.map +1 -1
  85. package/dist/resources/template-resource.d.ts +1 -9
  86. package/dist/resources/template-resource.js +0 -15
  87. package/dist/resources/template-resource.js.map +1 -1
  88. package/dist/resources/workflow-resource.js +1 -1
  89. package/dist/resources/workflow-resource.js.map +1 -1
  90. package/dist/utils/card-utils.js +1 -1
  91. package/dist/utils/card-utils.js.map +1 -1
  92. package/dist/utils/commit-context.d.ts +23 -0
  93. package/dist/utils/commit-context.js +30 -0
  94. package/dist/utils/commit-context.js.map +1 -0
  95. package/dist/utils/file-utils.js +3 -1
  96. package/dist/utils/file-utils.js.map +1 -1
  97. package/dist/utils/git-manager.d.ts +29 -0
  98. package/dist/utils/git-manager.js +76 -0
  99. package/dist/utils/git-manager.js.map +1 -0
  100. package/dist/utils/handlebars-helpers.d.ts +22 -0
  101. package/dist/utils/handlebars-helpers.js +78 -0
  102. package/dist/utils/handlebars-helpers.js.map +1 -0
  103. package/dist/utils/json.js +6 -2
  104. package/dist/utils/json.js.map +1 -1
  105. package/dist/utils/log-utils.d.ts +7 -2
  106. package/dist/utils/log-utils.js +28 -3
  107. package/dist/utils/log-utils.js.map +1 -1
  108. package/dist/utils/report.d.ts +0 -19
  109. package/dist/utils/report.js +4 -67
  110. package/dist/utils/report.js.map +1 -1
  111. package/dist/utils/rw-lock.d.ts +71 -0
  112. package/dist/utils/rw-lock.js +220 -0
  113. package/dist/utils/rw-lock.js.map +1 -0
  114. package/dist/utils/user-preferences.js +3 -3
  115. package/dist/utils/user-preferences.js.map +1 -1
  116. package/package.json +5 -5
  117. package/src/command-handler.ts +14 -22
  118. package/src/command-manager.ts +43 -37
  119. package/src/commands/calculate.ts +8 -1
  120. package/src/commands/create.ts +24 -1
  121. package/src/commands/edit.ts +3 -0
  122. package/src/commands/export.ts +8 -2
  123. package/src/commands/fetch.ts +3 -0
  124. package/src/commands/import.ts +5 -0
  125. package/src/commands/migrate.ts +2 -0
  126. package/src/commands/move.ts +34 -0
  127. package/src/commands/remove.ts +24 -2
  128. package/src/commands/rename.ts +2 -0
  129. package/src/commands/show.ts +63 -34
  130. package/src/commands/transition.ts +2 -0
  131. package/src/commands/update.ts +9 -3
  132. package/src/commands/validate.ts +1 -1
  133. package/src/containers/project/calculation-engine.ts +0 -1
  134. package/src/containers/project/card-cache.ts +1 -0
  135. package/src/containers/project.ts +75 -1
  136. package/src/containers/template.ts +1 -1
  137. package/src/interfaces/command-options.ts +1 -0
  138. package/src/interfaces/resource-interfaces.ts +5 -12
  139. package/src/macros/base-macro.ts +1 -1
  140. package/src/macros/graph/index.ts +3 -0
  141. package/src/macros/index.ts +3 -1
  142. package/src/macros/report/index.ts +1 -0
  143. package/src/module-manager.ts +5 -2
  144. package/src/project-settings.ts +2 -1
  145. package/src/resources/card-type-resource.ts +1 -1
  146. package/src/resources/create-defaults.ts +0 -1
  147. package/src/resources/field-type-resource.ts +2 -4
  148. package/src/resources/file-resource.ts +3 -1
  149. package/src/resources/folder-resource.ts +7 -2
  150. package/src/resources/graph-model-resource.ts +1 -25
  151. package/src/resources/graph-view-resource.ts +1 -25
  152. package/src/resources/link-type-resource.ts +1 -1
  153. package/src/resources/report-resource.ts +1 -25
  154. package/src/resources/resource-object.ts +22 -1
  155. package/src/resources/template-resource.ts +0 -23
  156. package/src/resources/workflow-resource.ts +1 -1
  157. package/src/utils/card-utils.ts +1 -1
  158. package/src/utils/commit-context.ts +45 -0
  159. package/src/utils/file-utils.ts +3 -1
  160. package/src/utils/git-manager.ts +87 -0
  161. package/src/utils/handlebars-helpers.ts +95 -0
  162. package/src/utils/json.ts +6 -2
  163. package/src/utils/log-utils.ts +33 -4
  164. package/src/utils/report.ts +8 -78
  165. package/src/utils/rw-lock.ts +279 -0
  166. package/src/utils/user-preferences.ts +3 -0
@@ -10,292 +10,372 @@
10
10
  details. You should have received a copy of the GNU Affero General Public
11
11
  License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
12
  */
13
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
14
+ var useValue = arguments.length > 2;
15
+ for (var i = 0; i < initializers.length; i++) {
16
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
17
+ }
18
+ return useValue ? value : void 0;
19
+ };
20
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
21
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
22
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
23
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
24
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
25
+ var _, done = false;
26
+ for (var i = decorators.length - 1; i >= 0; i--) {
27
+ var context = {};
28
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
29
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
30
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
31
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
32
+ if (kind === "accessor") {
33
+ if (result === void 0) continue;
34
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
35
+ if (_ = accept(result.get)) descriptor.get = _;
36
+ if (_ = accept(result.set)) descriptor.set = _;
37
+ if (_ = accept(result.init)) initializers.unshift(_);
38
+ }
39
+ else if (_ = accept(result)) {
40
+ if (kind === "field") initializers.unshift(_);
41
+ else descriptor[key] = _;
42
+ }
43
+ }
44
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
45
+ done = true;
46
+ };
13
47
  // node
14
48
  import { join } from 'node:path';
15
49
  import { ActionGuard } from '../permissions/action-guard.js';
16
50
  import { copyDir, deleteDir } from '../utils/file-utils.js';
51
+ import { write } from '../utils/rw-lock.js';
17
52
  import { EMPTY_RANK, FIRST_RANK, getRankAfter, getRankBetween, rebalanceRanks, sortItems, } from '../utils/lexorank.js';
18
53
  import { cardPathParts, isModuleCard, isTemplateCard, } from '../utils/card-utils.js';
19
54
  import { ROOT } from '../utils/constants.js';
20
- export class Move {
21
- project;
22
- constructor(project) {
23
- this.project = project;
24
- }
25
- // Returns children of a parent card or root cards
26
- getSiblings(card) {
27
- const parentCardKey = card.parent || ROOT;
28
- // since we don't know if 'root' is templateRoot or cardRoot, we need to check the card
29
- if (parentCardKey === ROOT) {
30
- if (isTemplateCard(card)) {
31
- if (isModuleCard(card)) {
32
- throw new Error(`Cannot rank module cards`);
55
+ let Move = (() => {
56
+ let _instanceExtraInitializers = [];
57
+ let _moveCard_decorators;
58
+ let _rankByIndex_decorators;
59
+ let _rankCard_decorators;
60
+ let _rankFirst_decorators;
61
+ let _rebalanceChildren_decorators;
62
+ let _rebalanceProject_decorators;
63
+ return class Move {
64
+ static {
65
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
66
+ _moveCard_decorators = [write((source, destination) => `Move card ${source} to ${destination}`)];
67
+ _rankByIndex_decorators = [write((cardKey) => `Reorder card ${cardKey}`)];
68
+ _rankCard_decorators = [write((cardKey) => `Reorder card ${cardKey}`)];
69
+ _rankFirst_decorators = [write((cardKey) => `Rank card ${cardKey} first`)];
70
+ _rebalanceChildren_decorators = [write((parentCardKey) => `Rebalance children of ${parentCardKey}`)];
71
+ _rebalanceProject_decorators = [write(() => 'Rebalance project')];
72
+ __esDecorate(this, null, _moveCard_decorators, { kind: "method", name: "moveCard", static: false, private: false, access: { has: obj => "moveCard" in obj, get: obj => obj.moveCard }, metadata: _metadata }, null, _instanceExtraInitializers);
73
+ __esDecorate(this, null, _rankByIndex_decorators, { kind: "method", name: "rankByIndex", static: false, private: false, access: { has: obj => "rankByIndex" in obj, get: obj => obj.rankByIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
74
+ __esDecorate(this, null, _rankCard_decorators, { kind: "method", name: "rankCard", static: false, private: false, access: { has: obj => "rankCard" in obj, get: obj => obj.rankCard }, metadata: _metadata }, null, _instanceExtraInitializers);
75
+ __esDecorate(this, null, _rankFirst_decorators, { kind: "method", name: "rankFirst", static: false, private: false, access: { has: obj => "rankFirst" in obj, get: obj => obj.rankFirst }, metadata: _metadata }, null, _instanceExtraInitializers);
76
+ __esDecorate(this, null, _rebalanceChildren_decorators, { kind: "method", name: "rebalanceChildren", static: false, private: false, access: { has: obj => "rebalanceChildren" in obj, get: obj => obj.rebalanceChildren }, metadata: _metadata }, null, _instanceExtraInitializers);
77
+ __esDecorate(this, null, _rebalanceProject_decorators, { kind: "method", name: "rebalanceProject", static: false, private: false, access: { has: obj => "rebalanceProject" in obj, get: obj => obj.rebalanceProject }, metadata: _metadata }, null, _instanceExtraInitializers);
78
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
79
+ }
80
+ project = __runInitializers(this, _instanceExtraInitializers);
81
+ constructor(project) {
82
+ this.project = project;
83
+ }
84
+ // Returns children of a parent card or root cards
85
+ getSiblings(card) {
86
+ const parentCardKey = card.parent || ROOT;
87
+ // since we don't know if 'root' is templateRoot or cardRoot, we need to check the card
88
+ if (parentCardKey === ROOT) {
89
+ if (isTemplateCard(card)) {
90
+ if (isModuleCard(card)) {
91
+ throw new Error(`Cannot rank module cards`);
92
+ }
93
+ const { template } = cardPathParts(this.project.projectPrefix, card.path);
94
+ return this.project.templateCards(template);
33
95
  }
34
- const { template } = cardPathParts(this.project.projectPrefix, card.path);
35
- return this.project.templateCards(template);
36
96
  }
37
- }
38
- let parentCard;
39
- if (parentCardKey !== ROOT) {
40
- parentCard = this.project.findCard(parentCardKey);
41
- return this.project.cardKeysToCards(parentCard.children);
42
- }
43
- return this.project
44
- .showProjectCards()
45
- .filter((item) => item.parent === 'root' || item.parent === '');
46
- }
47
- // Rebalances cards
48
- async rebalanceCards(cards) {
49
- const ranks = rebalanceRanks(cards.length);
50
- cards = sortItems(cards, (item) => item.metadata?.rank || 'z');
51
- for (let i = 0; i < cards.length; i++) {
52
- const card = cards[i];
53
- await this.project.updateCardMetadataKey(card.key, 'rank', ranks[i]);
54
- }
55
- }
56
- // Rebalances the project recursively.
57
- async rebalanceProjectRecursively(cards) {
58
- const ranks = rebalanceRanks(cards.length);
59
- cards = sortItems(cards, (item) => item.metadata?.rank || 'z');
60
- for (let i = 0; i < cards.length; i++) {
61
- const card = cards[i];
62
- await this.project.updateCardMetadataKey(card.key, 'rank', ranks[i]);
63
- if (card.children && card.children.length > 0) {
64
- await this.rebalanceProjectRecursively(this.project.cardKeysToCards(card.children));
97
+ let parentCard;
98
+ if (parentCardKey !== ROOT) {
99
+ parentCard = this.project.findCard(parentCardKey);
100
+ return this.project.cardKeysToCards(parentCard.children);
65
101
  }
66
- }
67
- }
68
- /**
69
- * Moves card from 'destination' to 'source'.
70
- * @param source source card to move
71
- * @param destination destination card where source card will be moved to; or to root
72
- */
73
- async moveCard(source, destination) {
74
- if (source === ROOT) {
75
- throw new Error('Cannot move "root"');
76
- }
77
- if (source === destination) {
78
- throw new Error(`Card cannot be moved to itself`);
79
- }
80
- const movingToRoot = destination === ROOT;
81
- const sourceCard = this.project.findCard(source);
82
- const destinationCard = !movingToRoot
83
- ? this.project.findCard(destination)
84
- : undefined;
85
- // Prevent moving card to inside its descendants
86
- if (destinationCard) {
87
- const { parents } = cardPathParts(this.project.projectPrefix, destinationCard.path);
88
- if (parents.includes(source)) {
89
- throw new Error(`Card cannot be moved to inside itself`);
102
+ return this.project
103
+ .showProjectCards()
104
+ .filter((item) => item.parent === 'root' || item.parent === '');
105
+ }
106
+ // Rebalances cards
107
+ async rebalanceCards(cards) {
108
+ const ranks = rebalanceRanks(cards.length);
109
+ cards = sortItems(cards, (item) => item.metadata?.rank || 'z');
110
+ for (let i = 0; i < cards.length; i++) {
111
+ const card = cards[i];
112
+ await this.project.updateCardMetadataKey(card.key, 'rank', ranks[i]);
90
113
  }
91
114
  }
92
- // Imported templates cannot be modified.
93
- if ((destinationCard && isModuleCard(destinationCard)) ||
94
- isModuleCard(sourceCard)) {
95
- throw new Error(`Cannot modify imported module templates`);
96
- }
97
- // Special handling for moving to root
98
- if (movingToRoot) {
99
- if (isTemplateCard(sourceCard)) {
100
- throw new Error(`Template cards cannot be moved to project root`);
115
+ // Rebalances the project recursively.
116
+ async rebalanceProjectRecursively(cards) {
117
+ const ranks = rebalanceRanks(cards.length);
118
+ cards = sortItems(cards, (item) => item.metadata?.rank || 'z');
119
+ for (let i = 0; i < cards.length; i++) {
120
+ const card = cards[i];
121
+ await this.project.updateCardMetadataKey(card.key, 'rank', ranks[i]);
122
+ if (card.children && card.children.length > 0) {
123
+ await this.rebalanceProjectRecursively(this.project.cardKeysToCards(card.children));
124
+ }
101
125
  }
102
126
  }
103
- else {
104
- const bothTemplateCards = isTemplateCard(sourceCard) &&
105
- destinationCard &&
106
- isTemplateCard(destinationCard);
107
- const bothProjectCards = this.project.hasProjectCard(sourceCard.key) &&
108
- destinationCard &&
109
- this.project.hasProjectCard(destinationCard.key);
110
- if (!(bothTemplateCards || bothProjectCards)) {
111
- throw new Error(`Cards cannot be moved from project to template or vice versa`);
127
+ /**
128
+ * Moves card from 'destination' to 'source'.
129
+ * @param source source card to move
130
+ * @param destination destination card where source card will be moved to; or to root
131
+ */
132
+ async moveCard(source, destination) {
133
+ if (source === ROOT) {
134
+ throw new Error('Cannot move "root"');
112
135
  }
113
- }
114
- const destinationPath = movingToRoot
115
- ? join(this.project.paths.cardRootFolder, sourceCard.key)
116
- : join(destinationCard.path, 'c', sourceCard.key);
117
- // if the card is already in the destination, do nothing
118
- if (sourceCard.path === destinationPath) {
119
- return;
120
- }
121
- // if both are project cards, make sure source card can be moved
122
- const actionGuard = new ActionGuard(this.project.calculationEngine);
123
- await actionGuard.checkPermission('move', source);
124
- // re-rank the card in the new location
125
- // it will be the last one in the new location
126
- let children;
127
- if (!movingToRoot) {
128
- const parent = this.project.findCard(destination);
129
- children = this.project.cardKeysToCards(parent.children);
130
- }
131
- else {
132
- children = this.project.showProjectCards();
133
- }
134
- if (!children) {
135
- throw new Error(`Children not found from card ${destination}`);
136
- }
137
- children = sortItems(children, (item) => item?.metadata?.rank || '1|z');
138
- const lastChild = children[children.length - 1];
139
- const rank = lastChild && lastChild.metadata
140
- ? getRankAfter(lastChild.metadata.rank)
141
- : FIRST_RANK;
142
- // First do the file operations, then update metadata
143
- await copyDir(sourceCard.path, destinationPath);
144
- await deleteDir(sourceCard.path);
145
- // Update card with new path, parent, and rank
146
- sourceCard.path = destinationPath;
147
- sourceCard.parent = movingToRoot ? ROOT : destination;
148
- if (sourceCard.metadata) {
149
- sourceCard.metadata.rank = rank;
150
- }
151
- // Handle cache update and persistence
152
- await this.project.updateCard(sourceCard);
153
- const updatedCard = {
154
- ...sourceCard,
155
- path: destinationPath,
156
- parent: movingToRoot ? ROOT : destination,
157
- metadata: sourceCard.metadata
158
- ? {
159
- ...sourceCard.metadata,
160
- rank: rank,
136
+ if (source === destination) {
137
+ throw new Error(`Card cannot be moved to itself`);
138
+ }
139
+ const movingToRoot = destination === ROOT;
140
+ const sourceCard = this.project.findCard(source);
141
+ const destinationCard = !movingToRoot
142
+ ? this.project.findCard(destination)
143
+ : undefined;
144
+ // Prevent moving card to inside its descendants
145
+ if (destinationCard) {
146
+ const { parents } = cardPathParts(this.project.projectPrefix, destinationCard.path);
147
+ if (parents.includes(source)) {
148
+ throw new Error(`Card cannot be moved to inside itself`);
161
149
  }
162
- : undefined,
163
- };
164
- // Fetch old parent
165
- const oldParent = sourceCard.parent;
166
- let oldParentCard;
167
- if (oldParent && oldParent !== ROOT) {
168
- oldParentCard = this.project.findCard(oldParent);
169
- }
170
- let newParentCard;
171
- if (!movingToRoot) {
172
- newParentCard = this.project.findCard(destination);
173
- }
174
- // Finally, update the project
175
- await this.project.handleCardMoved(updatedCard, newParentCard, oldParentCard);
176
- }
177
- /**
178
- * Ranks card using position given as 'index'.
179
- * @param cardKey card key
180
- * @param index to which position should card be ranked to
181
- */
182
- async rankByIndex(cardKey, index) {
183
- if (index < 0) {
184
- throw new Error(`Index must be greater than 0`);
185
- }
186
- if (index === 0) {
187
- await this.rankFirst(cardKey);
188
- return;
189
- }
190
- const card = this.project.findCard(cardKey);
191
- if (!card.parent) {
192
- throw new Error(`Parent card ${cardKey} not found from project`);
193
- }
194
- const children = sortItems(this.getSiblings(card), (item) => item.metadata?.rank || EMPTY_RANK);
195
- if (!children || children.length === 0) {
196
- throw new Error(`Children not found from card ${card.parent}`);
197
- }
198
- if (children.length < index) {
199
- throw new Error(`Index ${index} is out of bounds`);
200
- }
201
- await this.rankCard(cardKey, children[index - 1].key);
202
- }
203
- /**
204
- * Sets the rank of a card to be after another card.
205
- * @param cardKey Card to rank
206
- * @param beforeCardKey Card key after which the card will be ranked
207
- */
208
- async rankCard(cardKey, beforeCardKey) {
209
- const card = this.project.findCard(cardKey);
210
- const beforeCard = this.project.findCard(beforeCardKey);
211
- if (beforeCard.parent !== card.parent) {
212
- throw new Error(`Cards must be from the same parent`);
213
- }
214
- const children = sortItems(this.getSiblings(beforeCard), (item) => item.metadata?.rank || EMPTY_RANK);
215
- if (!children) {
216
- throw new Error(`Children not found from card ${beforeCard.parent}`);
217
- }
218
- const beforeCardIndex = children.findIndex((child) => child.key === beforeCard.key);
219
- if (beforeCardIndex === -1) {
220
- throw new Error(`Card ${beforeCardKey} is not a child of ${beforeCard.parent}`);
221
- }
222
- if (children[beforeCardIndex].key === cardKey) {
223
- throw new Error(`Card cannot be ranked after itself`);
224
- }
225
- if (beforeCardIndex === children.length - 1) {
226
- await this.project.updateCardMetadataKey(cardKey, 'rank', getRankAfter(beforeCard.metadata?.rank));
227
- }
228
- else {
229
- await this.project.updateCardMetadataKey(cardKey, 'rank', getRankBetween(beforeCard.metadata?.rank, children[beforeCardIndex + 1].metadata?.rank));
230
- }
231
- }
232
- /**
233
- * Ranks card first.
234
- * @param cardKey card key
235
- */
236
- async rankFirst(cardKey) {
237
- const card = this.project.findCard(cardKey);
238
- const children = sortItems(this.getSiblings(card), (item) => item.metadata?.rank || EMPTY_RANK);
239
- if (!children || children.length === 0) {
240
- throw new Error(`Children not found from card ${card.parent}`);
241
- }
242
- if (children[0].key === cardKey && children[0].metadata?.rank) {
243
- return;
244
- }
245
- const firstRank = children[0].metadata?.rank;
246
- if (!firstRank) {
247
- await this.project.updateCardMetadataKey(cardKey, 'rank', FIRST_RANK);
248
- return;
249
- }
250
- // Set the rank to be the first one
251
- if (firstRank === FIRST_RANK) {
252
- // if the first card is already at the first rank, we need to move the card to the next one
253
- const secondRank = children[1].metadata?.rank;
254
- if (!secondRank) {
255
- throw new Error(`Second rank not found`);
256
- }
257
- const rankBetween = getRankBetween(firstRank, secondRank);
258
- await this.project.updateCardMetadataKey(children[0].key, 'rank', rankBetween);
259
- await this.project.updateCardMetadataKey(cardKey, 'rank', firstRank);
260
- }
261
- else {
262
- // if the card is not at the first rank, we just use the first rank
263
- await this.project.updateCardMetadataKey(cardKey, 'rank', FIRST_RANK);
150
+ }
151
+ // Imported templates cannot be modified.
152
+ if ((destinationCard && isModuleCard(destinationCard)) ||
153
+ isModuleCard(sourceCard)) {
154
+ throw new Error(`Cannot modify imported module templates`);
155
+ }
156
+ // Special handling for moving to root
157
+ if (movingToRoot) {
158
+ if (isTemplateCard(sourceCard)) {
159
+ throw new Error(`Template cards cannot be moved to project root`);
160
+ }
161
+ }
162
+ else {
163
+ const bothTemplateCards = isTemplateCard(sourceCard) &&
164
+ destinationCard &&
165
+ isTemplateCard(destinationCard);
166
+ const bothProjectCards = this.project.hasProjectCard(sourceCard.key) &&
167
+ destinationCard &&
168
+ this.project.hasProjectCard(destinationCard.key);
169
+ if (!(bothTemplateCards || bothProjectCards)) {
170
+ throw new Error(`Cards cannot be moved from project to template or vice versa`);
171
+ }
172
+ }
173
+ const destinationPath = movingToRoot
174
+ ? join(this.project.paths.cardRootFolder, sourceCard.key)
175
+ : join(destinationCard.path, 'c', sourceCard.key);
176
+ // if the card is already in the destination, do nothing
177
+ if (sourceCard.path === destinationPath) {
178
+ return;
179
+ }
180
+ // if both are project cards, make sure source card can be moved
181
+ const actionGuard = new ActionGuard(this.project.calculationEngine);
182
+ await actionGuard.checkPermission('move', source);
183
+ // re-rank the card in the new location
184
+ // it will be the last one in the new location
185
+ let children;
186
+ if (!movingToRoot) {
187
+ const parent = this.project.findCard(destination);
188
+ children = this.project.cardKeysToCards(parent.children);
189
+ }
190
+ else {
191
+ children = this.project.showProjectCards();
192
+ }
193
+ if (!children) {
194
+ throw new Error(`Children not found from card ${destination}`);
195
+ }
196
+ children = sortItems(children, (item) => item?.metadata?.rank || '1|z');
197
+ const lastChild = children[children.length - 1];
198
+ const rank = lastChild && lastChild.metadata
199
+ ? getRankAfter(lastChild.metadata.rank)
200
+ : FIRST_RANK;
201
+ // Save old path before moving (needed to update descendant paths)
202
+ const oldPath = sourceCard.path;
203
+ // First do the file operations, then update metadata
204
+ await copyDir(sourceCard.path, destinationPath);
205
+ await deleteDir(sourceCard.path);
206
+ // Update card with new path, parent, and rank
207
+ sourceCard.path = destinationPath;
208
+ sourceCard.parent = movingToRoot ? ROOT : destination;
209
+ if (sourceCard.metadata) {
210
+ sourceCard.metadata.rank = rank;
211
+ }
212
+ // Update attachment paths for the moved card
213
+ if (sourceCard.attachments && sourceCard.attachments.length > 0) {
214
+ for (const attachment of sourceCard.attachments) {
215
+ if (attachment.path.startsWith(oldPath)) {
216
+ attachment.path = attachment.path.replace(oldPath, destinationPath);
217
+ }
218
+ }
219
+ }
220
+ // Handle cache update and persistence
221
+ await this.project.updateCard(sourceCard);
222
+ // Update all descendant card paths in the cache to reflect the new filesystem location.
223
+ // This is critical: files have been moved on disk, but children's cached paths
224
+ // still point to the old location. Without this, operations on children
225
+ // (like edit or delete) would target non-existent paths, leaving orphaned files.
226
+ if (sourceCard.children && sourceCard.children.length > 0) {
227
+ for (const childKey of sourceCard.children) {
228
+ this.project.updateDescendantPathsAfterMove(childKey, oldPath, destinationPath);
229
+ }
230
+ }
231
+ const updatedCard = {
232
+ ...sourceCard,
233
+ path: destinationPath,
234
+ parent: movingToRoot ? ROOT : destination,
235
+ metadata: sourceCard.metadata
236
+ ? {
237
+ ...sourceCard.metadata,
238
+ rank: rank,
239
+ }
240
+ : undefined,
241
+ };
242
+ // Fetch old parent
243
+ const oldParent = sourceCard.parent;
244
+ let oldParentCard;
245
+ if (oldParent && oldParent !== ROOT) {
246
+ oldParentCard = this.project.findCard(oldParent);
247
+ }
248
+ let newParentCard;
249
+ if (!movingToRoot) {
250
+ newParentCard = this.project.findCard(destination);
251
+ }
252
+ // Finally, update the project
253
+ await this.project.handleCardMoved(updatedCard, newParentCard, oldParentCard);
254
+ }
255
+ /**
256
+ * Ranks card using position given as 'index'.
257
+ * @param cardKey card key
258
+ * @param index to which position should card be ranked to
259
+ */
260
+ async rankByIndex(cardKey, index) {
261
+ if (index < 0) {
262
+ throw new Error(`Index must be greater than 0`);
263
+ }
264
+ if (index === 0) {
265
+ await this.rankFirst(cardKey);
266
+ return;
267
+ }
268
+ const card = this.project.findCard(cardKey);
269
+ if (!card.parent) {
270
+ throw new Error(`Parent card ${cardKey} not found from project`);
271
+ }
272
+ const children = sortItems(this.getSiblings(card), (item) => item.metadata?.rank || EMPTY_RANK);
273
+ if (!children || children.length === 0) {
274
+ throw new Error(`Children not found from card ${card.parent}`);
275
+ }
276
+ if (children.length < index) {
277
+ throw new Error(`Index ${index} is out of bounds`);
278
+ }
279
+ await this.rankCard(cardKey, children[index - 1].key);
280
+ }
281
+ /**
282
+ * Sets the rank of a card to be after another card.
283
+ * @param cardKey Card to rank
284
+ * @param beforeCardKey Card key after which the card will be ranked
285
+ */
286
+ async rankCard(cardKey, beforeCardKey) {
287
+ const card = this.project.findCard(cardKey);
288
+ const beforeCard = this.project.findCard(beforeCardKey);
289
+ if (beforeCard.parent !== card.parent) {
290
+ throw new Error(`Cards must be from the same parent`);
291
+ }
292
+ const children = sortItems(this.getSiblings(beforeCard), (item) => item.metadata?.rank || EMPTY_RANK);
293
+ if (!children) {
294
+ throw new Error(`Children not found from card ${beforeCard.parent}`);
295
+ }
296
+ const beforeCardIndex = children.findIndex((child) => child.key === beforeCard.key);
297
+ if (beforeCardIndex === -1) {
298
+ throw new Error(`Card ${beforeCardKey} is not a child of ${beforeCard.parent}`);
299
+ }
300
+ if (children[beforeCardIndex].key === cardKey) {
301
+ throw new Error(`Card cannot be ranked after itself`);
302
+ }
303
+ if (beforeCardIndex === children.length - 1) {
304
+ await this.project.updateCardMetadataKey(cardKey, 'rank', getRankAfter(beforeCard.metadata?.rank));
305
+ }
306
+ else {
307
+ await this.project.updateCardMetadataKey(cardKey, 'rank', getRankBetween(beforeCard.metadata?.rank, children[beforeCardIndex + 1].metadata?.rank));
308
+ }
264
309
  }
265
- }
266
- /**
267
- * Rebalances the ranks of the children of a card.
268
- * @param parentCardKey parent card key
269
- */
270
- async rebalanceChildren(parentCardKey) {
271
- const parentCard = this.project.findCard(parentCardKey);
272
- if (!parentCard || !parentCard.children) {
273
- throw new Error(`Card ${parentCardKey} not found from project`);
310
+ /**
311
+ * Ranks card first.
312
+ * @param cardKey card key
313
+ */
314
+ async rankFirst(cardKey) {
315
+ const card = this.project.findCard(cardKey);
316
+ const children = sortItems(this.getSiblings(card), (item) => item.metadata?.rank || EMPTY_RANK);
317
+ if (!children || children.length === 0) {
318
+ throw new Error(`Children not found from card ${card.parent}`);
319
+ }
320
+ if (children[0].key === cardKey && children[0].metadata?.rank) {
321
+ return;
322
+ }
323
+ const firstRank = children[0].metadata?.rank;
324
+ if (!firstRank) {
325
+ await this.project.updateCardMetadataKey(cardKey, 'rank', FIRST_RANK);
326
+ return;
327
+ }
328
+ // Set the rank to be the first one
329
+ if (firstRank === FIRST_RANK) {
330
+ // if the first card is already at the first rank, we need to move the card to the next one
331
+ const secondRank = children[1].metadata?.rank;
332
+ if (!secondRank) {
333
+ throw new Error(`Second rank not found`);
334
+ }
335
+ const rankBetween = getRankBetween(firstRank, secondRank);
336
+ await this.project.updateCardMetadataKey(children[0].key, 'rank', rankBetween);
337
+ await this.project.updateCardMetadataKey(cardKey, 'rank', firstRank);
338
+ }
339
+ else {
340
+ // if the card is not at the first rank, we just use the first rank
341
+ await this.project.updateCardMetadataKey(cardKey, 'rank', FIRST_RANK);
342
+ }
274
343
  }
275
- await this.rebalanceCards(this.project.cardKeysToCards(parentCard.children));
276
- }
277
- /**
278
- * Rebalances the ranks of the cards in the whole project, including templates
279
- * Can be used even if the ranks do not exist
280
- */
281
- async rebalanceProject() {
282
- const cards = this.project.showProjectCards();
283
- await this.rebalanceProjectRecursively(cards);
284
- const templateCards = this.project.allTemplateCards();
285
- const cardGroups = templateCards.reduce((result, card) => {
286
- // template card root cards always have a parent(, thus this shouldn't happen
287
- if (!card.parent) {
288
- return result;
344
+ /**
345
+ * Rebalances the ranks of the children of a card.
346
+ * @param parentCardKey parent card key
347
+ */
348
+ async rebalanceChildren(parentCardKey) {
349
+ const parentCard = this.project.findCard(parentCardKey);
350
+ if (!parentCard || !parentCard.children) {
351
+ throw new Error(`Card ${parentCardKey} not found from project`);
289
352
  }
290
- if (!result[card.parent]) {
291
- result[card.parent] = [];
353
+ await this.rebalanceCards(this.project.cardKeysToCards(parentCard.children));
354
+ }
355
+ /**
356
+ * Rebalances the ranks of the cards in the whole project, including templates
357
+ * Can be used even if the ranks do not exist
358
+ */
359
+ async rebalanceProject() {
360
+ const cards = this.project.showProjectCards();
361
+ await this.rebalanceProjectRecursively(cards);
362
+ const templateCards = this.project.allTemplateCards();
363
+ const cardGroups = templateCards.reduce((result, card) => {
364
+ // template card root cards always have a parent(, thus this shouldn't happen
365
+ if (!card.parent) {
366
+ return result;
367
+ }
368
+ if (!result[card.parent]) {
369
+ result[card.parent] = [];
370
+ }
371
+ result[card.parent].push(card);
372
+ return result;
373
+ }, {});
374
+ for (const [, cards] of Object.entries(cardGroups)) {
375
+ await this.rebalanceCards(cards);
292
376
  }
293
- result[card.parent].push(card);
294
- return result;
295
- }, {});
296
- for (const [, cards] of Object.entries(cardGroups)) {
297
- await this.rebalanceCards(cards);
298
377
  }
299
- }
300
- }
378
+ };
379
+ })();
380
+ export { Move };
301
381
  //# sourceMappingURL=move.js.map