@cyberismo/data-handler 0.0.8 → 0.0.10

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 (258) hide show
  1. package/dist/command-handler.d.ts +11 -2
  2. package/dist/command-handler.js +61 -18
  3. package/dist/command-handler.js.map +1 -1
  4. package/dist/command-manager.js +8 -8
  5. package/dist/command-manager.js.map +1 -1
  6. package/dist/commands/calculate.d.ts +7 -44
  7. package/dist/commands/calculate.js +8 -389
  8. package/dist/commands/calculate.js.map +1 -1
  9. package/dist/commands/create.d.ts +6 -3
  10. package/dist/commands/create.js +27 -5
  11. package/dist/commands/create.js.map +1 -1
  12. package/dist/commands/edit.d.ts +15 -3
  13. package/dist/commands/edit.js +52 -9
  14. package/dist/commands/edit.js.map +1 -1
  15. package/dist/commands/export.d.ts +11 -9
  16. package/dist/commands/export.js +80 -28
  17. package/dist/commands/export.js.map +1 -1
  18. package/dist/commands/import.d.ts +7 -0
  19. package/dist/commands/import.js +13 -0
  20. package/dist/commands/import.js.map +1 -1
  21. package/dist/commands/move.d.ts +11 -12
  22. package/dist/commands/move.js +12 -13
  23. package/dist/commands/move.js.map +1 -1
  24. package/dist/commands/remove.d.ts +1 -3
  25. package/dist/commands/remove.js +4 -6
  26. package/dist/commands/remove.js.map +1 -1
  27. package/dist/commands/rename.d.ts +1 -3
  28. package/dist/commands/rename.js +3 -6
  29. package/dist/commands/rename.js.map +1 -1
  30. package/dist/commands/show.d.ts +37 -5
  31. package/dist/commands/show.js +89 -8
  32. package/dist/commands/show.js.map +1 -1
  33. package/dist/commands/transition.d.ts +1 -3
  34. package/dist/commands/transition.js +3 -5
  35. package/dist/commands/transition.js.map +1 -1
  36. package/dist/commands/update.d.ts +5 -1
  37. package/dist/commands/update.js +7 -1
  38. package/dist/commands/update.js.map +1 -1
  39. package/dist/commands/validate.d.ts +7 -0
  40. package/dist/commands/validate.js +31 -4
  41. package/dist/commands/validate.js.map +1 -1
  42. package/dist/containers/card-container.d.ts +6 -0
  43. package/dist/containers/card-container.js +61 -0
  44. package/dist/containers/card-container.js.map +1 -1
  45. package/dist/containers/project/calculation-engine.d.ts +90 -0
  46. package/dist/containers/project/calculation-engine.js +402 -0
  47. package/dist/containers/project/calculation-engine.js.map +1 -0
  48. package/dist/containers/project/resource-collector.js +9 -13
  49. package/dist/containers/project/resource-collector.js.map +1 -1
  50. package/dist/containers/project.d.ts +18 -1
  51. package/dist/containers/project.js +28 -55
  52. package/dist/containers/project.js.map +1 -1
  53. package/dist/containers/template.d.ts +5 -0
  54. package/dist/containers/template.js +9 -0
  55. package/dist/containers/template.js.map +1 -1
  56. package/dist/index.d.ts +5 -2
  57. package/dist/index.js +5 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/interfaces/macros.d.ts +4 -2
  60. package/dist/interfaces/project-interfaces.d.ts +21 -0
  61. package/dist/interfaces/project-interfaces.js +4 -0
  62. package/dist/interfaces/project-interfaces.js.map +1 -1
  63. package/dist/interfaces/resource-interfaces.d.ts +4 -2
  64. package/dist/interfaces/resource-interfaces.js.map +1 -1
  65. package/dist/macros/base-macro.d.ts +2 -1
  66. package/dist/macros/base-macro.js +14 -2
  67. package/dist/macros/base-macro.js.map +1 -1
  68. package/dist/macros/common.d.ts +16 -9
  69. package/dist/macros/common.js +22 -9
  70. package/dist/macros/common.js.map +1 -1
  71. package/dist/macros/createCards/index.d.ts +2 -2
  72. package/dist/macros/createCards/index.js +4 -0
  73. package/dist/macros/createCards/index.js.map +1 -1
  74. package/dist/macros/graph/index.d.ts +1 -3
  75. package/dist/macros/graph/index.js +1 -6
  76. package/dist/macros/graph/index.js.map +1 -1
  77. package/dist/macros/image/index.d.ts +39 -0
  78. package/dist/macros/image/index.js +82 -0
  79. package/dist/macros/image/index.js.map +1 -0
  80. package/dist/macros/image/metadata.d.ts +18 -0
  81. package/dist/macros/image/metadata.js +22 -0
  82. package/dist/macros/image/metadata.js.map +1 -0
  83. package/dist/macros/include/index.d.ts +31 -0
  84. package/dist/macros/include/index.js +94 -0
  85. package/dist/macros/include/index.js.map +1 -0
  86. package/dist/macros/include/metadata.d.ts +15 -0
  87. package/dist/macros/include/metadata.js +19 -0
  88. package/dist/macros/include/metadata.js.map +1 -0
  89. package/dist/macros/index.d.ts +33 -31
  90. package/dist/macros/index.js +142 -71
  91. package/dist/macros/index.js.map +1 -1
  92. package/dist/macros/percentage/index.d.ts +28 -0
  93. package/dist/macros/percentage/index.js +33 -0
  94. package/dist/macros/percentage/index.js.map +1 -0
  95. package/dist/macros/percentage/metadata.d.ts +15 -0
  96. package/dist/macros/percentage/metadata.js +19 -0
  97. package/dist/macros/percentage/metadata.js.map +1 -0
  98. package/dist/macros/report/index.d.ts +2 -6
  99. package/dist/macros/report/index.js +3 -7
  100. package/dist/macros/report/index.js.map +1 -1
  101. package/dist/macros/scoreCard/index.d.ts +14 -15
  102. package/dist/macros/scoreCard/index.js +14 -18
  103. package/dist/macros/scoreCard/index.js.map +1 -1
  104. package/dist/macros/vega/index.d.ts +28 -0
  105. package/dist/macros/vega/index.js +27 -0
  106. package/dist/macros/vega/index.js.map +1 -0
  107. package/dist/macros/vega/metadata.d.ts +15 -0
  108. package/dist/macros/vega/metadata.js +7 -0
  109. package/dist/macros/vega/metadata.js.map +1 -0
  110. package/dist/macros/vegalite/index.d.ts +26 -0
  111. package/dist/macros/vegalite/index.js +24 -0
  112. package/dist/macros/vegalite/index.js.map +1 -0
  113. package/dist/macros/vegalite/metadata.d.ts +15 -0
  114. package/dist/macros/vegalite/metadata.js +7 -0
  115. package/dist/macros/vegalite/metadata.js.map +1 -0
  116. package/dist/macros/xref/index.d.ts +26 -0
  117. package/dist/macros/xref/index.js +53 -0
  118. package/dist/macros/xref/index.js.map +1 -0
  119. package/dist/macros/xref/metadata.d.ts +15 -0
  120. package/dist/macros/xref/metadata.js +19 -0
  121. package/dist/macros/xref/metadata.js.map +1 -0
  122. package/dist/module-manager.d.ts +1 -0
  123. package/dist/module-manager.js +14 -4
  124. package/dist/module-manager.js.map +1 -1
  125. package/dist/permissions/action-guard.d.ts +2 -2
  126. package/dist/permissions/action-guard.js +1 -1
  127. package/dist/permissions/action-guard.js.map +1 -1
  128. package/dist/resources/card-type-resource.d.ts +2 -0
  129. package/dist/resources/card-type-resource.js +63 -0
  130. package/dist/resources/card-type-resource.js.map +1 -1
  131. package/dist/resources/file-resource.d.ts +2 -0
  132. package/dist/resources/file-resource.js +12 -4
  133. package/dist/resources/file-resource.js.map +1 -1
  134. package/dist/resources/folder-resource.d.ts +19 -0
  135. package/dist/resources/folder-resource.js +51 -2
  136. package/dist/resources/folder-resource.js.map +1 -1
  137. package/dist/resources/graph-model-resource.js +1 -1
  138. package/dist/resources/graph-model-resource.js.map +1 -1
  139. package/dist/resources/graph-view-resource.js +1 -1
  140. package/dist/resources/graph-view-resource.js.map +1 -1
  141. package/dist/resources/report-resource.js +1 -1
  142. package/dist/resources/report-resource.js.map +1 -1
  143. package/dist/resources/resource-object.d.ts +8 -0
  144. package/dist/resources/resource-object.js +10 -1
  145. package/dist/resources/resource-object.js.map +1 -1
  146. package/dist/resources/template-resource.js +1 -1
  147. package/dist/resources/template-resource.js.map +1 -1
  148. package/dist/resources/workflow-resource.d.ts +2 -0
  149. package/dist/resources/workflow-resource.js +53 -9
  150. package/dist/resources/workflow-resource.js.map +1 -1
  151. package/dist/svg/index.d.ts +15 -0
  152. package/dist/svg/index.js +16 -0
  153. package/dist/svg/index.js.map +1 -0
  154. package/dist/svg/lib.d.ts +9 -0
  155. package/dist/svg/lib.js +26 -0
  156. package/dist/svg/lib.js.map +1 -0
  157. package/dist/svg/percentage.d.ts +25 -0
  158. package/dist/svg/percentage.js +90 -0
  159. package/dist/svg/percentage.js.map +1 -0
  160. package/dist/svg/scoreCard.d.ts +19 -0
  161. package/dist/svg/scoreCard.js +55 -0
  162. package/dist/svg/scoreCard.js.map +1 -0
  163. package/dist/types/queries.d.ts +8 -7
  164. package/dist/types/queries.js.map +1 -1
  165. package/dist/utils/card-utils.d.ts +6 -0
  166. package/dist/utils/card-utils.js +12 -0
  167. package/dist/utils/card-utils.js.map +1 -1
  168. package/dist/utils/clingo-facts.d.ts +2 -1
  169. package/dist/utils/clingo-facts.js +19 -2
  170. package/dist/utils/clingo-facts.js.map +1 -1
  171. package/dist/utils/clingo-parser.d.ts +1 -0
  172. package/dist/utils/clingo-parser.js +22 -100
  173. package/dist/utils/clingo-parser.js.map +1 -1
  174. package/dist/utils/constants.d.ts +7 -0
  175. package/dist/utils/constants.js +14 -0
  176. package/dist/utils/constants.js.map +1 -1
  177. package/dist/utils/csv.js.map +1 -1
  178. package/dist/utils/report.d.ts +17 -3
  179. package/dist/utils/report.js +38 -2
  180. package/dist/utils/report.js.map +1 -1
  181. package/dist/utils/resource-utils.d.ts +2 -1
  182. package/dist/utils/resource-utils.js +12 -3
  183. package/dist/utils/resource-utils.js.map +1 -1
  184. package/dist/utils/user-preferences.d.ts +1 -11
  185. package/dist/utils/user-preferences.js +30 -13
  186. package/dist/utils/user-preferences.js.map +1 -1
  187. package/dist/utils/validate.d.ts +2 -3
  188. package/dist/utils/validate.js +2 -2
  189. package/dist/utils/validate.js.map +1 -1
  190. package/package.json +8 -6
  191. package/src/command-handler.ts +96 -17
  192. package/src/command-manager.ts +8 -8
  193. package/src/commands/calculate.ts +11 -525
  194. package/src/commands/create.ts +35 -6
  195. package/src/commands/edit.ts +94 -11
  196. package/src/commands/export.ts +104 -31
  197. package/src/commands/import.ts +16 -0
  198. package/src/commands/move.ts +12 -15
  199. package/src/commands/remove.ts +4 -8
  200. package/src/commands/rename.ts +3 -12
  201. package/src/commands/show.ts +126 -9
  202. package/src/commands/transition.ts +3 -7
  203. package/src/commands/update.ts +6 -0
  204. package/src/commands/validate.ts +41 -13
  205. package/src/containers/card-container.ts +74 -0
  206. package/src/containers/project/calculation-engine.ts +535 -0
  207. package/src/containers/project/resource-collector.ts +13 -15
  208. package/src/containers/project.ts +30 -66
  209. package/src/containers/template.ts +16 -0
  210. package/src/index.ts +13 -2
  211. package/src/interfaces/macros.ts +4 -1
  212. package/src/interfaces/project-interfaces.ts +27 -0
  213. package/src/interfaces/resource-interfaces.ts +5 -2
  214. package/src/macros/base-macro.ts +19 -4
  215. package/src/macros/common.ts +22 -9
  216. package/src/macros/createCards/index.ts +6 -2
  217. package/src/macros/graph/index.ts +6 -10
  218. package/src/macros/image/index.ts +128 -0
  219. package/src/macros/image/metadata.ts +25 -0
  220. package/src/macros/include/index.ts +143 -0
  221. package/src/macros/include/metadata.ts +22 -0
  222. package/src/macros/index.ts +150 -98
  223. package/src/macros/percentage/index.ts +50 -0
  224. package/src/macros/percentage/metadata.ts +22 -0
  225. package/src/macros/report/index.ts +4 -12
  226. package/src/macros/scoreCard/index.ts +21 -25
  227. package/src/macros/vega/index.ts +55 -0
  228. package/src/macros/vega/metadata.ts +21 -0
  229. package/src/macros/vegalite/index.ts +46 -0
  230. package/src/macros/vegalite/metadata.ts +21 -0
  231. package/src/macros/xref/index.ts +73 -0
  232. package/src/macros/xref/metadata.ts +22 -0
  233. package/src/module-manager.ts +15 -5
  234. package/src/permissions/action-guard.ts +3 -3
  235. package/src/resources/card-type-resource.ts +100 -0
  236. package/src/resources/file-resource.ts +16 -4
  237. package/src/resources/folder-resource.ts +59 -2
  238. package/src/resources/graph-model-resource.ts +1 -1
  239. package/src/resources/graph-view-resource.ts +1 -1
  240. package/src/resources/report-resource.ts +1 -1
  241. package/src/resources/resource-object.ts +19 -1
  242. package/src/resources/template-resource.ts +1 -1
  243. package/src/resources/workflow-resource.ts +68 -13
  244. package/src/svg/index.ts +15 -0
  245. package/src/svg/lib.ts +31 -0
  246. package/src/svg/percentage.ts +97 -0
  247. package/src/svg/scoreCard.ts +88 -0
  248. package/src/types/queries.ts +8 -7
  249. package/src/types/string-pixel-width.d.ts +23 -0
  250. package/src/utils/card-utils.ts +13 -0
  251. package/src/utils/clingo-facts.ts +65 -3
  252. package/src/utils/clingo-parser.ts +31 -144
  253. package/src/utils/constants.ts +16 -0
  254. package/src/utils/csv.ts +1 -1
  255. package/src/utils/report.ts +45 -4
  256. package/src/utils/resource-utils.ts +12 -2
  257. package/src/utils/user-preferences.ts +32 -14
  258. package/src/utils/validate.ts +3 -3
