@cyberismo/data-handler 0.0.6 → 0.0.8

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 (175) hide show
  1. package/README.md +1 -0
  2. package/dist/card-metadata-updater.d.ts +1 -0
  3. package/dist/card-metadata-updater.js +7 -2
  4. package/dist/card-metadata-updater.js.map +1 -1
  5. package/dist/command-handler.d.ts +6 -1
  6. package/dist/command-handler.js +16 -15
  7. package/dist/command-handler.js.map +1 -1
  8. package/dist/command-manager.d.ts +15 -4
  9. package/dist/command-manager.js +41 -9
  10. package/dist/command-manager.js.map +1 -1
  11. package/dist/commands/calculate.d.ts +4 -10
  12. package/dist/commands/calculate.js +67 -78
  13. package/dist/commands/calculate.js.map +1 -1
  14. package/dist/commands/create.d.ts +1 -1
  15. package/dist/commands/create.js +15 -10
  16. package/dist/commands/create.js.map +1 -1
  17. package/dist/commands/export.js +3 -3
  18. package/dist/commands/export.js.map +1 -1
  19. package/dist/commands/import.d.ts +3 -8
  20. package/dist/commands/import.js +17 -15
  21. package/dist/commands/import.js.map +1 -1
  22. package/dist/commands/index.d.ts +1 -2
  23. package/dist/commands/index.js +1 -2
  24. package/dist/commands/index.js.map +1 -1
  25. package/dist/commands/remove.d.ts +1 -1
  26. package/dist/commands/remove.js +4 -10
  27. package/dist/commands/remove.js.map +1 -1
  28. package/dist/commands/show.d.ts +6 -3
  29. package/dist/commands/show.js +8 -5
  30. package/dist/commands/show.js.map +1 -1
  31. package/dist/commands/validate.d.ts +0 -8
  32. package/dist/commands/validate.js +6 -36
  33. package/dist/commands/validate.js.map +1 -1
  34. package/dist/containers/project/project-content-watcher.d.ts +28 -0
  35. package/dist/containers/project/project-content-watcher.js +54 -0
  36. package/dist/containers/project/project-content-watcher.js.map +1 -0
  37. package/dist/containers/project/project-paths.js +1 -1
  38. package/dist/containers/project/project-paths.js.map +1 -1
  39. package/dist/containers/project/resource-collector.d.ts +2 -1
  40. package/dist/containers/project/resource-collector.js +33 -23
  41. package/dist/containers/project/resource-collector.js.map +1 -1
  42. package/dist/containers/project.d.ts +9 -7
  43. package/dist/containers/project.js +58 -18
  44. package/dist/containers/project.js.map +1 -1
  45. package/dist/containers/template.d.ts +1 -0
  46. package/dist/containers/template.js +7 -2
  47. package/dist/containers/template.js.map +1 -1
  48. package/dist/exceptions/index.d.ts +20 -0
  49. package/dist/exceptions/index.js +16 -0
  50. package/dist/exceptions/index.js.map +1 -1
  51. package/dist/index.d.ts +2 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/interfaces/macros.d.ts +5 -1
  54. package/dist/interfaces/project-interfaces.d.ts +5 -0
  55. package/dist/interfaces/project-interfaces.js.map +1 -1
  56. package/dist/interfaces/resource-interfaces.d.ts +14 -22
  57. package/dist/interfaces/resource-interfaces.js +10 -9
  58. package/dist/interfaces/resource-interfaces.js.map +1 -1
  59. package/dist/macros/base-macro.d.ts +2 -0
  60. package/dist/macros/base-macro.js +66 -19
  61. package/dist/macros/base-macro.js.map +1 -1
  62. package/dist/macros/graph/index.d.ts +0 -1
  63. package/dist/macros/graph/index.js +16 -12
  64. package/dist/macros/graph/index.js.map +1 -1
  65. package/dist/macros/index.d.ts +30 -3
  66. package/dist/macros/index.js +36 -6
  67. package/dist/macros/index.js.map +1 -1
  68. package/dist/macros/report/index.d.ts +13 -10
  69. package/dist/macros/report/index.js +35 -38
  70. package/dist/macros/report/index.js.map +1 -1
  71. package/dist/module-manager.d.ts +32 -11
  72. package/dist/module-manager.js +301 -147
  73. package/dist/module-manager.js.map +1 -1
  74. package/dist/project-settings.js +8 -8
  75. package/dist/project-settings.js.map +1 -1
  76. package/dist/resources/array-handler.js +6 -1
  77. package/dist/resources/array-handler.js.map +1 -1
  78. package/dist/resources/card-type-resource.d.ts +13 -9
  79. package/dist/resources/card-type-resource.js +47 -23
  80. package/dist/resources/card-type-resource.js.map +1 -1
  81. package/dist/resources/create-defaults.d.ts +10 -9
  82. package/dist/resources/create-defaults.js +15 -12
  83. package/dist/resources/create-defaults.js.map +1 -1
  84. package/dist/resources/field-type-resource.d.ts +0 -1
  85. package/dist/resources/field-type-resource.js +2 -10
  86. package/dist/resources/field-type-resource.js.map +1 -1
  87. package/dist/resources/file-resource.d.ts +7 -7
  88. package/dist/resources/file-resource.js +32 -7
  89. package/dist/resources/file-resource.js.map +1 -1
  90. package/dist/resources/folder-resource.d.ts +10 -9
  91. package/dist/resources/folder-resource.js +10 -9
  92. package/dist/resources/folder-resource.js.map +1 -1
  93. package/dist/resources/report-resource.d.ts +5 -6
  94. package/dist/resources/report-resource.js +16 -7
  95. package/dist/resources/report-resource.js.map +1 -1
  96. package/dist/resources/template-resource.d.ts +5 -6
  97. package/dist/resources/template-resource.js +7 -6
  98. package/dist/resources/template-resource.js.map +1 -1
  99. package/dist/resources/workflow-resource.d.ts +15 -8
  100. package/dist/resources/workflow-resource.js +124 -8
  101. package/dist/resources/workflow-resource.js.map +1 -1
  102. package/dist/types/queries.d.ts +11 -10
  103. package/dist/types/queries.js +10 -9
  104. package/dist/types/queries.js.map +1 -1
  105. package/dist/utils/clingo-fact-builder.d.ts +1 -0
  106. package/dist/utils/clingo-fact-builder.js +8 -3
  107. package/dist/utils/clingo-fact-builder.js.map +1 -1
  108. package/dist/utils/clingo-facts.js +15 -11
  109. package/dist/utils/clingo-facts.js.map +1 -1
  110. package/dist/utils/constants.d.ts +18 -12
  111. package/dist/utils/constants.js +18 -11
  112. package/dist/utils/constants.js.map +1 -1
  113. package/dist/utils/log-utils.d.ts +15 -2
  114. package/dist/utils/log-utils.js +20 -37
  115. package/dist/utils/log-utils.js.map +1 -1
  116. package/dist/utils/report.d.ts +27 -0
  117. package/dist/utils/report.js +60 -0
  118. package/dist/utils/report.js.map +1 -0
  119. package/dist/utils/resource-utils.js +3 -0
  120. package/dist/utils/resource-utils.js.map +1 -1
  121. package/dist/utils/sanitize-svg.d.ts +3 -4
  122. package/dist/utils/sanitize-svg.js +4 -7
  123. package/dist/utils/sanitize-svg.js.map +1 -1
  124. package/dist/utils/validate.js +2 -1
  125. package/dist/utils/validate.js.map +1 -1
  126. package/package.json +9 -11
  127. package/src/card-metadata-updater.ts +7 -2
  128. package/src/command-handler.ts +23 -13
  129. package/src/command-manager.ts +54 -13
  130. package/src/commands/calculate.ts +90 -106
  131. package/src/commands/create.ts +18 -10
  132. package/src/commands/export.ts +3 -2
  133. package/src/commands/import.ts +30 -17
  134. package/src/commands/index.ts +0 -2
  135. package/src/commands/remove.ts +7 -12
  136. package/src/commands/show.ts +13 -5
  137. package/src/commands/validate.ts +14 -44
  138. package/src/containers/project/project-content-watcher.ts +65 -0
  139. package/src/containers/project/project-paths.ts +1 -1
  140. package/src/containers/project/resource-collector.ts +33 -14
  141. package/src/containers/project.ts +96 -19
  142. package/src/containers/template.ts +7 -2
  143. package/src/exceptions/index.ts +36 -0
  144. package/src/index.ts +2 -0
  145. package/src/interfaces/macros.ts +5 -1
  146. package/src/interfaces/project-interfaces.ts +8 -0
  147. package/src/interfaces/resource-interfaces.ts +15 -22
  148. package/src/macros/base-macro.ts +89 -25
  149. package/src/macros/graph/index.ts +22 -12
  150. package/src/macros/index.ts +61 -8
  151. package/src/macros/report/index.ts +42 -43
  152. package/src/module-manager.ts +383 -177
  153. package/src/project-settings.ts +9 -11
  154. package/src/resources/array-handler.ts +7 -2
  155. package/src/resources/card-type-resource.ts +61 -46
  156. package/src/resources/create-defaults.ts +15 -12
  157. package/src/resources/field-type-resource.ts +2 -17
  158. package/src/resources/file-resource.ts +46 -8
  159. package/src/resources/folder-resource.ts +11 -10
  160. package/src/resources/report-resource.ts +19 -7
  161. package/src/resources/template-resource.ts +7 -6
  162. package/src/resources/workflow-resource.ts +155 -8
  163. package/src/types/queries.ts +11 -10
  164. package/src/utils/clingo-fact-builder.ts +8 -3
  165. package/src/utils/clingo-facts.ts +18 -12
  166. package/src/utils/constants.ts +20 -12
  167. package/src/utils/log-utils.ts +24 -45
  168. package/src/utils/report.ts +86 -0
  169. package/src/utils/resource-utils.ts +4 -0
  170. package/src/utils/sanitize-svg.ts +4 -9
  171. package/src/utils/validate.ts +3 -2
  172. package/dist/commands/export-site.d.ts +0 -45
  173. package/dist/commands/export-site.js +0 -301
  174. package/dist/commands/export-site.js.map +0 -1
  175. package/src/commands/export-site.ts +0 -356
