@cyberismo/data-handler 0.0.14 → 0.0.16
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.
- package/dist/card-metadata-updater.js +8 -4
- package/dist/card-metadata-updater.js.map +1 -1
- package/dist/command-handler.d.ts +4 -0
- package/dist/command-handler.js +29 -19
- package/dist/command-handler.js.map +1 -1
- package/dist/command-manager.d.ts +25 -2
- package/dist/command-manager.js +30 -5
- package/dist/command-manager.js.map +1 -1
- package/dist/commands/create.d.ts +1 -1
- package/dist/commands/create.js +45 -93
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/edit.d.ts +1 -15
- package/dist/commands/edit.js +15 -89
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/export.d.ts +11 -2
- package/dist/commands/export.js +58 -58
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/import.d.ts +9 -1
- package/dist/commands/import.js +17 -11
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/move.d.ts +1 -2
- package/dist/commands/move.js +107 -146
- package/dist/commands/move.js.map +1 -1
- package/dist/commands/remove.d.ts +8 -1
- package/dist/commands/remove.js +17 -48
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/rename.d.ts +4 -9
- package/dist/commands/rename.js +34 -108
- package/dist/commands/rename.js.map +1 -1
- package/dist/commands/show.d.ts +22 -34
- package/dist/commands/show.js +103 -151
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/transition.d.ts +9 -2
- package/dist/commands/transition.js +49 -44
- package/dist/commands/transition.js.map +1 -1
- package/dist/commands/update.d.ts +18 -12
- package/dist/commands/update.js +34 -18
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.d.ts +18 -10
- package/dist/commands/validate.js +101 -47
- package/dist/commands/validate.js.map +1 -1
- package/dist/containers/card-container.d.ts +87 -24
- package/dist/containers/card-container.js +183 -279
- package/dist/containers/card-container.js.map +1 -1
- package/dist/containers/project/calculation-engine.d.ts +13 -4
- package/dist/containers/project/calculation-engine.js +79 -77
- package/dist/containers/project/calculation-engine.js.map +1 -1
- package/dist/containers/project/card-cache.d.ts +146 -0
- package/dist/containers/project/card-cache.js +411 -0
- package/dist/containers/project/card-cache.js.map +1 -0
- package/dist/containers/project/project-paths.d.ts +5 -4
- package/dist/containers/project/project-paths.js +16 -12
- package/dist/containers/project/project-paths.js.map +1 -1
- package/dist/containers/project/resource-cache.d.ts +169 -0
- package/dist/containers/project/resource-cache.js +507 -0
- package/dist/containers/project/resource-cache.js.map +1 -0
- package/dist/containers/project/resource-handler.d.ts +129 -0
- package/dist/containers/project/resource-handler.js +206 -0
- package/dist/containers/project/resource-handler.js.map +1 -0
- package/dist/containers/project.d.ts +114 -195
- package/dist/containers/project.js +425 -535
- package/dist/containers/project.js.map +1 -1
- package/dist/containers/template.d.ts +22 -32
- package/dist/containers/template.js +113 -115
- package/dist/containers/template.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/folder-content-interfaces.d.ts +7 -4
- package/dist/interfaces/folder-content-interfaces.js +3 -3
- package/dist/interfaces/folder-content-interfaces.js.map +1 -1
- package/dist/interfaces/macros.d.ts +1 -0
- package/dist/interfaces/macros.js +1 -1
- package/dist/interfaces/macros.js.map +1 -1
- package/dist/interfaces/project-interfaces.d.ts +7 -5
- package/dist/interfaces/project-interfaces.js.map +1 -1
- package/dist/interfaces/resource-interfaces.d.ts +25 -22
- package/dist/interfaces/resource-interfaces.js +3 -0
- package/dist/interfaces/resource-interfaces.js.map +1 -1
- package/dist/macros/common.d.ts +10 -10
- package/dist/macros/createCards/index.d.ts +0 -13
- package/dist/macros/createCards/index.js.map +1 -1
- package/dist/macros/createCards/types.d.ts +44 -0
- package/dist/macros/createCards/types.js +15 -0
- package/dist/macros/createCards/types.js.map +1 -0
- package/dist/macros/graph/index.d.ts +2 -6
- package/dist/macros/graph/index.js +14 -28
- package/dist/macros/graph/index.js.map +1 -1
- package/dist/macros/graph/types.d.ts +23 -0
- package/dist/macros/graph/types.js +15 -0
- package/dist/macros/graph/types.js.map +1 -0
- package/dist/macros/image/index.d.ts +8 -16
- package/dist/macros/image/index.js +36 -33
- package/dist/macros/image/index.js.map +1 -1
- package/dist/macros/image/types.d.ts +38 -0
- package/dist/macros/image/types.js +15 -0
- package/dist/macros/image/types.js.map +1 -0
- package/dist/macros/include/index.d.ts +1 -6
- package/dist/macros/include/index.js +4 -7
- package/dist/macros/include/index.js.map +1 -1
- package/dist/macros/include/types.d.ts +31 -0
- package/dist/macros/include/types.js +15 -0
- package/dist/macros/include/types.js.map +1 -0
- package/dist/macros/index.d.ts +1 -1
- package/dist/macros/index.js +2 -2
- package/dist/macros/index.js.map +1 -1
- package/dist/macros/percentage/index.d.ts +0 -6
- package/dist/macros/percentage/index.js.map +1 -1
- package/dist/macros/percentage/types.d.ts +31 -0
- package/dist/macros/percentage/types.js +15 -0
- package/dist/macros/percentage/types.js.map +1 -0
- package/dist/macros/report/index.d.ts +0 -3
- package/dist/macros/report/index.js +3 -6
- package/dist/macros/report/index.js.map +1 -1
- package/dist/macros/report/types.d.ts +19 -0
- package/dist/macros/report/types.js +15 -0
- package/dist/macros/report/types.js.map +1 -0
- package/dist/macros/scoreCard/index.d.ts +0 -6
- package/dist/macros/scoreCard/index.js.map +1 -1
- package/dist/macros/scoreCard/types.d.ts +31 -0
- package/dist/macros/scoreCard/types.js +15 -0
- package/dist/macros/scoreCard/types.js.map +1 -0
- package/dist/macros/types.d.ts +25 -0
- package/dist/macros/types.js +2 -0
- package/dist/macros/types.js.map +1 -0
- package/dist/macros/vega/index.d.ts +0 -4
- package/dist/macros/vega/index.js.map +1 -1
- package/dist/macros/vega/types.d.ts +20 -0
- package/dist/macros/vega/types.js +2 -0
- package/dist/macros/vega/types.js.map +1 -0
- package/dist/macros/vegalite/index.d.ts +0 -4
- package/dist/macros/vegalite/index.js.map +1 -1
- package/dist/macros/vegalite/types.d.ts +20 -0
- package/dist/macros/vegalite/types.js +15 -0
- package/dist/macros/vegalite/types.js.map +1 -0
- package/dist/macros/xref/index.d.ts +0 -3
- package/dist/macros/xref/index.js +5 -14
- package/dist/macros/xref/index.js.map +1 -1
- package/dist/macros/xref/types.d.ts +19 -0
- package/dist/macros/xref/types.js +15 -0
- package/dist/macros/xref/types.js.map +1 -0
- package/dist/module-manager.d.ts +16 -3
- package/dist/module-manager.js +55 -23
- package/dist/module-manager.js.map +1 -1
- package/dist/project-settings.d.ts +16 -3
- package/dist/project-settings.js +79 -14
- package/dist/project-settings.js.map +1 -1
- package/dist/resources/calculation-resource.d.ts +6 -33
- package/dist/resources/calculation-resource.js +11 -60
- package/dist/resources/calculation-resource.js.map +1 -1
- package/dist/resources/card-type-resource.d.ts +10 -22
- package/dist/resources/card-type-resource.js +46 -66
- package/dist/resources/card-type-resource.js.map +1 -1
- package/dist/resources/create-defaults.d.ts +3 -2
- package/dist/resources/create-defaults.js +3 -2
- package/dist/resources/create-defaults.js.map +1 -1
- package/dist/resources/field-type-resource.d.ts +8 -22
- package/dist/resources/field-type-resource.js +35 -60
- package/dist/resources/field-type-resource.js.map +1 -1
- package/dist/resources/file-resource.d.ts +14 -35
- package/dist/resources/file-resource.js +22 -301
- package/dist/resources/file-resource.js.map +1 -1
- package/dist/resources/folder-resource.d.ts +44 -66
- package/dist/resources/folder-resource.js +102 -149
- package/dist/resources/folder-resource.js.map +1 -1
- package/dist/resources/graph-model-resource.d.ts +9 -34
- package/dist/resources/graph-model-resource.js +18 -64
- package/dist/resources/graph-model-resource.js.map +1 -1
- package/dist/resources/graph-view-resource.d.ts +9 -29
- package/dist/resources/graph-view-resource.js +13 -48
- package/dist/resources/graph-view-resource.js.map +1 -1
- package/dist/resources/link-type-resource.d.ts +9 -23
- package/dist/resources/link-type-resource.js +11 -33
- package/dist/resources/link-type-resource.js.map +1 -1
- package/dist/resources/report-resource.d.ts +10 -23
- package/dist/resources/report-resource.js +20 -67
- package/dist/resources/report-resource.js.map +1 -1
- package/dist/resources/resource-object.d.ts +143 -23
- package/dist/resources/resource-object.js +369 -48
- package/dist/resources/resource-object.js.map +1 -1
- package/dist/resources/template-resource.d.ts +10 -17
- package/dist/resources/template-resource.js +19 -27
- package/dist/resources/template-resource.js.map +1 -1
- package/dist/resources/workflow-resource.d.ts +9 -25
- package/dist/resources/workflow-resource.js +25 -55
- package/dist/resources/workflow-resource.js.map +1 -1
- package/dist/utils/card-utils.d.ts +69 -19
- package/dist/utils/card-utils.js +179 -30
- package/dist/utils/card-utils.js.map +1 -1
- package/dist/utils/clingo-fact-builder.d.ts +25 -14
- package/dist/utils/clingo-fact-builder.js +27 -5
- package/dist/utils/clingo-fact-builder.js.map +1 -1
- package/dist/utils/clingo-facts.js +14 -7
- package/dist/utils/clingo-facts.js.map +1 -1
- package/dist/utils/clingo-parser.js +1 -1
- package/dist/utils/clingo-parser.js.map +1 -1
- package/dist/utils/constants.d.ts +2 -0
- package/dist/utils/constants.js +4 -0
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/csv.js +1 -1
- package/dist/utils/csv.js.map +1 -1
- package/dist/utils/resource-utils.d.ts +1 -0
- package/dist/utils/resource-utils.js +2 -1
- package/dist/utils/resource-utils.js.map +1 -1
- package/package.json +11 -11
- package/src/card-metadata-updater.ts +9 -7
- package/src/command-handler.ts +35 -23
- package/src/command-manager.ts +32 -19
- package/src/commands/create.ts +59 -160
- package/src/commands/edit.ts +16 -132
- package/src/commands/export.ts +71 -81
- package/src/commands/import.ts +26 -18
- package/src/commands/move.ts +143 -179
- package/src/commands/remove.ts +20 -59
- package/src/commands/rename.ts +45 -156
- package/src/commands/show.ts +153 -211
- package/src/commands/transition.ts +53 -58
- package/src/commands/update.ts +44 -23
- package/src/commands/validate.ts +108 -82
- package/src/containers/card-container.ts +200 -360
- package/src/containers/project/calculation-engine.ts +81 -105
- package/src/containers/project/card-cache.ts +497 -0
- package/src/containers/project/project-paths.ts +21 -13
- package/src/containers/project/resource-cache.ts +648 -0
- package/src/containers/project/resource-handler.ts +265 -0
- package/src/containers/project.ts +551 -693
- package/src/containers/template.ts +129 -142
- package/src/index.ts +1 -0
- package/src/interfaces/folder-content-interfaces.ts +14 -7
- package/src/interfaces/macros.ts +2 -0
- package/src/interfaces/project-interfaces.ts +14 -7
- package/src/interfaces/resource-interfaces.ts +30 -27
- package/src/macros/createCards/index.ts +1 -12
- package/src/macros/createCards/types.ts +46 -0
- package/src/macros/graph/index.ts +27 -52
- package/src/macros/graph/types.ts +24 -0
- package/src/macros/image/index.ts +50 -61
- package/src/macros/image/types.ts +39 -0
- package/src/macros/include/index.ts +6 -15
- package/src/macros/include/types.ts +32 -0
- package/src/macros/index.ts +2 -2
- package/src/macros/percentage/index.ts +1 -7
- package/src/macros/percentage/types.ts +32 -0
- package/src/macros/report/index.ts +4 -13
- package/src/macros/report/types.ts +20 -0
- package/src/macros/scoreCard/index.ts +1 -7
- package/src/macros/scoreCard/types.ts +32 -0
- package/src/macros/types.ts +48 -0
- package/src/macros/vega/index.ts +1 -4
- package/src/macros/vega/types.ts +21 -0
- package/src/macros/vegalite/index.ts +1 -4
- package/src/macros/vegalite/types.ts +22 -0
- package/src/macros/xref/index.ts +6 -20
- package/src/macros/xref/types.ts +20 -0
- package/src/module-manager.ts +79 -22
- package/src/project-settings.ts +84 -15
- package/src/resources/calculation-resource.ts +21 -91
- package/src/resources/card-type-resource.ts +74 -109
- package/src/resources/create-defaults.ts +3 -2
- package/src/resources/field-type-resource.ts +61 -104
- package/src/resources/file-resource.ts +33 -441
- package/src/resources/folder-resource.ts +130 -207
- package/src/resources/graph-model-resource.ts +36 -95
- package/src/resources/graph-view-resource.ts +28 -70
- package/src/resources/link-type-resource.ts +23 -53
- package/src/resources/report-resource.ts +34 -96
- package/src/resources/resource-object.ts +511 -66
- package/src/resources/template-resource.ts +32 -44
- package/src/resources/workflow-resource.ts +42 -85
- package/src/utils/card-utils.ts +217 -31
- package/src/utils/clingo-fact-builder.ts +28 -16
- package/src/utils/clingo-facts.ts +16 -7
- package/src/utils/clingo-parser.ts +1 -1
- package/src/utils/constants.ts +6 -0
- package/src/utils/csv.ts +1 -1
- package/src/utils/resource-utils.ts +2 -1
- package/dist/containers/project/resource-collector.d.ts +0 -87
- package/dist/containers/project/resource-collector.js +0 -337
- package/dist/containers/project/resource-collector.js.map +0 -1
- package/src/containers/project/resource-collector.ts +0 -396
|
@@ -12,59 +12,60 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { ActionGuard } from '../permissions/action-guard.js';
|
|
15
|
-
import type {
|
|
16
|
-
CardType,
|
|
17
|
-
Workflow,
|
|
18
|
-
WorkflowState,
|
|
19
|
-
} from '../interfaces/resource-interfaces.js';
|
|
20
15
|
import { CardMetadataUpdater } from '../card-metadata-updater.js';
|
|
21
16
|
import type { Project } from '../containers/project.js';
|
|
17
|
+
import type { WorkflowState } from '../interfaces/resource-interfaces.js';
|
|
22
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Handles transitions.
|
|
21
|
+
*/
|
|
23
22
|
export class Transition {
|
|
23
|
+
/**
|
|
24
|
+
* Creates an instance of Transition command.
|
|
25
|
+
* @param project Project to use.
|
|
26
|
+
*/
|
|
24
27
|
constructor(private project: Project) {}
|
|
25
28
|
|
|
29
|
+
// Wrapper to run onTransition query.
|
|
30
|
+
private async transitionChangesQuery(cardKey: string, transition: string) {
|
|
31
|
+
if (!cardKey || !transition) return undefined;
|
|
32
|
+
return this.project.calculationEngine.runQuery('onTransition', 'localApp', {
|
|
33
|
+
cardKey,
|
|
34
|
+
transition,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
26
38
|
/**
|
|
27
39
|
* Transitions a card from its current state to a new state.
|
|
28
40
|
* @param cardKey card key
|
|
29
41
|
* @param transition which transition to do
|
|
30
42
|
*/
|
|
31
43
|
public async cardTransition(cardKey: string, transition: WorkflowState) {
|
|
32
|
-
|
|
33
|
-
const details = await this.project.cardDetailsById(cardKey, {
|
|
34
|
-
metadata: true,
|
|
35
|
-
});
|
|
36
|
-
if (!details || !details.metadata) {
|
|
37
|
-
throw new Error(`Card ${cardKey} does not exist in the project`);
|
|
38
|
-
}
|
|
44
|
+
const card = this.project.findCard(cardKey);
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
details.metadata?.cardType,
|
|
43
|
-
);
|
|
44
|
-
if (cardType === undefined) {
|
|
45
|
-
throw new Error(
|
|
46
|
-
`Card's card type '${details.metadata?.cardType}' does not exist in the project`,
|
|
47
|
-
);
|
|
46
|
+
if (!card.metadata?.cardType) {
|
|
47
|
+
throw new Error(`Card does not have card type`);
|
|
48
48
|
}
|
|
49
|
+
// Card type
|
|
50
|
+
const cardType = this.project.resources
|
|
51
|
+
.byType(card.metadata?.cardType, 'cardTypes')
|
|
52
|
+
.show();
|
|
49
53
|
|
|
50
54
|
// Workflow
|
|
51
|
-
const workflow =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
`Card's workflow '${cardType.workflow}' does not exist in the project`,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
55
|
+
const workflow = this.project.resources
|
|
56
|
+
.byType(cardType.workflow, 'workflows')
|
|
57
|
+
.show();
|
|
57
58
|
|
|
58
59
|
// Check that the state transition can be made "from".
|
|
59
60
|
const foundFrom = workflow.transitions.find(
|
|
60
61
|
(item) =>
|
|
61
|
-
(
|
|
62
|
-
item.fromState.includes(
|
|
62
|
+
(card.metadata &&
|
|
63
|
+
item.fromState.includes(card.metadata?.workflowState)) ||
|
|
63
64
|
item.fromState.includes('*'),
|
|
64
65
|
);
|
|
65
66
|
if (!foundFrom) {
|
|
66
67
|
throw new Error(
|
|
67
|
-
`Card's workflow '${cardType.workflow}' does not contain transition from card's current state '${
|
|
68
|
+
`Card's workflow '${cardType.workflow}' does not contain transition from card's current state '${card.metadata?.workflowState}'`,
|
|
68
69
|
);
|
|
69
70
|
}
|
|
70
71
|
|
|
@@ -80,44 +81,38 @@ export class Transition {
|
|
|
80
81
|
|
|
81
82
|
if (
|
|
82
83
|
!(
|
|
83
|
-
|
|
84
|
+
(card.metadata?.workflowState &&
|
|
85
|
+
found.fromState.includes(card.metadata.workflowState)) ||
|
|
84
86
|
found.fromState.includes('*')
|
|
85
87
|
)
|
|
86
88
|
) {
|
|
87
89
|
throw new Error(
|
|
88
|
-
`Card's workflow '${cardType.workflow}' does not contain state transition from state '${
|
|
90
|
+
`Card's workflow '${cardType.workflow}' does not contain state transition from state '${card.metadata?.workflowState}' for '${transition.name}`,
|
|
89
91
|
);
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
const actionGuard = new ActionGuard(this.project.calculationEngine);
|
|
93
95
|
await actionGuard.checkPermission('transition', cardKey, transition.name);
|
|
94
96
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// Wrapper to run onTransition query.
|
|
116
|
-
private async transitionChangesQuery(cardKey: string, transition: string) {
|
|
117
|
-
if (!cardKey || !transition) return undefined;
|
|
118
|
-
return this.project.calculationEngine.runQuery('onTransition', 'localApp', {
|
|
119
|
-
cardKey,
|
|
120
|
-
transition,
|
|
121
|
-
});
|
|
97
|
+
if (card.metadata) {
|
|
98
|
+
card.metadata.workflowState = found.toState;
|
|
99
|
+
card.metadata.lastUpdated = new Date().toISOString();
|
|
100
|
+
card.metadata.lastTransitioned = new Date().toISOString();
|
|
101
|
+
return this.project
|
|
102
|
+
.updateCardMetadata(card, card.metadata)
|
|
103
|
+
.then(async () => this.transitionChangesQuery(cardKey, transition.name))
|
|
104
|
+
.then(async (queryResult) => {
|
|
105
|
+
if (
|
|
106
|
+
!queryResult ||
|
|
107
|
+
queryResult.at(0) === undefined ||
|
|
108
|
+
queryResult.at(0)?.updateFields === undefined
|
|
109
|
+
) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const fieldsToUpdate = queryResult.at(0)!.updateFields;
|
|
113
|
+
return CardMetadataUpdater.apply(this.project, fieldsToUpdate);
|
|
114
|
+
})
|
|
115
|
+
.catch((error) => console.error(error));
|
|
116
|
+
}
|
|
122
117
|
}
|
|
123
118
|
}
|
package/src/commands/update.ts
CHANGED
|
@@ -19,20 +19,44 @@ import type {
|
|
|
19
19
|
RemoveOperation,
|
|
20
20
|
UpdateOperations,
|
|
21
21
|
} from '../resources/resource-object.js';
|
|
22
|
-
import { Project } from '../containers/project.js';
|
|
23
|
-
import {
|
|
22
|
+
import type { Project } from '../containers/project.js';
|
|
23
|
+
import type { UpdateKey } from '../interfaces/resource-interfaces.js';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Class that handles 'update' commands.
|
|
27
27
|
*/
|
|
28
28
|
export class Update {
|
|
29
|
+
/**
|
|
30
|
+
* Creates an instance of Update command.
|
|
31
|
+
* @param project Project to use.
|
|
32
|
+
*/
|
|
29
33
|
constructor(private project: Project) {}
|
|
30
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Update single resource property
|
|
37
|
+
* This is similar to updateValue, but allows the operation to be fully specified
|
|
38
|
+
* @param name Name of the resource to operate on.
|
|
39
|
+
* @param updateKey Property to change in resource or in resource content.
|
|
40
|
+
* @param operation The full operation object
|
|
41
|
+
* @template Type Type of the target of the operation
|
|
42
|
+
* @template T Type of operation ('add', 'remove', 'change', 'rank')
|
|
43
|
+
* @template K Type of the key to change
|
|
44
|
+
*/
|
|
45
|
+
public async applyResourceOperation<
|
|
46
|
+
Type,
|
|
47
|
+
T extends UpdateOperations,
|
|
48
|
+
K extends string,
|
|
49
|
+
>(name: string, updateKey: UpdateKey<K>, operation: OperationFor<Type, T>) {
|
|
50
|
+
const type = this.project.resources.extractType(name);
|
|
51
|
+
const resource = this.project.resources.byType(name, type);
|
|
52
|
+
await resource?.update(updateKey, operation);
|
|
53
|
+
}
|
|
54
|
+
|
|
31
55
|
/**
|
|
32
56
|
* Updates single resource property.
|
|
33
57
|
* @param name Name of the resource to operate on.
|
|
34
58
|
* @param operation Operation to perform ('add', 'remove', 'change', 'rank')
|
|
35
|
-
* @param key Property to change in resource JSON
|
|
59
|
+
* @param key Property to change in resource JSON. If content, content/<property>
|
|
36
60
|
* @param value Value for 'key'
|
|
37
61
|
* @param optionalDetail Additional detail needed for some operations. For example, 'update' needs a new value.
|
|
38
62
|
* @param mappingTable Optional mapping table for workflow state transitions (only used for workflow changes)
|
|
@@ -75,26 +99,23 @@ export class Update {
|
|
|
75
99
|
? optionalDetail
|
|
76
100
|
: undefined;
|
|
77
101
|
}
|
|
102
|
+
const splitKey = key.split('/');
|
|
103
|
+
if (splitKey.length !== 1 && splitKey.length !== 2) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
`Invalid key format: ${key}. Use 'property' or 'content/<property>'.`,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
78
108
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
*/
|
|
91
|
-
public async applyResourceOperation<Type, T extends UpdateOperations>(
|
|
92
|
-
name: string,
|
|
93
|
-
key: string,
|
|
94
|
-
operation: OperationFor<Type, T>,
|
|
95
|
-
) {
|
|
96
|
-
const resource = Project.resourceObject(this.project, resourceName(name));
|
|
97
|
-
await resource?.update(key, operation);
|
|
98
|
-
this.project.collectLocalResources();
|
|
109
|
+
if (splitKey.length === 2 && splitKey[0] !== 'content') {
|
|
110
|
+
throw new Error(
|
|
111
|
+
`Invalid key format: ${key}. When using 'content', always use as 'content/<property>'.`,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
const [parsedKey, subKey] = splitKey;
|
|
115
|
+
if (parsedKey === 'content') {
|
|
116
|
+
await this.applyResourceOperation(name, { key: parsedKey, subKey }, op);
|
|
117
|
+
} else {
|
|
118
|
+
await this.applyResourceOperation(name, { key: parsedKey }, op);
|
|
119
|
+
}
|
|
99
120
|
}
|
|
100
121
|
}
|
package/src/commands/validate.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
// node
|
|
15
|
-
import {
|
|
15
|
+
import type { Dirent } from 'node:fs';
|
|
16
16
|
import { basename, dirname, extname, join, parse, resolve } from 'node:path';
|
|
17
17
|
import { readdir } from 'node:fs/promises';
|
|
18
18
|
|
|
@@ -33,13 +33,14 @@ import type {
|
|
|
33
33
|
CustomField,
|
|
34
34
|
FieldType,
|
|
35
35
|
ReportMetadata,
|
|
36
|
-
|
|
36
|
+
AnyResourceContent,
|
|
37
37
|
Workflow,
|
|
38
38
|
} from '../interfaces/resource-interfaces.js';
|
|
39
39
|
import { errorFunction } from '../utils/error-utils.js';
|
|
40
40
|
import { isTemplateCard } from '../utils/card-utils.js';
|
|
41
|
+
import { isPredefinedField } from '../utils/constants.js';
|
|
41
42
|
import { pathExists } from '../utils/file-utils.js';
|
|
42
|
-
import { Project } from '../containers/project.js';
|
|
43
|
+
import type { Project } from '../containers/project.js';
|
|
43
44
|
import { readJsonFile } from '../utils/json.js';
|
|
44
45
|
import { type ResourceName, resourceName } from '../utils/resource-utils.js';
|
|
45
46
|
|
|
@@ -51,7 +52,7 @@ const SHORT_TEXT_MAX_LENGTH = 80;
|
|
|
51
52
|
|
|
52
53
|
import * as EmailValidator from 'email-validator';
|
|
53
54
|
import { evaluateMacros } from '../macros/index.js';
|
|
54
|
-
const baseDir = import.meta.dirname;
|
|
55
|
+
const baseDir = import.meta.dirname ?? new URL('.', import.meta.url).pathname;
|
|
55
56
|
const subFoldersToValidate = ['.cards', 'cardRoot'];
|
|
56
57
|
|
|
57
58
|
export interface LengthProvider {
|
|
@@ -82,6 +83,9 @@ export class Validate {
|
|
|
82
83
|
static dotSchemaSchemaId = '/dotSchema';
|
|
83
84
|
static parameterSchemaFile = 'parameterSchema.json';
|
|
84
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Creates an instance of Validate command.
|
|
88
|
+
*/
|
|
85
89
|
constructor() {
|
|
86
90
|
Validate.baseFolder = pathExists(
|
|
87
91
|
join(process.cwd(), '../../schema', 'cardTreeDirectorySchema.json'),
|
|
@@ -117,7 +121,7 @@ export class Validate {
|
|
|
117
121
|
private checkResourceName(
|
|
118
122
|
file: Dirent,
|
|
119
123
|
content:
|
|
120
|
-
|
|
|
124
|
+
| AnyResourceContent
|
|
121
125
|
| CustomField
|
|
122
126
|
| DotSchemaContent
|
|
123
127
|
| ProjectSettings
|
|
@@ -133,7 +137,7 @@ export class Validate {
|
|
|
133
137
|
file.name !== Validate.dotSchemaSchemaId &&
|
|
134
138
|
file.name !== Validate.parameterSchemaFile
|
|
135
139
|
) {
|
|
136
|
-
const namedContent = content as
|
|
140
|
+
const namedContent = content as AnyResourceContent | ReportMetadata;
|
|
137
141
|
if (!namedContent.name) {
|
|
138
142
|
errors.push(
|
|
139
143
|
`File '${file.name}' does not contain 'name' property. Cannot validate resource's 'name'.`,
|
|
@@ -167,25 +171,7 @@ export class Validate {
|
|
|
167
171
|
return join(file.parentPath, file.name);
|
|
168
172
|
}
|
|
169
173
|
|
|
170
|
-
//
|
|
171
|
-
// If value is already cached, returns from cache.
|
|
172
|
-
private async getAndCacheResource<Type>(
|
|
173
|
-
project: Project,
|
|
174
|
-
cachedValues: Map<string, Type>,
|
|
175
|
-
valueName: string,
|
|
176
|
-
): Promise<Type | undefined> {
|
|
177
|
-
return (
|
|
178
|
-
cachedValues.get(valueName) ||
|
|
179
|
-
project.resource<Type>(valueName).then((resource) => {
|
|
180
|
-
if (!resource) {
|
|
181
|
-
return undefined;
|
|
182
|
-
}
|
|
183
|
-
cachedValues.set(valueName, resource);
|
|
184
|
-
return resource;
|
|
185
|
-
})
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
|
|
174
|
+
// Parses validator messages
|
|
189
175
|
private parseValidatorMessage(errorObject: object[]): string {
|
|
190
176
|
let parsedErrorMessage = '';
|
|
191
177
|
// todo: get schema name here?
|
|
@@ -236,7 +222,7 @@ export class Validate {
|
|
|
236
222
|
): Promise<string[]> {
|
|
237
223
|
const message: string[] = [];
|
|
238
224
|
try {
|
|
239
|
-
const prefixes =
|
|
225
|
+
const prefixes = project.projectPrefixes();
|
|
240
226
|
const files = await readdir(path, {
|
|
241
227
|
withFileTypes: true,
|
|
242
228
|
});
|
|
@@ -395,11 +381,13 @@ export class Validate {
|
|
|
395
381
|
const errors: string[] = [];
|
|
396
382
|
if (cardType && fieldArray) {
|
|
397
383
|
const validationPromises = fieldArray.map(async (field) => {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
384
|
+
let fieldType;
|
|
385
|
+
try {
|
|
386
|
+
fieldType = project.resources.byType(field, 'fieldTypes').show();
|
|
387
|
+
} catch {
|
|
388
|
+
fieldType = undefined;
|
|
389
|
+
}
|
|
390
|
+
|
|
403
391
|
if (!fieldType) {
|
|
404
392
|
return `Card type '${cardType.name}' has invalid reference to unknown ${nameOfArray} '${field}'`;
|
|
405
393
|
}
|
|
@@ -476,7 +464,7 @@ export class Validate {
|
|
|
476
464
|
|
|
477
465
|
/**
|
|
478
466
|
* Validates that new identifier of a resource is according to naming convention.
|
|
479
|
-
* @param identifier
|
|
467
|
+
* @param identifier Resource identifier
|
|
480
468
|
* returns true if identifier is valid, and false otherwise.
|
|
481
469
|
*/
|
|
482
470
|
public static isValidIdentifierName(identifier: string): boolean {
|
|
@@ -550,6 +538,7 @@ export class Validate {
|
|
|
550
538
|
} else {
|
|
551
539
|
const errorMsg: string[] = [];
|
|
552
540
|
const project = projectFn();
|
|
541
|
+
await project.populateCaches();
|
|
553
542
|
|
|
554
543
|
// Then, validate that each 'contentSchema' children as well.
|
|
555
544
|
const result = await this.readAndValidateContentFiles(
|
|
@@ -561,10 +550,11 @@ export class Validate {
|
|
|
561
550
|
}
|
|
562
551
|
|
|
563
552
|
// Finally, validate that each card is correct
|
|
564
|
-
const cards =
|
|
565
|
-
cards.push(...
|
|
553
|
+
const cards = project.cards();
|
|
554
|
+
cards.push(...project.allTemplateCards());
|
|
566
555
|
|
|
567
556
|
const cardIds = new Map<string, number>();
|
|
557
|
+
const allPrefixes = await project.projectPrefixes();
|
|
568
558
|
|
|
569
559
|
for (const card of cards) {
|
|
570
560
|
if (cardIds.has(card.key)) {
|
|
@@ -574,7 +564,6 @@ export class Validate {
|
|
|
574
564
|
}
|
|
575
565
|
|
|
576
566
|
if (card.metadata) {
|
|
577
|
-
// validate card's workflow
|
|
578
567
|
if (!isTemplateCard(card)) {
|
|
579
568
|
const validWorkflow = await this.validateWorkflowState(
|
|
580
569
|
project,
|
|
@@ -585,10 +574,10 @@ export class Validate {
|
|
|
585
574
|
}
|
|
586
575
|
}
|
|
587
576
|
}
|
|
588
|
-
|
|
589
577
|
const validCustomFields = await this.validateCustomFields(
|
|
590
578
|
project,
|
|
591
579
|
card,
|
|
580
|
+
allPrefixes,
|
|
592
581
|
);
|
|
593
582
|
if (validCustomFields.length !== 0) {
|
|
594
583
|
errorMsg.push(validCustomFields);
|
|
@@ -604,7 +593,7 @@ export class Validate {
|
|
|
604
593
|
await evaluateMacros(card.content, {
|
|
605
594
|
context: 'localApp',
|
|
606
595
|
mode: 'validate',
|
|
607
|
-
project,
|
|
596
|
+
project: project,
|
|
608
597
|
cardKey: card.key,
|
|
609
598
|
});
|
|
610
599
|
}
|
|
@@ -671,21 +660,20 @@ export class Validate {
|
|
|
671
660
|
* @param resourceType Type of resource
|
|
672
661
|
* @param name Name of resource
|
|
673
662
|
* @param prefixes currently used project prefixes
|
|
663
|
+
* @throws when resource is not from given prefixes,
|
|
664
|
+
* or when actual resource does not match the type,
|
|
665
|
+
* or when identifier name is not valid
|
|
674
666
|
* @returns resource name as valid resource name; throws in error cases.
|
|
675
667
|
*/
|
|
676
|
-
public
|
|
668
|
+
public validResourceName(
|
|
677
669
|
resourceType: ResourceTypes,
|
|
678
670
|
name: string,
|
|
679
671
|
prefixes: string[],
|
|
680
|
-
):
|
|
672
|
+
): string {
|
|
681
673
|
const resource = resourceName(name);
|
|
682
674
|
resource.type = resource.type ? resource.type : resourceType;
|
|
683
|
-
// a bit shaky way to ensure that prefix is set; first of the project prefixes should be the actual project prefix.
|
|
684
675
|
if (resource.prefix === '') {
|
|
685
|
-
|
|
686
|
-
if (resource.prefix === '') {
|
|
687
|
-
throw new Error(`Project prefix cannot be empty string`);
|
|
688
|
-
}
|
|
676
|
+
throw new Error(`Project prefix cannot be empty string`);
|
|
689
677
|
}
|
|
690
678
|
if (!prefixes.includes(resource.prefix)) {
|
|
691
679
|
throw new Error(
|
|
@@ -721,11 +709,13 @@ export class Validate {
|
|
|
721
709
|
* Validates that card's custom fields are according to schema and have correct data in them.
|
|
722
710
|
* @param project currently used Project
|
|
723
711
|
* @param card specific card
|
|
724
|
-
* @
|
|
712
|
+
* @throws when card does not have metadata
|
|
713
|
+
* @returns validation errors, if any.
|
|
725
714
|
*/
|
|
726
715
|
public async validateCustomFields(
|
|
727
716
|
project: Project,
|
|
728
717
|
card: Card,
|
|
718
|
+
prefixes: string[],
|
|
729
719
|
): Promise<string> {
|
|
730
720
|
const validationErrors: string[] = [];
|
|
731
721
|
|
|
@@ -735,11 +725,14 @@ export class Validate {
|
|
|
735
725
|
);
|
|
736
726
|
}
|
|
737
727
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
728
|
+
let cardType;
|
|
729
|
+
try {
|
|
730
|
+
cardType = project.resources
|
|
731
|
+
.byType(card.metadata?.cardType, 'cardTypes')
|
|
732
|
+
.show();
|
|
733
|
+
} catch {
|
|
734
|
+
cardType = undefined;
|
|
735
|
+
}
|
|
743
736
|
|
|
744
737
|
if (!cardType) {
|
|
745
738
|
validationErrors.push(
|
|
@@ -765,11 +758,19 @@ export class Validate {
|
|
|
765
758
|
validationErrors.push(...fieldErrors);
|
|
766
759
|
|
|
767
760
|
for (const field of cardType.customFields) {
|
|
768
|
-
|
|
769
|
-
|
|
761
|
+
let fieldType;
|
|
762
|
+
try {
|
|
763
|
+
fieldType = await project.resources
|
|
764
|
+
.byType(field.name, 'fieldTypes')
|
|
765
|
+
.show();
|
|
766
|
+
} catch {
|
|
767
|
+
fieldType = undefined;
|
|
768
|
+
}
|
|
769
|
+
if (!fieldType) {
|
|
770
770
|
validationErrors.push(
|
|
771
|
-
`
|
|
771
|
+
`In card '${card.key}' field '${field.name}' is missing from project\n`,
|
|
772
772
|
);
|
|
773
|
+
continue;
|
|
773
774
|
}
|
|
774
775
|
if (field.isCalculated) {
|
|
775
776
|
if (card.metadata[field.name] !== undefined) {
|
|
@@ -787,19 +788,6 @@ export class Validate {
|
|
|
787
788
|
}
|
|
788
789
|
}
|
|
789
790
|
|
|
790
|
-
const fieldType = await this.getAndCacheResource(
|
|
791
|
-
project,
|
|
792
|
-
this.validatedFieldTypes,
|
|
793
|
-
field.name,
|
|
794
|
-
);
|
|
795
|
-
|
|
796
|
-
if (!fieldType) {
|
|
797
|
-
validationErrors.push(
|
|
798
|
-
`In card '${card.key}' field '${field.name}' is missing from project\n`,
|
|
799
|
-
);
|
|
800
|
-
continue;
|
|
801
|
-
}
|
|
802
|
-
|
|
803
791
|
if (!this.validType(card.metadata[field.name], fieldType)) {
|
|
804
792
|
const typeOfValue = typeof card.metadata[field.name];
|
|
805
793
|
let fieldValue = card.metadata[field.name];
|
|
@@ -829,14 +817,46 @@ export class Validate {
|
|
|
829
817
|
}
|
|
830
818
|
}
|
|
831
819
|
|
|
820
|
+
// Validate that all metadata keys are either predefined fields or valid field type names
|
|
821
|
+
for (const key of Object.keys(card.metadata)) {
|
|
822
|
+
if (
|
|
823
|
+
(isPredefinedField(key) as boolean) ||
|
|
824
|
+
key === 'labels' ||
|
|
825
|
+
key === 'links'
|
|
826
|
+
) {
|
|
827
|
+
continue;
|
|
828
|
+
}
|
|
829
|
+
try {
|
|
830
|
+
this.validResourceName('fieldTypes', key, prefixes);
|
|
831
|
+
} catch {
|
|
832
|
+
validationErrors.push(
|
|
833
|
+
`Card '${card.key}' has invalid metadata key '${key}'`,
|
|
834
|
+
);
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
// Check that the card's fieldType exists in the project
|
|
838
|
+
let fieldType;
|
|
839
|
+
try {
|
|
840
|
+
fieldType = await project.resources.byType(key, 'fieldTypes').show();
|
|
841
|
+
} catch {
|
|
842
|
+
fieldType = undefined;
|
|
843
|
+
}
|
|
844
|
+
if (!fieldType) {
|
|
845
|
+
validationErrors.push(
|
|
846
|
+
`Card '${card.key}' has field '${key}' that does not exist in the project`,
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
832
851
|
return validationErrors.join('\n');
|
|
833
852
|
}
|
|
834
853
|
|
|
835
854
|
/**
|
|
836
855
|
* Validates the labels of a card
|
|
837
856
|
* @param card card to validate. Card must have metadata.
|
|
857
|
+
* @returns validation errors, if any.
|
|
838
858
|
*/
|
|
839
|
-
public
|
|
859
|
+
public validateCardLabels(card: Card): string {
|
|
840
860
|
const validationErrors: string[] = [];
|
|
841
861
|
if (!card.metadata) {
|
|
842
862
|
validationErrors.push(
|
|
@@ -868,7 +888,7 @@ export class Validate {
|
|
|
868
888
|
* Template cards are expected to have empty workflow state.
|
|
869
889
|
* @param project Project object.
|
|
870
890
|
* @param card Card object to validate
|
|
871
|
-
* @returns
|
|
891
|
+
* @returns validation errors, if any.
|
|
872
892
|
*/
|
|
873
893
|
public async validateWorkflowState(
|
|
874
894
|
project: Project,
|
|
@@ -882,12 +902,14 @@ export class Validate {
|
|
|
882
902
|
);
|
|
883
903
|
}
|
|
884
904
|
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
905
|
+
let cardType;
|
|
906
|
+
try {
|
|
907
|
+
cardType = card.metadata?.cardType
|
|
908
|
+
? project.resources.byType(card.metadata?.cardType, 'cardTypes').show()
|
|
909
|
+
: undefined;
|
|
910
|
+
} catch {
|
|
911
|
+
cardType = undefined;
|
|
912
|
+
}
|
|
891
913
|
if (!cardType) {
|
|
892
914
|
validationErrors.push(
|
|
893
915
|
`Card '${card.key}' has invalid card type '${card.metadata?.cardType}'`,
|
|
@@ -901,11 +923,14 @@ export class Validate {
|
|
|
901
923
|
return validationErrors.join('\n');
|
|
902
924
|
}
|
|
903
925
|
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
926
|
+
let workflow;
|
|
927
|
+
try {
|
|
928
|
+
workflow = project.resources
|
|
929
|
+
.byType(cardType.workflow, 'workflows')
|
|
930
|
+
.show();
|
|
931
|
+
} catch {
|
|
932
|
+
workflow = undefined;
|
|
933
|
+
}
|
|
909
934
|
|
|
910
935
|
if (!workflow) {
|
|
911
936
|
validationErrors.push(
|
|
@@ -934,15 +959,16 @@ export class Validate {
|
|
|
934
959
|
|
|
935
960
|
/**
|
|
936
961
|
* Validates a single resource.
|
|
937
|
-
* @param
|
|
938
|
-
* @
|
|
962
|
+
* @param resourceName Resource to validate
|
|
963
|
+
* @param project Project instance to use.
|
|
964
|
+
* @returns validation errors, if any.
|
|
939
965
|
*/
|
|
940
966
|
public async validateResource(
|
|
941
967
|
resourceName: ResourceName,
|
|
942
968
|
project: Project,
|
|
943
969
|
): Promise<string> {
|
|
944
970
|
try {
|
|
945
|
-
const resource =
|
|
971
|
+
const resource = project.resources.byType(resourceName);
|
|
946
972
|
await resource.validate();
|
|
947
973
|
return '';
|
|
948
974
|
} catch (error) {
|