@@ -11,490 +11,19 @@
11
11
  License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
12
  */
13
13
 
14
- // node
15
- import { basename, join, resolve } from 'node:path';
16
- import { readFile } from 'node:fs/promises';
17
- import { sanitizeSvgBase64 } from '../utils/sanitize-svg.js';
18
- import { instance } from '@viz-js/viz';
19
-
20
- import type {
21
- BaseResult,
22
- ParseResult,
23
- QueryName,
24
- QueryResult,
25
- } from '../types/queries.js';
26
- import type { Card } from '../interfaces/project-interfaces.js';
27
- import ClingoParser from '../utils/clingo-parser.js';
28
- import { pathExists } from '../utils/file-utils.js';
29
- import { Mutex } from 'async-mutex';
30
- import Handlebars from 'handlebars';
31
- import { type Project, ResourcesFrom } from '../containers/project.js';
32
- import { flattenCardArray } from '../utils/card-utils.js';
33
- import { getChildLogger } from '../utils/log-utils.js';
34
- import {
35
- createCardFacts,
36
- createCardTypeFacts,
37
- createFieldTypeFacts,
38
- createLinkTypeFacts,
39
- createModuleFacts,
40
- createProjectFacts,
41
- createReportFacts,
42
- createTemplateFacts,
43
- createWorkflowFacts,
44
- } from '../utils/clingo-facts.js';
45
- import { CardMetadataUpdater } from '../card-metadata-updater.js';
46
- import type {
47
- CardType,
48
- FieldType,
49
- LinkType,
50
- ReportMetadata,
51
- TemplateMetadata,
52
- Workflow,
53
- } from '../interfaces/resource-interfaces.js';
54
- import { solve, setBaseProgram } from '@cyberismo/node-clingo';
55
- import { generateReportContent } from '../utils/report.js';
56
- import { lpFiles, graphvizReport } from '@cyberismo/assets';
57
-
58
- // Define names for the base programs
59
- const BASE_PROGRAM_KEY = 'base';
60
- const QUERY_LANGUAGE_KEY = 'queryLanguage';
14
+ import type { Context } from '../interfaces/project-interfaces.js';
15
+ import type { Project } from '../containers/project.js';
16
+ import type { QueryName, QueryResult } from '../types/queries.js';
61
17
 
