@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,519 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2024
4
+
5
+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
6
+
7
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
8
+
9
+ You should have received a copy of the GNU Affero General Public
10
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
11
+ */
12
+
13
+ import type { DataType } from '../interfaces/resource-interfaces.js';
14
+ import type {
15
+ BaseResult,
16
+ LinkDirection,
17
+ ParseResult,
18
+ } from '../types/queries.js';
19
+
20
+ /**
21
+ * This function reverses the encoding made by the "encodeClingoValue" function
22
+ */
23
+ export function decodeClingoValue(value: string) {
24
+ return value.replace(/\\([n\\"])/g, (_, char) => {
25
+ if (char === 'n') {
26
+ return '\n';
27
+ }
28
+ return char;
29
+ });
30
+ }
31
+
32
+ class ClingoParser {
33
+ private keywords = [
34
+ 'queryError',
35
+ 'result',
36
+ 'childResult',
37
+ 'field',
38
+ 'enumField',
39
+ 'listField',
40
+ 'label',
41
+ 'link',
42
+ 'transitionDenied',
43
+ 'movingCardDenied',
44
+ 'deletingCardDenied',
45
+ 'editingFieldDenied',
46
+ 'editingContentDenied',
47
+ 'notification',
48
+ 'policyCheckFailure',
49
+ 'policyCheckSuccess',
50
+ 'order',
51
+ ];
52
+
53
+ private result: ParseResult<BaseResult> = {
54
+ results: [],
55
+ error: null,
56
+ };
57
+
58
+ // The queue now stores the parameters instead of functions
59
+ private resultQueue: { key: string }[] = [];
60
+ private childResultQueue: {
61
+ parentKey: string;
62
+ childKey: string;
63
+ collection: string;
64
+ }[] = [];
65
+ private tempResults: { [key: string]: BaseResult } = {};
66
+ private orderQueue: {
67
+ level: number;
68
+ collection: string;
69
+ fieldIndex: number;
70
+ field: string;
71
+ direction: 'ASC' | 'DESC';
72
+ }[] = [];
73
+ private collections: Set<string> = new Set();
74
+ private reset() {
75
+ this.result = {
76
+ results: [],
77
+ error: null,
78
+ };
79
+ this.resultQueue = [];
80
+ this.childResultQueue = [];
81
+ this.tempResults = {};
82
+ this.orderQueue = [];
83
+ this.collections = new Set();
84
+ }
85
+
86
+ /**
87
+ * Command handlers for each possible keyword
88
+ * All of them will get parameters as strings
89
+ * You can trust that clingo will always provide the correct number of parameters / types
90
+ */
91
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
92
+ private commandHandlers: Record<string, Function> = {
93
+ queryError: (message: string, ...params: string[]) => {
94
+ this.result.error = `${message}${params.length > 1 ? ` ${params.join(', ')}` : ''}`;
95
+ },
96
+ result: (key: string) => {
97
+ this.resultQueue.push({ key });
98
+ },
99
+ childResult: (parentKey: string, childKey: string, collection: string) => {
100
+ this.childResultQueue.push({ parentKey, childKey, collection });
101
+ this.collections.add(collection);
102
+ },
103
+ enumField: async (
104
+ key: string,
105
+ fieldName: string,
106
+ fieldValue: string,
107
+ index: string,
108
+ displayValue: string,
109
+ ) => {
110
+ const res = this.getOrInitResult(key);
111
+ const decoded = decodeClingoValue(fieldValue);
112
+ const parsedIndex = parseInt(index, 10);
113
+ res[fieldName] = {
114
+ value: decoded,
115
+ index: parsedIndex,
116
+ displayValue,
117
+ };
118
+ },
119
+ // NOTE: Must be tested in INTDEV-623
120
+ listField: async (
121
+ key: string,
122
+ fieldName: string,
123
+ fieldValue: string,
124
+ index: string,
125
+ displayValue: string,
126
+ ) => {
127
+ const res = this.getOrInitResult(key);
128
+ const decoded = decodeClingoValue(fieldValue);
129
+ if (!res[fieldName] || !Array.isArray(res[fieldName])) {
130
+ res[fieldName] = [];
131
+ }
132
+ const parsedIndex = parseInt(index, 10);
133
+ (res[fieldName] as unknown[]).push({
134
+ value: decoded,
135
+ index: parsedIndex,
136
+ displayValue,
137
+ });
138
+ },
139
+ field: async (
140
+ key: string,
141
+ fieldName: string,
142
+ fieldValue: string,
143
+ dataType: DataType,
144
+ ) => {
145
+ const res = this.getOrInitResult(key);
146
+ const decoded = decodeClingoValue(fieldValue);
147
+ switch (dataType) {
148
+ case 'shortText':
149
+ case 'longText':
150
+ case 'person':
151
+ case 'date':
152
+ case 'dateTime':
153
+ res[fieldName] = decoded;
154
+ break;
155
+ case 'number':
156
+ res[fieldName] = parseFloat(decoded);
157
+ break;
158
+ case 'integer':
159
+ res[fieldName] = parseInt(decoded, 10);
160
+ break;
161
+ case 'boolean':
162
+ res[fieldName] = fieldValue === 'true';
163
+ break;
164
+ }
165
+ },
166
+ label: (key: string, label: string) => {
167
+ const res = this.getOrInitResult(key);
168
+ res.labels.push(label);
169
+ },
170
+ link: (
171
+ key: string, // key is the card itself
172
+ cardKey: string, // cardKey is otherCard this is being linked to
173
+ title: string,
174
+ linkType: string,
175
+ displayName: string,
176
+ direction: LinkDirection,
177
+ linkSource: 'user' | 'calculated',
178
+ linkDescription?: string,
179
+ ) => {
180
+ const res = this.getOrInitResult(key);
181
+ res.links.push({
182
+ key: cardKey,
183
+ linkType,
184
+ displayName,
185
+ linkDescription,
186
+ direction,
187
+ linkSource,
188
+ title,
189
+ });
190
+ },
191
+ transitionDenied: (
192
+ key: string,
193
+ transitionName: string,
194
+ errorMessage: string,
195
+ ) => {
196
+ const res = this.getOrInitResult(key);
197
+ res.deniedOperations.transition.push({ transitionName, errorMessage });
198
+ },
199
+ movingCardDenied: (key: string, errorMessage: string) => {
200
+ const res = this.getOrInitResult(key);
201
+ res.deniedOperations.move.push({ errorMessage });
202
+ },
203
+ deletingCardDenied: (key: string, errorMessage: string) => {
204
+ const res = this.getOrInitResult(key);
205
+ res.deniedOperations.delete.push({ errorMessage });
206
+ },
207
+ editingFieldDenied: (
208
+ key: string,
209
+ fieldName: string,
210
+ errorMessage: string,
211
+ ) => {
212
+ const res = this.getOrInitResult(key);
213
+ res.deniedOperations.editField.push({ fieldName, errorMessage });
214
+ },
215
+ editingContentDenied: (key: string, errorMessage: string) => {
216
+ const res = this.getOrInitResult(key);
217
+ res.deniedOperations.editContent.push({ errorMessage });
218
+ },
219
+ notification: (
220
+ key: string,
221
+ category: string,
222
+ title: string,
223
+ message: string,
224
+ ) => {
225
+ const res = this.getOrInitResult(key);
226
+ res.notifications.push({ key, category, title, message });
227
+ },
228
+ policyCheckFailure: (
229
+ key: string,
230
+ category: string,
231
+ title: string,
232
+ errorMessage: string,
233
+ fieldName?: string,
234
+ ) => {
235
+ const res = this.getOrInitResult(key);
236
+ res.policyChecks.failures.push({
237
+ category,
238
+ title,
239
+ errorMessage,
240
+ fieldName,
241
+ });
242
+ },
243
+ policyCheckSuccess: (key: string, category: string, title: string) => {
244
+ const res = this.getOrInitResult(key);
245
+ res.policyChecks.successes.push({ category, title });
246
+ },
247
+ order: (
248
+ level: string,
249
+ collection: string,
250
+ fieldIndex: string,
251
+ field: string,
252
+ direction: 'ASC' | 'DESC',
253
+ ) => {
254
+ const parsedLevel = parseInt(level, 10);
255
+ const parsedFieldIndex = parseInt(fieldIndex, 10);
256
+ this.orderQueue.push({
257
+ level: parsedLevel,
258
+ collection,
259
+ fieldIndex: parsedFieldIndex,
260
+ field,
261
+ direction,
262
+ });
263
+ },
264
+ };
265
+
266
+ private getOrInitResult(key: string): BaseResult {
267
+ if (!this.tempResults[key]) {
268
+ this.tempResults[key] = {
269
+ key,
270
+ labels: [],
271
+ links: [],
272
+ notifications: [],
273
+ policyChecks: { successes: [], failures: [] },
274
+ deniedOperations: {
275
+ transition: [],
276
+ move: [],
277
+ delete: [],
278
+ editField: [],
279
+ editContent: [],
280
+ },
281
+ };
282
+ }
283
+ return this.tempResults[key];
284
+ }
285
+ private sortByLevel(
286
+ results: BaseResult[],
287
+ level: number = 1,
288
+ currentCollection?: string,
289
+ ) {
290
+ const levelOrders = this.orderQueue
291
+ .filter(
292
+ (order) =>
293
+ order.level === level &&
294
+ (currentCollection ? order.collection === currentCollection : true), // if no collection specified at top-level, take all
295
+ )
296
+ .sort((a, b) => a.fieldIndex - b.fieldIndex);
297
+
298
+ // Apply sorting instructions for this level/collection if any
299
+ if (levelOrders.length > 0) {
300
+ results.sort((a, b) => {
301
+ for (const { field, direction } of levelOrders) {
302
+ const sortOrder = direction === 'ASC' ? -1 : 1;
303
+
304
+ const firstValue = this.getComparableValue(a[field]);
305
+ const secondValue = this.getComparableValue(b[field]);
306
+
307
+ if (firstValue == null && secondValue == null) {
308
+ continue; // both are null, move on to next field
309
+ } else if (firstValue == null) {
310
+ return sortOrder; // first is considered less
311
+ } else if (secondValue == null) {
312
+ return -sortOrder; // second is considered less
313
+ }
314
+
315
+ // Regular comparison
316
+ if (firstValue < secondValue) return sortOrder;
317
+ if (firstValue > secondValue) return -sortOrder;
318
+ // if equal, try next field
319
+ }
320
+ // if all fields equal
321
+ return 0;
322
+ });
323
+ }
324
+
325
+ // Recursively sort all known child collections
326
+ for (const result of results) {
327
+ for (const childCollection of this.collections) {
328
+ const childResults = result[childCollection];
329
+ if (Array.isArray(childResults)) {
330
+ this.sortByLevel(childResults, level + 1, childCollection);
331
+ }
332
+ }
333
+ }
334
+ }
335
+
336
+ private getComparableValue(value: unknown) {
337
+ if (value == null) {
338
+ return null;
339
+ }
340
+ if (
341
+ typeof value === 'object' &&
342
+ 'index' in value &&
343
+ typeof value.index === 'number'
344
+ ) {
345
+ return value.index;
346
+ }
347
+ if (Array.isArray(value)) {
348
+ const indeces: number[] = [];
349
+ for (const item of value) {
350
+ if (
351
+ item != null &&
352
+ typeof item === 'object' &&
353
+ 'index' in item &&
354
+ typeof item.index === 'number'
355
+ ) {
356
+ indeces.push(item.index);
357
+ }
358
+ }
359
+ return Math.min(...indeces);
360
+ }
361
+ return value;
362
+ }
363
+
364
+ private applyResultProcessing() {
365
+ // Process results and parent-child relationships
366
+ this.resultQueue.forEach(({ key }) => {
367
+ const res = this.getOrInitResult(key);
368
+ this.result.results.push(res); // Here we assume the query is correct and returns the data specified by the query
369
+ });
370
+
371
+ this.childResultQueue.forEach(({ parentKey, childKey, collection }) => {
372
+ const parent = this.getOrInitResult(parentKey);
373
+ const child = this.getOrInitResult(childKey);
374
+
375
+ if (!parent[collection] || !Array.isArray(parent[collection])) {
376
+ parent[collection] = [];
377
+ }
378
+
379
+ (parent[collection] as unknown[]).push(child);
380
+ });
381
+
382
+ this.sortByLevel(this.result.results);
383
+ }
384
+
385
+ /**
386
+ * This methods is responsible for converting clingo output to a parsed object
387
+ * @param input clingo input to parse
388
+ * @returns
389
+ */
390
+ public async parseInput(input: string): Promise<ParseResult<BaseResult>> {
391
+ let position = 0;
392
+
393
+ while (position < input.length) {
394
+ const keywordMatch = this.findKeyword(input, position);
395
+
396
+ if (!keywordMatch) {
397
+ break;
398
+ }
399
+
400
+ const { keyword, endIndex } = keywordMatch;
401
+ position = endIndex;
402
+
403
+ const parsed = this.parseArguments(input, position);
404
+ if (parsed) {
405
+ // Apply the command handler with sanitized arguments
406
+ await this.commandHandlers[keyword](...parsed.args);
407
+ position = parsed.endPosition; // move position after the argument closing parenthesis
408
+ }
409
+ }
410
+
411
+ this.applyResultProcessing();
412
+ const result = this.result;
413
+
414
+ // Reset the parser state
415
+ this.reset();
416
+
417
+ return result;
418
+ }
419
+
420
+ /**
421
+ * This method finds the next keyword in a string after a specified point
422
+ * @param input The string which it being searched
423
+ * @param start The position from which to start the search from
424
+ * @returns
425
+ */
426
+ private findKeyword(
427
+ input: string,
428
+ start: number,
429
+ ): { keyword: string; startIndex: number; endIndex: number } | null {
430
+ // Create a regex dynamically from the keywords list
431
+ const regex = new RegExp(`(${this.keywords.join('|')})\\(`, 'g');
432
+
433
+ // Apply the regex starting from the current position
434
+ regex.lastIndex = start;
435
+ const match = regex.exec(input);
436
+
437
+ if (match) {
438
+ return {
439
+ keyword: match[1], // The matched keyword (first capture group)
440
+ startIndex: match.index, // Position of the matched keyword
441
+ endIndex: match.index + match[0].length, // Position after the keyword and opening parenthesis
442
+ };
443
+ }
444
+
445
+ return null;
446
+ }
447
+
448
+ /**
449
+ * This method is a custom parser, which takes in the whole clingo output and parses the arguments.
450
+ * Note: Do not decode in this function. It will be handled on a higher level.
451
+ * As long as this function returns valid clingo, it has done it's responsibility
452
+ * @param input Clingo output
453
+ * @param position Position of the command being parsed inside the string
454
+ * @returns
455
+ */
456
+ private parseArguments(
457
+ input: string,
458
+ position: number,
459
+ ): { args: string[]; endPosition: number } | null {
460
+ let currentArg = '';
461
+ const args: string[] = [];
462
+ let insideQuote = false;
463
+
464
+ // calculates how deep into parenthesis we are
465
+ let insideParanthesis = 0;
466
+
467
+ for (let i = position; i < input.length; i++) {
468
+ const char = input[i];
469
+
470
+ if (char === '"') {
471
+ if (i !== 0 && input[i - 1] === '\\') {
472
+ currentArg += '"';
473
+ continue;
474
+ }
475
+ if (!insideQuote && insideParanthesis === 0) {
476
+ // We can ignore the chars, which are before a quoted string
477
+ currentArg = '';
478
+ }
479
+ insideQuote = !insideQuote; // Toggle inside/outside quotes
480
+ continue;
481
+ }
482
+
483
+ if (char === ',' && !insideQuote) {
484
+ if (insideParanthesis > 0) {
485
+ currentArg += char;
486
+ continue;
487
+ }
488
+ args.push(currentArg);
489
+ currentArg = '';
490
+ insideParanthesis = 0;
491
+ continue;
492
+ }
493
+ if (char === '(' && !insideQuote) {
494
+ if (insideParanthesis === 0) {
495
+ currentArg = '';
496
+ }
497
+ insideParanthesis++;
498
+ }
499
+
500
+ if (char === ')' && !insideQuote) {
501
+ if (insideParanthesis-- !== 0) {
502
+ currentArg += char;
503
+ continue;
504
+ }
505
+ args.push(currentArg);
506
+ return {
507
+ args,
508
+ endPosition: i + 1,
509
+ };
510
+ }
511
+
512
+ currentArg += char;
513
+ }
514
+
515
+ return null; // No valid arguments found
516
+ }
517
+ }
518
+
519
+ export default ClingoParser;
@@ -0,0 +1,71 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2024
4
+
5
+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
6
+
7
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
8
+
9
+ You should have received a copy of the GNU Affero General Public
10
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
11
+ */
12
+ import {
13
+ type ClingoArgument,
14
+ ClingoFactBuilder,
15
+ } from './clingo-fact-builder.js';
16
+
17
+ interface IBuilder {
18
+ build(): string;
19
+ }
20
+
21
+ export class ClingoProgramBuilder {
22
+ private rows: IBuilder[] = [];
23
+
24
+ /**
25
+ * Adds a new fact with a simple configuration.
26
+ * @param predicate - The fact's predicate
27
+ * @param args - The fact's arguments
28
+ */
29
+ addFact(predicate: string, ...args: ClingoArgument[]): ClingoProgramBuilder {
30
+ const fact = new ClingoFactBuilder(predicate).addArguments(...args);
31
+ this.rows.push(fact);
32
+ return this;
33
+ }
34
+
35
+ /**
36
+ * Adds a custom fact allowing use of the builder methods directly for more control.
37
+ * @param predicate - The fact's predicate
38
+ * @param configure - Function to configure the fact with builder methods
39
+ */
40
+ addCustomFact(
41
+ predicate: string,
42
+ configure: (builder: ClingoFactBuilder) => ClingoFactBuilder,
43
+ ): ClingoProgramBuilder {
44
+ const factBuilder = new ClingoFactBuilder(predicate);
45
+ // Allow configuration of the fact
46
+ this.rows.push(configure(factBuilder));
47
+ return this;
48
+ }
49
+ /**
50
+ * Adds an import to the clingo program
51
+ */
52
+ addImport(path: string): ClingoProgramBuilder {
53
+ this.rows.push({ build: () => `#include "${path}".` });
54
+ return this;
55
+ }
56
+
57
+ /**
58
+ * Adds a comment
59
+ */
60
+ addComment(comment: string): ClingoProgramBuilder {
61
+ this.rows.push({ build: () => `% ${comment}` });
62
+ return this;
63
+ }
64
+
65
+ /**
66
+ * Builds all facts and returns them as a single string with each fact on a new line.
67
+ */
68
+ buildAll(): string {
69
+ return this.rows.map((row) => row.build()).join('\n') + '\n';
70
+ }
71
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2024
4
+
5
+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
6
+
7
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
8
+
9
+ You should have received a copy of the GNU Affero General Public
10
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
11
+ */
12
+
13
+ /**
14
+ * Makes deep comparison between two objects.
15
+ * @param arg1 First object to compare.
16
+ * @param arg2 Second object to compare.
17
+ * @returns true, if objects are the same, false otherwise.
18
+ */
19
+ export function deepCompare(arg1: object, arg2: object): boolean {
20
+ if (
21
+ Object.prototype.toString.call(arg1) ===
22
+ Object.prototype.toString.call(arg2)
23
+ ) {
24
+ if (
25
+ Object.prototype.toString.call(arg1) === '[object Object]' ||
26
+ Object.prototype.toString.call(arg1) === '[object Array]'
27
+ ) {
28
+ if (Object.keys(arg1).length !== Object.keys(arg2).length) {
29
+ return false;
30
+ }
31
+ return Object.keys(arg1).every(function (key) {
32
+ return deepCompare(
33
+ arg1[key as keyof typeof arg1],
34
+ arg2[key as keyof typeof arg2],
35
+ );
36
+ });
37
+ }
38
+ return arg1 === arg2;
39
+ }
40
+ return false;
41
+ }
42
+
43
+ /**
44
+ * Checks if string could be represented as BigInt.
45
+ * @param value String value
46
+ * @returns true, if 'value' can be represented as BigInt; false otherwise.
47
+ */
48
+ export function isBigInt(value: string): boolean {
49
+ try {
50
+ return BigInt(parseInt(value, 10)) !== BigInt(value);
51
+ } catch {
52
+ return false;
53
+ }
54
+ }
@@ -0,0 +1,32 @@
1
+ import type { PredefinedCardMetadata } from '../interfaces/project-interfaces.js';
2
+
3
+ export const INT32_MAX = 2147483647; // 2^31-1
4
+ /**
5
+ Cyberismo
6
+ Copyright © Cyberismo Ltd and contributors 2024
7
+
8
+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
9
+
10
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
11
+
12
+ You should have received a copy of the GNU Affero General Public
13
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
14
+ */
15
+
16
+ /**
17
+ * These are names of the fields that are non-custom fields that present in metadata
18
+ */
19
+ export const PREDEFINED_FIELDS = [
20
+ 'rank',
21
+ 'cardType',
22
+ 'title',
23
+ 'workflowState',
24
+ 'lastUpdated',
25
+ 'lastTransitioned',
26
+ ] satisfies (keyof PredefinedCardMetadata)[];
27
+
28
+ export function isPredefinedField(
29
+ value: string,
30
+ ): value is keyof PredefinedCardMetadata {
31
+ return (PREDEFINED_FIELDS as string[]).includes(value);
32
+ }