@cyberismo/data-handler 0.0.2

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 (306) hide show
  1. package/LICENSE +702 -0
  2. package/dist/card-metadata-updater.d.ts +33 -0
  3. package/dist/card-metadata-updater.js +121 -0
  4. package/dist/card-metadata-updater.js.map +1 -0
  5. package/dist/command-handler.d.ts +96 -0
  6. package/dist/command-handler.js +557 -0
  7. package/dist/command-handler.js.map +1 -0
  8. package/dist/command-manager.d.ts +43 -0
  9. package/dist/command-manager.js +73 -0
  10. package/dist/command-manager.js.map +1 -0
  11. package/dist/commands/calculate.d.ts +86 -0
  12. package/dist/commands/calculate.js +444 -0
  13. package/dist/commands/calculate.js.map +1 -0
  14. package/dist/commands/create.d.ts +114 -0
  15. package/dist/commands/create.js +389 -0
  16. package/dist/commands/create.js.map +1 -0
  17. package/dist/commands/edit.d.ts +37 -0
  18. package/dist/commands/edit.js +99 -0
  19. package/dist/commands/edit.js.map +1 -0
  20. package/dist/commands/export-site.d.ts +45 -0
  21. package/dist/commands/export-site.js +301 -0
  22. package/dist/commands/export-site.js.map +1 -0
  23. package/dist/commands/export.d.ts +53 -0
  24. package/dist/commands/export.js +251 -0
  25. package/dist/commands/export.js.map +1 -0
  26. package/dist/commands/import.d.ts +53 -0
  27. package/dist/commands/import.js +133 -0
  28. package/dist/commands/import.js.map +1 -0
  29. package/dist/commands/index.d.ts +26 -0
  30. package/dist/commands/index.js +27 -0
  31. package/dist/commands/index.js.map +1 -0
  32. package/dist/commands/move.d.ts +55 -0
  33. package/dist/commands/move.js +341 -0
  34. package/dist/commands/move.js.map +1 -0
  35. package/dist/commands/remove.d.ts +38 -0
  36. package/dist/commands/remove.js +192 -0
  37. package/dist/commands/remove.js.map +1 -0
  38. package/dist/commands/rename.d.ts +46 -0
  39. package/dist/commands/rename.js +289 -0
  40. package/dist/commands/rename.js.map +1 -0
  41. package/dist/commands/show.d.ts +124 -0
  42. package/dist/commands/show.js +345 -0
  43. package/dist/commands/show.js.map +1 -0
  44. package/dist/commands/transition.d.ts +27 -0
  45. package/dist/commands/transition.js +92 -0
  46. package/dist/commands/transition.js.map +1 -0
  47. package/dist/commands/update.d.ts +29 -0
  48. package/dist/commands/update.js +64 -0
  49. package/dist/commands/update.js.map +1 -0
  50. package/dist/commands/validate.d.ts +143 -0
  51. package/dist/commands/validate.js +689 -0
  52. package/dist/commands/validate.js.map +1 -0
  53. package/dist/containers/card-container.d.ts +44 -0
  54. package/dist/containers/card-container.js +282 -0
  55. package/dist/containers/card-container.js.map +1 -0
  56. package/dist/containers/project/project-paths.d.ts +46 -0
  57. package/dist/containers/project/project-paths.js +105 -0
  58. package/dist/containers/project/project-paths.js.map +1 -0
  59. package/dist/containers/project/resource-collector.d.ts +86 -0
  60. package/dist/containers/project/resource-collector.js +331 -0
  61. package/dist/containers/project/resource-collector.js.map +1 -0
  62. package/dist/containers/project.d.ts +351 -0
  63. package/dist/containers/project.js +896 -0
  64. package/dist/containers/project.js.map +1 -0
  65. package/dist/containers/template.d.ts +108 -0
  66. package/dist/containers/template.js +433 -0
  67. package/dist/containers/template.js.map +1 -0
  68. package/dist/exceptions/index.d.ts +19 -0
  69. package/dist/exceptions/index.js +26 -0
  70. package/dist/exceptions/index.js.map +1 -0
  71. package/dist/index.d.ts +16 -0
  72. package/dist/index.js +15 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/interfaces/adoc.d.ts +12 -0
  75. package/dist/interfaces/adoc.js +13 -0
  76. package/dist/interfaces/adoc.js.map +1 -0
  77. package/dist/interfaces/macros.d.ts +45 -0
  78. package/dist/interfaces/macros.js +13 -0
  79. package/dist/interfaces/macros.js.map +1 -0
  80. package/dist/interfaces/project-interfaces.d.ts +121 -0
  81. package/dist/interfaces/project-interfaces.js +21 -0
  82. package/dist/interfaces/project-interfaces.js.map +1 -0
  83. package/dist/interfaces/request-status-interfaces.d.ts +28 -0
  84. package/dist/interfaces/request-status-interfaces.js +20 -0
  85. package/dist/interfaces/request-status-interfaces.js.map +1 -0
  86. package/dist/interfaces/resource-interfaces.d.ts +117 -0
  87. package/dist/interfaces/resource-interfaces.js +20 -0
  88. package/dist/interfaces/resource-interfaces.js.map +1 -0
  89. package/dist/macros/base-macro.d.ts +31 -0
  90. package/dist/macros/base-macro.js +126 -0
  91. package/dist/macros/base-macro.js.map +1 -0
  92. package/dist/macros/common.d.ts +17 -0
  93. package/dist/macros/common.js +23 -0
  94. package/dist/macros/common.js.map +1 -0
  95. package/dist/macros/createCards/index.d.ts +36 -0
  96. package/dist/macros/createCards/index.js +35 -0
  97. package/dist/macros/createCards/index.js.map +1 -0
  98. package/dist/macros/createCards/metadata.d.ts +14 -0
  99. package/dist/macros/createCards/metadata.js +18 -0
  100. package/dist/macros/createCards/metadata.js.map +1 -0
  101. package/dist/macros/graph/index.d.ts +29 -0
  102. package/dist/macros/graph/index.js +91 -0
  103. package/dist/macros/graph/index.js.map +1 -0
  104. package/dist/macros/graph/metadata.d.ts +14 -0
  105. package/dist/macros/graph/metadata.js +18 -0
  106. package/dist/macros/graph/metadata.js.map +1 -0
  107. package/dist/macros/index.d.ts +93 -0
  108. package/dist/macros/index.js +237 -0
  109. package/dist/macros/index.js.map +1 -0
  110. package/dist/macros/report/index.d.ts +26 -0
  111. package/dist/macros/report/index.js +70 -0
  112. package/dist/macros/report/index.js.map +1 -0
  113. package/dist/macros/report/metadata.d.ts +14 -0
  114. package/dist/macros/report/metadata.js +18 -0
  115. package/dist/macros/report/metadata.js.map +1 -0
  116. package/dist/macros/scoreCard/index.d.ts +30 -0
  117. package/dist/macros/scoreCard/index.js +38 -0
  118. package/dist/macros/scoreCard/index.js.map +1 -0
  119. package/dist/macros/scoreCard/metadata.d.ts +14 -0
  120. package/dist/macros/scoreCard/metadata.js +18 -0
  121. package/dist/macros/scoreCard/metadata.js.map +1 -0
  122. package/dist/macros/task-queue.d.ts +46 -0
  123. package/dist/macros/task-queue.js +69 -0
  124. package/dist/macros/task-queue.js.map +1 -0
  125. package/dist/module-manager.d.ts +62 -0
  126. package/dist/module-manager.js +350 -0
  127. package/dist/module-manager.js.map +1 -0
  128. package/dist/permissions/action-guard.d.ts +28 -0
  129. package/dist/permissions/action-guard.js +61 -0
  130. package/dist/permissions/action-guard.js.map +1 -0
  131. package/dist/project-settings.d.ts +42 -0
  132. package/dist/project-settings.js +120 -0
  133. package/dist/project-settings.js.map +1 -0
  134. package/dist/resources/array-handler.d.ts +28 -0
  135. package/dist/resources/array-handler.js +116 -0
  136. package/dist/resources/array-handler.js.map +1 -0
  137. package/dist/resources/card-type-resource.d.ts +72 -0
  138. package/dist/resources/card-type-resource.js +334 -0
  139. package/dist/resources/card-type-resource.js.map +1 -0
  140. package/dist/resources/create-defaults.d.ts +81 -0
  141. package/dist/resources/create-defaults.js +184 -0
  142. package/dist/resources/create-defaults.js.map +1 -0
  143. package/dist/resources/field-type-resource.d.ts +88 -0
  144. package/dist/resources/field-type-resource.js +411 -0
  145. package/dist/resources/field-type-resource.js.map +1 -0
  146. package/dist/resources/file-resource.d.ts +50 -0
  147. package/dist/resources/file-resource.js +301 -0
  148. package/dist/resources/file-resource.js.map +1 -0
  149. package/dist/resources/folder-resource.d.ts +66 -0
  150. package/dist/resources/folder-resource.js +100 -0
  151. package/dist/resources/folder-resource.js.map +1 -0
  152. package/dist/resources/graph-model-resource.d.ts +78 -0
  153. package/dist/resources/graph-model-resource.js +164 -0
  154. package/dist/resources/graph-model-resource.js.map +1 -0
  155. package/dist/resources/graph-view-resource.d.ts +78 -0
  156. package/dist/resources/graph-view-resource.js +163 -0
  157. package/dist/resources/graph-view-resource.js.map +1 -0
  158. package/dist/resources/link-type-resource.d.ts +62 -0
  159. package/dist/resources/link-type-resource.js +150 -0
  160. package/dist/resources/link-type-resource.js.map +1 -0
  161. package/dist/resources/report-resource.d.ts +77 -0
  162. package/dist/resources/report-resource.js +171 -0
  163. package/dist/resources/report-resource.js.map +1 -0
  164. package/dist/resources/resource-object.d.ts +108 -0
  165. package/dist/resources/resource-object.js +147 -0
  166. package/dist/resources/resource-object.js.map +1 -0
  167. package/dist/resources/template-resource.d.ts +82 -0
  168. package/dist/resources/template-resource.js +173 -0
  169. package/dist/resources/template-resource.js.map +1 -0
  170. package/dist/resources/workflow-resource.d.ts +67 -0
  171. package/dist/resources/workflow-resource.js +156 -0
  172. package/dist/resources/workflow-resource.js.map +1 -0
  173. package/dist/types/queries.d.ts +142 -0
  174. package/dist/types/queries.js +16 -0
  175. package/dist/types/queries.js.map +1 -0
  176. package/dist/utils/card-utils.d.ts +34 -0
  177. package/dist/utils/card-utils.js +78 -0
  178. package/dist/utils/card-utils.js.map +1 -0
  179. package/dist/utils/clingo-fact-builder.d.ts +58 -0
  180. package/dist/utils/clingo-fact-builder.js +126 -0
  181. package/dist/utils/clingo-fact-builder.js.map +1 -0
  182. package/dist/utils/clingo-facts.d.ts +97 -0
  183. package/dist/utils/clingo-facts.js +352 -0
  184. package/dist/utils/clingo-facts.js.map +1 -0
  185. package/dist/utils/clingo-parser.d.ts +59 -0
  186. package/dist/utils/clingo-parser.js +403 -0
  187. package/dist/utils/clingo-parser.js.map +1 -0
  188. package/dist/utils/clingo-program-builder.d.ts +39 -0
  189. package/dist/utils/clingo-program-builder.js +57 -0
  190. package/dist/utils/clingo-program-builder.js.map +1 -0
  191. package/dist/utils/common-utils.d.ts +24 -0
  192. package/dist/utils/common-utils.js +47 -0
  193. package/dist/utils/common-utils.js.map +1 -0
  194. package/dist/utils/constants.d.ts +18 -0
  195. package/dist/utils/constants.js +27 -0
  196. package/dist/utils/constants.js.map +1 -0
  197. package/dist/utils/csv.d.ts +18 -0
  198. package/dist/utils/csv.js +45 -0
  199. package/dist/utils/csv.js.map +1 -0
  200. package/dist/utils/file-utils.d.ts +69 -0
  201. package/dist/utils/file-utils.js +158 -0
  202. package/dist/utils/file-utils.js.map +1 -0
  203. package/dist/utils/json.d.ts +61 -0
  204. package/dist/utils/json.js +108 -0
  205. package/dist/utils/json.js.map +1 -0
  206. package/dist/utils/lexorank.d.ts +59 -0
  207. package/dist/utils/lexorank.js +159 -0
  208. package/dist/utils/lexorank.js.map +1 -0
  209. package/dist/utils/log-utils.d.ts +40 -0
  210. package/dist/utils/log-utils.js +109 -0
  211. package/dist/utils/log-utils.js.map +1 -0
  212. package/dist/utils/random.d.ts +19 -0
  213. package/dist/utils/random.js +34 -0
  214. package/dist/utils/random.js.map +1 -0
  215. package/dist/utils/resource-utils.d.ts +45 -0
  216. package/dist/utils/resource-utils.js +137 -0
  217. package/dist/utils/resource-utils.js.map +1 -0
  218. package/dist/utils/sanitize-svg.d.ts +18 -0
  219. package/dist/utils/sanitize-svg.js +38 -0
  220. package/dist/utils/sanitize-svg.js.map +1 -0
  221. package/dist/utils/user-preferences.d.ts +64 -0
  222. package/dist/utils/user-preferences.js +106 -0
  223. package/dist/utils/user-preferences.js.map +1 -0
  224. package/dist/utils/validate.d.ts +26 -0
  225. package/dist/utils/validate.js +53 -0
  226. package/dist/utils/validate.js.map +1 -0
  227. package/dist/utils/value-utils.d.ts +58 -0
  228. package/dist/utils/value-utils.js +181 -0
  229. package/dist/utils/value-utils.js.map +1 -0
  230. package/package.json +67 -0
  231. package/src/card-metadata-updater.ts +182 -0
  232. package/src/command-handler.ts +686 -0
  233. package/src/command-manager.ts +99 -0
  234. package/src/commands/calculate.ts +591 -0
  235. package/src/commands/create.ts +559 -0
  236. package/src/commands/edit.ts +123 -0
  237. package/src/commands/export-site.ts +356 -0
  238. package/src/commands/export.ts +315 -0
  239. package/src/commands/import.ts +169 -0
  240. package/src/commands/index.ts +42 -0
  241. package/src/commands/move.ts +451 -0
  242. package/src/commands/remove.ts +244 -0
  243. package/src/commands/rename.ts +378 -0
  244. package/src/commands/show.ts +442 -0
  245. package/src/commands/transition.ts +127 -0
  246. package/src/commands/update.ts +76 -0
  247. package/src/commands/validate.ts +962 -0
  248. package/src/containers/card-container.ts +378 -0
  249. package/src/containers/project/project-paths.ts +127 -0
  250. package/src/containers/project/resource-collector.ts +379 -0
  251. package/src/containers/project.ts +1135 -0
  252. package/src/containers/template.ts +573 -0
  253. package/src/exceptions/index.ts +29 -0
  254. package/src/index.ts +33 -0
  255. package/src/interfaces/adoc.ts +18 -0
  256. package/src/interfaces/macros.ts +54 -0
  257. package/src/interfaces/project-interfaces.ts +208 -0
  258. package/src/interfaces/request-status-interfaces.ts +30 -0
  259. package/src/interfaces/resource-interfaces.ts +179 -0
  260. package/src/macros/base-macro.ts +176 -0
  261. package/src/macros/common.ts +24 -0
  262. package/src/macros/createCards/index.ts +57 -0
  263. package/src/macros/createCards/metadata.ts +21 -0
  264. package/src/macros/graph/index.ts +130 -0
  265. package/src/macros/graph/metadata.ts +21 -0
  266. package/src/macros/index.ts +321 -0
  267. package/src/macros/report/index.ts +88 -0
  268. package/src/macros/report/metadata.ts +21 -0
  269. package/src/macros/scoreCard/index.ts +55 -0
  270. package/src/macros/scoreCard/metadata.ts +21 -0
  271. package/src/macros/task-queue.ts +79 -0
  272. package/src/module-manager.ts +443 -0
  273. package/src/permissions/action-guard.ts +77 -0
  274. package/src/project-settings.ts +140 -0
  275. package/src/resources/array-handler.ts +141 -0
  276. package/src/resources/card-type-resource.ts +455 -0
  277. package/src/resources/create-defaults.ts +216 -0
  278. package/src/resources/field-type-resource.ts +533 -0
  279. package/src/resources/file-resource.ts +433 -0
  280. package/src/resources/folder-resource.ts +140 -0
  281. package/src/resources/graph-model-resource.ts +205 -0
  282. package/src/resources/graph-view-resource.ts +199 -0
  283. package/src/resources/link-type-resource.ts +191 -0
  284. package/src/resources/report-resource.ts +224 -0
  285. package/src/resources/resource-object.ts +246 -0
  286. package/src/resources/template-resource.ts +210 -0
  287. package/src/resources/workflow-resource.ts +205 -0
  288. package/src/types/queries.ts +149 -0
  289. package/src/utils/card-utils.ts +83 -0
  290. package/src/utils/clingo-fact-builder.ts +167 -0
  291. package/src/utils/clingo-facts.ts +550 -0
  292. package/src/utils/clingo-parser.ts +519 -0
  293. package/src/utils/clingo-program-builder.ts +71 -0
  294. package/src/utils/common-utils.ts +54 -0
  295. package/src/utils/constants.ts +32 -0
  296. package/src/utils/csv.ts +53 -0
  297. package/src/utils/file-utils.ts +182 -0
  298. package/src/utils/json.ts +118 -0
  299. package/src/utils/lexorank.ts +180 -0
  300. package/src/utils/log-utils.ts +127 -0
  301. package/src/utils/random.ts +37 -0
  302. package/src/utils/resource-utils.ts +180 -0
  303. package/src/utils/sanitize-svg.ts +46 -0
  304. package/src/utils/user-preferences.ts +126 -0
  305. package/src/utils/validate.ts +66 -0
  306. package/src/utils/value-utils.ts +189 -0