62
18
  // Class that calculates with logic program card / project level calculations.
63
19
  export class Calculate {
64
- private get logger() {
65
- return getChildLogger({
66
- module: 'calculate',
67
- });
68
- }
69
- private static mutex = new Mutex();
70
-
71
20
  constructor(private project: Project) {}
72
21
 
73
- // Storage for in-memory program content
74
- private logicProgram: string = '';
75
- private modules: string = '';
76
-
77
- private modulesInitialized = false;
78
-
79
- // Initialize modules during construction
80
- private async initializeModules() {
81
- try {
82
- // Collect all available calculations at initialization time
83
- const modules = await this.generateModules();
84
- this.modules = modules; // Store initial modules in logicProgram
85
- } catch (error) {
86
- this.logger.error(error, 'Failed to initialize modules');
87
- }
88
- }
89
-
90
- // Wrapper to run onCreation query.
91
- private async creationQuery(cardKeys: string[]) {
92
- if (!cardKeys) return undefined;
93
- return this.runQuery('onCreation', {
94
- cardKeys,
95
- });
96
- }
97
-
98
- // Generate card tree content
99
- private async generateCardTreeContent(parentCard: Card | undefined) {
100
- const cards = await this.getCards(parentCard);
101
-
102
- let content = '% SECTION: CARDS_START\n';
103
-
104
- for (const card of cards) {
105
- const cardContent = await createCardFacts(card, this.project);
106
- content += `% SECTION: CARD_${card.key}_START\n`;
107
- content += `% Card ${card.key}\n`;
108
- content += `${cardContent}\n`;
109
- content += `% SECTION: CARD_${card.key}_END\n\n`;
110
- }
111
-
112
- content += '% SECTION: CARDS_END';
113
-
114
- return content;
115
- }
116
-
117
- //
118
- private async generateCardTypes() {
119
- const cardTypes = await this.project.cardTypes();
120
- let content = '';
121
-
122
- for (const cardType of await Promise.all(
123
- cardTypes.map((c) => this.project.resource<CardType>(c.name)),
124
- )) {
125
- if (!cardType) continue;
126
-
127
- const cardTypeContent = createCardTypeFacts(cardType);
128
- content += `% CardType ${cardType.name}\n${cardTypeContent}\n\n`;
129
- }
130
-
131
- return content;
132
- }
133
-
134
- //
135
- private async generateFieldTypes() {
136
- const fieldTypes = await this.project.fieldTypes();
137
- let content = '';
138
-
139
- for (const fieldType of await Promise.all(
140
- fieldTypes.map((m) => this.project.resource<FieldType>(m.name)),
141
- )) {
142
- if (!fieldType) continue;
143
-
144
- const fieldTypeContent = createFieldTypeFacts(fieldType);
145
- content += `% FieldType ${fieldType.name}\n${fieldTypeContent}\n\n`;
146
- }
147
- return content;
148
- }
149
-
150
- // Collects all linkTypes from the project
151
- private async generateLinkTypes() {
152
- const linkTypes = await this.project.linkTypes();
153
- let content = '';
154
-
155
- for (const linkType of await Promise.all(
156
- linkTypes.map((c) => this.project.resource<LinkType>(c.name)),
157
- )) {
158
- if (!linkType) continue;
159
-
160
- const linkTypeContent = createLinkTypeFacts(linkType);
161
- content += `% LinkType ${linkType.name}\n${linkTypeContent}\n\n`;
162
- }
163
-
164
- return content;
165
- }
166
-
167
- // Generates logic programs related to modules (and project itself).
168
- private async generateModules() {
169
- const modules = await this.project.modules();
170
- let content = '';
171
- for (const module of await Promise.all(
172
- modules.map((mod) => this.project.module(mod.name)),
173
- )) {
174
- if (!module) continue;
175
- const moduleContent = createModuleFacts(module);
176
- content = content.concat(moduleContent);
177
- }
178
- const projectContent = createProjectFacts(this.project.projectPrefix);
179
- content = content.concat(projectContent);
180
- return content;
181
- }
182
-
183
- // Collects all logic calculation files from project (local and imported modules)
184
- private async generateCalculations() {
185
- // Collect all available calculations
186
- const calculations = await this.project.calculations(ResourcesFrom.all);
187
- let content = '% SECTION: MODULES_START\n';
188
-
189
- // Process modules content
190
- for (const calculationFile of calculations) {
191
- if (calculationFile.path) {
192
- const moduleLogicFile = resolve(
193
- join(calculationFile.path, basename(calculationFile.name)),
194
- );
195
-
196
- const filePath = moduleLogicFile.endsWith('.lp')
197
- ? moduleLogicFile
198
- : moduleLogicFile + '.lp';
199
-
200
- if (pathExists(filePath)) {
201
- try {
202
- const moduleContent = await readFile(filePath, 'utf-8');
203
- content += `% SECTION: MODULE_${calculationFile.name}_START\n`;
204
- content += `% Module ${calculationFile.name}\n`;
205
- content += `${moduleContent}\n`;
206
- content += `% SECTION: MODULE_${calculationFile.name}_END\n\n`;
207
- } catch (error) {
208
- this.logger.warn(
209
- error,
210
- `Failed to read module ${calculationFile.name}`,
211
- );
212
- }
213
- }
214
- }
215
- }
216
- content += '% SECTION: MODULES_END';
217
- return content;
218
- }
219
-
220
- // Generates logic programs related to reports.
221
- private async generateReports() {
222
- const reports = await this.project.reports();
223
- let content = '';
224
-
225
- for (const report of await Promise.all(
226
- reports.map((r) => this.project.resource<ReportMetadata>(r.name)),
227
- )) {
228
- if (!report) continue;
229
- content += createReportFacts(report);
230
- }
231
- return content;
232
- }
233
-
234
- // Generates logic programs related to templates (including their cards).
235
- private async generateTemplates() {
236
- const templates = await this.project.templates();
237
- let content = '';
238
-
239
- for (const template of await Promise.all(
240
- templates.map((r) => this.project.resource<TemplateMetadata>(r.name)),
241
- )) {
242
- if (!template) continue;
243
-
244
- let templateContent = createTemplateFacts(template);
245
- const cards = await this.getCards(undefined, template.name);
246
- for (const card of cards) {
247
- const cardContent = await createCardFacts(card, this.project);
248
- templateContent = templateContent.concat(cardContent);
249
- }
250
- content = content.concat(templateContent);
251
- }
252
- return content;
253
- }
254
-
255
- //
256
- private async generateWorkFlows() {
257
- const workflows = await this.project.workflows();
258
- let content = '';
259
-
260
- // loop through workflows
261
- for (const workflow of await Promise.all(
262
- workflows.map((m) => this.project.resource<Workflow>(m.name)),
263
- )) {
264
- if (!workflow) continue;
265
-
266
- const workflowContent = createWorkflowFacts(workflow);
267
- content += `% Workflow ${workflow.name}\n${workflowContent}\n\n`;
268
- }
269
-
270
- return content;
271
- }
272
-
273
- // Gets either all the cards (no parent), or a subtree.
274
- private async getCards(
275
- card: Card | undefined,
276
- templateName?: string,
277
- ): Promise<Card[]> {
278
- let cards: Card[] = [];
279
- if (!card) {
280
- return templateName
281
- ? this.project.templateCards(templateName)
282
- : this.project.cards();
283
- }
284
- if (card.children) {
285
- cards = flattenCardArray(card.children);
286
- }
287
- card.children = [];
288
- cards.unshift(card);
289
- return cards;
290
- }
291
-
292
- // Checks that Clingo successfully returned result.
293
- private async parseClingoResult(
294
- data: string[],
295
- ): Promise<ParseResult<BaseResult>> {
296
- const parser = new ClingoParser();
297
- return parser.parseInput(data.join('\n'));
298
- }
299
-
300
- private async run(query: string): Promise<string[]> {
301
- try {
302
- const res = await Calculate.mutex.runExclusive(async () => {
303
- // For queries, use both base and queryLanguage
304
- const basePrograms = [BASE_PROGRAM_KEY, QUERY_LANGUAGE_KEY];
305
-
306
- this.logger.trace(
307
- {
308
- clingo: true,
309
- },
310
- 'Solving',
311
- );
312
-
313
- // Then solve with the program - need to pass the program as parameter
314
- return solve(query, basePrograms);
315
- });
316
-
317
- if (res && res.answers && res.answers.length > 0) {
318
- return res.answers;
319
- }
320
- throw new Error('Failed to run Clingo solve. No answers returned.');
321
- } catch (error) {
322
- this.logger.error(
323
- {
324
- error,
325
- query,
326
- },
327
- 'Clingo solve failed',
328
- );
329
- throw error;
330
- }
331
- }
332
-
333
22
  /**
334
23
  * Generates a logic program.
335
- * @param cardKey Optional, sub-card tree defining card
336
24
  */
337
- public async generate(cardKey?: string) {
338
- await Calculate.mutex.runExclusive(async () => {
339
- this.logger.trace(
340
- {
341
- clingo: true,
342
- cardKey,
343
- },
344
- 'Generating logic program',
345
- );
346
-
347
- if (!this.modulesInitialized) {
348
- await this.initializeModules();
349
- this.modulesInitialized = true;
350
- }
351
-
352
- let card: Card | undefined;
353
- if (cardKey) {
354
- card = await this.project.findSpecificCard(cardKey, {
355
- metadata: true,
356
- children: true,
357
- content: false,
358
- parent: false,
359
- });
360
- if (!card) {
361
- throw new Error(`Card '${cardKey}' not found`);
362
- }
363
- }
364
- const calculations = await this.generateCalculations();
365
- const cardTreeContent = await this.generateCardTreeContent(card);
366
- const workFlows = await this.generateWorkFlows();
367
- const cardTypes = await this.generateCardTypes();
368
- const fieldTypes = await this.generateFieldTypes();
369
- const linkTypes = await this.generateLinkTypes();
370
- const reports = await this.generateReports();
371
- const templates = await this.generateTemplates();
372
-
373
- // Combine all resources
374
- const resourcesProgram =
375
- '% SECTION: RESOURCES_START\n' +
376
- calculations +
377
- workFlows +
378
- cardTypes +
379
- fieldTypes +
380
- linkTypes +
381
- reports +
382
- templates +
383
- '% SECTION: RESOURCES_END';
384
-
385
- // Create base program content
386
- const baseProgram =
387
- '% SECTION: BASE_START\n' +
388
- lpFiles.common.base +
389
- '\n% SECTION: BASE_END\n\n' +
390
- this.modules +
391
- '\n\n' +
392
- cardTreeContent +
393
- '\n\n' +
394
- resourcesProgram;
395
-
396
- // Set the base programs separately
397
- setBaseProgram(baseProgram, BASE_PROGRAM_KEY);
398
- setBaseProgram(
399
- '% SECTION: QUERY_LANGUAGE_START\n' +
400
- lpFiles.common.queryLanguage +
401
- '\n% SECTION: QUERY_LANGUAGE_END',
402
- QUERY_LANGUAGE_KEY,
403
- );
404
-
405
- // Also store the base program (without query language) for updates
406
- this.logicProgram = baseProgram;
407
- this.logger.trace(
408
- {
409
- clingo: true,
410
- cardKey,
411
- },
412
- 'Logic program set',
413
- );
414
- });
415
- }
416
-
417
- /**
418
- * When card changes, update the card specific calculations.
419
- * @param changedCard Card that was changed.
420
- */
421
- public async handleCardChanged(changedCard: Card) {
422
- await this.generate(changedCard.key);
423
- return { statusCode: 200 };
424
- }
425
-
426
- /**
427
- * When cards are removed, automatically remove card-specific calculations.
428
- * @param deletedCard Card that is to be removed.
429
- */
430
- public async handleDeleteCard(deletedCard: Card) {
431
- if (!deletedCard) {
432
- return;
433
- }
434
-
435
- await Calculate.mutex.runExclusive(async () => {
436
- const affectedCards = await this.getCards(deletedCard);
437
-
438
- // Filter out deleted cards' content from the cardsProgram string
439
- for (const card of affectedCards) {
440
- // Remove card-specific content from the in-memory program using section markers
441
- const cardSectionPattern = new RegExp(
442
- `% SECTION: CARD_${card.key}_START[\\s\\S]*?% SECTION: CARD_${card.key}_END\\n\\n`,
443
- 'g',
444
- );
445
- this.logicProgram = this.logicProgram.replace(cardSectionPattern, '');
446
- }
447
-
448
- // Update the base program after modifying logicProgram
449
- setBaseProgram(this.logicProgram, BASE_PROGRAM_KEY);
450
- });
451
- }
452
-
453
- /**
454
- * When new cards are added, automatically calculate card-specific values.
455
- * @param cards Added cards.
456
- */
457
- public async handleNewCards(cards: Card[]) {
458
- if (!cards) {
459
- return;
460
- }
461
-
462
- // Only proceed if we already have a logic program
463
- if (!this.logicProgram) {
464
- return;
465
- }
466
-
467
- await Calculate.mutex.runExclusive(async () => {
468
- // Generate content for all cards (including new ones)
469
- const cardTreeContent = await this.generateCardTreeContent(undefined);
470
-
471
- // Update the main logic program with the new cards program
472
- if (
473
- this.logicProgram.includes('% SECTION: CARDS_START') &&
474
- this.logicProgram.includes('% SECTION: CARDS_END')
475
- ) {
476
- this.logicProgram = this.logicProgram.replace(
477
- /% SECTION: CARDS_START[\s\S]*?% SECTION: CARDS_END/,
478
- cardTreeContent,
479
- );
480
- }
481
-
482
- // Update the base program after modifying logicProgram
483
- setBaseProgram(this.logicProgram, BASE_PROGRAM_KEY);
484
- });
485
-
486
- const cardKeys = cards.map((item) => item.key);
487
- const queryResult = await this.creationQuery(cardKeys);
488
- if (
489
- !queryResult ||
490
- queryResult.at(0) === undefined ||
491
- queryResult.at(0)?.updateFields === undefined
492
- ) {
493
- return;
494
- }
495
-
496
- const fieldsToUpdate = queryResult.at(0)!.updateFields;
497
- await CardMetadataUpdater.apply(this.project, fieldsToUpdate);
25
+ public async generate() {
26
+ return this.project.calculationEngine.generate();
498
27
  }
499
28
 
500
29
  /**
@@ -503,31 +32,8 @@ export class Calculate {
503
32
  * @param timeout Maximum amount of milliseconds clingraph is allowed to run
504
33
  * @returns a base64 encoded image as a string
505
34
  */
506
- public async runGraph(model: string, view: string) {
507
- this.logger.trace(
508
- {
509
- model,
510
- view,
511
- },
512
- 'Running graph',
513
- );
514
-
515
- // Let's run the clingraph query
516
- const result = await generateReportContent({
517
- calculate: this,
518
- contentTemplate: graphvizReport.content,
519
- queryTemplate: graphvizReport.query,
520
- options: {
521
- model: model,
522
- view: view,
523
- },
524
- graph: true,
525
- });
526
- return sanitizeSvgBase64(
527
- (await instance()).renderString(result, {
528
- format: 'svg',
529
- }),
530
- );
35
+ public async runGraph(model: string, view: string, context: Context) {
36
+ return this.project.calculationEngine.runGraph(model, view, context);
531
37
  }
532
38
 
533
39
  /**
@@ -535,10 +41,8 @@ export class Calculate {
535
41
  * @param query Logic program to be run
536
42
  * @returns parsed program output
537
43
  */
538
- public async runLogicProgram(query: string) {
539
- const clingoOutput = await this.run(query);
540
-
541
- return this.parseClingoResult(clingoOutput);
44
+ public async runLogicProgram(query: string, context: Context = 'localApp') {
45
+ return this.project.calculationEngine.runLogicProgram(query, context);
542
46
  }
543
47
 
544
48
  /**
@@ -549,27 +53,9 @@ export class Calculate {
549
53
  */
550
54
  public async runQuery<T extends QueryName>(
551
55
  queryName: T,
56
+ context: Context = 'localApp',
552
57
  options?: unknown,
553
58
  ): Promise<QueryResult<T>[]> {
554
- let content = lpFiles.queries[queryName];
555
- if (options && typeof options === 'object') {
556
- const handlebars = Handlebars.create();
557
- const compiled = handlebars.compile(content);
558
- content = compiled(options);
559
- }
560
-
561
- if (!content) {
562
- throw new Error(`Query file ${queryName} not found`);
563
- }
564
-
565
- this.logger.trace({ queryName }, 'Running query');
566
- const clingoOutput = await this.run(content);
567
-
568
- const result = await this.parseClingoResult(clingoOutput);
569
-
570
- if (result.error) {
571
- throw new Error(result.error);
572
- }
573
- return result.results as QueryResult<T>[];
59
+ return this.project.calculationEngine.runQuery(queryName, context, options);
574
60
  }
575
61
  }
@@ -20,9 +20,10 @@ import {
20
20
  writeFile,
21
21
  } from 'node:fs/promises';
22
22
 
23
- import { type Calculate, Validate } from './index.js';
24
23
  import { errorFunction } from '../utils/log-utils.js';
25
24
  import { Project } from '../containers/project.js';
25
+ import { Validate } from './index.js';
26
+
26
27
  import { EMPTY_RANK, sortItems } from '../utils/lexorank.js';
27
28
  import type {
28
29
  DataType,
@@ -50,10 +51,7 @@ import { WorkflowResource } from '../resources/workflow-resource.js';
50
51
  * Handles all create commands.
51
52
  */
52
53
  export class Create {
53
- constructor(
54
- private project: Project,
55
- private calculateCmd: Calculate,
56
- ) {}
54
+ constructor(private project: Project) {}
57
55
 
58
56
  static JSONFileContent: ProjectFile[] = [
59
57
  {
@@ -205,6 +203,37 @@ export class Create {
205
203
  }
206
204
  }
207
205
 
206
+ /**
207
+ * Creates a calculation file.
208
+ * @param fileName name for the calculation file (without .lp extension)
209
+ */
210
+ public async createCalculation(fileName: string) {
211
+ const calculationFolder = this.project.paths.calculationProjectFolder;
212
+
213
+ await mkdir(calculationFolder, { recursive: true });
214
+
215
+ const calculationFileName = fileName.endsWith('.lp')
216
+ ? fileName
217
+ : `${fileName}.lp`;
218
+ const calculationFilePath = join(calculationFolder, calculationFileName);
219
+
220
+ const calculationContent = `% Calculation file: ${calculationFileName}
221
+ % Add your logic programming rules here
222
+ `;
223
+
224
+ await writeFile(calculationFilePath, calculationContent, { flag: 'wx' });
225
+
226
+ // add to cache manually
227
+ // TODO: remove once calculations are a proper resource
228
+ const resourceName = `${this.project.projectPrefix}/calculations/${fileName.replace('.lp', '')}`;
229
+ const resource = {
230
+ name: resourceName,
231
+ path: calculationFolder,
232
+ };
233
+
234
+ this.project.addResource(resource, {} as JSON);
235
+ }
236
+
208
237
  /**
209
238
  * Creates card(s) to a project. All cards from template are instantiated to the project.
210
239
  * @param templateName name of a template to use
@@ -245,7 +274,7 @@ export class Create {
245
274
 
246
275
  const createdCards = await templateObject.createCards(specificCard);
247
276
  if (createdCards.length > 0) {
248
- await this.calculateCmd.handleNewCards(createdCards);
277
+ await this.project.handleNewCards(createdCards);
249
278
  // Note: This assumes that parent keys will be ahead of 'a' in the sort order.
250
279
  const sorted = sortItems(createdCards, (item) => {
251
280
  return `${item.parent === 'root' ? 'a' : item.parent}${item.metadata?.rank || EMPTY_RANK}`;