@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,130 @@
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
6
+ the terms of the GNU Affero General Public License version 3 as published by
7
+ the Free Software Foundation. This program is distributed in the hope that it
8
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
9
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
+ See the GNU Affero General Public License for more details.
11
+ You should have received a copy of the GNU Affero General Public
12
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
13
+ */
14
+
15
+ import BaseMacro from '../base-macro.js';
16
+ import { Calculate } from '../../commands/index.js';
17
+ import type { MacroOptions } from '../index.js';
18
+ import { createImage, validateMacroContent } from '../index.js';
19
+ import Handlebars from 'handlebars';
20
+ import { join } from 'node:path';
21
+ import { logger } from '../../utils/log-utils.js';
22
+ import type { MacroGenerationContext } from '../../interfaces/macros.js';
23
+ import macroMetadata from './metadata.js';
24
+ import { pathExists } from '../../utils/file-utils.js';
25
+ import { Project } from '../../containers/project.js';
26
+ import { readFile } from 'node:fs/promises';
27
+ import { resourceName } from '../../utils/resource-utils.js';
28
+ import type { Schema } from 'jsonschema';
29
+ import { validateJson } from '../../utils/validate.js';
30
+ import type TaskQueue from '../task-queue.js';
31
+
32
+ export interface GraphOptions extends MacroOptions {
33
+ model: string;
34
+ view: string;
35
+ }
36
+
37
+ class ReportMacro extends BaseMacro {
38
+ constructor(tasksQueue: TaskQueue) {
39
+ super(macroMetadata, tasksQueue);
40
+ }
41
+
42
+ handleValidate = (input: unknown) => {
43
+ this.parseOptions(input);
44
+ };
45
+
46
+ handleStatic = async (context: MacroGenerationContext, input: unknown) => {
47
+ return this.handleInject(context, input);
48
+ };
49
+
50
+ handleInject = async (context: MacroGenerationContext, input: unknown) => {
51
+ const project = new Project(context.projectPath);
52
+ const calculate = new Calculate(project);
53
+
54
+ const resourceNameToPath = (name: string, fileName: string) => {
55
+ const { identifier, prefix, type } = resourceName(name);
56
+ if (prefix === project.projectPrefix) {
57
+ return join(project.paths.resourcesFolder, type, identifier, fileName);
58
+ }
59
+ return join(
60
+ project.paths.modulesFolder,
61
+ prefix,
62
+ type,
63
+ identifier,
64
+ fileName,
65
+ );
66
+ };
67
+
68
+ const options = this.parseOptions(input);
69
+
70
+ let schema: Schema | null = null;
71
+ try {
72
+ schema = JSON.parse(
73
+ await readFile(
74
+ resourceNameToPath(options.view, 'parameterSchema.json'),
75
+ { encoding: 'utf-8' },
76
+ ),
77
+ );
78
+ } catch (err) {
79
+ logger.trace(
80
+ err,
81
+ 'Graph schema not found or failed to read, skipping validation',
82
+ );
83
+ }
84
+
85
+ if (schema) {
86
+ validateJson(options, {
87
+ schema,
88
+ });
89
+ }
90
+
91
+ const modelLocation = resourceNameToPath(options.model, 'model.lp');
92
+ const viewLocation = resourceNameToPath(options.view, 'view.lp.hbs');
93
+
94
+ if (!pathExists(modelLocation)) {
95
+ throw new Error(`Graph: Model ${options.model} does not exist`);
96
+ }
97
+
98
+ let viewContent = '';
99
+ try {
100
+ viewContent = await readFile(viewLocation, { encoding: 'utf-8' });
101
+ } catch {
102
+ throw new Error(`Graph: View ${options.view} does not exist`);
103
+ }
104
+ const handlebarsContext = {
105
+ cardKey: context.cardKey,
106
+ ...options,
107
+ };
108
+
109
+ const handlebars = Handlebars.create();
110
+ const view = handlebars.compile(viewContent)(handlebarsContext);
111
+
112
+ const modelContent = await readFile(modelLocation, { encoding: 'utf-8' });
113
+ const result = await calculate.runGraph({
114
+ query: view + '\n' + modelContent,
115
+ });
116
+
117
+ if (typeof result !== 'string') {
118
+ throw new Error(
119
+ 'Graph macro expected a string from clingo, but received an object',
120
+ );
121
+ }
122
+ return createImage(result);
123
+ };
124
+
125
+ private parseOptions(input: unknown): GraphOptions {
126
+ return validateMacroContent<GraphOptions>(this.metadata, input);
127
+ }
128
+ }
129
+
130
+ export default ReportMacro;
@@ -0,0 +1,21 @@
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 { MacroMetadata } from '../../interfaces/macros.js';
14
+
15
+ const macroMetadata: MacroMetadata = {
16
+ name: 'graph',
17
+ tagName: 'graph',
18
+ schema: 'graphMacroBaseSchema',
19
+ };
20
+
21
+ export default macroMetadata;
@@ -0,0 +1,321 @@
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 Handlebars from 'handlebars';
14
+
15
+ import createCards from './createCards/index.js';
16
+ import graph from './graph/index.js';
17
+ import report from './report/index.js';
18
+ import scoreCard from './scoreCard/index.js';
19
+
20
+ import { validateJson } from '../utils/validate.js';
21
+ import { DHValidationError } from '../exceptions/index.js';
22
+ import type { AdmonitionType } from '../interfaces/adoc.js';
23
+ import type { Validator } from 'jsonschema';
24
+ import type {
25
+ MacroGenerationContext,
26
+ MacroMetadata,
27
+ MacroName,
28
+ } from '../interfaces/macros.js';
29
+ import type BaseMacro from './base-macro.js';
30
+ import TaskQueue from './task-queue.js';
31
+
32
+ const CURLY_LEFT = '&#123;';
33
+ const CURLY_RIGHT = '&#125;';
34
+
35
+ export interface MacroConstructor {
36
+ new (tasks: TaskQueue): BaseMacro; // Constructor signature
37
+ }
38
+
39
+ export const macros: { [K in MacroName]: MacroConstructor } = {
40
+ createCards,
41
+ graph,
42
+ report,
43
+ scoreCard,
44
+ };
45
+
46
+ export function validateMacroContent<T>(
47
+ macro: MacroMetadata,
48
+ data: unknown,
49
+ validator?: Validator,
50
+ ): T {
51
+ if (!macro.schema) {
52
+ throw new Error(`Macro ${macro.name} does not have a schema`);
53
+ }
54
+
55
+ try {
56
+ return validateJson<T>(data, {
57
+ schemaId: macro.schema,
58
+ validator,
59
+ });
60
+ } catch (error) {
61
+ let message = `Error: ${error instanceof Error ? error.message : 'Unknown error'}`;
62
+ if (error instanceof DHValidationError) {
63
+ message = `${error.errors?.map((e) => e.message).join(', ')}`;
64
+ }
65
+ throw new Error(`${macro.name} macro JSON validation error: ${message}`);
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Registers the macros with Handlebars
71
+ * @param {Mode} mode - The mode to register the macros in
72
+ */
73
+ export function registerMacros(
74
+ instance: typeof Handlebars,
75
+ context: MacroGenerationContext,
76
+ tasks: TaskQueue,
77
+ ) {
78
+ const macroInstances: BaseMacro[] = [];
79
+ for (const macro of Object.keys(macros) as MacroName[]) {
80
+ const MacroClass = macros[macro];
81
+ const macroInstance = new MacroClass(tasks);
82
+ instance.registerHelper(macro, function (this: unknown, options) {
83
+ if (
84
+ this != null &&
85
+ typeof this === 'object' &&
86
+ '__isRaw' in this &&
87
+ this.__isRaw
88
+ ) {
89
+ // we use escaped chars so that they will not be re-run
90
+ return `${CURLY_LEFT}${CURLY_LEFT}#${macro}${CURLY_RIGHT}${CURLY_RIGHT}${options.fn(this)}${CURLY_LEFT}${CURLY_LEFT}/${macro}${CURLY_RIGHT}${CURLY_RIGHT}`;
91
+ }
92
+ return macroInstance.invokeMacro(context, options);
93
+ });
94
+ macroInstances.push(macroInstance);
95
+ }
96
+
97
+ instance.registerHelper('raw', function (options) {
98
+ return options.fn({
99
+ __isRaw: true,
100
+ });
101
+ });
102
+
103
+ return macroInstances;
104
+ }
105
+ /**
106
+ * Calculate amount of handlebars templates inside a string
107
+ * @param input
108
+ */
109
+ export function macroCount(input: string): number {
110
+ const regex = /{{#[\w\s-]+?}}/g;
111
+ const match = input.match(regex);
112
+ return match ? match.length : 0;
113
+ }
114
+
115
+ /**
116
+ * Registers macros as handlebars helpers, which just leaves the macros in the content
117
+ * Can be used when your macro uses handlebars and handles content that might contain macros
118
+ * The handleMacros function will handle recursive macros so do not execute them inside your macro
119
+ * @param instance handlebars instance
120
+ */
121
+ export function registerEmptyMacros(instance: typeof Handlebars) {
122
+ for (const macro of Object.keys(macros) as MacroName[]) {
123
+ instance.registerHelper(macro, function (this: unknown, options) {
124
+ return `{{#${macro}}}${options.fn(this)}{{/${macro}}}`;
125
+ });
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Handle the macros in the content
131
+ * @param content - The content to handle the macros in
132
+ * @param mode - The mode to handle the macros in. Inject mode will generate injectable placeholders for the macros while static mode will generate valid adoc. Validate mode will only validate the macros syntax and throw errors in case of issues.
133
+ */
134
+ export async function evaluateMacros(
135
+ content: string,
136
+ context: MacroGenerationContext,
137
+ maxTries: number = 10,
138
+ ) {
139
+ const handlebars = Handlebars.create();
140
+ const tasks = new TaskQueue();
141
+ registerMacros(handlebars, context, tasks);
142
+ let result = content;
143
+ while (maxTries-- > 0) {
144
+ tasks.reset();
145
+ const compiled = handlebars.compile(result, {
146
+ strict: true,
147
+ });
148
+ try {
149
+ result = compiled({});
150
+
151
+ await tasks.waitAll();
152
+
153
+ result = applyMacroResults(result, tasks, context);
154
+
155
+ if (macroCount(result) === 0) {
156
+ break;
157
+ }
158
+ } catch (err) {
159
+ // This will produce a warning in the output in inject/static modes and throw an error in validate mode
160
+ return handleMacroError(err, '', context);
161
+ }
162
+ }
163
+ if (macroCount(result) !== 0) {
164
+ return handleMacroError(
165
+ new Error(`Too many recursive macro evaluations.`),
166
+ '',
167
+ context,
168
+ );
169
+ }
170
+ return result.replaceAll(CURLY_LEFT, '{').replaceAll(CURLY_RIGHT, '}');
171
+ }
172
+
173
+ /**
174
+ * This function assumes that tasks, which were started by macros, are complete.
175
+ * It replaces the placeholders of the tasks with the actual results
176
+ * @param input Adoc content, which might have macro placeholders
177
+ * @param tasks The taskqueue, which was used to run the macros
178
+ * @param context General context for the macro evaluation process
179
+ * @returns Adoc, where placeholders have been replaced with the results.
180
+ * Note that the results might include new macros.
181
+ */
182
+ export function applyMacroResults(
183
+ input: string,
184
+ tasks: TaskQueue,
185
+ context: MacroGenerationContext,
186
+ ) {
187
+ for (const item of tasks) {
188
+ if (item.promiseResult === null) {
189
+ input = handleMacroError(
190
+ new Error(
191
+ `Tried to access result before it was resolved for ${item.placeholder}`,
192
+ ),
193
+ item.macro,
194
+ context,
195
+ );
196
+ } else {
197
+ input = input.replace(item.placeholder, item.promiseResult);
198
+ }
199
+ }
200
+ return input;
201
+ }
202
+
203
+ /**
204
+ * Handles errors that come when handling macros
205
+ * @param error - The error that was thrown
206
+ * @param macro - The macro that caused the error
207
+ * @returns The error message that is valid adoc
208
+ */
209
+ export function handleMacroError(
210
+ error: unknown,
211
+ macro: string,
212
+ context: MacroGenerationContext,
213
+ ): string {
214
+ let message = `Error: ${error instanceof Error ? error.message : 'Unknown error'}`;
215
+ if (error instanceof DHValidationError) {
216
+ message = `Check json syntax of macro ${macro}: ${error.errors?.map((e) => e.message).join(', ')}`;
217
+ }
218
+ if (
219
+ typeof error === 'object' &&
220
+ error != null &&
221
+ 'lineNumber' in error &&
222
+ typeof error.lineNumber === 'number'
223
+ ) {
224
+ message += ` at line ${error.lineNumber}`;
225
+ }
226
+ if (context.mode === 'validate') {
227
+ throw new Error(message);
228
+ } else {
229
+ return createAdmonition('WARNING', 'Macro Error', message);
230
+ }
231
+ }
232
+
233
+ // This is used to generate unique keys for macros
234
+ // There might be a better way to do this
235
+ let macroCounter = 0;
236
+
237
+ type Value = string | number | boolean | undefined;
238
+
239
+ /**
240
+ * Macro options can be a flat object or a nested object
241
+ * The nested object will be flattened into dot notation attributes
242
+ */
243
+ export type MacroOptions = {
244
+ [key: string]: Value | MacroOptions;
245
+ };
246
+ /**
247
+ * Creates an injectable placeholder for a macro
248
+ * @param macro - The macro to create the placeholder for
249
+ * @param options - Options will be passed to the html element as attributes
250
+ */
251
+ export function createHtmlPlaceholder(
252
+ macro: MacroMetadata,
253
+ options: MacroOptions,
254
+ ) {
255
+ // Flatten nested objects into dot notation attributes
256
+ const flattenedOptions: Record<string, Value> = {};
257
+
258
+ // Helper function to flatten nested objects
259
+ const flatten = (obj: MacroOptions, prefix = ''): void => {
260
+ Object.entries(obj).forEach(([key, value]) => {
261
+ const newKey = prefix ? `${prefix}.${key}` : key;
262
+
263
+ if (
264
+ value !== null &&
265
+ typeof value === 'object' &&
266
+ !Array.isArray(value)
267
+ ) {
268
+ // Recursively flatten nested objects
269
+ flatten(value, newKey);
270
+ } else {
271
+ // Add leaf values to flattened options
272
+ flattenedOptions[newKey] = value as Value;
273
+ }
274
+ });
275
+ };
276
+
277
+ flatten(options);
278
+
279
+ // Convert flattened options to attribute strings
280
+ const attributeStrings = Object.entries(flattenedOptions)
281
+ .filter(([, value]) => value !== undefined)
282
+ .map(([key, value]) => `${key}="${value}"`);
283
+
284
+ const optionString = attributeStrings.join(' ');
285
+
286
+ // start with a line change to ensure that inline passthrough +++ is on its own line
287
+ return `\n+++\n<${macro.tagName}${optionString ? ` ${optionString}` : ''} key="macro-${macroCounter++}"></${macro.tagName}>\n+++\n`;
288
+ }
289
+
290
+ /**
291
+ * Creates an adoc admonition
292
+ * @param type - The type of admonition
293
+ * @param label - The label of the admonition
294
+ * @param content - The content of the admonition
295
+ * @returns The adoc admonition as a string
296
+ */
297
+ export function createAdmonition(
298
+ type: AdmonitionType,
299
+ label: string,
300
+ content: string,
301
+ ) {
302
+ return `[${type}]\n.${label}\n====\n${content}\n====\n\n`;
303
+ }
304
+
305
+ /**
306
+ * Helper function for including base64 encoded images for now
307
+ * @param image base64 encoded image
308
+ * @returns valid asciidoc with the image
309
+ */
310
+ export function createImage(image: string) {
311
+ if (process.env.EXPORT_FORMAT) {
312
+ return `image::data:image/svg+xml;base64,${image}[]\n`;
313
+ } else {
314
+ return `++++
315
+ <div class="cyberismo-svg-wrapper" data-type="cyberismo-svg-wrapper">
316
+ ${Buffer.from(image, 'base64').toString('utf-8')}
317
+ </div>
318
+ ++++
319
+ `;
320
+ }
321
+ }
@@ -0,0 +1,88 @@
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 { registerEmptyMacros, validateMacroContent } from '../index.js';
14
+ import type { MacroOptions } from '../index.js';
15
+ import type { MacroGenerationContext } from '../../interfaces/macros.js';
16
+ import macroMetadata from './metadata.js';
17
+ import { Project } from '../../containers/project.js';
18
+ import { Calculate } from '../../commands/index.js';
19
+ import Handlebars from 'handlebars';
20
+ import BaseMacro from '../base-macro.js';
21
+ import { validateJson } from '../../utils/validate.js';
22
+ import type TaskQueue from '../task-queue.js';
23
+ import { ReportResource } from '../../resources/report-resource.js';
24
+ import { resourceName } from '../../utils/resource-utils.js';
25
+
26
+ export interface ReportOptions extends MacroOptions {
27
+ name: string;
28
+ }
29
+
30
+ class ReportMacro extends BaseMacro {
31
+ constructor(tasksQueue: TaskQueue) {
32
+ super(macroMetadata, tasksQueue);
33
+ }
34
+ handleValidate = (input: unknown) => {
35
+ this.validate(input);
36
+ };
37
+
38
+ handleStatic = async (context: MacroGenerationContext, data: unknown) => {
39
+ return this.handleInject(context, data);
40
+ };
41
+
42
+ handleInject = async (context: MacroGenerationContext, data: unknown) => {
43
+ const options = this.validate(data);
44
+ const project = new Project(context.projectPath);
45
+ const resource = new ReportResource(project, resourceName(options.name));
46
+ const report = await resource.show();
47
+
48
+ if (!report) throw new Error(`Report ${options} does not exist`);
49
+
50
+ if (report.schema) {
51
+ validateJson(options, {
52
+ schema: report.schema,
53
+ });
54
+ }
55
+
56
+ const handlebarsContext = {
57
+ cardKey: context.cardKey,
58
+ ...options,
59
+ };
60
+
61
+ const handlebars = Handlebars.create();
62
+
63
+ const template = handlebars.compile(report.queryTemplate, {
64
+ strict: true,
65
+ });
66
+
67
+ const calculate = new Calculate(project);
68
+ const result = await calculate.runLogicProgram({
69
+ query: template(handlebarsContext),
70
+ });
71
+ if (result.error) {
72
+ throw new Error(result.error);
73
+ }
74
+ // register empty macros so that other macros aren't touched yet
75
+ registerEmptyMacros(handlebars);
76
+
77
+ return handlebars.compile(report.contentTemplate)({
78
+ ...handlebarsContext,
79
+ ...result,
80
+ });
81
+ };
82
+
83
+ private validate(data: unknown): ReportOptions {
84
+ return validateMacroContent<ReportOptions>(this.metadata, data);
85
+ }
86
+ }
87
+
88
+ export default ReportMacro;
@@ -0,0 +1,21 @@
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 { MacroMetadata } from '../../interfaces/macros.js';
14
+
15
+ const macroMetadata: MacroMetadata = {
16
+ name: 'report',
17
+ tagName: 'report',
18
+ schema: 'reportMacroBaseSchema',
19
+ };
20
+
21
+ export default macroMetadata;
@@ -0,0 +1,55 @@
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 { MacroOptions } from '../index.js';
14
+ import { createHtmlPlaceholder, validateMacroContent } from '../index.js';
15
+
16
+ import type { MacroGenerationContext } from '../../interfaces/macros.js';
17
+ import macroMetadata from './metadata.js';
18
+ import BaseMacro from '../base-macro.js';
19
+ import type TaskQueue from '../task-queue.js';
20
+
21
+ export interface ScoreCardOptions extends MacroOptions {
22
+ title?: string;
23
+ value: number;
24
+ unit?: string;
25
+ legend?: string;
26
+ }
27
+
28
+ class ScoreCardMacro extends BaseMacro {
29
+ constructor(tasksQueue: TaskQueue) {
30
+ super(macroMetadata, tasksQueue);
31
+ }
32
+ handleValidate = (data: string) => {
33
+ this.validate(data);
34
+ };
35
+
36
+ handleStatic = async (context: MacroGenerationContext, input: unknown) => {
37
+ const options = this.validate(input);
38
+ return this.createAsciidocElement(options);
39
+ };
40
+
41
+ handleInject = async (_: MacroGenerationContext, input: unknown) => {
42
+ const options = this.validate(input);
43
+ return createHtmlPlaceholder(this.metadata, options);
44
+ };
45
+
46
+ private validate(input: unknown): ScoreCardOptions {
47
+ return validateMacroContent<ScoreCardOptions>(this.metadata, input);
48
+ }
49
+
50
+ private createAsciidocElement(options: ScoreCardOptions) {
51
+ return `\n----\n${options.title}: ${options.value} ${options.unit ?? ''} ${options.legend ?? ''}\n----\n`;
52
+ }
53
+ }
54
+
55
+ export default ScoreCardMacro;
@@ -0,0 +1,21 @@
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 { MacroMetadata } from '../../interfaces/macros.js';
14
+
15
+ const macroMetadata: MacroMetadata = {
16
+ name: 'scoreCard',
17
+ tagName: 'score-card',
18
+ schema: 'scoreCardMacroSchema',
19
+ };
20
+
21
+ export default macroMetadata;