@@ -0,0 +1,686 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2024
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation.
7
+ This program is distributed in the hope that it will be useful, but WITHOUT
8
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9
+ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
10
+ details. You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+
14
+ import { dirname, join, resolve } from 'node:path';
15
+ import { execFileSync } from 'node:child_process';
16
+ import { fileURLToPath } from 'node:url';
17
+ import { readFileSync } from 'node:fs';
18
+
19
+ import type {
20
+ Card,
21
+ CardAttachment,
22
+ CardListContainer,
23
+ FileContentType,
24
+ ModuleContent,
25
+ ProjectMetadata,
26
+ RemovableResourceTypes,
27
+ ResourceTypes,
28
+ } from './interfaces/project-interfaces.js';
29
+ import type {
30
+ DataType,
31
+ ResourceContent,
32
+ } from './interfaces/resource-interfaces.js';
33
+
34
+ import type { requestStatus } from './interfaces/request-status-interfaces.js';
35
+
36
+ import { Create, Validate } from './commands/index.js';
37
+ import { CommandManager } from './command-manager.js';
38
+ import type { UpdateOperations } from './resources/resource-object.js';
39
+ import { Project } from './containers/project.js';
40
+
41
+ import { pathExists, resolveTilde } from './utils/file-utils.js';
42
+ import { errorFunction } from './utils/log-utils.js';
43
+ import { readJsonFile } from './utils/json.js';
44
+ import { resourceName } from './utils/resource-utils.js';
45
+
46
+ // Generic options interface
47
+ export interface CardsOptions {
48
+ details?: boolean;
49
+ forceStart?: boolean;
50
+ projectPath?: string;
51
+ repeat?: number;
52
+ showUse?: boolean;
53
+ }
54
+
55
+ // Commands that this class supports.
56
+ // todo: Could be inside the `CommandHandler` ?
57
+ export enum Cmd {
58
+ add = 'add',
59
+ calc = 'calc',
60
+ create = 'create',
61
+ edit = 'edit',
62
+ export = 'export',
63
+ import = 'import',
64
+ move = 'move',
65
+ rank = 'rank',
66
+ remove = 'remove',
67
+ rename = 'rename',
68
+ report = 'report',
69
+ show = 'show',
70
+ start = 'start',
71
+ transition = 'transition',
72
+ update = 'update',
73
+ updateModules = 'update-modules',
74
+ validate = 'validate',
75
+ }
76
+
77
+ // To what format the content can be exported to.
78
+ export enum ExportFormats {
79
+ adoc = 'adoc',
80
+ html = 'html',
81
+ site = 'site',
82
+ }
83
+
84
+ export { CommandManager } from './command-manager.js';
85
+
86
+ /**
87
+ * Class that handles all CLI commands.
88
+ */
89
+ export class Commands {
90
+ private commands?: CommandManager;
91
+ private projectPath: string;
92
+ private validateCmd: Validate;
93
+
94
+ constructor() {
95
+ this.projectPath = '';
96
+ this.validateCmd = Validate.getInstance();
97
+ }
98
+
99
+ /**
100
+ * Executes one command for CLI.
101
+ *
102
+ * @note internal functions that this method calls, should return a Promise and throw on error.
103
+ * No internal trap harnesses; all exceptions from internal methods should be caught by this methods trap handler.
104
+ * If internal method has payload, the method should return requestStatus that can be directly returned from calling that function.
105
+ *
106
+ * @param command command to execute
107
+ * @param args arguments for the command
108
+ * @param options options for the command
109
+ * @returns request status; 200 if success; 400 in handled error; 500 in unknown error
110
+ */
111
+ public async command(
112
+ command: Cmd,
113
+ args: string[],
114
+ options: CardsOptions,
115
+ ): Promise<requestStatus> {
116
+ // Set project path and validate it.
117
+ const creatingNewProject = command === Cmd.create && args[0] === 'project';
118
+ if (!creatingNewProject) {
119
+ try {
120
+ await this.doSetProject(options.projectPath || '');
121
+ } catch (error) {
122
+ return { statusCode: 400, message: errorFunction(error) };
123
+ }
124
+ } else {
125
+ this.projectPath = options.projectPath || '';
126
+ }
127
+ return await this.doHandleCommand(command, args, options);
128
+ }
129
+
130
+ // Returns command 'target'.
131
+ // If name is resource name -> returns from <prefix/type/identifier> 'type' in singular form.
132
+ // If not, returns the input parameter.
133
+ private commandType<Type>(type: string): Type {
134
+ const resource = resourceName(type);
135
+ return (resource.type.substring(0, resource.type.length - 1) ||
136
+ type) as Type;
137
+ }
138
+
139
+ // If 'type' is resource name, replaces original 'target' with 'type'
140
+ private commandTarget(type: string, target: string) {
141
+ const resource = resourceName(type);
142
+ return resource.type ? type : target;
143
+ }
144
+
145
+ // Handles initializing the project so that it can be used in the class.
146
+ private async doSetProject(path: string) {
147
+ this.projectPath = resolveTilde(await this.setProjectPath(path));
148
+ if (!Validate.validateFolder(this.projectPath)) {
149
+ let errorMessage = '';
150
+ if (path === '' || path === undefined) {
151
+ errorMessage = `No 'cardRoot' in the current folder`;
152
+ } else {
153
+ errorMessage = `Input validation error: folder name '${path}' is invalid`;
154
+ }
155
+ throw new Error(errorMessage);
156
+ }
157
+
158
+ if (!pathExists(this.projectPath)) {
159
+ throw new Error(`Input validation error: cannot find project '${path}'`);
160
+ }
161
+
162
+ this.commands = await CommandManager.getInstance(this.projectPath);
163
+ if (!this.commands) {
164
+ throw new Error('Cannot get instance of CommandManager');
165
+ }
166
+ await this.commands.initialize();
167
+ }
168
+
169
+ // Handles actual command. Sets returns values correctly.
170
+ private async doHandleCommand(
171
+ command: Cmd,
172
+ args: string[],
173
+ options: CardsOptions,
174
+ ) {
175
+ try {
176
+ if (command === Cmd.add) {
177
+ const [template, cardType, cardKey] = args;
178
+ return await this.addCard(template, cardType, cardKey, options.repeat);
179
+ } else if (command === Cmd.calc) {
180
+ const [command, cardKey] = args;
181
+ if (command === 'run') {
182
+ if (!cardKey) {
183
+ return { statusCode: 400, message: 'File path is missing' };
184
+ }
185
+ await this.generateLogicProgram();
186
+ return this.runLogicProgram(cardKey);
187
+ }
188
+ if (command === 'generate') {
189
+ return this.generateLogicProgram(cardKey);
190
+ }
191
+ } else if (command === Cmd.create) {
192
+ const [type, ...rest] = args;
193
+ const target = this.commandType(type);
194
+ // If 'type' was used to deduce 'target', put the parameter back into the args.
195
+ if (target !== type) {
196
+ rest.unshift(type as string);
197
+ }
198
+ if (target === 'attachment') {
199
+ const [cardKey, attachment] = rest;
200
+ await this.commands?.createCmd.createAttachment(cardKey, attachment);
201
+ } else if (target === 'card') {
202
+ const [template, parent] = rest;
203
+ return await this.createCard(template, parent);
204
+ } else if (target === 'cardType') {
205
+ const [name, workflow] = rest;
206
+ await this.commands?.createCmd.createCardType(name, workflow);
207
+ } else if (target === 'fieldType') {
208
+ const [name, datatype] = rest;
209
+ await this.commands?.createCmd.createFieldType(
210
+ name,
211
+ datatype as DataType,
212
+ );
213
+ } else if (target === 'graphModel') {
214
+ const [name] = rest;
215
+ await this.commands?.createCmd.createGraphModel(name);
216
+ } else if (target === 'graphView') {
217
+ const [name] = rest;
218
+ await this.commands?.createCmd.createGraphView(name);
219
+ } else if (target == 'label') {
220
+ const [cardKey, label] = rest;
221
+ await this.commands?.createCmd.createLabel(cardKey, label);
222
+ } else if (target === 'link') {
223
+ const [cardKey, destinationCardKey, linkType, linkDescription] = rest;
224
+ await this.commands?.createCmd.createLink(
225
+ cardKey,
226
+ destinationCardKey,
227
+ linkType,
228
+ linkDescription,
229
+ );
230
+ } else if (target === 'linkType') {
231
+ const [name] = rest;
232
+ await this.commands?.createCmd.createLinkType(name);
233
+ } else if (target === 'project') {
234
+ const [name, prefix] = rest;
235
+ await Create.createProject(
236
+ resolveTilde(this.projectPath),
237
+ prefix,
238
+ name,
239
+ );
240
+ } else if (target === 'report') {
241
+ const [name] = rest;
242
+ await this.commands?.createCmd.createReport(name);
243
+ } else if (target === 'template') {
244
+ const [name, content] = rest;
245
+ await this.commands?.createCmd.createTemplate(name, content);
246
+ } else if (target === 'workflow') {
247
+ const [name, content] = rest;
248
+ await this.commands?.createCmd.createWorkflow(name, content);
249
+ } else {
250
+ throw new Error(`Unknown type to create: '${target}'`);
251
+ }
252
+ } else if (command === Cmd.edit) {
253
+ const [cardKey] = args;
254
+ await this.commands?.editCmd.editCard(cardKey);
255
+ } else if (command === Cmd.export) {
256
+ const [format, output, cardKey] = args;
257
+ await this.export(output, format as ExportFormats, cardKey);
258
+ } else if (command === Cmd.import) {
259
+ const target = args.splice(0, 1)[0];
260
+ if (target === 'module') {
261
+ const [source, branch, useCredentials] = args;
262
+ await this.import(
263
+ source,
264
+ branch,
265
+ useCredentials && useCredentials === 'true' ? true : false,
266
+ );
267
+ }
268
+ if (target === 'csv') {
269
+ const [csvFile, cardKey] = args;
270
+ return await this.importCsv(csvFile, cardKey);
271
+ }
272
+ } else if (command === Cmd.move) {
273
+ const [source, destination] = args;
274
+ await this.commands?.moveCmd.moveCard(source, destination);
275
+ } else if (command === Cmd.rank) {
276
+ const target = args.splice(0, 1)[0];
277
+ if (target === 'card') {
278
+ const [card, before] = args;
279
+ if (before === 'first') {
280
+ await this.commands?.moveCmd.rankFirst(card);
281
+ } else {
282
+ await this.commands?.moveCmd.rankCard(card, before);
283
+ }
284
+ } else if (target === 'rebalance') {
285
+ const [cardKey] = args;
286
+ if (cardKey) {
287
+ await this.commands?.moveCmd.rebalanceChildren(cardKey);
288
+ } else {
289
+ await this.commands?.moveCmd.rebalanceProject();
290
+ }
291
+ }
292
+ } else if (command === Cmd.remove) {
293
+ const [type, target, ...rest] = args;
294
+ await this.remove(
295
+ this.commandType(type),
296
+ this.commandTarget(type, target),
297
+ rest,
298
+ );
299
+ } else if (command === Cmd.rename) {
300
+ const [to] = args;
301
+ await this.commands?.renameCmd.rename(to);
302
+ } else if (command === Cmd.show) {
303
+ const [type, detail] = args;
304
+ options.projectPath = this.projectPath;
305
+ return this.show(
306
+ this.commandType(type),
307
+ this.commandTarget(type, detail),
308
+ options,
309
+ );
310
+ } else if (command === Cmd.report) {
311
+ const [parameters, outputPath] = args;
312
+ return this.runReport(parameters, outputPath);
313
+ } else if (command === Cmd.start) {
314
+ return this.startApp(options.forceStart);
315
+ } else if (command === Cmd.transition) {
316
+ const [cardKey, state] = args;
317
+ await this.commands?.transitionCmd.cardTransition(cardKey, {
318
+ name: state,
319
+ });
320
+ } else if (command === Cmd.update) {
321
+ const [resource, operation, key, value, newValue] = args;
322
+ let parsedValue = '';
323
+ try {
324
+ parsedValue = JSON.parse(value);
325
+ } catch {
326
+ parsedValue = value;
327
+ }
328
+
329
+ await this.commands?.updateCmd.updateValue(
330
+ resource,
331
+ operation as UpdateOperations,
332
+ key,
333
+ parsedValue,
334
+ newValue ? JSON.parse(newValue) : undefined,
335
+ );
336
+ } else if (command === Cmd.updateModules) {
337
+ await this.commands?.importCmd.updateAllModules();
338
+ } else if (command === Cmd.validate) {
339
+ return this.validate();
340
+ } else {
341
+ return { statusCode: 500, message: 'Unknown command' };
342
+ }
343
+ } catch (e) {
344
+ return { statusCode: 400, message: errorFunction(e) };
345
+ }
346
+ return { statusCode: 200 };
347
+ }
348
+
349
+ /**
350
+ * Returns project path, if running operation within project folder.
351
+ * @param path Initial path from where the project path search is started.
352
+ */
353
+ public async getProjectPath(path?: string): Promise<string> {
354
+ return this.setProjectPath(path);
355
+ }
356
+
357
+ /**
358
+ * Returns project path, if running operation within project folder.
359
+ * Implementation will automatically look for valid project path starting from 'path' and moving upwards in the
360
+ * path until 'root' is reached.
361
+ * @param path Initial path from where the project path search is started.
362
+ * Returns valid project path (contains both .cards and cardRoot subfolders).
363
+ */
364
+ public async setProjectPath(path?: string): Promise<string> {
365
+ // Check that path is a project path; ie. contains both .cards and cardRoot subfolders.
366
+ function isProjectPath(path: string) {
367
+ const cardsPath = resolve(join(path, '.cards'));
368
+ const cardRootPath = resolve(join(path, 'cardRoot'));
369
+ return pathExists(cardsPath) && pathExists(cardRootPath);
370
+ }
371
+
372
+ if (!path) {
373
+ path = await Project.findProjectRoot(process.cwd());
374
+ if (path === '') {
375
+ console.error(
376
+ 'No path defined with "-p" flag and could not find project. Sorry.',
377
+ );
378
+ process.exit(1);
379
+ }
380
+ }
381
+ path = resolveTilde(path);
382
+ return isProjectPath(path) ? path : '';
383
+ }
384
+
385
+ // Adds a new card to a template.
386
+ private async addCard(
387
+ templateName: string,
388
+ cardTypeName: string,
389
+ cardKey: string,
390
+ repeat?: number,
391
+ ): Promise<requestStatus> {
392
+ const addedCards = await this.commands?.createCmd.addCards(
393
+ cardTypeName,
394
+ templateName,
395
+ cardKey,
396
+ repeat,
397
+ );
398
+
399
+ if (!addedCards || addedCards.length === 0) {
400
+ throw new Error('Failed to add cards');
401
+ }
402
+
403
+ const messageTxt =
404
+ addedCards.length > 1
405
+ ? `${addedCards.length} cards were added to the template '${templateName} : ${JSON.stringify(addedCards)}'`
406
+ : `card '${addedCards[0]}' was added to the template '${templateName}'`;
407
+
408
+ return {
409
+ statusCode: 200,
410
+ affectsCards: addedCards,
411
+ message: messageTxt,
412
+ };
413
+ }
414
+
415
+ // Creates a new card to a project, or to a template.
416
+ private async createCard(
417
+ templateName: string,
418
+ parentCardKey: string,
419
+ ): Promise<requestStatus> {
420
+ const createdCards = await this.commands?.createCmd.createCard(
421
+ templateName,
422
+ parentCardKey,
423
+ );
424
+ return {
425
+ statusCode: 200,
426
+ affectsCards: createdCards?.map((card) => card.key),
427
+ message: `Created cards ${JSON.stringify(createdCards?.map((card) => card.key))}`,
428
+ };
429
+ }
430
+
431
+ // Exports whole or partial card tree to a given format.
432
+ private async export(
433
+ destination: string = 'output',
434
+ format: ExportFormats,
435
+ parentCardKey?: string,
436
+ ): Promise<requestStatus> {
437
+ if (!this.commands) {
438
+ return { statusCode: 500 };
439
+ }
440
+ process.env.EXPORT_FORMAT = format;
441
+ let message = '';
442
+ if (format === 'adoc') {
443
+ message = await this.commands?.exportCmd.exportToADoc(
444
+ destination,
445
+ parentCardKey,
446
+ );
447
+ } else if (format === 'html') {
448
+ message = await this.commands?.exportCmd.exportToHTML(
449
+ destination,
450
+ parentCardKey,
451
+ );
452
+ } else if (format === 'site') {
453
+ message = await this.commands?.exportSiteCmd.exportToSite(
454
+ destination,
455
+ parentCardKey,
456
+ );
457
+ }
458
+ process.env.EXPORT_FORMAT = '';
459
+ return { statusCode: 200, message: message };
460
+ }
461
+
462
+ // Generates logic program for a card.
463
+ private async generateLogicProgram(cardKey?: string): Promise<requestStatus> {
464
+ try {
465
+ await this.commands?.calculateCmd.generate(cardKey);
466
+ return { statusCode: 200 };
467
+ } catch (e) {
468
+ return { statusCode: 500, message: errorFunction(e) };
469
+ }
470
+ }
471
+
472
+ // Imports another project to the 'destination' project as a module.
473
+ private async import(
474
+ source: string,
475
+ branch?: string,
476
+ useCredentials?: boolean,
477
+ ) {
478
+ return this.commands?.importCmd.importModule(source, this.projectPath, {
479
+ branch: branch,
480
+ private: useCredentials,
481
+ });
482
+ }
483
+
484
+ // Imports cards from a CSV file to a project.
485
+ private async importCsv(
486
+ filePath: string,
487
+ parentCardKey: string,
488
+ ): Promise<requestStatus> {
489
+ const cards = await this.commands?.importCmd.importCsv(
490
+ filePath,
491
+ parentCardKey,
492
+ );
493
+ return {
494
+ statusCode: 200,
495
+ message: `Imported cards:`,
496
+ payload: cards,
497
+ };
498
+ }
499
+
500
+ // Removes a card (single card, or parent card and children), or an attachment.
501
+ private async remove(
502
+ type: RemovableResourceTypes,
503
+ targetName: string,
504
+ args: string[],
505
+ ): Promise<void> {
506
+ return await this.commands?.removeCmd.remove(type, targetName, ...args);
507
+ }
508
+
509
+ // Runs a given logic program along with the query-language
510
+ private async runLogicProgram(filePath: string): Promise<requestStatus> {
511
+ try {
512
+ const res = await this.commands?.calculateCmd.runLogicProgram({
513
+ query: readFileSync(filePath, 'utf-8'),
514
+ });
515
+ return {
516
+ statusCode: 200,
517
+ payload: res,
518
+ };
519
+ } catch (e) {
520
+ return { statusCode: 500, message: errorFunction(e) };
521
+ }
522
+ }
523
+
524
+ // Runs a report using Handlebars and the provided parameters.
525
+ private async runReport(parametersPath: string, outputPath?: string) {
526
+ const parametersFile = await readJsonFile(parametersPath);
527
+
528
+ // Validate the parameters file.
529
+ if (!parametersFile.name) {
530
+ return {
531
+ statusCode: 500,
532
+ message:
533
+ 'The parameters file must include a "name" field (report name).',
534
+ };
535
+ }
536
+ if (!parametersFile.parameters) {
537
+ return {
538
+ statusCode: 500,
539
+ message:
540
+ 'The parameters file must include a "parameters" field (report parameters).',
541
+ };
542
+ }
543
+ if (!parametersFile.parameters.cardKey) {
544
+ return {
545
+ statusCode: 500,
546
+ message:
547
+ 'The parameters file must include a "cardKey" field included in the "parameters".',
548
+ };
549
+ }
550
+
551
+ const { name, parameters } = parametersFile;
552
+ let result: string | undefined = '';
553
+ try {
554
+ result = await this.commands?.showCmd.showReportResults(
555
+ name,
556
+ parameters.cardKey,
557
+ parameters,
558
+ outputPath,
559
+ );
560
+ } catch (e) {
561
+ return { statusCode: 500, message: errorFunction(e) };
562
+ }
563
+
564
+ const message = !result && !outputPath ? 'No report results' : result;
565
+ return { statusCode: 200, message: message };
566
+ }
567
+
568
+ // Shows wanted resources from a project / template.
569
+ private async show(
570
+ type: ResourceTypes,
571
+ typeDetail: string,
572
+ options: CardsOptions,
573
+ ): Promise<requestStatus> {
574
+ const detail = typeDetail || '';
575
+ let promise: Promise<
576
+ | Card
577
+ | CardAttachment[]
578
+ | CardListContainer[]
579
+ | ModuleContent
580
+ | ProjectMetadata
581
+ | ResourceContent
582
+ | string[]
583
+ | undefined
584
+ >;
585
+
586
+ switch (type) {
587
+ case 'attachments':
588
+ promise = this.commands!.showCmd.showAttachments();
589
+ break;
590
+ case 'card':
591
+ {
592
+ const cardDetails = {
593
+ contentType: 'adoc' as FileContentType,
594
+ content: options?.details,
595
+ metadata: true,
596
+ children: options?.details,
597
+ parent: options?.details,
598
+ attachments: true,
599
+ };
600
+ promise = this.commands!.showCmd.showCardDetails(cardDetails, detail);
601
+ }
602
+ break;
603
+ case 'cards':
604
+ promise = this.commands!.showCmd.showCards();
605
+ break;
606
+ case 'cardType':
607
+ case 'fieldType':
608
+ case 'graphView':
609
+ case 'graphModel':
610
+ case 'linkType':
611
+ case 'report':
612
+ case 'template':
613
+ case 'workflow':
614
+ promise = this.commands!.showCmd.showResource(detail, options.showUse);
615
+ break;
616
+ case 'cardTypes':
617
+ case 'fieldTypes':
618
+ case 'graphModels':
619
+ case 'graphViews':
620
+ case 'linkTypes':
621
+ case 'reports':
622
+ case 'templates':
623
+ case 'workflows':
624
+ promise = this.commands!.showCmd.showResources(type);
625
+ break;
626
+ case 'labels':
627
+ promise = this.commands!.showCmd.showLabels();
628
+ break;
629
+ case 'module':
630
+ promise = this.commands!.showCmd.showModule(detail);
631
+ break;
632
+ case 'modules':
633
+ promise = this.commands!.showCmd.showModules();
634
+ break;
635
+ case 'project':
636
+ promise = this.commands!.showCmd.showProject();
637
+ break;
638
+ case 'attachment': // fallthrough - not implemented yet
639
+ case 'link': // fallthrough - not implemented yet
640
+ case 'links': // fallthrough - not implemented yet
641
+ case 'label':
642
+ default:
643
+ throw new Error(`Unknown or not yet handled type ${type}`);
644
+ }
645
+ return { statusCode: 200, payload: await Promise.resolve(promise) };
646
+ }
647
+
648
+ // Starts the Cyberismo app by running npm start in the app project folder
649
+ private async startApp(forceStart: boolean = false): Promise<requestStatus> {
650
+ // __dirname when running cards ends with /tools/data-handler/dist - use that to navigate to app path
651
+ const baseDir = dirname(fileURLToPath(import.meta.url));
652
+ const appPath = resolve(baseDir, '../../app');
653
+
654
+ // since current working directory changes, we need to resolve the project path
655
+ const projectPath = resolve(this.projectPath);
656
+
657
+ if (!forceStart) {
658
+ const validationErrors = await this.validateCmd.validate(projectPath);
659
+ if (validationErrors) {
660
+ return { statusCode: 400, message: validationErrors };
661
+ }
662
+ }
663
+
664
+ console.log('Running Cyberismo app on http://localhost:3000/');
665
+ console.log('Press Control+C to stop.');
666
+
667
+ const args = [`start`];
668
+ execFileSync(`npm`, args, {
669
+ shell: true,
670
+ cwd: appPath,
671
+ stdio: 'ignore',
672
+ env: { ...process.env, npm_config_project_path: projectPath },
673
+ });
674
+
675
+ return { statusCode: 200 };
676
+ }
677
+
678
+ // Validates that a given path conforms to schema. Validates both file/folder structure and file content.
679
+ private async validate(): Promise<requestStatus> {
680
+ const result = await this.validateCmd.validate(this.projectPath);
681
+ return {
682
+ statusCode: 200,
683
+ message: result.length ? result : 'Project structure validated',
684
+ };
685
+ }
686
+ }