@@ -1,13 +1,15 @@
1
1
  /**
2
- Cyberismo
3
- Copyright © Cyberismo Ltd and contributors 2024
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2024
4
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/>.
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/>.
11
13
  */
12
14
 
13
15
  import type {
@@ -22,6 +24,7 @@ import type {
22
24
  ChangeOperation,
23
25
  Operation,
24
26
  Project,
27
+ RemoveOperation,
25
28
  ResourceName,
26
29
  } from './file-resource.js';
27
30
  import {
@@ -46,6 +49,27 @@ export class WorkflowResource extends FileResource {
46
49
  this.initialize();
47
50
  }
48
51
 
52
+ // Collect all cards that use this workflow.
53
+ private async collectCardsUsingWorkflow(): Promise<Card[]> {
54
+ const cardTypes = await this.project.cardTypes(ResourcesFrom.localOnly);
55
+ const promises: Promise<Card[]>[] = [];
56
+ for (const cardType of cardTypes) {
57
+ const object = new CardTypeResource(
58
+ this.project,
59
+ resourceName(cardType.name),
60
+ );
61
+ if (
62
+ object.data &&
63
+ (object.data as CardType).workflow ===
64
+ resourceNameToString(this.resourceName)
65
+ ) {
66
+ // fetch all cards with card type
67
+ promises.push(this.collectCards({ metadata: true }, cardType.name));
68
+ }
69
+ }
70
+ return (await Promise.all(promises)).flat();
71
+ }
72
+
49
73
  // When resource name changes.
50
74
  private async handleNameChange(existingName: string) {
51
75
  await Promise.all([
@@ -56,6 +80,96 @@ export class WorkflowResource extends FileResource {
56
80
  await this.write();
57
81
  }
58
82
 
83
+ // Handle change of workflow state.
84
+ private async handleStateChange(op: ChangeOperation<WorkflowState>) {
85
+ const content = { ...(this.content as Workflow) };
86
+ const stateName = (
87
+ (op.target as WorkflowState).name
88
+ ? (op.target as WorkflowState).name
89
+ : op.target
90
+ ) as string;
91
+ // Check that state can be changed to
92
+ content.transitions = content.transitions.filter(
93
+ (t) => t.toState !== stateName,
94
+ );
95
+ content.transitions.forEach((t) => {
96
+ t.fromState = t.fromState.filter((state) => state !== stateName);
97
+ });
98
+ // validate that new state contains 'name' and 'category'
99
+ if (op.to.name === undefined || op.to.category === undefined) {
100
+ throw new Error(
101
+ `Cannot change state '${stateName}' for workflow '${this.content.name}'.
102
+ Updated state must have 'name' and 'category' properties.`,
103
+ );
104
+ }
105
+ // Update all cards that use this state.
106
+ const toStateName = op.to.name;
107
+
108
+ await this.updateCardStates(stateName, toStateName);
109
+ }
110
+
111
+ // Handle removal of workflow state.
112
+ // State can be removed with or without replacement.
113
+ private async handleStateRemoval(op: RemoveOperation<WorkflowState>) {
114
+ const content = { ...(this.content as Workflow) };
115
+ const stateName = (
116
+ (op.target as WorkflowState).name
117
+ ? (op.target as WorkflowState).name
118
+ : op.target
119
+ ) as string;
120
+
121
+ // If there is no replacement value, remove all transitions "to" and "from" this state.
122
+ if (!op.replacementValue) {
123
+ content.transitions = content.transitions.filter(
124
+ (t) => t.toState !== stateName,
125
+ );
126
+ content.transitions.forEach((t) => {
127
+ t.fromState = t.fromState.filter((state) => state !== stateName);
128
+ });
129
+ } else {
130
+ // Replace transitions "to" the removed state with the replacement state.
131
+ const replacementState = op.replacementValue;
132
+ const stateExists = content.states.some(
133
+ (state) => state.name === replacementState.name,
134
+ );
135
+ if (!stateExists) {
136
+ throw new Error(
137
+ `Cannot change to unknown state '${replacementState.name}' for Workflow`,
138
+ );
139
+ }
140
+
141
+ content.transitions.forEach((t) => {
142
+ if (t.toState === stateName) {
143
+ t.toState = replacementState.name;
144
+ }
145
+ });
146
+ // Replace transitions "from" the removed state with the replacement state.
147
+ content.transitions.forEach((t) => {
148
+ t.fromState = t.fromState.map((state) =>
149
+ state === stateName ? replacementState.name : state,
150
+ );
151
+ });
152
+ // Update all cards that use this state.
153
+ await this.updateCardStates(stateName, replacementState.name);
154
+ }
155
+ }
156
+
157
+ // Check if operation is a string operation.
158
+ private isStringOperation(op: Operation<unknown>): op is Operation<string> {
159
+ return typeof op.target === 'string';
160
+ }
161
+
162
+ // Update card states when state is changed
163
+ private async updateCardStates(oldState: string, newState: string) {
164
+ const cards = await this.collectCardsUsingWorkflow();
165
+ cards.forEach(async (card) => {
166
+ if (card.metadata?.workflowState === oldState) {
167
+ card.metadata.workflowState = newState;
168
+ await this.project.updateCardMetadata(card, card.metadata);
169
+ }
170
+ });
171
+ }
172
+
59
173
  // Update dependant card types.
60
174
  private async updateCardTypes(oldName: string) {
61
175
  const cardTypes = await this.project.cardTypes(ResourcesFrom.localOnly);
@@ -156,6 +270,39 @@ export class WorkflowResource extends FileResource {
156
270
  throw new Error(`Unknown property '${key}' for Workflow`);
157
271
  }
158
272
 
273
+ if (key === 'states' && op.name === 'remove') {
274
+ // If workflow state is removed, remove all transitions "to" and "from" this state.
275
+ let removeOp: RemoveOperation<WorkflowState>;
276
+ if (this.isStringOperation(op)) {
277
+ const toBeRemovedState = (this.content as Workflow).states.find(
278
+ (state) => state.name === op.target,
279
+ );
280
+ removeOp = {
281
+ name: 'remove',
282
+ target: toBeRemovedState as WorkflowState,
283
+ };
284
+ } else {
285
+ removeOp = op as RemoveOperation<WorkflowState>;
286
+ }
287
+ await this.handleStateRemoval(removeOp);
288
+ } else if (key === 'states' && op.name === 'change') {
289
+ // If workflow state is renamed, replace all transitions "to" and "from" the old state with new state.
290
+ let changeOp: ChangeOperation<WorkflowState>;
291
+ if (this.isStringOperation(op)) {
292
+ const toBeChangedState = (this.content as Workflow).states.find(
293
+ (state) => state.name === op.target,
294
+ );
295
+ changeOp = {
296
+ name: 'change',
297
+ target: toBeChangedState as WorkflowState,
298
+ to: { name: op.to },
299
+ };
300
+ } else {
301
+ changeOp = op as ChangeOperation<WorkflowState>;
302
+ }
303
+ await this.handleStateChange(changeOp);
304
+ }
305
+
159
306
  await super.postUpdate(content, key, op);
160
307
 
161
308
  // Renaming this workflow causes that references to its name must be updated.
@@ -1,13 +1,14 @@
1
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/>.
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2024
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation.
7
+ This program is distributed in the hope that it will be useful, but WITHOUT
8
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9
+ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
10
+ details. You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
11
12
  */
12
13
 
13
14
  /**
@@ -134,7 +135,7 @@ interface CardQueryField extends BaseResult {
134
135
  visibility: 'always' | 'optional';
135
136
  index: number;
136
137
  fieldDisplayName: string;
137
- fieldDescription: string;
138
+ description: string;
138
139
  dataType: DataType;
139
140
  isCalculated: boolean;
140
141
  value: string | number | boolean | null | EnumValue | ListValueItem[];
@@ -1,5 +1,5 @@
1
1
  import { INT32_MAX } from './constants.js';
2
- import { logger } from './log-utils.js';
2
+ import { getChildLogger } from './log-utils.js';
3
3
 
4
4
  /**
5
5
  Cyberismo
@@ -40,6 +40,11 @@ export class ClingoFactBuilder {
40
40
  protected predicate: string;
41
41
  private end: string;
42
42
  private arguments: ClingoArgumentInternal[] = [];
43
+ private get logger() {
44
+ return getChildLogger({
45
+ module: 'clingoFactBuilder',
46
+ });
47
+ }
43
48
 
44
49
  constructor(predicate: string, end: string = '.') {
45
50
  this.predicate = predicate;
@@ -120,7 +125,7 @@ export class ClingoFactBuilder {
120
125
  } else if (typeof value === 'number') {
121
126
  let floored = Math.floor(value);
122
127
  if (floored !== value) {
123
- logger.warn(
128
+ this.logger.warn(
124
129
  {
125
130
  value,
126
131
  },
@@ -130,7 +135,7 @@ export class ClingoFactBuilder {
130
135
 
131
136
  const exceedsInt32Max = floored > INT32_MAX;
132
137
  if (exceedsInt32Max || floored < -INT32_MAX) {
133
- logger.warn(
138
+ this.logger.warn(
134
139
  {
135
140
  value,
136
141
  },
@@ -1,13 +1,14 @@
1
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/>.
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2024
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation.
7
+ This program is distributed in the hope that it will be useful, but WITHOUT
8
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9
+ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
10
+ details. You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
11
12
  */
12
13
  import { sep } from 'node:path';
13
14
 
@@ -249,6 +250,11 @@ export const createCardFacts = async (card: Card, project: Project) => {
249
250
  b.addLiteralArguments(card.key, parentsPath),
250
251
  );
251
252
  }
253
+ builder.addCustomFact(Facts.Common.FIELD, (b) =>
254
+ b
255
+ .addLiteralArgument(card.key)
256
+ .addArguments('container', isTemplateCard(card) ? 'template' : 'project'),
257
+ );
252
258
 
253
259
  return builder.buildAll();
254
260
  };
@@ -270,12 +276,12 @@ export const createFieldTypeFacts = (fieldType: FieldType) => {
270
276
  fieldType.displayName,
271
277
  );
272
278
 
273
- if (fieldType.fieldDescription)
279
+ if (fieldType.description)
274
280
  builder.addFact(
275
281
  Facts.Common.FIELD,
276
282
  fieldType.name,
277
- 'fieldDescription',
278
- fieldType.fieldDescription,
283
+ 'description',
284
+ fieldType.description,
279
285
  );
280
286
 
281
287
  builder.addFact(
@@ -1,20 +1,22 @@
1
- import type { PredefinedCardMetadata } from '../interfaces/project-interfaces.js';
2
-
3
- export const INT32_MAX = 2147483647; // 2^31-1
4
1
  /**
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.
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2024
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation.
7
+ This program is distributed in the hope that it will be useful, but WITHOUT
8
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9
+ FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
10
+ details. You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
9
13
 
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.
14
+ import type { PredefinedCardMetadata } from '../interfaces/project-interfaces.js';
11
15
 
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
- */
16
+ export const INT32_MAX = 2147483647; // 2^31-1
15
17
 
16
18
  /**
17
- * These are names of the fields that are non-custom fields that present in metadata
19
+ * These are field names that are non-custom fields that present in metadata
18
20
  */
19
21
  export const PREDEFINED_FIELDS = [
20
22
  'rank',
@@ -23,8 +25,14 @@ export const PREDEFINED_FIELDS = [
23
25
  'workflowState',
24
26
  'lastUpdated',
25
27
  'lastTransitioned',
28
+ 'templateCardKey',
26
29
  ] satisfies (keyof PredefinedCardMetadata)[];
27
30
 
31
+ /**
32
+ * Checks if the given value is a predefined field.
33
+ * @param value The field name to check.
34
+ * @returns True if the value is a predefined field, false otherwise.
35
+ */
28
36
  export function isPredefinedField(
29
37
  value: string,
30
38
  ): value is keyof PredefinedCardMetadata {
@@ -9,54 +9,33 @@
9
9
  You should have received a copy of the GNU Affero General Public
10
10
  License along with this program. If not, see <https://www.gnu.org/licenses/>.
11
11
  */
12
+ import pino, { type ChildLoggerOptions, type Logger } from 'pino';
12
13
 
13
- import { join } from 'path';
14
- import pino, { type TransportTargetOptions } from 'pino';
15
- import { fileURLToPath } from 'url';
16
- const LOG_FILE_LOCATION: string = join(
17
- fileURLToPath(import.meta.url),
18
- '../../../../../logs/data-handler.trace',
19
- );
14
+ // This could be also a more generic interface, but since we use pino and this is an internal package, let's keep it simple
15
+ // silent logger as default
16
+ let _logger: Logger = pino.default({ level: 'silent' });
20
17
 
21
- function getLogger() {
22
- const all: TransportTargetOptions[] = [
23
- {
24
- target: 'pino/file',
25
- options: { destination: LOG_FILE_LOCATION, mkdir: true }, // trace file
26
- level: 'trace',
27
- },
28
- {
29
- target: 'pino-pretty',
30
- level: process.env.LOG_LEVEL || 'debug',
31
- },
32
- ];
33
-
34
- const [file, stdout] = all;
35
-
36
- if (process.env.NODE_ENV === 'test') {
37
- // While testing, we simply use stdout and info level by default
38
- return pino.default({
39
- level: process.env.LOG_LEVEL || 'info',
40
- transport: stdout,
41
- });
42
- }
43
- if (process.env.NODE_ENV === 'development') {
44
- // In dev mode, only stdout and debug logs by default
45
- return pino.default({
46
- level: 'trace',
47
- transport: {
48
- targets: all,
49
- },
50
- });
51
- }
52
- return pino.default({
53
- level: 'trace',
54
- transport: file,
55
- });
18
+ export function setLogger(logger: Logger) {
19
+ _logger = logger;
20
+ }
21
+ /**
22
+ * Returns the logger instance.
23
+ */
24
+ export function getLogger(): Logger {
25
+ return _logger;
26
+ }
27
+ /**
28
+ * Returns a child logger instance.
29
+ * @param context Context to add to the logger.
30
+ * @param options Options to pass to the logger.
31
+ * @returns Child logger instance.
32
+ */
33
+ export function getChildLogger(
34
+ context: { module: string } & Record<string, unknown>,
35
+ options?: ChildLoggerOptions,
36
+ ): Logger {
37
+ return _logger.child(context, options);
56
38
  }
57
-
58
- export const logger = getLogger();
59
-
60
39
  /**
61
40
  * Returns error message string from an Error object.
62
41
  * @param error Error object
@@ -0,0 +1,86 @@
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 Handlebars from 'handlebars';
13
+ import type { Calculate } from '../commands/index.js';
14
+ import { registerEmptyMacros } from '../macros/index.js';
15
+
16
+ /**
17
+ * Formats a value from a logic program for use to graphviz
18
+ * @param value - The value to format
19
+ * @returns The formatted value
20
+ */
21
+ export function formatAttributeValue(value?: string) {
22
+ if (!value) {
23
+ return '';
24
+ }
25
+ // value is an html-like string
26
+ if (value.length > 1 && value.startsWith('<') && value.endsWith('>')) {
27
+ return value;
28
+ }
29
+ // value is a normal string and needs to be wrapped in quotes
30
+ return `"${value}"`;
31
+ }
32
+
33
+ /**
34
+ * Parameters for the core generation function
35
+ */
36
+ interface GenerateReportContentParams {
37
+ calculate: Calculate;
38
+ contentTemplate: string;
39
+ queryTemplate: string;
40
+ options: Record<string, string>;
41
+ graph?: boolean;
42
+ }
43
+
44
+ /**
45
+ * Generates report content based on a report definition, project context, and options,
46
+ * by utilizing the ReportRunner class.
47
+ *
48
+ * @param params - The parameters for report generation.
49
+ * @returns The rendered report content as a string.
50
+ * @throws Error if the report definition is invalid, schema validation fails, or logic program execution fails.
51
+ */
52
+ export async function generateReportContent(
53
+ params: GenerateReportContentParams,
54
+ ): Promise<string> {
55
+ const {
56
+ calculate,
57
+ contentTemplate,
58
+ queryTemplate,
59
+ graph,
60
+ options, // Destructure options
61
+ } = params;
62
+
63
+ const handlebars = Handlebars.create();
64
+
65
+ // Compile and execute the query template
66
+ const template = handlebars.compile(queryTemplate, {
67
+ strict: true,
68
+ });
69
+
70
+ const result = await calculate.runLogicProgram(template(options));
71
+
72
+ if (result.error) {
73
+ throw new Error(result.error);
74
+ }
75
+ // register empty macros so that other macros aren't touched yet
76
+ registerEmptyMacros(handlebars);
77
+
78
+ if (graph) {
79
+ handlebars.registerHelper('formatAttributeValue', formatAttributeValue);
80
+ }
81
+
82
+ return handlebars.compile(contentTemplate)({
83
+ ...options,
84
+ ...result,
85
+ });
86
+ }
@@ -140,6 +140,10 @@ export function pathToResourceName(
140
140
  if (!identifier || !type || !prefix) {
141
141
  throw new Error(`invalid path: ${path}`);
142
142
  }
143
+ if (identifierIndex + 1 !== parts.length) {
144
+ throw new Error(`not a resource path: ${path}`);
145
+ }
146
+
143
147
  return {
144
148
  prefix: prefix,
145
149
  type: type,
@@ -25,22 +25,17 @@ const removeSvgWidthAndHeight = (node: Element) => {
25
25
  };
26
26
 
27
27
  /**
28
- * Sanitize an SVG Buffer and return a base64-encoded string
29
- * @param buffer - SVG content as a Buffer
28
+ * Sanitize an SVG string and return a base64-encoded string
29
+ * @param svg - SVG content as a string
30
30
  * @returns base64-encoded sanitized SVG string
31
31
  */
32
- export function sanitizeSvgBase64(buffer: Buffer): string {
32
+ export function sanitizeSvgBase64(svg: string): string {
33
33
  const DOMPurify = createDOMPurify(window as unknown as WindowLike);
34
34
 
35
- const dirty = buffer.toString('utf-8');
36
-
37
35
  DOMPurify.setConfig({ USE_PROFILES: { svg: true } });
38
36
  DOMPurify.addHook('afterSanitizeAttributes', removeSvgWidthAndHeight);
39
37
 
40
- let cleaned = DOMPurify.sanitize(dirty);
41
-
42
- // Remove link titles, quick fix for Clingraph/Graphviz generated titles for links that are quite strange
43
- cleaned = cleaned.replace(/\s*xlink:title=(["']).*?\1/g, '');
38
+ const cleaned = DOMPurify.sanitize(svg);
44
39
 
45
40
  return Buffer.from(cleaned, 'utf-8').toString('base64');
46
41
  }
@@ -11,7 +11,7 @@
11
11
  */
12
12
  import { type Schema, Validator } from 'jsonschema';
13
13
  import { DHValidationError, SchemaNotFound } from '../exceptions/index.js';
14
- import { schemas } from '@cyberismo/resources';
14
+ import { schemas } from '@cyberismo/assets';
15
15
 
16
16
  /**
17
17
  * Validates a JSON object against a schema
@@ -40,7 +40,8 @@ export function validateJson<T>(
40
40
  if (!validator) {
41
41
  validator = new Validator();
42
42
  for (const schema of schemas) {
43
- validator.addSchema(schema, schema.$id);
43
+ // For some reason, the draft-07 schema is not a valid Schema, so we need to cast it
44
+ validator.addSchema(schema as Schema, schema.$id);
44
45
  }
45
46
  }
46
47
 
@@ -1,45 +0,0 @@
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
- import { type Calculate, type Show } from './index.js';
15
- import { Export } from './export.js';
16
- import type { Project } from '../containers/project.js';
17
- interface ExportOptions {
18
- silent: boolean;
19
- }
20
- export declare class ExportSite extends Export {
21
- private tmpDir;
22
- private moduleDir;
23
- private pagesDir;
24
- private imagesDir;
25
- private playbookDir;
26
- private playbookFile;
27
- private navFile;
28
- private options;
29
- constructor(project: Project, calculateCmd: Calculate, showCmd: Show);
30
- private createCardsIndex;
31
- private initDirectories;
32
- private generate;
33
- private createPlaybook;
34
- private createDescriptor;
35
- private initRepo;
36
- private toAdocDirectoryAsContent;
37
- private export;
38
- /**
39
- * Export the card tree as an Antora site
40
- * @param destination Path where the site is generated
41
- * @param cardKey Optional; If defined exports the card tree from underneath this card.
42
- */
43
- exportToSite(destination: string, cardKey?: string, options?: ExportOptions): Promise<string>;
44
- }
45
- export {};