@cyberismo/data-handler 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +702 -0
- package/dist/card-metadata-updater.d.ts +33 -0
- package/dist/card-metadata-updater.js +121 -0
- package/dist/card-metadata-updater.js.map +1 -0
- package/dist/command-handler.d.ts +96 -0
- package/dist/command-handler.js +557 -0
- package/dist/command-handler.js.map +1 -0
- package/dist/command-manager.d.ts +43 -0
- package/dist/command-manager.js +73 -0
- package/dist/command-manager.js.map +1 -0
- package/dist/commands/calculate.d.ts +86 -0
- package/dist/commands/calculate.js +444 -0
- package/dist/commands/calculate.js.map +1 -0
- package/dist/commands/create.d.ts +114 -0
- package/dist/commands/create.js +389 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/edit.d.ts +37 -0
- package/dist/commands/edit.js +99 -0
- package/dist/commands/edit.js.map +1 -0
- package/dist/commands/export-site.d.ts +45 -0
- package/dist/commands/export-site.js +301 -0
- package/dist/commands/export-site.js.map +1 -0
- package/dist/commands/export.d.ts +53 -0
- package/dist/commands/export.js +251 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/import.d.ts +53 -0
- package/dist/commands/import.js +133 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/index.d.ts +26 -0
- package/dist/commands/index.js +27 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/move.d.ts +55 -0
- package/dist/commands/move.js +341 -0
- package/dist/commands/move.js.map +1 -0
- package/dist/commands/remove.d.ts +38 -0
- package/dist/commands/remove.js +192 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/rename.d.ts +46 -0
- package/dist/commands/rename.js +289 -0
- package/dist/commands/rename.js.map +1 -0
- package/dist/commands/show.d.ts +124 -0
- package/dist/commands/show.js +345 -0
- package/dist/commands/show.js.map +1 -0
- package/dist/commands/transition.d.ts +27 -0
- package/dist/commands/transition.js +92 -0
- package/dist/commands/transition.js.map +1 -0
- package/dist/commands/update.d.ts +29 -0
- package/dist/commands/update.js +64 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.d.ts +143 -0
- package/dist/commands/validate.js +689 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/containers/card-container.d.ts +44 -0
- package/dist/containers/card-container.js +282 -0
- package/dist/containers/card-container.js.map +1 -0
- package/dist/containers/project/project-paths.d.ts +46 -0
- package/dist/containers/project/project-paths.js +105 -0
- package/dist/containers/project/project-paths.js.map +1 -0
- package/dist/containers/project/resource-collector.d.ts +86 -0
- package/dist/containers/project/resource-collector.js +331 -0
- package/dist/containers/project/resource-collector.js.map +1 -0
- package/dist/containers/project.d.ts +351 -0
- package/dist/containers/project.js +896 -0
- package/dist/containers/project.js.map +1 -0
- package/dist/containers/template.d.ts +108 -0
- package/dist/containers/template.js +433 -0
- package/dist/containers/template.js.map +1 -0
- package/dist/exceptions/index.d.ts +19 -0
- package/dist/exceptions/index.js +26 -0
- package/dist/exceptions/index.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/adoc.d.ts +12 -0
- package/dist/interfaces/adoc.js +13 -0
- package/dist/interfaces/adoc.js.map +1 -0
- package/dist/interfaces/macros.d.ts +45 -0
- package/dist/interfaces/macros.js +13 -0
- package/dist/interfaces/macros.js.map +1 -0
- package/dist/interfaces/project-interfaces.d.ts +121 -0
- package/dist/interfaces/project-interfaces.js +21 -0
- package/dist/interfaces/project-interfaces.js.map +1 -0
- package/dist/interfaces/request-status-interfaces.d.ts +28 -0
- package/dist/interfaces/request-status-interfaces.js +20 -0
- package/dist/interfaces/request-status-interfaces.js.map +1 -0
- package/dist/interfaces/resource-interfaces.d.ts +117 -0
- package/dist/interfaces/resource-interfaces.js +20 -0
- package/dist/interfaces/resource-interfaces.js.map +1 -0
- package/dist/macros/base-macro.d.ts +31 -0
- package/dist/macros/base-macro.js +126 -0
- package/dist/macros/base-macro.js.map +1 -0
- package/dist/macros/common.d.ts +17 -0
- package/dist/macros/common.js +23 -0
- package/dist/macros/common.js.map +1 -0
- package/dist/macros/createCards/index.d.ts +36 -0
- package/dist/macros/createCards/index.js +35 -0
- package/dist/macros/createCards/index.js.map +1 -0
- package/dist/macros/createCards/metadata.d.ts +14 -0
- package/dist/macros/createCards/metadata.js +18 -0
- package/dist/macros/createCards/metadata.js.map +1 -0
- package/dist/macros/graph/index.d.ts +29 -0
- package/dist/macros/graph/index.js +91 -0
- package/dist/macros/graph/index.js.map +1 -0
- package/dist/macros/graph/metadata.d.ts +14 -0
- package/dist/macros/graph/metadata.js +18 -0
- package/dist/macros/graph/metadata.js.map +1 -0
- package/dist/macros/index.d.ts +93 -0
- package/dist/macros/index.js +237 -0
- package/dist/macros/index.js.map +1 -0
- package/dist/macros/report/index.d.ts +26 -0
- package/dist/macros/report/index.js +70 -0
- package/dist/macros/report/index.js.map +1 -0
- package/dist/macros/report/metadata.d.ts +14 -0
- package/dist/macros/report/metadata.js +18 -0
- package/dist/macros/report/metadata.js.map +1 -0
- package/dist/macros/scoreCard/index.d.ts +30 -0
- package/dist/macros/scoreCard/index.js +38 -0
- package/dist/macros/scoreCard/index.js.map +1 -0
- package/dist/macros/scoreCard/metadata.d.ts +14 -0
- package/dist/macros/scoreCard/metadata.js +18 -0
- package/dist/macros/scoreCard/metadata.js.map +1 -0
- package/dist/macros/task-queue.d.ts +46 -0
- package/dist/macros/task-queue.js +69 -0
- package/dist/macros/task-queue.js.map +1 -0
- package/dist/module-manager.d.ts +62 -0
- package/dist/module-manager.js +350 -0
- package/dist/module-manager.js.map +1 -0
- package/dist/permissions/action-guard.d.ts +28 -0
- package/dist/permissions/action-guard.js +61 -0
- package/dist/permissions/action-guard.js.map +1 -0
- package/dist/project-settings.d.ts +42 -0
- package/dist/project-settings.js +120 -0
- package/dist/project-settings.js.map +1 -0
- package/dist/resources/array-handler.d.ts +28 -0
- package/dist/resources/array-handler.js +116 -0
- package/dist/resources/array-handler.js.map +1 -0
- package/dist/resources/card-type-resource.d.ts +72 -0
- package/dist/resources/card-type-resource.js +334 -0
- package/dist/resources/card-type-resource.js.map +1 -0
- package/dist/resources/create-defaults.d.ts +81 -0
- package/dist/resources/create-defaults.js +184 -0
- package/dist/resources/create-defaults.js.map +1 -0
- package/dist/resources/field-type-resource.d.ts +88 -0
- package/dist/resources/field-type-resource.js +411 -0
- package/dist/resources/field-type-resource.js.map +1 -0
- package/dist/resources/file-resource.d.ts +50 -0
- package/dist/resources/file-resource.js +301 -0
- package/dist/resources/file-resource.js.map +1 -0
- package/dist/resources/folder-resource.d.ts +66 -0
- package/dist/resources/folder-resource.js +100 -0
- package/dist/resources/folder-resource.js.map +1 -0
- package/dist/resources/graph-model-resource.d.ts +78 -0
- package/dist/resources/graph-model-resource.js +164 -0
- package/dist/resources/graph-model-resource.js.map +1 -0
- package/dist/resources/graph-view-resource.d.ts +78 -0
- package/dist/resources/graph-view-resource.js +163 -0
- package/dist/resources/graph-view-resource.js.map +1 -0
- package/dist/resources/link-type-resource.d.ts +62 -0
- package/dist/resources/link-type-resource.js +150 -0
- package/dist/resources/link-type-resource.js.map +1 -0
- package/dist/resources/report-resource.d.ts +77 -0
- package/dist/resources/report-resource.js +171 -0
- package/dist/resources/report-resource.js.map +1 -0
- package/dist/resources/resource-object.d.ts +108 -0
- package/dist/resources/resource-object.js +147 -0
- package/dist/resources/resource-object.js.map +1 -0
- package/dist/resources/template-resource.d.ts +82 -0
- package/dist/resources/template-resource.js +173 -0
- package/dist/resources/template-resource.js.map +1 -0
- package/dist/resources/workflow-resource.d.ts +67 -0
- package/dist/resources/workflow-resource.js +156 -0
- package/dist/resources/workflow-resource.js.map +1 -0
- package/dist/types/queries.d.ts +142 -0
- package/dist/types/queries.js +16 -0
- package/dist/types/queries.js.map +1 -0
- package/dist/utils/card-utils.d.ts +34 -0
- package/dist/utils/card-utils.js +78 -0
- package/dist/utils/card-utils.js.map +1 -0
- package/dist/utils/clingo-fact-builder.d.ts +58 -0
- package/dist/utils/clingo-fact-builder.js +126 -0
- package/dist/utils/clingo-fact-builder.js.map +1 -0
- package/dist/utils/clingo-facts.d.ts +97 -0
- package/dist/utils/clingo-facts.js +352 -0
- package/dist/utils/clingo-facts.js.map +1 -0
- package/dist/utils/clingo-parser.d.ts +59 -0
- package/dist/utils/clingo-parser.js +403 -0
- package/dist/utils/clingo-parser.js.map +1 -0
- package/dist/utils/clingo-program-builder.d.ts +39 -0
- package/dist/utils/clingo-program-builder.js +57 -0
- package/dist/utils/clingo-program-builder.js.map +1 -0
- package/dist/utils/common-utils.d.ts +24 -0
- package/dist/utils/common-utils.js +47 -0
- package/dist/utils/common-utils.js.map +1 -0
- package/dist/utils/constants.d.ts +18 -0
- package/dist/utils/constants.js +27 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/csv.d.ts +18 -0
- package/dist/utils/csv.js +45 -0
- package/dist/utils/csv.js.map +1 -0
- package/dist/utils/file-utils.d.ts +69 -0
- package/dist/utils/file-utils.js +158 -0
- package/dist/utils/file-utils.js.map +1 -0
- package/dist/utils/json.d.ts +61 -0
- package/dist/utils/json.js +108 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/lexorank.d.ts +59 -0
- package/dist/utils/lexorank.js +159 -0
- package/dist/utils/lexorank.js.map +1 -0
- package/dist/utils/log-utils.d.ts +40 -0
- package/dist/utils/log-utils.js +109 -0
- package/dist/utils/log-utils.js.map +1 -0
- package/dist/utils/random.d.ts +19 -0
- package/dist/utils/random.js +34 -0
- package/dist/utils/random.js.map +1 -0
- package/dist/utils/resource-utils.d.ts +45 -0
- package/dist/utils/resource-utils.js +137 -0
- package/dist/utils/resource-utils.js.map +1 -0
- package/dist/utils/sanitize-svg.d.ts +18 -0
- package/dist/utils/sanitize-svg.js +38 -0
- package/dist/utils/sanitize-svg.js.map +1 -0
- package/dist/utils/user-preferences.d.ts +64 -0
- package/dist/utils/user-preferences.js +106 -0
- package/dist/utils/user-preferences.js.map +1 -0
- package/dist/utils/validate.d.ts +26 -0
- package/dist/utils/validate.js +53 -0
- package/dist/utils/validate.js.map +1 -0
- package/dist/utils/value-utils.d.ts +58 -0
- package/dist/utils/value-utils.js +181 -0
- package/dist/utils/value-utils.js.map +1 -0
- package/package.json +67 -0
- package/src/card-metadata-updater.ts +182 -0
- package/src/command-handler.ts +686 -0
- package/src/command-manager.ts +99 -0
- package/src/commands/calculate.ts +591 -0
- package/src/commands/create.ts +559 -0
- package/src/commands/edit.ts +123 -0
- package/src/commands/export-site.ts +356 -0
- package/src/commands/export.ts +315 -0
- package/src/commands/import.ts +169 -0
- package/src/commands/index.ts +42 -0
- package/src/commands/move.ts +451 -0
- package/src/commands/remove.ts +244 -0
- package/src/commands/rename.ts +378 -0
- package/src/commands/show.ts +442 -0
- package/src/commands/transition.ts +127 -0
- package/src/commands/update.ts +76 -0
- package/src/commands/validate.ts +962 -0
- package/src/containers/card-container.ts +378 -0
- package/src/containers/project/project-paths.ts +127 -0
- package/src/containers/project/resource-collector.ts +379 -0
- package/src/containers/project.ts +1135 -0
- package/src/containers/template.ts +573 -0
- package/src/exceptions/index.ts +29 -0
- package/src/index.ts +33 -0
- package/src/interfaces/adoc.ts +18 -0
- package/src/interfaces/macros.ts +54 -0
- package/src/interfaces/project-interfaces.ts +208 -0
- package/src/interfaces/request-status-interfaces.ts +30 -0
- package/src/interfaces/resource-interfaces.ts +179 -0
- package/src/macros/base-macro.ts +176 -0
- package/src/macros/common.ts +24 -0
- package/src/macros/createCards/index.ts +57 -0
- package/src/macros/createCards/metadata.ts +21 -0
- package/src/macros/graph/index.ts +130 -0
- package/src/macros/graph/metadata.ts +21 -0
- package/src/macros/index.ts +321 -0
- package/src/macros/report/index.ts +88 -0
- package/src/macros/report/metadata.ts +21 -0
- package/src/macros/scoreCard/index.ts +55 -0
- package/src/macros/scoreCard/metadata.ts +21 -0
- package/src/macros/task-queue.ts +79 -0
- package/src/module-manager.ts +443 -0
- package/src/permissions/action-guard.ts +77 -0
- package/src/project-settings.ts +140 -0
- package/src/resources/array-handler.ts +141 -0
- package/src/resources/card-type-resource.ts +455 -0
- package/src/resources/create-defaults.ts +216 -0
- package/src/resources/field-type-resource.ts +533 -0
- package/src/resources/file-resource.ts +433 -0
- package/src/resources/folder-resource.ts +140 -0
- package/src/resources/graph-model-resource.ts +205 -0
- package/src/resources/graph-view-resource.ts +199 -0
- package/src/resources/link-type-resource.ts +191 -0
- package/src/resources/report-resource.ts +224 -0
- package/src/resources/resource-object.ts +246 -0
- package/src/resources/template-resource.ts +210 -0
- package/src/resources/workflow-resource.ts +205 -0
- package/src/types/queries.ts +149 -0
- package/src/utils/card-utils.ts +83 -0
- package/src/utils/clingo-fact-builder.ts +167 -0
- package/src/utils/clingo-facts.ts +550 -0
- package/src/utils/clingo-parser.ts +519 -0
- package/src/utils/clingo-program-builder.ts +71 -0
- package/src/utils/common-utils.ts +54 -0
- package/src/utils/constants.ts +32 -0
- package/src/utils/csv.ts +53 -0
- package/src/utils/file-utils.ts +182 -0
- package/src/utils/json.ts +118 -0
- package/src/utils/lexorank.ts +180 -0
- package/src/utils/log-utils.ts +127 -0
- package/src/utils/random.ts +37 -0
- package/src/utils/resource-utils.ts +180 -0
- package/src/utils/sanitize-svg.ts +46 -0
- package/src/utils/user-preferences.ts +126 -0
- package/src/utils/validate.ts +66 -0
- package/src/utils/value-utils.ts +189 -0
|
@@ -0,0 +1,896 @@
|
|
|
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 { dirname, join, resolve, sep } from 'node:path';
|
|
15
|
+
import { readdir } from 'node:fs/promises';
|
|
16
|
+
import { CardContainer } from './card-container.js'; // base class
|
|
17
|
+
import { CardLocation, CardNameRegEx, } from '../interfaces/project-interfaces.js';
|
|
18
|
+
import { findParentPath } from '../utils/card-utils.js';
|
|
19
|
+
import { getFilesSync, pathExists } from '../utils/file-utils.js';
|
|
20
|
+
import { generateRandomString } from '../utils/random.js';
|
|
21
|
+
import { isTemplateCard } from '../utils/card-utils.js';
|
|
22
|
+
import { ProjectConfiguration } from '../project-settings.js';
|
|
23
|
+
import { ProjectPaths } from './project/project-paths.js';
|
|
24
|
+
import { readJsonFile } from '../utils/json.js';
|
|
25
|
+
import { resourceName, resourceNameToString, } from '../utils/resource-utils.js';
|
|
26
|
+
import { ResourcesFrom, ResourceCollector, } from './project/resource-collector.js';
|
|
27
|
+
import { Validate } from '../commands/validate.js';
|
|
28
|
+
import { CardTypeResource } from '../resources/card-type-resource.js';
|
|
29
|
+
import { FieldTypeResource } from '../resources/field-type-resource.js';
|
|
30
|
+
import { GraphModelResource } from '../resources/graph-model-resource.js';
|
|
31
|
+
import { GraphViewResource } from '../resources/graph-view-resource.js';
|
|
32
|
+
import { LinkTypeResource } from '../resources/link-type-resource.js';
|
|
33
|
+
import { ReportResource } from '../resources/report-resource.js';
|
|
34
|
+
import { TemplateResource } from '../resources/template-resource.js';
|
|
35
|
+
import { WorkflowResource } from '../resources/workflow-resource.js';
|
|
36
|
+
// Re-export this, so that classes that use Project do not need to have separate import.
|
|
37
|
+
export { ResourcesFrom };
|
|
38
|
+
/**
|
|
39
|
+
* Represents project folder.
|
|
40
|
+
*/
|
|
41
|
+
export class Project extends CardContainer {
|
|
42
|
+
resources;
|
|
43
|
+
projectPaths;
|
|
44
|
+
settings;
|
|
45
|
+
validator;
|
|
46
|
+
// Created resources are held in a cache.
|
|
47
|
+
// In the cache, key is resource name, and data is resource metadata (as JSON).
|
|
48
|
+
createdResources = new Map();
|
|
49
|
+
constructor(path) {
|
|
50
|
+
super(path, '');
|
|
51
|
+
this.settings = new ProjectConfiguration(join(path, '.cards', 'local', Project.projectConfigFileName));
|
|
52
|
+
this.projectPaths = new ProjectPaths(path);
|
|
53
|
+
this.resources = new ResourceCollector(this);
|
|
54
|
+
this.containerName = this.settings.name;
|
|
55
|
+
// todo: implement project validation
|
|
56
|
+
this.validator = Validate.getInstance();
|
|
57
|
+
this.resources.collectLocalResources();
|
|
58
|
+
}
|
|
59
|
+
// Finds specific module.
|
|
60
|
+
async findModule(moduleName) {
|
|
61
|
+
return (await this.resources.resources('modules')).find((item) => item.name === moduleName && item.path);
|
|
62
|
+
}
|
|
63
|
+
// Returns (local or all) resources of a given type.
|
|
64
|
+
// @todo: if this would be public, we could remove cardTypes(), fieldTypes(), ... and similar APIs
|
|
65
|
+
async resourcesOfType(type, from = ResourcesFrom.localOnly) {
|
|
66
|
+
return this.resources.resources(type, from);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Add a given 'resource' to the local resource arrays.
|
|
70
|
+
* @param resource Resource to add.
|
|
71
|
+
*/
|
|
72
|
+
addResource(resource, data) {
|
|
73
|
+
this.resources.add(resource);
|
|
74
|
+
this.createdResources.set(resource.name, data);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Returns an array of all the attachments in the project card's (excluding ones in templates).
|
|
78
|
+
* @returns all attachments in the project.
|
|
79
|
+
*/
|
|
80
|
+
async attachments() {
|
|
81
|
+
return super.attachments(this.paths.cardRootFolder);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Returns an array of all the calculation files (*.lp) in the project.
|
|
85
|
+
* @param from Defines where resources are collected from.
|
|
86
|
+
* @returns array of all calculation files in the project.
|
|
87
|
+
*/
|
|
88
|
+
async calculations(from = ResourcesFrom.localOnly) {
|
|
89
|
+
return this.resources.resources('calculations', from);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Returns path to card's attachment folder.
|
|
93
|
+
* @param cardKey card key
|
|
94
|
+
* @returns path to card's attachment folder.
|
|
95
|
+
*/
|
|
96
|
+
async cardAttachmentFolder(cardKey) {
|
|
97
|
+
// Check if it is a template card.
|
|
98
|
+
if (await this.isTemplateCard(cardKey)) {
|
|
99
|
+
const cardPath = await this.cardFolder(cardKey);
|
|
100
|
+
return join(cardPath, 'a');
|
|
101
|
+
}
|
|
102
|
+
const pathToProjectCard = this.pathToCard(cardKey);
|
|
103
|
+
return pathToProjectCard
|
|
104
|
+
? join(this.paths.cardRootFolder, pathToProjectCard, 'a')
|
|
105
|
+
: '';
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Returns details (as defined by cardDetails) of a card.
|
|
109
|
+
* @param cardKey card key (project prefix and a number, e.g. test_1)
|
|
110
|
+
* @param cardDetails which card details are returned.
|
|
111
|
+
* @returns Card details, or undefined if the card cannot be found.
|
|
112
|
+
*/
|
|
113
|
+
async cardDetailsById(cardKey, cardDetails) {
|
|
114
|
+
return this.findSpecificCard(cardKey, cardDetails);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Returns path to card's folder.
|
|
118
|
+
* @param cardKey card key
|
|
119
|
+
* @returns path to card's folder.
|
|
120
|
+
*/
|
|
121
|
+
async cardFolder(cardKey) {
|
|
122
|
+
const found = await super.findCard(this.paths.cardRootFolder, cardKey);
|
|
123
|
+
if (found) {
|
|
124
|
+
return found.path;
|
|
125
|
+
}
|
|
126
|
+
const templates = await this.templates();
|
|
127
|
+
const templatePromises = templates.map(async (template) => {
|
|
128
|
+
const templateObject = new TemplateResource(this, resourceName(template.name)).templateObject();
|
|
129
|
+
const templateCard = templateObject
|
|
130
|
+
? await templateObject.findSpecificCard(cardKey)
|
|
131
|
+
: undefined;
|
|
132
|
+
return templateCard ? templateCard.path : '';
|
|
133
|
+
});
|
|
134
|
+
const templatePaths = await Promise.all(templatePromises);
|
|
135
|
+
return templatePaths.find((path) => path !== '') || '';
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Splits card path to parts. Returns the parts.
|
|
139
|
+
* Returned parts are: prefix, card key, array of parents and template name. Template name is returned only for template cards.
|
|
140
|
+
* @param cardPath path to a card
|
|
141
|
+
* @returns card path logical parts
|
|
142
|
+
* todo: if prefix would be parameter; this could be static, or util method
|
|
143
|
+
*/
|
|
144
|
+
cardPathParts(cardPath) {
|
|
145
|
+
const pathParts = cardPath.split(sep);
|
|
146
|
+
const cardKey = pathParts.at(pathParts.length - 1);
|
|
147
|
+
const parents = [];
|
|
148
|
+
let prefix = this.projectPrefix;
|
|
149
|
+
let template = '';
|
|
150
|
+
let startIndex = -1;
|
|
151
|
+
let templatesNameIndex = -1;
|
|
152
|
+
const cardRootIndex = pathParts.indexOf('cardRoot');
|
|
153
|
+
const projectInternalsIndex = pathParts.indexOf('.cards');
|
|
154
|
+
if (projectInternalsIndex === -1 && cardRootIndex >= 0) {
|
|
155
|
+
startIndex = projectInternalsIndex;
|
|
156
|
+
}
|
|
157
|
+
else if (projectInternalsIndex >= 0 && cardRootIndex === -1) {
|
|
158
|
+
const templatesIndex = pathParts.indexOf('templates');
|
|
159
|
+
startIndex = templatesIndex;
|
|
160
|
+
if (templatesIndex === -1) {
|
|
161
|
+
throw new Error(`Invalid card path. Template card must have 'templates' in path`);
|
|
162
|
+
}
|
|
163
|
+
const modulesIndex = pathParts.indexOf('modules');
|
|
164
|
+
if (modulesIndex !== -1) {
|
|
165
|
+
prefix = pathParts.at(modulesIndex + 1) || '';
|
|
166
|
+
}
|
|
167
|
+
templatesNameIndex = templatesIndex + 1;
|
|
168
|
+
template = `${prefix}/templates/${pathParts.at(templatesNameIndex)}`;
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
throw new Error(`Card must be either project card, or template card`);
|
|
172
|
+
}
|
|
173
|
+
// Look for parents in the path.
|
|
174
|
+
let previousWasParent = false;
|
|
175
|
+
for (let index = startIndex; index <= pathParts.length; index++) {
|
|
176
|
+
if (previousWasParent) {
|
|
177
|
+
previousWasParent = false;
|
|
178
|
+
parents.push(pathParts.at(index - 2));
|
|
179
|
+
}
|
|
180
|
+
const cardsSubFolder = pathParts.at(index) === 'c';
|
|
181
|
+
const ignoreOrNotTemplatesParent = index - 1 !== templatesNameIndex || templatesNameIndex === -1;
|
|
182
|
+
if (cardsSubFolder && ignoreOrNotTemplatesParent) {
|
|
183
|
+
previousWasParent = true;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
cardKey: cardKey,
|
|
188
|
+
parents: parents,
|
|
189
|
+
prefix: prefix,
|
|
190
|
+
template: template,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Returns an array of all the cards in the project. Cards have content and metadata
|
|
195
|
+
* @param path Optional path from which to fetch the cards. Generally it is best to fetch from Project root, e.g. Project.cardRootFolder
|
|
196
|
+
* @param details Which details to include in the cards; by default only "content" and "metadata" are included.
|
|
197
|
+
* @returns all cards from the given path in the project.
|
|
198
|
+
*/
|
|
199
|
+
async cards(path = this.paths.cardRootFolder, details = { content: true, metadata: true }) {
|
|
200
|
+
return super.cards(path, details);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Returns an array of all the card types in the project.
|
|
204
|
+
* @param from Defines where resources are collected from.
|
|
205
|
+
* @returns array of all card types in the project.
|
|
206
|
+
*/
|
|
207
|
+
async cardTypes(from = ResourcesFrom.all) {
|
|
208
|
+
return this.resources.resources('cardTypes', from);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Updates all local resources.
|
|
212
|
+
*/
|
|
213
|
+
collectLocalResources() {
|
|
214
|
+
this.resources.changed();
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Updates all imported module resources.
|
|
218
|
+
*/
|
|
219
|
+
async collectModuleResources() {
|
|
220
|
+
await this.resources.moduleImported();
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Returns project configuration.
|
|
224
|
+
* @returns project configuration.
|
|
225
|
+
*/
|
|
226
|
+
get configuration() {
|
|
227
|
+
return this.settings;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Creates a Template object from template Card. It is ensured that the template is part of project.
|
|
231
|
+
* @param card Card that is part of some template.
|
|
232
|
+
* @returns Template object, or undefined if card is not part of template.
|
|
233
|
+
*/
|
|
234
|
+
createTemplateObjectFromCard(card) {
|
|
235
|
+
if (!card || !card.path || !isTemplateCard(card)) {
|
|
236
|
+
return undefined;
|
|
237
|
+
}
|
|
238
|
+
const { template } = this.cardPathParts(card.path);
|
|
239
|
+
return new TemplateResource(this, resourceName(template)).templateObject();
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Returns an array of all the field types in the project.
|
|
243
|
+
* @param from Defines where resources are collected from.
|
|
244
|
+
* @returns array of all field types in the project.
|
|
245
|
+
*/
|
|
246
|
+
async fieldTypes(from = ResourcesFrom.all) {
|
|
247
|
+
return this.resources.resources('fieldTypes', from);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Finds root of a project
|
|
251
|
+
* @param path Path where to start looking for the project root.
|
|
252
|
+
* @returns path to a project root, or empty string.
|
|
253
|
+
*/
|
|
254
|
+
static async findProjectRoot(path) {
|
|
255
|
+
const currentPath = resolve(join(path, '.cards'));
|
|
256
|
+
if (pathExists(currentPath)) {
|
|
257
|
+
return path;
|
|
258
|
+
}
|
|
259
|
+
const parentPath = resolve(path, '..');
|
|
260
|
+
if (parentPath === path) {
|
|
261
|
+
return '';
|
|
262
|
+
}
|
|
263
|
+
return Project.findProjectRoot(parentPath);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Returns specific card.
|
|
267
|
+
* @param cardToFind Card key to find
|
|
268
|
+
* @param details Defines which card details are included in the return values.
|
|
269
|
+
* @returns specific card details, or undefined if card is not part of the project.
|
|
270
|
+
*/
|
|
271
|
+
async findSpecificCard(cardToFind, details = {}) {
|
|
272
|
+
let card;
|
|
273
|
+
if (details.location === CardLocation.projectOnly ||
|
|
274
|
+
details.location === CardLocation.all ||
|
|
275
|
+
!details.location) {
|
|
276
|
+
card = await super.findCard(this.paths.cardRootFolder, cardToFind, details);
|
|
277
|
+
}
|
|
278
|
+
if (!card &&
|
|
279
|
+
(details.location === CardLocation.templatesOnly ||
|
|
280
|
+
details.location === CardLocation.all ||
|
|
281
|
+
!details.location)) {
|
|
282
|
+
const templates = await this.templates();
|
|
283
|
+
for (const template of templates) {
|
|
284
|
+
const templateObject = new TemplateResource(this, resourceName(template.name)).templateObject();
|
|
285
|
+
if (!templateObject)
|
|
286
|
+
continue;
|
|
287
|
+
// optimize: execute each find in template parallel
|
|
288
|
+
card = await templateObject.findSpecificCard(cardToFind, details);
|
|
289
|
+
if (card) {
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return card;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Returns an array of all the graph models in the project.
|
|
298
|
+
* @param from Defines where resources are collected from.
|
|
299
|
+
* @returns array of all the graph models in the project.
|
|
300
|
+
*/
|
|
301
|
+
async graphModels(from = ResourcesFrom.all) {
|
|
302
|
+
return this.resources.resources('graphModels', from);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Returns an array of all the graph views in the project.
|
|
306
|
+
* @param from Defines where resources are collected from.
|
|
307
|
+
* @returns array of all the graph views in the project.
|
|
308
|
+
*/
|
|
309
|
+
async graphViews(from = ResourcesFrom.all) {
|
|
310
|
+
return this.resources.resources('graphViews', from);
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Checks if a given card is part of this project.
|
|
314
|
+
* @param cardKey card to check.
|
|
315
|
+
* @returns true if a given card is found from project, false otherwise.
|
|
316
|
+
*/
|
|
317
|
+
hasCard(cardKey) {
|
|
318
|
+
return super.hasCard(cardKey, this.paths.cardRootFolder);
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Adds a module from project.
|
|
322
|
+
* @param moduleName Name of the module
|
|
323
|
+
*/
|
|
324
|
+
async importModule(module) {
|
|
325
|
+
// Add module as a dependency.
|
|
326
|
+
await this.configuration.addModule(module);
|
|
327
|
+
await this.collectModuleResources();
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Checks if given path is a project.
|
|
331
|
+
* @param path Path to a project
|
|
332
|
+
* @returns true, if in the given path there is a project; false otherwise
|
|
333
|
+
*/
|
|
334
|
+
static isCreated(path) {
|
|
335
|
+
return pathExists(join(path, 'cardRoot'));
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Returns whether card is a template card or not
|
|
339
|
+
* @param cardKey card to check.
|
|
340
|
+
* @todo: This is only used from 'remove'. Could it use the static checker?
|
|
341
|
+
*/
|
|
342
|
+
async isTemplateCard(cardKey) {
|
|
343
|
+
const templateCards = await this.allTemplateCards();
|
|
344
|
+
return templateCards.find((card) => card.key === cardKey) != null;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Returns an array of all the link types in the project.
|
|
348
|
+
* @param from Defines where resources are collected from.
|
|
349
|
+
* @returns array of all link types in the project.
|
|
350
|
+
*/
|
|
351
|
+
async linkTypes(from = ResourcesFrom.all) {
|
|
352
|
+
return this.resources.resources('linkTypes', from);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Returns an array of cards in the project, in the templates or both.
|
|
356
|
+
* Cards don't have content and nor metadata.
|
|
357
|
+
* @param includeCardsFrom Where to return cards from (project, templates, or both)
|
|
358
|
+
* @returns all cards in the project.
|
|
359
|
+
*/
|
|
360
|
+
async listCards(cardsFrom = CardLocation.all) {
|
|
361
|
+
const cardListContainer = [];
|
|
362
|
+
if (cardsFrom === CardLocation.all ||
|
|
363
|
+
cardsFrom === CardLocation.projectOnly) {
|
|
364
|
+
const projectCards = (await super.cards(this.paths.cardRootFolder)).map((item) => item.key);
|
|
365
|
+
cardListContainer.push({
|
|
366
|
+
name: this.projectName,
|
|
367
|
+
type: 'project',
|
|
368
|
+
cards: projectCards,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
if (cardsFrom === CardLocation.all ||
|
|
372
|
+
cardsFrom === CardLocation.templatesOnly) {
|
|
373
|
+
const templates = await this.templates();
|
|
374
|
+
for (const template of templates) {
|
|
375
|
+
const templateObject = new TemplateResource(this, resourceName(template.name)).templateObject();
|
|
376
|
+
if (templateObject) {
|
|
377
|
+
// todo: optimization - do all this in parallel
|
|
378
|
+
const templateCards = await templateObject.listCards();
|
|
379
|
+
if (templateCards) {
|
|
380
|
+
cardListContainer.push({
|
|
381
|
+
name: template.name,
|
|
382
|
+
type: 'template',
|
|
383
|
+
cards: templateCards.map((item) => item.key),
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return cardListContainer;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Return cardIDs of the cards in the project or from templates, or both.
|
|
393
|
+
* @param includeCardsFrom Where to return cards from (project, templates, or both)
|
|
394
|
+
* @returns Array of cardIDs.
|
|
395
|
+
* @note that cardIDs are not sorted.
|
|
396
|
+
*/
|
|
397
|
+
async listCardIds(cardsFrom = CardLocation.all) {
|
|
398
|
+
const promises = [];
|
|
399
|
+
if (cardsFrom === CardLocation.all ||
|
|
400
|
+
cardsFrom === CardLocation.projectOnly) {
|
|
401
|
+
promises.push(super
|
|
402
|
+
.cards(this.paths.cardRootFolder)
|
|
403
|
+
.then((cards) => new Set(cards.map((card) => card.key))));
|
|
404
|
+
}
|
|
405
|
+
if (cardsFrom === CardLocation.all ||
|
|
406
|
+
cardsFrom === CardLocation.templatesOnly) {
|
|
407
|
+
promises.push(this.templates().then((templates) => Promise.allSettled(templates.map((template) => new TemplateResource(this, resourceName(template.name))))
|
|
408
|
+
.then((results) => results
|
|
409
|
+
.filter((result) => result.status === 'fulfilled' && result.value !== null)
|
|
410
|
+
.map((result) => result.value))
|
|
411
|
+
.then((templateObjects) => Promise.allSettled(templateObjects.map((obj) => obj.templateObject().listCards())))
|
|
412
|
+
.then((results) => {
|
|
413
|
+
const templateCardIds = new Set();
|
|
414
|
+
results
|
|
415
|
+
.filter((result) => result.status === 'fulfilled')
|
|
416
|
+
.forEach((result) => {
|
|
417
|
+
result.value.forEach((card) => templateCardIds.add(card.key));
|
|
418
|
+
});
|
|
419
|
+
return templateCardIds;
|
|
420
|
+
})));
|
|
421
|
+
}
|
|
422
|
+
const allCardIdSets = await Promise.all(promises);
|
|
423
|
+
return new Set(allCardIdSets.flatMap((set) => [...set]));
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Returns details of a certain module.
|
|
427
|
+
* @param moduleName Name of the module.
|
|
428
|
+
* @returns module details, or undefined if workflow cannot be found.
|
|
429
|
+
*/
|
|
430
|
+
async module(moduleName) {
|
|
431
|
+
const module = await this.findModule(moduleName);
|
|
432
|
+
if (module && module.path) {
|
|
433
|
+
const modulePath = join(module.path, module.name);
|
|
434
|
+
const moduleConfig = (await readJsonFile(join(modulePath, Project.projectConfigFileName)));
|
|
435
|
+
return {
|
|
436
|
+
name: moduleConfig.name,
|
|
437
|
+
modules: moduleConfig.modules,
|
|
438
|
+
path: modulePath,
|
|
439
|
+
cardKeyPrefix: moduleConfig.cardKeyPrefix,
|
|
440
|
+
calculations: [
|
|
441
|
+
...(await this.resources.collectResourcesFromModules('calculations')),
|
|
442
|
+
],
|
|
443
|
+
cardTypes: [
|
|
444
|
+
...(await this.resources.collectResourcesFromModules('cardTypes')),
|
|
445
|
+
],
|
|
446
|
+
fieldTypes: [
|
|
447
|
+
...(await this.resources.collectResourcesFromModules('fieldTypes')),
|
|
448
|
+
],
|
|
449
|
+
graphModels: [
|
|
450
|
+
...(await this.resources.collectResourcesFromModules('graphModels')),
|
|
451
|
+
],
|
|
452
|
+
graphViews: [
|
|
453
|
+
...(await this.resources.collectResourcesFromModules('graphViews')),
|
|
454
|
+
],
|
|
455
|
+
linkTypes: [
|
|
456
|
+
...(await this.resources.collectResourcesFromModules('linkTypes')),
|
|
457
|
+
],
|
|
458
|
+
reports: [
|
|
459
|
+
...(await this.resources.collectResourcesFromModules('reports')),
|
|
460
|
+
],
|
|
461
|
+
templates: [
|
|
462
|
+
...(await this.resources.collectResourcesFromModules('templates')),
|
|
463
|
+
],
|
|
464
|
+
workflows: [
|
|
465
|
+
...(await this.resources.collectResourcesFromModules('workflows')),
|
|
466
|
+
],
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
return undefined;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Returns list of modules in the project.
|
|
473
|
+
* @returns list of modules in the project.
|
|
474
|
+
*/
|
|
475
|
+
async modules() {
|
|
476
|
+
return this.resources.resources('modules');
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Returns a new unique card key with project prefix (e.g. test_x649it4x).
|
|
480
|
+
* Random part of string will be always 8 characters in base-36 (0-9a-z)
|
|
481
|
+
* @returns a new card key string
|
|
482
|
+
* @throws if a unique key could not be created within set number of attempts
|
|
483
|
+
*/
|
|
484
|
+
newCardKey(cardIds) {
|
|
485
|
+
const maxAttempts = 10;
|
|
486
|
+
const base = 36;
|
|
487
|
+
const length = 8;
|
|
488
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
489
|
+
// Create a key and check that there are no collisions with other keys in project
|
|
490
|
+
const newKey = `${this.settings.cardKeyPrefix}_${generateRandomString(base, length)}`;
|
|
491
|
+
if (cardIds.has(newKey)) {
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
cardIds.add(newKey);
|
|
496
|
+
}
|
|
497
|
+
return newKey;
|
|
498
|
+
}
|
|
499
|
+
throw 'Could not generate unique card key';
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Returns an array of new unique card keys with project prefix (e.g. test_x649it4x).
|
|
503
|
+
* Random part of string will be always 8 characters in base-36 (0-9a-z)
|
|
504
|
+
* @returns an array of new card key strings
|
|
505
|
+
* @throws if a unique key could not be created within set number of attempts
|
|
506
|
+
*/
|
|
507
|
+
newCardKeys(keysToCreate, cardIds) {
|
|
508
|
+
if (keysToCreate < 1) {
|
|
509
|
+
return [];
|
|
510
|
+
}
|
|
511
|
+
const createdKeys = [];
|
|
512
|
+
const base = 36;
|
|
513
|
+
const length = 8;
|
|
514
|
+
let maxAttempts = 10 * keysToCreate;
|
|
515
|
+
while (true) {
|
|
516
|
+
if (maxAttempts <= 0) {
|
|
517
|
+
throw new Error('Could not generate unique card key');
|
|
518
|
+
}
|
|
519
|
+
const newKey = `${this.settings.cardKeyPrefix}_${generateRandomString(base, length)}`;
|
|
520
|
+
if (cardIds.has(newKey)) {
|
|
521
|
+
--maxAttempts;
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
cardIds.add(newKey);
|
|
526
|
+
createdKeys.push(newKey);
|
|
527
|
+
}
|
|
528
|
+
if (createdKeys.length >= keysToCreate) {
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
return createdKeys;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Getter. Returns a class that handles the project's paths.
|
|
536
|
+
*/
|
|
537
|
+
get paths() {
|
|
538
|
+
return this.projectPaths;
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Returns full path to a given card.
|
|
542
|
+
* @param cardKey card to check path for.
|
|
543
|
+
* @returns path to a given card.
|
|
544
|
+
*/
|
|
545
|
+
pathToCard(cardKey) {
|
|
546
|
+
const allFiles = getFilesSync(this.paths.cardRootFolder);
|
|
547
|
+
const cardIndexJsonFile = join(cardKey, Project.cardMetadataFile);
|
|
548
|
+
const foundFile = allFiles.find((file) => file.includes(cardIndexJsonFile));
|
|
549
|
+
return foundFile ? dirname(foundFile) : '';
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Getter. Returns project name.
|
|
553
|
+
*/
|
|
554
|
+
get projectName() {
|
|
555
|
+
return this.settings.name;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Getter. Returns project prefix.
|
|
559
|
+
*/
|
|
560
|
+
get projectPrefix() {
|
|
561
|
+
return this.settings.cardKeyPrefix;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Collects all prefixes used in the project (project's own plus all from modules).
|
|
565
|
+
* @returns all prefixes used in the project.
|
|
566
|
+
* @todo - move the module prefix fetch to resource-collector.
|
|
567
|
+
* Make it use cached value that is only changed when module is removed/imported.
|
|
568
|
+
*/
|
|
569
|
+
async projectPrefixes() {
|
|
570
|
+
const prefixes = [this.projectPrefix];
|
|
571
|
+
let files;
|
|
572
|
+
try {
|
|
573
|
+
files = await readdir(this.paths.modulesFolder, {
|
|
574
|
+
withFileTypes: true,
|
|
575
|
+
recursive: true,
|
|
576
|
+
});
|
|
577
|
+
const configurationFiles = files
|
|
578
|
+
.filter((dirent) => dirent.isFile())
|
|
579
|
+
.filter((dirent) => dirent.name === Project.projectConfigFileName);
|
|
580
|
+
const configurationPromises = configurationFiles.map(async (file) => {
|
|
581
|
+
const configuration = (await readJsonFile(join(file.parentPath, file.name)));
|
|
582
|
+
return configuration.cardKeyPrefix;
|
|
583
|
+
});
|
|
584
|
+
const configurationPrefixes = await Promise.all(configurationPromises);
|
|
585
|
+
prefixes.push(...configurationPrefixes);
|
|
586
|
+
}
|
|
587
|
+
catch {
|
|
588
|
+
// do nothing if readdir throws
|
|
589
|
+
}
|
|
590
|
+
return prefixes;
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Removes a module from project.
|
|
594
|
+
* @param moduleName Name of the module
|
|
595
|
+
*/
|
|
596
|
+
async removeModule(moduleName) {
|
|
597
|
+
await this.configuration.removeModule(moduleName);
|
|
598
|
+
await this.collectModuleResources();
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Array of reports in the project.
|
|
602
|
+
* @param from Defines where resources are collected from.
|
|
603
|
+
* @returns array of all reports in the project.
|
|
604
|
+
*/
|
|
605
|
+
async reports(from = ResourcesFrom.all) {
|
|
606
|
+
return this.resources.resources('reports', from);
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Returns handlebar files from reports.
|
|
610
|
+
* @param from Defines where report handlebar files are collected from.
|
|
611
|
+
* @returns handlebar files from reports.
|
|
612
|
+
*/
|
|
613
|
+
async reportHandlerBarFiles(from = ResourcesFrom.all) {
|
|
614
|
+
const reports = await this.reports(from);
|
|
615
|
+
const handleBarFiles = [];
|
|
616
|
+
for (const reportResourceName of reports) {
|
|
617
|
+
const name = resourceName(reportResourceName.name);
|
|
618
|
+
const report = new ReportResource(this, name);
|
|
619
|
+
handleBarFiles.push(...(await report.handleBarFiles()));
|
|
620
|
+
}
|
|
621
|
+
return handleBarFiles;
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Removes a resource from Project.
|
|
625
|
+
* @param resource Resource to remove.
|
|
626
|
+
*/
|
|
627
|
+
removeResource(resource) {
|
|
628
|
+
this.resources.remove(resource);
|
|
629
|
+
this.createdResources.delete(resource.name);
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Returns metadata from a given resource
|
|
633
|
+
* @param name Name of a resource
|
|
634
|
+
* @returns Metadata from the resource.
|
|
635
|
+
*/
|
|
636
|
+
async resource(name) {
|
|
637
|
+
const resName = resourceName(name);
|
|
638
|
+
if (this.createdResources.has(resourceNameToString(resName))) {
|
|
639
|
+
const value = this.createdResources.get(resourceNameToString(resName));
|
|
640
|
+
return value;
|
|
641
|
+
}
|
|
642
|
+
let resource = undefined;
|
|
643
|
+
try {
|
|
644
|
+
resource = Project.resourceObject(this, resName);
|
|
645
|
+
}
|
|
646
|
+
catch {
|
|
647
|
+
return undefined;
|
|
648
|
+
}
|
|
649
|
+
const data = resource?.data;
|
|
650
|
+
if (!data) {
|
|
651
|
+
return undefined;
|
|
652
|
+
}
|
|
653
|
+
return data;
|
|
654
|
+
}
|
|
655
|
+
get resourceCache() {
|
|
656
|
+
return this.createdResources;
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Checks if a given resource exists in the project already.
|
|
660
|
+
* @param resourceType Type of resource as a string.
|
|
661
|
+
* @param name Valid name of resource.
|
|
662
|
+
* @returns boolean, true if resource exists; false otherwise.
|
|
663
|
+
*/
|
|
664
|
+
async resourceExists(resourceType, name) {
|
|
665
|
+
const resources = await this.resourcesOfType(resourceType, ResourcesFrom.all);
|
|
666
|
+
const resource = resources.find((item) => item.name === name);
|
|
667
|
+
return resource !== undefined;
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Instantiates resource object from project with a resource name.
|
|
671
|
+
* @note that this is memory based object only.
|
|
672
|
+
* To manipulate the resource (create files, delete files etc), use the resource object's API.
|
|
673
|
+
* @param project Project from which resources are created from.
|
|
674
|
+
* @param name Resource name
|
|
675
|
+
* @throws if called with unsupported resource type.
|
|
676
|
+
* @returns Created resource.
|
|
677
|
+
*/
|
|
678
|
+
static resourceObject(project, name) {
|
|
679
|
+
if (name.type === 'cardTypes') {
|
|
680
|
+
return new CardTypeResource(project, name);
|
|
681
|
+
}
|
|
682
|
+
else if (name.type === 'fieldTypes') {
|
|
683
|
+
return new FieldTypeResource(project, name);
|
|
684
|
+
}
|
|
685
|
+
else if (name.type === 'graphModels') {
|
|
686
|
+
return new GraphModelResource(project, name);
|
|
687
|
+
}
|
|
688
|
+
else if (name.type === 'graphViews') {
|
|
689
|
+
return new GraphViewResource(project, name);
|
|
690
|
+
}
|
|
691
|
+
else if (name.type === 'linkTypes') {
|
|
692
|
+
return new LinkTypeResource(project, name);
|
|
693
|
+
}
|
|
694
|
+
else if (name.type === 'reports') {
|
|
695
|
+
return new ReportResource(project, name);
|
|
696
|
+
}
|
|
697
|
+
else if (name.type === 'templates') {
|
|
698
|
+
return new TemplateResource(project, name);
|
|
699
|
+
}
|
|
700
|
+
else if (name.type === 'workflows') {
|
|
701
|
+
return new WorkflowResource(project, name);
|
|
702
|
+
}
|
|
703
|
+
throw new Error(`Unsupported resource type '${resourceNameToString(name)}'`);
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Shows details of a project.
|
|
707
|
+
* @returns details of a project.
|
|
708
|
+
*/
|
|
709
|
+
async show() {
|
|
710
|
+
return {
|
|
711
|
+
name: this.containerName,
|
|
712
|
+
path: this.basePath,
|
|
713
|
+
prefix: this.projectPrefix,
|
|
714
|
+
modules: (await this.modules()).map((item) => item.name),
|
|
715
|
+
numberOfCards: (await this.listCards(CardLocation.projectOnly))[0].cards
|
|
716
|
+
.length,
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Show cards of a project.
|
|
721
|
+
* @returns an array of all project cards in the project.
|
|
722
|
+
*/
|
|
723
|
+
async showProjectCards() {
|
|
724
|
+
const cards = [];
|
|
725
|
+
const cardPathMap = new Map();
|
|
726
|
+
const entries = await readdir(this.paths.cardRootFolder, {
|
|
727
|
+
withFileTypes: true,
|
|
728
|
+
recursive: true,
|
|
729
|
+
});
|
|
730
|
+
// Checks if Dirent folder is a card folder
|
|
731
|
+
function cardFolder(entry, cardPathMap) {
|
|
732
|
+
const fullPath = join(entry.parentPath, entry.name);
|
|
733
|
+
if (!cardPathMap.has(fullPath)) {
|
|
734
|
+
const newCard = {
|
|
735
|
+
key: entry.name,
|
|
736
|
+
path: fullPath,
|
|
737
|
+
children: [],
|
|
738
|
+
attachments: [],
|
|
739
|
+
};
|
|
740
|
+
cardPathMap.set(fullPath, newCard);
|
|
741
|
+
return newCard;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
// Process card directories first
|
|
745
|
+
entries
|
|
746
|
+
.filter((entry) => entry.isDirectory() && CardNameRegEx.test(entry.name))
|
|
747
|
+
.forEach((entry) => {
|
|
748
|
+
const card = cardFolder(entry, cardPathMap);
|
|
749
|
+
if (card)
|
|
750
|
+
cards.push(card);
|
|
751
|
+
});
|
|
752
|
+
// Process metadata files in parallel
|
|
753
|
+
await Promise.all(entries
|
|
754
|
+
.filter((entry) => entry.isFile() && entry.name === Project.cardMetadataFile)
|
|
755
|
+
.map(async (entry) => {
|
|
756
|
+
const parentCard = cardPathMap.get(entry.parentPath);
|
|
757
|
+
if (!parentCard)
|
|
758
|
+
return;
|
|
759
|
+
parentCard.metadata = (await readJsonFile(join(entry.parentPath, entry.name)));
|
|
760
|
+
}));
|
|
761
|
+
// Finally, build the card hierarchy
|
|
762
|
+
Array.from(cardPathMap.entries()).map(([cardPath, card]) => {
|
|
763
|
+
const parentPath = findParentPath(cardPath);
|
|
764
|
+
if (!parentPath)
|
|
765
|
+
return;
|
|
766
|
+
const parentCard = cardPathMap.get(parentPath);
|
|
767
|
+
if (!parentCard)
|
|
768
|
+
return;
|
|
769
|
+
parentCard.children.push(card);
|
|
770
|
+
const index = cards.indexOf(card);
|
|
771
|
+
if (index > -1) {
|
|
772
|
+
cards.splice(index, 1);
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
return cards;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Returns all template cards from the project. This includes all module templates' cards.
|
|
779
|
+
* @param cardDetails which details to fetch. Optional.
|
|
780
|
+
* @returns all the template cards from the project
|
|
781
|
+
*/
|
|
782
|
+
async allTemplateCards(cardDetails) {
|
|
783
|
+
const templates = await this.templates();
|
|
784
|
+
const cards = [];
|
|
785
|
+
for (const template of templates) {
|
|
786
|
+
const templateCards = await this.templateCards(template.name, cardDetails);
|
|
787
|
+
if (templateCards)
|
|
788
|
+
cards.push(...templateCards);
|
|
789
|
+
}
|
|
790
|
+
return cards;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Returns cards from single template.
|
|
794
|
+
* @param templateName Name of the template
|
|
795
|
+
* @param cardDetails Card information
|
|
796
|
+
* @returns List of cards from template.
|
|
797
|
+
*/
|
|
798
|
+
async templateCards(templateName, cardDetails) {
|
|
799
|
+
const templateObject = new TemplateResource(this, resourceName(templateName)).templateObject();
|
|
800
|
+
return await templateObject?.cards('', cardDetails);
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Array of templates in the project.
|
|
804
|
+
* @param from Defines where resources are collected from.
|
|
805
|
+
* @returns array of all templates in the project.
|
|
806
|
+
*/
|
|
807
|
+
async templates(from = ResourcesFrom.all) {
|
|
808
|
+
return this.resources.resources('templates', from);
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Update card content.
|
|
812
|
+
* @param cardKey card's ID that is updated.
|
|
813
|
+
* @param content changed content
|
|
814
|
+
*/
|
|
815
|
+
async updateCardContent(cardKey, content) {
|
|
816
|
+
const card = await this.findCard(this.basePath, cardKey, {
|
|
817
|
+
metadata: true,
|
|
818
|
+
content: true,
|
|
819
|
+
});
|
|
820
|
+
if (!card) {
|
|
821
|
+
throw new Error(`Card '${cardKey}' does not exist in the project`);
|
|
822
|
+
}
|
|
823
|
+
card.content = content;
|
|
824
|
+
await this.saveCard(card);
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Updates card metadata's single key.
|
|
828
|
+
* @param cardKey card that is updated.
|
|
829
|
+
* @param changedKey changed metadata key
|
|
830
|
+
* @param newValue changed value for the key
|
|
831
|
+
*/
|
|
832
|
+
async updateCardMetadataKey(cardKey, changedKey, newValue) {
|
|
833
|
+
const templateCard = await this.isTemplateCard(cardKey);
|
|
834
|
+
const card = await this.findCard(templateCard ? this.paths.templatesFolder : this.paths.cardRootFolder, cardKey, {
|
|
835
|
+
metadata: true,
|
|
836
|
+
});
|
|
837
|
+
if (!card) {
|
|
838
|
+
throw new Error(`Card '${cardKey}' does not exist in the project`);
|
|
839
|
+
}
|
|
840
|
+
if (!card.metadata || card.metadata[changedKey] === newValue) {
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
const cardAsRecord = card.metadata;
|
|
844
|
+
cardAsRecord[changedKey] = newValue;
|
|
845
|
+
const invalidCard = isTemplateCard(card)
|
|
846
|
+
? ''
|
|
847
|
+
: await this.validateCard(card);
|
|
848
|
+
if (invalidCard.length !== 0) {
|
|
849
|
+
throw new Error(invalidCard);
|
|
850
|
+
}
|
|
851
|
+
await this.saveCardMetadata(card);
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Updates card metadata.
|
|
855
|
+
* @param card affected card
|
|
856
|
+
* @param changedMetadata changed content for the card
|
|
857
|
+
*/
|
|
858
|
+
async updateCardMetadata(card, changedMetadata) {
|
|
859
|
+
card.metadata = changedMetadata;
|
|
860
|
+
return this.saveCardMetadata(card);
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Validates that card's data is valid.
|
|
864
|
+
* @param card Card to validate.
|
|
865
|
+
*/
|
|
866
|
+
async validateCard(card) {
|
|
867
|
+
const invalidCustomData = await this.validator.validateCustomFields(this, card);
|
|
868
|
+
const invalidWorkFlow = await this.validator.validateWorkflowState(this, card);
|
|
869
|
+
const invalidLabels = await this.validator.validateCardLabels(card);
|
|
870
|
+
if (invalidCustomData.length === 0 &&
|
|
871
|
+
invalidWorkFlow.length === 0 &&
|
|
872
|
+
invalidLabels.length === 0) {
|
|
873
|
+
return '';
|
|
874
|
+
}
|
|
875
|
+
const errors = [];
|
|
876
|
+
if (invalidCustomData.length > 0) {
|
|
877
|
+
errors.push(invalidCustomData);
|
|
878
|
+
}
|
|
879
|
+
if (invalidWorkFlow.length > 0) {
|
|
880
|
+
errors.push(invalidWorkFlow);
|
|
881
|
+
}
|
|
882
|
+
if (invalidLabels.length > 0) {
|
|
883
|
+
errors.push(invalidLabels);
|
|
884
|
+
}
|
|
885
|
+
return errors.join('\n');
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Array of workflows in the project.
|
|
889
|
+
* @param from Defines where resources are collected from.
|
|
890
|
+
* @returns array of all workflows in the project.
|
|
891
|
+
*/
|
|
892
|
+
async workflows(from = ResourcesFrom.all) {
|
|
893
|
+
return this.resources.resources('workflows', from);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
//# sourceMappingURL=project.js.map
|