@cyberismo/data-handler 0.0.15 → 0.0.17
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 +7 -1
- package/dist/card-metadata-updater.js.map +1 -1
- package/dist/command-handler.d.ts +4 -0
- package/dist/command-handler.js +22 -8
- package/dist/command-handler.js.map +1 -1
- package/dist/command-manager.d.ts +24 -1
- package/dist/command-manager.js +31 -7
- package/dist/command-manager.js.map +1 -1
- package/dist/commands/create.d.ts +1 -1
- package/dist/commands/create.js +34 -36
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/export.d.ts +11 -2
- package/dist/commands/export.js +54 -41
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/fetch.d.ts +8 -0
- package/dist/commands/fetch.js +101 -23
- package/dist/commands/fetch.js.map +1 -1
- package/dist/commands/import.d.ts +14 -3
- package/dist/commands/import.js +27 -10
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/move.js +0 -1
- package/dist/commands/move.js.map +1 -1
- package/dist/commands/remove.d.ts +11 -2
- package/dist/commands/remove.js +15 -5
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/rename.d.ts +4 -9
- package/dist/commands/rename.js +37 -101
- package/dist/commands/rename.js.map +1 -1
- package/dist/commands/show.d.ts +20 -12
- package/dist/commands/show.js +79 -57
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/transition.d.ts +9 -2
- package/dist/commands/transition.js +25 -17
- package/dist/commands/transition.js.map +1 -1
- package/dist/commands/update.d.ts +16 -12
- package/dist/commands/update.js +19 -17
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.d.ts +17 -9
- package/dist/commands/validate.js +94 -35
- package/dist/commands/validate.js.map +1 -1
- package/dist/containers/card-container.d.ts +7 -5
- package/dist/containers/card-container.js +30 -5
- package/dist/containers/card-container.js.map +1 -1
- package/dist/containers/project/calculation-engine.d.ts +7 -4
- package/dist/containers/project/calculation-engine.js +61 -66
- package/dist/containers/project/calculation-engine.js.map +1 -1
- package/dist/containers/project/project-paths.d.ts +7 -4
- package/dist/containers/project/project-paths.js +22 -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 +509 -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 +46 -152
- package/dist/containers/project.js +179 -409
- package/dist/containers/project.js.map +1 -1
- package/dist/containers/template.d.ts +8 -2
- package/dist/containers/template.js +24 -19
- package/dist/containers/template.js.map +1 -1
- package/dist/interfaces/command-options.d.ts +3 -1
- package/dist/interfaces/folder-content-interfaces.d.ts +5 -3
- package/dist/interfaces/folder-content-interfaces.js +3 -3
- package/dist/interfaces/folder-content-interfaces.js.map +1 -1
- package/dist/interfaces/project-interfaces.d.ts +7 -9
- package/dist/interfaces/project-interfaces.js.map +1 -1
- package/dist/interfaces/resource-interfaces.d.ts +14 -1
- package/dist/interfaces/resource-interfaces.js.map +1 -1
- package/dist/macros/graph/index.js +12 -26
- package/dist/macros/graph/index.js.map +1 -1
- 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/report/index.js +3 -6
- package/dist/macros/report/index.js.map +1 -1
- package/dist/module-manager.d.ts +16 -3
- package/dist/module-manager.js +51 -19
- package/dist/module-manager.js.map +1 -1
- package/dist/project-settings.d.ts +21 -3
- package/dist/project-settings.js +91 -14
- package/dist/project-settings.js.map +1 -1
- package/dist/resources/calculation-resource.d.ts +4 -3
- package/dist/resources/calculation-resource.js +11 -5
- package/dist/resources/calculation-resource.js.map +1 -1
- package/dist/resources/card-type-resource.d.ts +6 -1
- package/dist/resources/card-type-resource.js +34 -23
- 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 +4 -1
- package/dist/resources/field-type-resource.js +22 -23
- package/dist/resources/field-type-resource.js.map +1 -1
- package/dist/resources/file-resource.d.ts +5 -9
- package/dist/resources/file-resource.js +6 -11
- package/dist/resources/file-resource.js.map +1 -1
- package/dist/resources/folder-resource.d.ts +29 -32
- package/dist/resources/folder-resource.js +59 -78
- package/dist/resources/folder-resource.js.map +1 -1
- package/dist/resources/graph-model-resource.d.ts +4 -1
- package/dist/resources/graph-model-resource.js +11 -4
- package/dist/resources/graph-model-resource.js.map +1 -1
- package/dist/resources/graph-view-resource.d.ts +5 -2
- package/dist/resources/graph-view-resource.js +7 -3
- package/dist/resources/graph-view-resource.js.map +1 -1
- package/dist/resources/link-type-resource.d.ts +5 -2
- package/dist/resources/link-type-resource.js +5 -2
- package/dist/resources/link-type-resource.js.map +1 -1
- package/dist/resources/report-resource.d.ts +6 -7
- package/dist/resources/report-resource.js +14 -23
- package/dist/resources/report-resource.js.map +1 -1
- package/dist/resources/resource-object.d.ts +94 -8
- package/dist/resources/resource-object.js +212 -109
- package/dist/resources/resource-object.js.map +1 -1
- package/dist/resources/template-resource.d.ts +7 -3
- package/dist/resources/template-resource.js +10 -3
- package/dist/resources/template-resource.js.map +1 -1
- package/dist/resources/workflow-resource.d.ts +5 -2
- package/dist/resources/workflow-resource.js +18 -22
- package/dist/resources/workflow-resource.js.map +1 -1
- package/dist/utils/card-utils.d.ts +2 -2
- package/dist/utils/card-utils.js +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 +3 -4
- package/dist/utils/clingo-facts.js.map +1 -1
- package/dist/utils/configuration-logger.d.ts +91 -0
- package/dist/utils/configuration-logger.js +151 -0
- package/dist/utils/configuration-logger.js.map +1 -0
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.js +5 -3
- package/dist/utils/constants.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 +9 -9
- package/src/card-metadata-updater.ts +6 -2
- package/src/command-handler.ts +39 -12
- package/src/command-manager.ts +33 -21
- package/src/commands/create.ts +43 -78
- package/src/commands/export.ts +63 -52
- package/src/commands/fetch.ts +143 -34
- package/src/commands/import.ts +37 -15
- package/src/commands/move.ts +0 -1
- package/src/commands/remove.ts +20 -7
- package/src/commands/rename.ts +58 -149
- package/src/commands/show.ts +123 -80
- package/src/commands/transition.ts +26 -28
- package/src/commands/update.ts +25 -22
- package/src/commands/validate.ts +104 -67
- package/src/containers/card-container.ts +37 -5
- package/src/containers/project/calculation-engine.ts +61 -93
- package/src/containers/project/project-paths.ts +29 -13
- package/src/containers/project/resource-cache.ts +651 -0
- package/src/containers/project/resource-handler.ts +265 -0
- package/src/containers/project.ts +250 -527
- package/src/containers/template.ts +28 -23
- package/src/interfaces/command-options.ts +3 -1
- package/src/interfaces/folder-content-interfaces.ts +7 -6
- package/src/interfaces/project-interfaces.ts +12 -11
- package/src/interfaces/resource-interfaces.ts +18 -3
- package/src/macros/graph/index.ts +26 -47
- package/src/macros/index.ts +2 -2
- package/src/macros/report/index.ts +3 -9
- package/src/module-manager.ts +74 -17
- package/src/project-settings.ts +96 -14
- package/src/resources/calculation-resource.ts +18 -18
- package/src/resources/card-type-resource.ts +50 -50
- package/src/resources/create-defaults.ts +3 -2
- package/src/resources/field-type-resource.ts +41 -55
- package/src/resources/file-resource.ts +10 -36
- package/src/resources/folder-resource.ts +69 -120
- package/src/resources/graph-model-resource.ts +20 -22
- package/src/resources/graph-view-resource.ts +15 -17
- package/src/resources/link-type-resource.ts +10 -13
- package/src/resources/report-resource.ts +21 -43
- package/src/resources/resource-object.ts +263 -149
- package/src/resources/template-resource.ts +17 -16
- package/src/resources/workflow-resource.ts +25 -44
- package/src/utils/card-utils.ts +2 -2
- package/src/utils/clingo-fact-builder.ts +28 -16
- package/src/utils/clingo-facts.ts +3 -4
- package/src/utils/configuration-logger.ts +206 -0
- package/src/utils/constants.ts +5 -3
- package/src/utils/resource-utils.ts +2 -1
- package/dist/containers/project/resource-collector.d.ts +0 -110
- package/dist/containers/project/resource-collector.js +0 -344
- package/dist/containers/project/resource-collector.js.map +0 -1
- package/src/containers/project/resource-collector.ts +0 -404
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,20 +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 getAndCacheResource<Type>(
|
|
173
|
-
project: Project,
|
|
174
|
-
cachedValues: Map<string, Type>,
|
|
175
|
-
valueName: string,
|
|
176
|
-
): Type | undefined {
|
|
177
|
-
const resource = project.resource<Type>(valueName);
|
|
178
|
-
if (resource) {
|
|
179
|
-
cachedValues.set(valueName, resource);
|
|
180
|
-
}
|
|
181
|
-
return resource;
|
|
182
|
-
}
|
|
183
|
-
|
|
174
|
+
// Parses validator messages
|
|
184
175
|
private parseValidatorMessage(errorObject: object[]): string {
|
|
185
176
|
let parsedErrorMessage = '';
|
|
186
177
|
// todo: get schema name here?
|
|
@@ -231,7 +222,7 @@ export class Validate {
|
|
|
231
222
|
): Promise<string[]> {
|
|
232
223
|
const message: string[] = [];
|
|
233
224
|
try {
|
|
234
|
-
const prefixes =
|
|
225
|
+
const prefixes = project.allModulePrefixes();
|
|
235
226
|
const files = await readdir(path, {
|
|
236
227
|
withFileTypes: true,
|
|
237
228
|
});
|
|
@@ -390,11 +381,13 @@ export class Validate {
|
|
|
390
381
|
const errors: string[] = [];
|
|
391
382
|
if (cardType && fieldArray) {
|
|
392
383
|
const validationPromises = fieldArray.map(async (field) => {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
384
|
+
let fieldType;
|
|
385
|
+
try {
|
|
386
|
+
fieldType = project.resources.byType(field, 'fieldTypes').show();
|
|
387
|
+
} catch {
|
|
388
|
+
fieldType = undefined;
|
|
389
|
+
}
|
|
390
|
+
|
|
398
391
|
if (!fieldType) {
|
|
399
392
|
return `Card type '${cardType.name}' has invalid reference to unknown ${nameOfArray} '${field}'`;
|
|
400
393
|
}
|
|
@@ -471,7 +464,7 @@ export class Validate {
|
|
|
471
464
|
|
|
472
465
|
/**
|
|
473
466
|
* Validates that new identifier of a resource is according to naming convention.
|
|
474
|
-
* @param identifier
|
|
467
|
+
* @param identifier Resource identifier
|
|
475
468
|
* returns true if identifier is valid, and false otherwise.
|
|
476
469
|
*/
|
|
477
470
|
public static isValidIdentifierName(identifier: string): boolean {
|
|
@@ -561,6 +554,7 @@ export class Validate {
|
|
|
561
554
|
cards.push(...project.allTemplateCards());
|
|
562
555
|
|
|
563
556
|
const cardIds = new Map<string, number>();
|
|
557
|
+
const allPrefixes = project.allModulePrefixes();
|
|
564
558
|
|
|
565
559
|
for (const card of cards) {
|
|
566
560
|
if (cardIds.has(card.key)) {
|
|
@@ -571,16 +565,19 @@ export class Validate {
|
|
|
571
565
|
|
|
572
566
|
if (card.metadata) {
|
|
573
567
|
if (!isTemplateCard(card)) {
|
|
574
|
-
const validWorkflow = this.validateWorkflowState(
|
|
568
|
+
const validWorkflow = await this.validateWorkflowState(
|
|
569
|
+
project,
|
|
570
|
+
card,
|
|
571
|
+
);
|
|
575
572
|
if (validWorkflow.length !== 0) {
|
|
576
573
|
errorMsg.push(validWorkflow);
|
|
577
574
|
}
|
|
578
575
|
}
|
|
579
576
|
}
|
|
580
|
-
|
|
581
577
|
const validCustomFields = await this.validateCustomFields(
|
|
582
578
|
project,
|
|
583
579
|
card,
|
|
580
|
+
allPrefixes,
|
|
584
581
|
);
|
|
585
582
|
if (validCustomFields.length !== 0) {
|
|
586
583
|
errorMsg.push(validCustomFields);
|
|
@@ -663,6 +660,9 @@ export class Validate {
|
|
|
663
660
|
* @param resourceType Type of resource
|
|
664
661
|
* @param name Name of resource
|
|
665
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
|
|
666
666
|
* @returns resource name as valid resource name; throws in error cases.
|
|
667
667
|
*/
|
|
668
668
|
public validResourceName(
|
|
@@ -709,11 +709,13 @@ export class Validate {
|
|
|
709
709
|
* Validates that card's custom fields are according to schema and have correct data in them.
|
|
710
710
|
* @param project currently used Project
|
|
711
711
|
* @param card specific card
|
|
712
|
-
* @
|
|
712
|
+
* @throws when card does not have metadata
|
|
713
|
+
* @returns validation errors, if any.
|
|
713
714
|
*/
|
|
714
715
|
public async validateCustomFields(
|
|
715
716
|
project: Project,
|
|
716
717
|
card: Card,
|
|
718
|
+
prefixes: string[],
|
|
717
719
|
): Promise<string> {
|
|
718
720
|
const validationErrors: string[] = [];
|
|
719
721
|
|
|
@@ -723,11 +725,14 @@ export class Validate {
|
|
|
723
725
|
);
|
|
724
726
|
}
|
|
725
727
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
728
|
+
let cardType;
|
|
729
|
+
try {
|
|
730
|
+
cardType = project.resources
|
|
731
|
+
.byType(card.metadata?.cardType, 'cardTypes')
|
|
732
|
+
.show();
|
|
733
|
+
} catch {
|
|
734
|
+
cardType = undefined;
|
|
735
|
+
}
|
|
731
736
|
|
|
732
737
|
if (!cardType) {
|
|
733
738
|
validationErrors.push(
|
|
@@ -753,11 +758,19 @@ export class Validate {
|
|
|
753
758
|
validationErrors.push(...fieldErrors);
|
|
754
759
|
|
|
755
760
|
for (const field of cardType.customFields) {
|
|
756
|
-
|
|
757
|
-
|
|
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) {
|
|
758
770
|
validationErrors.push(
|
|
759
|
-
`
|
|
771
|
+
`In card '${card.key}' field '${field.name}' is missing from project\n`,
|
|
760
772
|
);
|
|
773
|
+
continue;
|
|
761
774
|
}
|
|
762
775
|
if (field.isCalculated) {
|
|
763
776
|
if (card.metadata[field.name] !== undefined) {
|
|
@@ -775,19 +788,6 @@ export class Validate {
|
|
|
775
788
|
}
|
|
776
789
|
}
|
|
777
790
|
|
|
778
|
-
const fieldType = await this.getAndCacheResource(
|
|
779
|
-
project,
|
|
780
|
-
this.validatedFieldTypes,
|
|
781
|
-
field.name,
|
|
782
|
-
);
|
|
783
|
-
|
|
784
|
-
if (!fieldType) {
|
|
785
|
-
validationErrors.push(
|
|
786
|
-
`In card '${card.key}' field '${field.name}' is missing from project\n`,
|
|
787
|
-
);
|
|
788
|
-
continue;
|
|
789
|
-
}
|
|
790
|
-
|
|
791
791
|
if (!this.validType(card.metadata[field.name], fieldType)) {
|
|
792
792
|
const typeOfValue = typeof card.metadata[field.name];
|
|
793
793
|
let fieldValue = card.metadata[field.name];
|
|
@@ -817,12 +817,40 @@ export class Validate {
|
|
|
817
817
|
}
|
|
818
818
|
}
|
|
819
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 (isPredefinedField(key) as boolean) {
|
|
823
|
+
continue;
|
|
824
|
+
}
|
|
825
|
+
try {
|
|
826
|
+
this.validResourceName('fieldTypes', key, prefixes);
|
|
827
|
+
} catch {
|
|
828
|
+
validationErrors.push(
|
|
829
|
+
`Card '${card.key}' has invalid metadata key '${key}'`,
|
|
830
|
+
);
|
|
831
|
+
continue;
|
|
832
|
+
}
|
|
833
|
+
// Check that the card's fieldType exists in the project
|
|
834
|
+
let fieldType;
|
|
835
|
+
try {
|
|
836
|
+
fieldType = await project.resources.byType(key, 'fieldTypes').show();
|
|
837
|
+
} catch {
|
|
838
|
+
fieldType = undefined;
|
|
839
|
+
}
|
|
840
|
+
if (!fieldType) {
|
|
841
|
+
validationErrors.push(
|
|
842
|
+
`Card '${card.key}' has field '${key}' that does not exist in the project`,
|
|
843
|
+
);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
820
847
|
return validationErrors.join('\n');
|
|
821
848
|
}
|
|
822
849
|
|
|
823
850
|
/**
|
|
824
851
|
* Validates the labels of a card
|
|
825
852
|
* @param card card to validate. Card must have metadata.
|
|
853
|
+
* @returns validation errors, if any.
|
|
826
854
|
*/
|
|
827
855
|
public validateCardLabels(card: Card): string {
|
|
828
856
|
const validationErrors: string[] = [];
|
|
@@ -856,9 +884,12 @@ export class Validate {
|
|
|
856
884
|
* Template cards are expected to have empty workflow state.
|
|
857
885
|
* @param project Project object.
|
|
858
886
|
* @param card Card object to validate
|
|
859
|
-
* @returns
|
|
887
|
+
* @returns validation errors, if any.
|
|
860
888
|
*/
|
|
861
|
-
public validateWorkflowState(
|
|
889
|
+
public async validateWorkflowState(
|
|
890
|
+
project: Project,
|
|
891
|
+
card: Card,
|
|
892
|
+
): Promise<string> {
|
|
862
893
|
const validationErrors: string[] = [];
|
|
863
894
|
|
|
864
895
|
if (!card.metadata) {
|
|
@@ -867,12 +898,14 @@ export class Validate {
|
|
|
867
898
|
);
|
|
868
899
|
}
|
|
869
900
|
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
901
|
+
let cardType;
|
|
902
|
+
try {
|
|
903
|
+
cardType = card.metadata?.cardType
|
|
904
|
+
? project.resources.byType(card.metadata?.cardType, 'cardTypes').show()
|
|
905
|
+
: undefined;
|
|
906
|
+
} catch {
|
|
907
|
+
cardType = undefined;
|
|
908
|
+
}
|
|
876
909
|
if (!cardType) {
|
|
877
910
|
validationErrors.push(
|
|
878
911
|
`Card '${card.key}' has invalid card type '${card.metadata?.cardType}'`,
|
|
@@ -886,11 +919,14 @@ export class Validate {
|
|
|
886
919
|
return validationErrors.join('\n');
|
|
887
920
|
}
|
|
888
921
|
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
922
|
+
let workflow;
|
|
923
|
+
try {
|
|
924
|
+
workflow = project.resources
|
|
925
|
+
.byType(cardType.workflow, 'workflows')
|
|
926
|
+
.show();
|
|
927
|
+
} catch {
|
|
928
|
+
workflow = undefined;
|
|
929
|
+
}
|
|
894
930
|
|
|
895
931
|
if (!workflow) {
|
|
896
932
|
validationErrors.push(
|
|
@@ -919,15 +955,16 @@ export class Validate {
|
|
|
919
955
|
|
|
920
956
|
/**
|
|
921
957
|
* Validates a single resource.
|
|
922
|
-
* @param
|
|
923
|
-
* @
|
|
958
|
+
* @param resourceName Resource to validate
|
|
959
|
+
* @param project Project instance to use.
|
|
960
|
+
* @returns validation errors, if any.
|
|
924
961
|
*/
|
|
925
962
|
public async validateResource(
|
|
926
963
|
resourceName: ResourceName,
|
|
927
964
|
project: Project,
|
|
928
965
|
): Promise<string> {
|
|
929
966
|
try {
|
|
930
|
-
const resource =
|
|
967
|
+
const resource = project.resources.byType(resourceName);
|
|
931
968
|
await resource.validate();
|
|
932
969
|
return '';
|
|
933
970
|
} catch (error) {
|
|
@@ -19,17 +19,19 @@ import { writeFile } from 'node:fs/promises';
|
|
|
19
19
|
import { CardCache } from './project/card-cache.js';
|
|
20
20
|
import { cardPathParts } from '../utils/card-utils.js';
|
|
21
21
|
import { deleteDir } from '../utils/file-utils.js';
|
|
22
|
+
import { getChildLogger } from '../utils/log-utils.js';
|
|
22
23
|
import { writeJsonFile } from '../utils/json.js';
|
|
23
24
|
|
|
24
25
|
import type {
|
|
25
26
|
CardAttachment,
|
|
26
27
|
Card,
|
|
28
|
+
CardMetadata,
|
|
27
29
|
FetchCardDetails,
|
|
28
30
|
} from '../interfaces/project-interfaces.js';
|
|
29
31
|
|
|
30
32
|
import asciidoctor from '@asciidoctor/core';
|
|
31
33
|
|
|
32
|
-
import { ROOT } from '../utils/constants.js';
|
|
34
|
+
import { isPredefinedField, ROOT } from '../utils/constants.js';
|
|
33
35
|
|
|
34
36
|
/**
|
|
35
37
|
* Card container base class. Used for both Project and Template.
|
|
@@ -38,17 +40,19 @@ import { ROOT } from '../utils/constants.js';
|
|
|
38
40
|
export class CardContainer {
|
|
39
41
|
public basePath: string;
|
|
40
42
|
protected cardCache: CardCache;
|
|
41
|
-
protected containerName: string;
|
|
42
43
|
protected prefix: string;
|
|
43
44
|
|
|
45
|
+
protected static get logger() {
|
|
46
|
+
return getChildLogger({ module: 'CardContainer' });
|
|
47
|
+
}
|
|
48
|
+
|
|
44
49
|
static cardContentFile = 'index.adoc';
|
|
45
50
|
static cardMetadataFile = 'index.json';
|
|
46
51
|
static projectConfigFileName = 'cardsConfig.json';
|
|
47
52
|
static schemaContentFile = '.schema';
|
|
48
53
|
|
|
49
|
-
constructor(path: string, prefix: string
|
|
54
|
+
constructor(path: string, prefix: string) {
|
|
50
55
|
this.basePath = path;
|
|
51
|
-
this.containerName = name;
|
|
52
56
|
this.prefix = prefix;
|
|
53
57
|
this.cardCache = new CardCache(this.prefix);
|
|
54
58
|
}
|
|
@@ -226,13 +230,41 @@ export class CardContainer {
|
|
|
226
230
|
if (card.metadata != null) {
|
|
227
231
|
const metadataFile = join(card.path, CardContainer.cardMetadataFile);
|
|
228
232
|
card.metadata!.lastUpdated = new Date().toISOString();
|
|
229
|
-
|
|
233
|
+
|
|
234
|
+
const sanitizedMetadata = CardContainer.sanitizeMetadata(card);
|
|
235
|
+
await writeJsonFile(metadataFile, sanitizedMetadata);
|
|
230
236
|
return this.cardCache.updateCardMetadata(card.key, card.metadata);
|
|
231
237
|
}
|
|
232
238
|
return false;
|
|
233
239
|
}
|
|
234
240
|
|
|
235
241
|
/**
|
|
242
|
+
* Removes non-metadata fields that should not be persisted.
|
|
243
|
+
*
|
|
244
|
+
* @param metadata The metadata object to sanitize
|
|
245
|
+
* @returns Clean metadata object with only valid metadata fields
|
|
246
|
+
*/
|
|
247
|
+
private static sanitizeMetadata(card: Card): CardMetadata {
|
|
248
|
+
const sanitized: Record<string, unknown> = {};
|
|
249
|
+
|
|
250
|
+
if (card.metadata) {
|
|
251
|
+
for (const [key, value] of Object.entries(card.metadata)) {
|
|
252
|
+
// Keys are not filtered out if they are: predefined, or field types
|
|
253
|
+
if (isPredefinedField(key) || key.includes('/')) {
|
|
254
|
+
sanitized[key] = value;
|
|
255
|
+
} else {
|
|
256
|
+
this.logger.warn(
|
|
257
|
+
`Card ${card.key} had extra metadata key ${key} with value ${value}. Key was removed`,
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
// Everything else is filtered out
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return sanitized as CardMetadata;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/*
|
|
236
268
|
* Show root cards from a given path.
|
|
237
269
|
* @param path The path to get cards from
|
|
238
270
|
* @returns an array of root-level cards (each with their children populated).
|