@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
|
@@ -18,12 +18,13 @@ import {
|
|
|
18
18
|
constants as fsConstants,
|
|
19
19
|
copyFile,
|
|
20
20
|
mkdir,
|
|
21
|
-
readdir,
|
|
22
21
|
unlink,
|
|
23
22
|
writeFile,
|
|
24
23
|
} from 'node:fs/promises';
|
|
24
|
+
import { readdirSync } from 'node:fs';
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
// base class
|
|
27
|
+
import { CardContainer } from './card-container.js';
|
|
27
28
|
|
|
28
29
|
import { CalculationEngine } from './project/calculation-engine.js';
|
|
29
30
|
import {
|
|
@@ -38,9 +39,6 @@ import {
|
|
|
38
39
|
type ModuleSetting,
|
|
39
40
|
type ProjectFetchCardDetails,
|
|
40
41
|
type ProjectMetadata,
|
|
41
|
-
type ProjectSettings,
|
|
42
|
-
type Resource,
|
|
43
|
-
type ResourceFolderType,
|
|
44
42
|
} from '../interfaces/project-interfaces.js';
|
|
45
43
|
import { pathExists } from '../utils/file-utils.js';
|
|
46
44
|
import { generateRandomString } from '../utils/random.js';
|
|
@@ -52,107 +50,90 @@ import {
|
|
|
52
50
|
import { ProjectConfiguration } from '../project-settings.js';
|
|
53
51
|
import { ProjectPaths } from './project/project-paths.js';
|
|
54
52
|
import { readJsonFile } from '../utils/json.js';
|
|
55
|
-
import {
|
|
56
|
-
|
|
57
|
-
resourceName,
|
|
58
|
-
type ResourceName,
|
|
59
|
-
resourceNameToString,
|
|
60
|
-
} from '../utils/resource-utils.js';
|
|
61
|
-
import {
|
|
62
|
-
ResourcesFrom,
|
|
63
|
-
ResourceCollector,
|
|
64
|
-
} from './project/resource-collector.js';
|
|
65
|
-
import type { Template } from './template.js';
|
|
53
|
+
import { ResourcesFrom } from './project/resource-cache.js';
|
|
54
|
+
import { ResourceHandler } from './project/resource-handler.js';
|
|
66
55
|
import { Validate } from '../commands/validate.js';
|
|
67
|
-
|
|
68
|
-
import { CalculationResource } from '../resources/calculation-resource.js';
|
|
69
|
-
import { CardTypeResource } from '../resources/card-type-resource.js';
|
|
70
|
-
import { FieldTypeResource } from '../resources/field-type-resource.js';
|
|
71
|
-
import { GraphModelResource } from '../resources/graph-model-resource.js';
|
|
72
|
-
import { GraphViewResource } from '../resources/graph-view-resource.js';
|
|
73
|
-
import { LinkTypeResource } from '../resources/link-type-resource.js';
|
|
74
|
-
import { ReportResource } from '../resources/report-resource.js';
|
|
75
|
-
import { TemplateResource } from '../resources/template-resource.js';
|
|
76
|
-
import { WorkflowResource } from '../resources/workflow-resource.js';
|
|
77
|
-
|
|
78
56
|
import { ContentWatcher } from './project/project-content-watcher.js';
|
|
79
57
|
import { getChildLogger } from '../utils/log-utils.js';
|
|
80
58
|
|
|
59
|
+
import type { Template } from './template.js';
|
|
60
|
+
|
|
81
61
|
import { ROOT } from '../utils/constants.js';
|
|
82
62
|
|
|
63
|
+
import {
|
|
64
|
+
ConfigurationLogger,
|
|
65
|
+
ConfigurationOperation,
|
|
66
|
+
} from '../utils/configuration-logger.js';
|
|
67
|
+
|
|
83
68
|
// Re-export this, so that classes that use Project do not need to have separate import.
|
|
84
69
|
export { ResourcesFrom };
|
|
85
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Options for Project initialization.
|
|
73
|
+
* autoSave - If project configuration changes are saved automatically. Default true.
|
|
74
|
+
* watchResourceChanges - If project refresh automatically to filesystem changes. Default false.
|
|
75
|
+
*/
|
|
76
|
+
export interface ProjectOptions {
|
|
77
|
+
autoSave?: boolean;
|
|
78
|
+
watchResourceChanges?: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
86
81
|
/**
|
|
87
82
|
* Represents project folder.
|
|
88
83
|
*/
|
|
89
84
|
export class Project extends CardContainer {
|
|
90
85
|
public calculationEngine: CalculationEngine;
|
|
91
|
-
// Created resources are held in a cache.
|
|
92
|
-
// In the cache, key is resource name, and data is resource metadata (as JSON).
|
|
93
|
-
private createdResources = new Map<string, JSON>();
|
|
94
86
|
private logger = getChildLogger({ module: 'Project' });
|
|
95
87
|
private projectPaths: ProjectPaths;
|
|
96
|
-
private
|
|
88
|
+
private resourceHandler: ResourceHandler;
|
|
97
89
|
private resourceWatcher: ContentWatcher | undefined;
|
|
98
90
|
private settings: ProjectConfiguration;
|
|
99
91
|
private validator: Validate;
|
|
92
|
+
private cachedAllModulePrefixes: string[] = [];
|
|
100
93
|
|
|
101
94
|
constructor(
|
|
102
95
|
path: string,
|
|
103
|
-
private
|
|
96
|
+
private options: ProjectOptions = {
|
|
97
|
+
autoSave: true,
|
|
98
|
+
watchResourceChanges: false,
|
|
99
|
+
},
|
|
104
100
|
) {
|
|
105
101
|
const settings = new ProjectConfiguration(
|
|
106
102
|
join(path, '.cards', 'local', Project.projectConfigFileName),
|
|
103
|
+
options.autoSave ?? true,
|
|
107
104
|
);
|
|
108
|
-
super(path, settings.cardKeyPrefix
|
|
105
|
+
super(path, settings.cardKeyPrefix);
|
|
109
106
|
this.settings = settings;
|
|
110
107
|
|
|
111
108
|
this.logger.info({ path }, 'Initializing project');
|
|
112
109
|
|
|
113
110
|
this.calculationEngine = new CalculationEngine(this);
|
|
114
111
|
this.projectPaths = new ProjectPaths(path);
|
|
115
|
-
this.
|
|
116
|
-
|
|
117
|
-
this.containerName = this.settings.name;
|
|
112
|
+
this.resourceHandler = new ResourceHandler(this);
|
|
118
113
|
// todo: implement project validation
|
|
119
114
|
this.validator = Validate.getInstance();
|
|
115
|
+
|
|
120
116
|
this.logger.info(
|
|
121
|
-
{
|
|
122
|
-
'Collecting local resources',
|
|
123
|
-
);
|
|
124
|
-
this.resources.collectLocalResources();
|
|
125
|
-
this.logger.info(
|
|
126
|
-
{ name: this.containerName },
|
|
117
|
+
{ name: this.settings.name },
|
|
127
118
|
'Project initialization complete',
|
|
128
119
|
);
|
|
129
120
|
|
|
121
|
+
this.refreshAllModulePrefixes();
|
|
122
|
+
|
|
130
123
|
const ignoreRenameFileChanges = true;
|
|
131
124
|
|
|
132
125
|
// Watch changes in .cards if there are multiple instances of Project being
|
|
133
126
|
// run concurrently.
|
|
134
|
-
if (this.watchResourceChanges) {
|
|
127
|
+
if (this.options.watchResourceChanges) {
|
|
135
128
|
this.resourceWatcher = new ContentWatcher(
|
|
136
129
|
ignoreRenameFileChanges,
|
|
137
130
|
this.paths.resourcesFolder,
|
|
138
131
|
(fileName: string) => {
|
|
139
132
|
void (async () => {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
join(this.paths.resourcesFolder, fileName),
|
|
145
|
-
);
|
|
146
|
-
if (!resource) {
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
} catch {
|
|
150
|
-
// it wasn't a resource that changed, so ignore the change
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
const resourceName = `${resource.prefix}/${resource.type}/${resource.identifier}`;
|
|
154
|
-
await this.replaceCacheValue(resourceName);
|
|
155
|
-
this.resources.collectLocalResources();
|
|
133
|
+
this.resources.handleFileSystemChange(
|
|
134
|
+
join(this.paths.resourcesFolder, fileName),
|
|
135
|
+
);
|
|
136
|
+
this.resources.changed();
|
|
156
137
|
})();
|
|
157
138
|
},
|
|
158
139
|
);
|
|
@@ -171,10 +152,26 @@ export class Project extends CardContainer {
|
|
|
171
152
|
}
|
|
172
153
|
|
|
173
154
|
// Finds specific module.
|
|
174
|
-
private async findModule(
|
|
175
|
-
|
|
176
|
-
|
|
155
|
+
private async findModule(
|
|
156
|
+
moduleName: string,
|
|
157
|
+
): Promise<{ name: string; path: string } | undefined> {
|
|
158
|
+
const moduleExists = this.resources.moduleNames().includes(moduleName);
|
|
159
|
+
if (!moduleExists) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// For modules, we need to construct the local path where the module is stored
|
|
164
|
+
const moduleConfig = this.configuration.modules?.find(
|
|
165
|
+
(module) => module.name === moduleName,
|
|
177
166
|
);
|
|
167
|
+
if (!moduleConfig) {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
name: moduleName,
|
|
173
|
+
path: join(this.paths.modulesFolder, moduleConfig.name),
|
|
174
|
+
};
|
|
178
175
|
}
|
|
179
176
|
|
|
180
177
|
// Handles attachment changes after filesystem operations.
|
|
@@ -196,6 +193,7 @@ export class Project extends CardContainer {
|
|
|
196
193
|
}
|
|
197
194
|
|
|
198
195
|
// Determines the parent card key from a card's filesystem path.
|
|
196
|
+
// todo: could be moved to card-utils
|
|
199
197
|
private parentFromPath(cardPath: string): string {
|
|
200
198
|
return cardPathParts(this.projectPrefix, cardPath).parents.at(-1) || 'root';
|
|
201
199
|
}
|
|
@@ -211,28 +209,6 @@ export class Project extends CardContainer {
|
|
|
211
209
|
}
|
|
212
210
|
}
|
|
213
211
|
|
|
214
|
-
// Removes current version of a resource from the resource cache.
|
|
215
|
-
// Then re-creates the resource with current data and caches the value again.
|
|
216
|
-
// If the value wasn't in the cache before, it will be added.
|
|
217
|
-
private async replaceCacheValue(resourceName: string) {
|
|
218
|
-
if (this.createdResources.has(resourceName)) {
|
|
219
|
-
// First, remove the old version from cache
|
|
220
|
-
this.createdResources.delete(resourceName);
|
|
221
|
-
}
|
|
222
|
-
const resourceData = await this.resource(resourceName);
|
|
223
|
-
if (resourceData) {
|
|
224
|
-
this.createdResources.set(resourceName, resourceData as JSON);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Returns (local or all) resources of a given type.
|
|
229
|
-
private async resourcesOfType(
|
|
230
|
-
type: ResourceFolderType,
|
|
231
|
-
from: ResourcesFrom = ResourcesFrom.localOnly,
|
|
232
|
-
): Promise<Resource[]> {
|
|
233
|
-
return this.resources.resources(type, from);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
212
|
// Updates children in the card cache
|
|
237
213
|
private updateCachedChildren(parentKey: string, newChild: Card) {
|
|
238
214
|
const parentCard = this.cardCache.getCard(parentKey);
|
|
@@ -248,35 +224,84 @@ export class Project extends CardContainer {
|
|
|
248
224
|
}
|
|
249
225
|
}
|
|
250
226
|
|
|
227
|
+
// Refreshes the cached list of all module prefixes.
|
|
228
|
+
// This includes both direct and transient module dependencies.
|
|
229
|
+
private refreshAllModulePrefixes(): void {
|
|
230
|
+
const prefixes: string[] = [this.projectPrefix];
|
|
231
|
+
|
|
232
|
+
try {
|
|
233
|
+
const modules = readdirSync(this.paths.modulesFolder, {
|
|
234
|
+
withFileTypes: true,
|
|
235
|
+
})
|
|
236
|
+
.filter((item) => item.isDirectory())
|
|
237
|
+
.map((item) => item.name);
|
|
238
|
+
|
|
239
|
+
prefixes.push(...modules);
|
|
240
|
+
} catch {
|
|
241
|
+
// If modules folder doesn't exist, fall back to configuration modules only
|
|
242
|
+
const moduleNames = this.configuration.modules.map((item) => item.name);
|
|
243
|
+
prefixes.push(...moduleNames);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
this.cachedAllModulePrefixes = prefixes;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Validates that card's data is valid.
|
|
250
|
+
private async validateCard(card: Card): Promise<string> {
|
|
251
|
+
const invalidCustomData = await this.validator.validateCustomFields(
|
|
252
|
+
this,
|
|
253
|
+
card,
|
|
254
|
+
this.allModulePrefixes(),
|
|
255
|
+
);
|
|
256
|
+
const invalidWorkFlow = await this.validator.validateWorkflowState(
|
|
257
|
+
this,
|
|
258
|
+
card,
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
const invalidLabels = this.validator.validateCardLabels(card);
|
|
262
|
+
if (
|
|
263
|
+
invalidCustomData.length === 0 &&
|
|
264
|
+
invalidWorkFlow.length === 0 &&
|
|
265
|
+
invalidLabels.length === 0
|
|
266
|
+
) {
|
|
267
|
+
return '';
|
|
268
|
+
}
|
|
269
|
+
const errors: string[] = [];
|
|
270
|
+
if (invalidCustomData.length > 0) {
|
|
271
|
+
errors.push(invalidCustomData);
|
|
272
|
+
}
|
|
273
|
+
if (invalidWorkFlow.length > 0) {
|
|
274
|
+
errors.push(invalidWorkFlow);
|
|
275
|
+
}
|
|
276
|
+
if (invalidLabels.length > 0) {
|
|
277
|
+
errors.push(invalidLabels);
|
|
278
|
+
}
|
|
279
|
+
return errors.join('\n');
|
|
280
|
+
}
|
|
281
|
+
|
|
251
282
|
/**
|
|
252
283
|
* Populate template cards into the card cache.
|
|
253
284
|
*/
|
|
254
285
|
protected async populateTemplateCards(): Promise<void> {
|
|
255
286
|
try {
|
|
256
|
-
|
|
257
|
-
const
|
|
258
|
-
const prefixes = await this.projectPrefixes();
|
|
287
|
+
const templateResources = this.resources.templates();
|
|
288
|
+
const prefixes = this.allModulePrefixes();
|
|
259
289
|
const loadPromises = templateResources.map(async (template) => {
|
|
260
290
|
try {
|
|
261
291
|
this.validator.validResourceName(
|
|
262
292
|
'templates',
|
|
263
|
-
template.name,
|
|
293
|
+
template.data?.name || '',
|
|
264
294
|
prefixes,
|
|
265
295
|
);
|
|
266
296
|
} catch (error) {
|
|
267
297
|
this.logger.warn(
|
|
268
|
-
{ templateName: template
|
|
269
|
-
`Template name '${template
|
|
298
|
+
{ templateName: template, error },
|
|
299
|
+
`Template name '${template}' does not follow required format, skipping`,
|
|
270
300
|
);
|
|
271
301
|
return;
|
|
272
302
|
}
|
|
273
303
|
|
|
274
|
-
const
|
|
275
|
-
this,
|
|
276
|
-
resourceName(template.name),
|
|
277
|
-
);
|
|
278
|
-
|
|
279
|
-
const templateObject = templateResource.templateObject();
|
|
304
|
+
const templateObject = template.templateObject();
|
|
280
305
|
const isCreated = templateObject && templateObject.isCreated();
|
|
281
306
|
if (!templateObject || !isCreated) {
|
|
282
307
|
return;
|
|
@@ -308,16 +333,6 @@ export class Project extends CardContainer {
|
|
|
308
333
|
await this.populateTemplateCards();
|
|
309
334
|
}
|
|
310
335
|
|
|
311
|
-
/**
|
|
312
|
-
* Add a given 'resource' to the local resource arrays.
|
|
313
|
-
* @param resource Resource to add.
|
|
314
|
-
* @param data JSON data for the resource.
|
|
315
|
-
*/
|
|
316
|
-
public addResource(resource: Resource, data: JSON) {
|
|
317
|
-
this.resources.add(resource);
|
|
318
|
-
this.createdResources.set(resource.name, data);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
336
|
/**
|
|
322
337
|
* Returns all template cards from the project. This includes all module templates' cards.
|
|
323
338
|
* @returns all the template cards from the project
|
|
@@ -344,37 +359,6 @@ export class Project extends CardContainer {
|
|
|
344
359
|
return super.attachments(path);
|
|
345
360
|
}
|
|
346
361
|
|
|
347
|
-
/**
|
|
348
|
-
* Returns all the attachments in the template cards.
|
|
349
|
-
* @returns all the attachments in the template cards.
|
|
350
|
-
*/
|
|
351
|
-
public async attachmentsFromTemplates() {
|
|
352
|
-
const templateAttachments: CardAttachment[] = [];
|
|
353
|
-
const templates = await this.templates();
|
|
354
|
-
for (const template of templates) {
|
|
355
|
-
const templateResource = new TemplateResource(
|
|
356
|
-
this,
|
|
357
|
-
resourceName(template.name),
|
|
358
|
-
);
|
|
359
|
-
const templateObject = templateResource.templateObject();
|
|
360
|
-
if (templateObject) {
|
|
361
|
-
templateAttachments.push(...templateObject.attachments());
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
return templateAttachments;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
/**
|
|
368
|
-
* Returns an array of all the calculation files (*.lp) in the project.
|
|
369
|
-
* @param from Defines where resources are collected from.
|
|
370
|
-
* @returns array of all calculation files in the project.
|
|
371
|
-
*/
|
|
372
|
-
public async calculations(
|
|
373
|
-
from: ResourcesFrom = ResourcesFrom.all,
|
|
374
|
-
): Promise<Resource[]> {
|
|
375
|
-
return this.resources.resources('calculations', from);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
362
|
/**
|
|
379
363
|
* Returns path to a card's attachment folder.
|
|
380
364
|
* @param cardKey card key
|
|
@@ -431,34 +415,6 @@ export class Project extends CardContainer {
|
|
|
431
415
|
);
|
|
432
416
|
}
|
|
433
417
|
|
|
434
|
-
/**
|
|
435
|
-
* Removes an attachment from a card.
|
|
436
|
-
* @param cardKey The card to remove attachment from
|
|
437
|
-
* @param fileName The name of the attachment file to remove
|
|
438
|
-
* @throws if trying to remove module card attachment, or the attachment was not found.
|
|
439
|
-
*/
|
|
440
|
-
public async removeCardAttachment(
|
|
441
|
-
cardKey: string,
|
|
442
|
-
fileName: string,
|
|
443
|
-
): Promise<void> {
|
|
444
|
-
const attachmentFolder = this.cardAttachmentFolder(cardKey);
|
|
445
|
-
|
|
446
|
-
// Modules cannot be modified.
|
|
447
|
-
if (isModulePath(attachmentFolder)) {
|
|
448
|
-
throw new Error(`Cannot modify imported module`);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
const attachmentPath = join(attachmentFolder, fileName);
|
|
452
|
-
|
|
453
|
-
try {
|
|
454
|
-
await unlink(attachmentPath);
|
|
455
|
-
} catch (error) {
|
|
456
|
-
this.logger.error({ error }, 'Removing card attachment');
|
|
457
|
-
throw new Error(`Attachment not found: ${fileName}`);
|
|
458
|
-
}
|
|
459
|
-
await this.handleAttachmentChange(cardKey, 'removed', fileName);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
418
|
/**
|
|
463
419
|
* Returns path to a card's folder.
|
|
464
420
|
* @param cardKey card key
|
|
@@ -470,12 +426,9 @@ export class Project extends CardContainer {
|
|
|
470
426
|
return found.path;
|
|
471
427
|
}
|
|
472
428
|
|
|
473
|
-
const templates =
|
|
429
|
+
const templates = this.resources.templates();
|
|
474
430
|
const templatePromises = templates.map((template) => {
|
|
475
|
-
const templateObject =
|
|
476
|
-
this,
|
|
477
|
-
resourceName(template.name),
|
|
478
|
-
).templateObject();
|
|
431
|
+
const templateObject = template.templateObject();
|
|
479
432
|
const templateCard = templateObject
|
|
480
433
|
? templateObject.findCard(cardKey)
|
|
481
434
|
: undefined;
|
|
@@ -503,15 +456,6 @@ export class Project extends CardContainer {
|
|
|
503
456
|
return cards;
|
|
504
457
|
}
|
|
505
458
|
|
|
506
|
-
/**
|
|
507
|
-
* Accessor for cards cache.
|
|
508
|
-
* Used by template container (it needs to access project's cache, not their own instance).
|
|
509
|
-
* @note Should not be used directly (other than Template).
|
|
510
|
-
*/
|
|
511
|
-
public get cardsCache() {
|
|
512
|
-
return this.cardCache;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
459
|
/**
|
|
516
460
|
* Returns an array of all the cards in the project.
|
|
517
461
|
* @note These are project cards only, by default (unless path dictates otherwise).
|
|
@@ -527,14 +471,12 @@ export class Project extends CardContainer {
|
|
|
527
471
|
}
|
|
528
472
|
|
|
529
473
|
/**
|
|
530
|
-
*
|
|
531
|
-
*
|
|
532
|
-
* @
|
|
474
|
+
* Accessor for cards cache.
|
|
475
|
+
* Used by template container (it needs to access project's cache, not their own instance).
|
|
476
|
+
* @note Should not be used directly (other than Template).
|
|
533
477
|
*/
|
|
534
|
-
public
|
|
535
|
-
|
|
536
|
-
): Promise<Resource[]> {
|
|
537
|
-
return this.resources.resources('cardTypes', from);
|
|
478
|
+
public get cardsCache() {
|
|
479
|
+
return this.cardCache;
|
|
538
480
|
}
|
|
539
481
|
|
|
540
482
|
/**
|
|
@@ -553,20 +495,6 @@ export class Project extends CardContainer {
|
|
|
553
495
|
return cards;
|
|
554
496
|
}
|
|
555
497
|
|
|
556
|
-
/**
|
|
557
|
-
* Updates all local resources.
|
|
558
|
-
*/
|
|
559
|
-
public collectLocalResources() {
|
|
560
|
-
this.resources.changed();
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
/**
|
|
564
|
-
* Updates all imported module resources.
|
|
565
|
-
*/
|
|
566
|
-
public collectModuleResources() {
|
|
567
|
-
this.resources.moduleImported();
|
|
568
|
-
}
|
|
569
|
-
|
|
570
498
|
/**
|
|
571
499
|
* Returns project configuration.
|
|
572
500
|
* @returns project configuration.
|
|
@@ -585,7 +513,8 @@ export class Project extends CardContainer {
|
|
|
585
513
|
return undefined;
|
|
586
514
|
}
|
|
587
515
|
const { template } = cardPathParts(this.projectPrefix, card.path);
|
|
588
|
-
|
|
516
|
+
const templateResource = this.resources.byType(template, 'templates');
|
|
517
|
+
return templateResource.templateObject();
|
|
589
518
|
}
|
|
590
519
|
|
|
591
520
|
/**
|
|
@@ -599,14 +528,13 @@ export class Project extends CardContainer {
|
|
|
599
528
|
}
|
|
600
529
|
|
|
601
530
|
/**
|
|
602
|
-
* Returns
|
|
603
|
-
* @param
|
|
604
|
-
* @
|
|
531
|
+
* Returns specific card.
|
|
532
|
+
* @param cardToFind Card key to find
|
|
533
|
+
* @param details Defines which card details are included in the return values.
|
|
534
|
+
* @returns specific card details, or undefined if card is not part of the project.
|
|
605
535
|
*/
|
|
606
|
-
public
|
|
607
|
-
|
|
608
|
-
): Promise<Resource[]> {
|
|
609
|
-
return this.resources.resources('fieldTypes', from);
|
|
536
|
+
public findCard(cardToFind: string, details?: ProjectFetchCardDetails): Card {
|
|
537
|
+
return super.findCard(cardToFind, details);
|
|
610
538
|
}
|
|
611
539
|
|
|
612
540
|
/**
|
|
@@ -628,38 +556,6 @@ export class Project extends CardContainer {
|
|
|
628
556
|
return Project.findProjectRoot(parentPath);
|
|
629
557
|
}
|
|
630
558
|
|
|
631
|
-
/**
|
|
632
|
-
* Returns specific card.
|
|
633
|
-
* @param cardToFind Card key to find
|
|
634
|
-
* @param details Defines which card details are included in the return values.
|
|
635
|
-
* @returns specific card details, or undefined if card is not part of the project.
|
|
636
|
-
*/
|
|
637
|
-
public findCard(cardToFind: string, details?: ProjectFetchCardDetails): Card {
|
|
638
|
-
return super.findCard(cardToFind, details);
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
/**
|
|
642
|
-
* Returns an array of all the graph models in the project.
|
|
643
|
-
* @param from Defines where resources are collected from.
|
|
644
|
-
* @returns array of all the graph models in the project.
|
|
645
|
-
*/
|
|
646
|
-
public async graphModels(
|
|
647
|
-
from: ResourcesFrom = ResourcesFrom.all,
|
|
648
|
-
): Promise<Resource[]> {
|
|
649
|
-
return this.resources.resources('graphModels', from);
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
/**
|
|
653
|
-
* Returns an array of all the graph views in the project.
|
|
654
|
-
* @param from Defines where resources are collected from.
|
|
655
|
-
* @returns array of all the graph views in the project.
|
|
656
|
-
*/
|
|
657
|
-
public async graphViews(
|
|
658
|
-
from: ResourcesFrom = ResourcesFrom.all,
|
|
659
|
-
): Promise<Resource[]> {
|
|
660
|
-
return this.resources.resources('graphViews', from);
|
|
661
|
-
}
|
|
662
|
-
|
|
663
559
|
/**
|
|
664
560
|
* When card changes.
|
|
665
561
|
* @param changedCard Card that was changed.
|
|
@@ -742,12 +638,30 @@ export class Project extends CardContainer {
|
|
|
742
638
|
/**
|
|
743
639
|
* Adds a module from project.
|
|
744
640
|
* @param module Module to add
|
|
641
|
+
* @param skipMigrationLog If true, skip logging to migration log. Used during project creation.
|
|
745
642
|
*/
|
|
746
|
-
public async importModule(module: ModuleSetting) {
|
|
643
|
+
public async importModule(module: ModuleSetting, skipMigrationLog = false) {
|
|
747
644
|
// Add module as a dependency.
|
|
748
645
|
await this.configuration.addModule(module);
|
|
749
|
-
this.
|
|
646
|
+
this.resources.changedModules();
|
|
647
|
+
this.refreshAllModulePrefixes();
|
|
750
648
|
await this.populateTemplateCards();
|
|
649
|
+
|
|
650
|
+
// Log configuration change
|
|
651
|
+
if (!skipMigrationLog) {
|
|
652
|
+
await ConfigurationLogger.log(
|
|
653
|
+
this.basePath,
|
|
654
|
+
ConfigurationOperation.MODULE_ADD,
|
|
655
|
+
module.name,
|
|
656
|
+
{
|
|
657
|
+
parameters: {
|
|
658
|
+
location: module.location,
|
|
659
|
+
branch: module.branch,
|
|
660
|
+
private: module.private,
|
|
661
|
+
},
|
|
662
|
+
},
|
|
663
|
+
);
|
|
664
|
+
}
|
|
751
665
|
this.logger.info(`Imported module '${module.name}'`);
|
|
752
666
|
}
|
|
753
667
|
|
|
@@ -760,17 +674,6 @@ export class Project extends CardContainer {
|
|
|
760
674
|
return pathExists(join(path, 'cardRoot'));
|
|
761
675
|
}
|
|
762
676
|
|
|
763
|
-
/**
|
|
764
|
-
* Returns an array of all the link types in the project.
|
|
765
|
-
* @param from Defines where resources are collected from.
|
|
766
|
-
* @returns array of all link types in the project.
|
|
767
|
-
*/
|
|
768
|
-
public async linkTypes(
|
|
769
|
-
from: ResourcesFrom = ResourcesFrom.all,
|
|
770
|
-
): Promise<Resource[]> {
|
|
771
|
-
return this.resources.resources('linkTypes', from);
|
|
772
|
-
}
|
|
773
|
-
|
|
774
677
|
/**
|
|
775
678
|
* Returns an array of cards in the project, in the templates or both.
|
|
776
679
|
* Cards don't have content and nor metadata.
|
|
@@ -799,18 +702,15 @@ export class Project extends CardContainer {
|
|
|
799
702
|
cardsFrom === CardLocation.all ||
|
|
800
703
|
cardsFrom === CardLocation.templatesOnly
|
|
801
704
|
) {
|
|
802
|
-
const templates =
|
|
705
|
+
const templates = this.resources.templates();
|
|
803
706
|
for (const template of templates) {
|
|
804
|
-
const templateObject =
|
|
805
|
-
this,
|
|
806
|
-
resourceName(template.name),
|
|
807
|
-
).templateObject();
|
|
707
|
+
const templateObject = template.templateObject();
|
|
808
708
|
if (templateObject) {
|
|
809
709
|
// todo: optimization - do all this in parallel
|
|
810
710
|
const templateCards = templateObject.listCards();
|
|
811
711
|
if (templateCards.length) {
|
|
812
712
|
cardListContainer.push({
|
|
813
|
-
name: template.name,
|
|
713
|
+
name: template.data?.name || '',
|
|
814
714
|
type: 'template',
|
|
815
715
|
cards: templateCards.map((item) => item.key),
|
|
816
716
|
});
|
|
@@ -847,7 +747,7 @@ export class Project extends CardContainer {
|
|
|
847
747
|
public async module(moduleName: string): Promise<ModuleContent | undefined> {
|
|
848
748
|
const module = await this.findModule(moduleName);
|
|
849
749
|
if (module && module.path) {
|
|
850
|
-
const modulePath =
|
|
750
|
+
const modulePath = module.path;
|
|
851
751
|
const moduleConfig = await readJsonFile(
|
|
852
752
|
join(modulePath, Project.projectConfigFileName),
|
|
853
753
|
);
|
|
@@ -857,73 +757,32 @@ export class Project extends CardContainer {
|
|
|
857
757
|
hubs: moduleConfig.hubs,
|
|
858
758
|
path: modulePath,
|
|
859
759
|
cardKeyPrefix: moduleConfig.cardKeyPrefix,
|
|
860
|
-
calculations:
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
moduleName,
|
|
882
|
-
)),
|
|
883
|
-
],
|
|
884
|
-
graphViews: [
|
|
885
|
-
...(await this.resources.collectResourcesFromModules(
|
|
886
|
-
'graphViews',
|
|
887
|
-
moduleName,
|
|
888
|
-
)),
|
|
889
|
-
],
|
|
890
|
-
linkTypes: [
|
|
891
|
-
...(await this.resources.collectResourcesFromModules(
|
|
892
|
-
'linkTypes',
|
|
893
|
-
moduleName,
|
|
894
|
-
)),
|
|
895
|
-
],
|
|
896
|
-
reports: [
|
|
897
|
-
...(await this.resources.collectResourcesFromModules(
|
|
898
|
-
'reports',
|
|
899
|
-
moduleName,
|
|
900
|
-
)),
|
|
901
|
-
],
|
|
902
|
-
templates: [
|
|
903
|
-
...(await this.resources.collectResourcesFromModules(
|
|
904
|
-
'templates',
|
|
905
|
-
moduleName,
|
|
906
|
-
)),
|
|
907
|
-
],
|
|
908
|
-
workflows: [
|
|
909
|
-
...(await this.resources.collectResourcesFromModules(
|
|
910
|
-
'workflows',
|
|
911
|
-
moduleName,
|
|
912
|
-
)),
|
|
913
|
-
],
|
|
760
|
+
calculations: this.resources.moduleResourceNames(
|
|
761
|
+
'calculations',
|
|
762
|
+
moduleName,
|
|
763
|
+
),
|
|
764
|
+
cardTypes: this.resources.moduleResourceNames('cardTypes', moduleName),
|
|
765
|
+
fieldTypes: this.resources.moduleResourceNames(
|
|
766
|
+
'fieldTypes',
|
|
767
|
+
moduleName,
|
|
768
|
+
),
|
|
769
|
+
graphModels: this.resources.moduleResourceNames(
|
|
770
|
+
'graphModels',
|
|
771
|
+
moduleName,
|
|
772
|
+
),
|
|
773
|
+
graphViews: this.resources.moduleResourceNames(
|
|
774
|
+
'graphViews',
|
|
775
|
+
moduleName,
|
|
776
|
+
),
|
|
777
|
+
linkTypes: this.resources.moduleResourceNames('linkTypes', moduleName),
|
|
778
|
+
reports: this.resources.moduleResourceNames('reports', moduleName),
|
|
779
|
+
templates: this.resources.moduleResourceNames('templates', moduleName),
|
|
780
|
+
workflows: this.resources.moduleResourceNames('workflows', moduleName),
|
|
914
781
|
};
|
|
915
782
|
}
|
|
916
783
|
return undefined;
|
|
917
784
|
}
|
|
918
785
|
|
|
919
|
-
/**
|
|
920
|
-
* Returns list of modules in the project.
|
|
921
|
-
* @returns list of modules in the project.
|
|
922
|
-
*/
|
|
923
|
-
public async modules(): Promise<Resource[]> {
|
|
924
|
-
return this.resources.resources('modules');
|
|
925
|
-
}
|
|
926
|
-
|
|
927
786
|
/**
|
|
928
787
|
* Returns a new unique card key with project prefix (e.g. test_x649it4x).
|
|
929
788
|
* Random part of string will be always 8 characters in base-36 (0-9a-z)
|
|
@@ -996,6 +855,10 @@ export class Project extends CardContainer {
|
|
|
996
855
|
*/
|
|
997
856
|
public async populateCaches() {
|
|
998
857
|
if (!this.cardCache.isPopulated) {
|
|
858
|
+
// Only collect modules that are registered in the project configuration
|
|
859
|
+
if (this.configuration.modules && this.configuration.modules.length > 0) {
|
|
860
|
+
this.resources.changedModules();
|
|
861
|
+
}
|
|
999
862
|
await this.populateCardsCache();
|
|
1000
863
|
}
|
|
1001
864
|
}
|
|
@@ -1015,185 +878,96 @@ export class Project extends CardContainer {
|
|
|
1015
878
|
}
|
|
1016
879
|
|
|
1017
880
|
/**
|
|
1018
|
-
*
|
|
881
|
+
* Returns all prefixes used in the project.
|
|
882
|
+
* This includes both direct dependencies and transient dependencies.
|
|
1019
883
|
* @returns all prefixes used in the project.
|
|
1020
|
-
* @todo - move the module prefix fetch to resource-collector.
|
|
1021
|
-
* Make it use cached value that is only changed when module is removed/imported.
|
|
1022
884
|
*/
|
|
1023
|
-
public
|
|
1024
|
-
|
|
1025
|
-
let files;
|
|
1026
|
-
try {
|
|
1027
|
-
// TODO: Could be optimized so that prefixes are stored once fetched.
|
|
1028
|
-
files = await readdir(this.paths.modulesFolder, {
|
|
1029
|
-
withFileTypes: true,
|
|
1030
|
-
recursive: true,
|
|
1031
|
-
});
|
|
1032
|
-
const configurationFiles = files
|
|
1033
|
-
.filter((dirent) => dirent.isFile())
|
|
1034
|
-
.filter((dirent) => dirent.name === Project.projectConfigFileName);
|
|
1035
|
-
|
|
1036
|
-
const configurationPromises = configurationFiles.map(async (file) => {
|
|
1037
|
-
const configuration = (await readJsonFile(
|
|
1038
|
-
join(file.parentPath, file.name),
|
|
1039
|
-
)) as ProjectSettings;
|
|
1040
|
-
return configuration.cardKeyPrefix;
|
|
1041
|
-
});
|
|
1042
|
-
|
|
1043
|
-
const configurationPrefixes = await Promise.all(configurationPromises);
|
|
1044
|
-
prefixes.push(...configurationPrefixes);
|
|
1045
|
-
} catch (error) {
|
|
1046
|
-
this.logger.error({ error }, 'Failed to collect prefixes in use');
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
return prefixes;
|
|
885
|
+
public allModulePrefixes(): string[] {
|
|
886
|
+
return this.cachedAllModulePrefixes;
|
|
1050
887
|
}
|
|
1051
888
|
|
|
1052
889
|
/**
|
|
1053
|
-
*
|
|
1054
|
-
* @
|
|
890
|
+
* Returns prefixes for direct module dependencies only (from cardsConfig.json).
|
|
891
|
+
* @returns prefixes for direct module dependencies.
|
|
1055
892
|
*/
|
|
1056
|
-
public
|
|
1057
|
-
const
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
);
|
|
1061
|
-
// First, remove cards from the cache
|
|
1062
|
-
for (const template of toBeRemovedTemplates) {
|
|
1063
|
-
this.cardCache.deleteCardsFromTemplate(template.name);
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
// Then, remove module from project configuration
|
|
1067
|
-
await this.configuration.removeModule(moduleName);
|
|
1068
|
-
this.collectModuleResources();
|
|
893
|
+
public projectPrefixes(): string[] {
|
|
894
|
+
const prefixes: string[] = [this.projectPrefix];
|
|
895
|
+
const moduleNames = this.configuration.modules.map((item) => item.name);
|
|
896
|
+
prefixes.push(...moduleNames);
|
|
1069
897
|
|
|
1070
|
-
|
|
898
|
+
return prefixes;
|
|
1071
899
|
}
|
|
1072
900
|
|
|
1073
901
|
/**
|
|
1074
|
-
* Removes
|
|
1075
|
-
* @param
|
|
902
|
+
* Removes an attachment from a card.
|
|
903
|
+
* @param cardKey The card to remove attachment from
|
|
904
|
+
* @param fileName The name of the attachment file to remove
|
|
905
|
+
* @throws if trying to remove module card attachment, or the attachment was not found.
|
|
1076
906
|
*/
|
|
1077
|
-
public
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
907
|
+
public async removeCardAttachment(
|
|
908
|
+
cardKey: string,
|
|
909
|
+
fileName: string,
|
|
910
|
+
): Promise<void> {
|
|
911
|
+
const attachmentFolder = this.cardAttachmentFolder(cardKey);
|
|
912
|
+
|
|
913
|
+
// Modules cannot be modified.
|
|
914
|
+
if (isModulePath(attachmentFolder)) {
|
|
915
|
+
throw new Error(`Cannot modify imported module`);
|
|
1082
916
|
}
|
|
1083
|
-
this.resources.remove(resource);
|
|
1084
|
-
this.createdResources.delete(resource.name);
|
|
1085
|
-
}
|
|
1086
917
|
|
|
1087
|
-
|
|
1088
|
-
* Array of reports in the project.
|
|
1089
|
-
* @param from Defines where resources are collected from.
|
|
1090
|
-
* @returns array of all reports in the project.
|
|
1091
|
-
*/
|
|
1092
|
-
public async reports(
|
|
1093
|
-
from: ResourcesFrom = ResourcesFrom.all,
|
|
1094
|
-
): Promise<Resource[]> {
|
|
1095
|
-
return this.resources.resources('reports', from);
|
|
1096
|
-
}
|
|
918
|
+
const attachmentPath = join(attachmentFolder, fileName);
|
|
1097
919
|
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
public async reportHandlerBarFiles(from: ResourcesFrom = ResourcesFrom.all) {
|
|
1104
|
-
const reports = await this.reports(from);
|
|
1105
|
-
const handleBarFiles: string[] = [];
|
|
1106
|
-
for (const reportResourceName of reports) {
|
|
1107
|
-
const name = resourceName(reportResourceName.name);
|
|
1108
|
-
const report = new ReportResource(this, name);
|
|
1109
|
-
handleBarFiles.push(...(await report.handleBarFiles()));
|
|
920
|
+
try {
|
|
921
|
+
await unlink(attachmentPath);
|
|
922
|
+
} catch (error) {
|
|
923
|
+
this.logger.error({ error }, 'Removing card attachment');
|
|
924
|
+
throw new Error(`Attachment not found: ${fileName}`);
|
|
1110
925
|
}
|
|
1111
|
-
|
|
926
|
+
await this.handleAttachmentChange(cardKey, 'removed', fileName);
|
|
1112
927
|
}
|
|
1113
928
|
|
|
1114
929
|
/**
|
|
1115
|
-
*
|
|
1116
|
-
* @
|
|
1117
|
-
* @
|
|
930
|
+
* Removes a module from the project cache and configuration.
|
|
931
|
+
* @note that ModuleManager removes the actual files.
|
|
932
|
+
* @param moduleName Module name to remove.
|
|
1118
933
|
*/
|
|
1119
|
-
public
|
|
1120
|
-
const
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
try {
|
|
1129
|
-
resource = Project.resourceObject(this, resName);
|
|
1130
|
-
} catch {
|
|
1131
|
-
return undefined;
|
|
1132
|
-
}
|
|
1133
|
-
const data = resource?.data as Type;
|
|
1134
|
-
if (!data) {
|
|
1135
|
-
return undefined;
|
|
934
|
+
public async removeModule(moduleName: string) {
|
|
935
|
+
const toBeRemovedTemplates = this.resources.moduleResourceNames(
|
|
936
|
+
'templates',
|
|
937
|
+
moduleName,
|
|
938
|
+
);
|
|
939
|
+
|
|
940
|
+
// First, remove template cards from the cache that are part of removed templates.
|
|
941
|
+
for (const templateName of toBeRemovedTemplates) {
|
|
942
|
+
this.cardCache.deleteCardsFromTemplate(templateName);
|
|
1136
943
|
}
|
|
1137
|
-
return data;
|
|
1138
|
-
}
|
|
1139
944
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
*/
|
|
1143
|
-
public get resourceCache(): Map<string, JSON> {
|
|
1144
|
-
return this.createdResources;
|
|
1145
|
-
}
|
|
945
|
+
// Then, remove all module resources from cache
|
|
946
|
+
this.resources.removeModule(moduleName);
|
|
1146
947
|
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
ResourcesFrom.all,
|
|
948
|
+
// Finally, remove module from project configuration
|
|
949
|
+
await this.configuration.removeModule(moduleName);
|
|
950
|
+
|
|
951
|
+
// Refresh cached module prefixes after removal
|
|
952
|
+
this.refreshAllModulePrefixes();
|
|
953
|
+
|
|
954
|
+
// Log configuration change
|
|
955
|
+
await ConfigurationLogger.log(
|
|
956
|
+
this.basePath,
|
|
957
|
+
ConfigurationOperation.MODULE_REMOVE,
|
|
958
|
+
moduleName,
|
|
959
|
+
{},
|
|
1160
960
|
);
|
|
1161
|
-
|
|
1162
|
-
|
|
961
|
+
|
|
962
|
+
this.logger.info(`Removed module '${moduleName}'`);
|
|
1163
963
|
}
|
|
1164
964
|
|
|
1165
965
|
/**
|
|
1166
|
-
*
|
|
1167
|
-
* @
|
|
1168
|
-
* To manipulate the resource (create files, delete files etc), use the resource object's API.
|
|
1169
|
-
* @param project Project from which resources are created from.
|
|
1170
|
-
* @param name Resource name
|
|
1171
|
-
* @throws if called with unsupported resource type.
|
|
1172
|
-
* @returns Created resource.
|
|
966
|
+
* Accessor for resource handler.
|
|
967
|
+
* @returns Resource handler instance.
|
|
1173
968
|
*/
|
|
1174
|
-
public
|
|
1175
|
-
|
|
1176
|
-
return new CalculationResource(project, name);
|
|
1177
|
-
} else if (name.type === 'cardTypes') {
|
|
1178
|
-
return new CardTypeResource(project, name);
|
|
1179
|
-
} else if (name.type === 'fieldTypes') {
|
|
1180
|
-
return new FieldTypeResource(project, name);
|
|
1181
|
-
} else if (name.type === 'graphModels') {
|
|
1182
|
-
return new GraphModelResource(project, name);
|
|
1183
|
-
} else if (name.type === 'graphViews') {
|
|
1184
|
-
return new GraphViewResource(project, name);
|
|
1185
|
-
} else if (name.type === 'linkTypes') {
|
|
1186
|
-
return new LinkTypeResource(project, name);
|
|
1187
|
-
} else if (name.type === 'reports') {
|
|
1188
|
-
return new ReportResource(project, name);
|
|
1189
|
-
} else if (name.type === 'templates') {
|
|
1190
|
-
return new TemplateResource(project, name);
|
|
1191
|
-
} else if (name.type === 'workflows') {
|
|
1192
|
-
return new WorkflowResource(project, name);
|
|
1193
|
-
}
|
|
1194
|
-
throw new Error(
|
|
1195
|
-
`Unsupported resource type '${resourceNameToString(name)}'`,
|
|
1196
|
-
);
|
|
969
|
+
public get resources(): ResourceHandler {
|
|
970
|
+
return this.resourceHandler;
|
|
1197
971
|
}
|
|
1198
972
|
|
|
1199
973
|
/**
|
|
@@ -1202,11 +976,11 @@ export class Project extends CardContainer {
|
|
|
1202
976
|
*/
|
|
1203
977
|
public async show(): Promise<ProjectMetadata> {
|
|
1204
978
|
return {
|
|
1205
|
-
name: this.
|
|
979
|
+
name: this.settings.name,
|
|
1206
980
|
path: this.basePath,
|
|
1207
981
|
prefix: this.projectPrefix,
|
|
1208
982
|
hubs: this.configuration.hubs,
|
|
1209
|
-
modules:
|
|
983
|
+
modules: this.resources.moduleNames(),
|
|
1210
984
|
numberOfCards: (await this.listCards(CardLocation.projectOnly))[0].cards
|
|
1211
985
|
.length,
|
|
1212
986
|
};
|
|
@@ -1235,17 +1009,6 @@ export class Project extends CardContainer {
|
|
|
1235
1009
|
});
|
|
1236
1010
|
}
|
|
1237
1011
|
|
|
1238
|
-
/**
|
|
1239
|
-
* Array of templates in the project.
|
|
1240
|
-
* @param from Defines where resources are collected from.
|
|
1241
|
-
* @returns array of all templates in the project.
|
|
1242
|
-
*/
|
|
1243
|
-
public async templates(
|
|
1244
|
-
from: ResourcesFrom = ResourcesFrom.all,
|
|
1245
|
-
): Promise<Resource[]> {
|
|
1246
|
-
return this.resources.resources('templates', from);
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
1012
|
/**
|
|
1250
1013
|
* Update a card's content.
|
|
1251
1014
|
* @param cardKey card key to update.
|
|
@@ -1348,44 +1111,4 @@ export class Project extends CardContainer {
|
|
|
1348
1111
|
await this.handleCardChanged(card);
|
|
1349
1112
|
}
|
|
1350
1113
|
}
|
|
1351
|
-
|
|
1352
|
-
// Validates that card's data is valid.
|
|
1353
|
-
private async validateCard(card: Card): Promise<string> {
|
|
1354
|
-
const invalidCustomData = await this.validator.validateCustomFields(
|
|
1355
|
-
this,
|
|
1356
|
-
card,
|
|
1357
|
-
);
|
|
1358
|
-
const invalidWorkFlow = this.validator.validateWorkflowState(this, card);
|
|
1359
|
-
|
|
1360
|
-
const invalidLabels = this.validator.validateCardLabels(card);
|
|
1361
|
-
if (
|
|
1362
|
-
invalidCustomData.length === 0 &&
|
|
1363
|
-
invalidWorkFlow.length === 0 &&
|
|
1364
|
-
invalidLabels.length === 0
|
|
1365
|
-
) {
|
|
1366
|
-
return '';
|
|
1367
|
-
}
|
|
1368
|
-
const errors: string[] = [];
|
|
1369
|
-
if (invalidCustomData.length > 0) {
|
|
1370
|
-
errors.push(invalidCustomData);
|
|
1371
|
-
}
|
|
1372
|
-
if (invalidWorkFlow.length > 0) {
|
|
1373
|
-
errors.push(invalidWorkFlow);
|
|
1374
|
-
}
|
|
1375
|
-
if (invalidLabels.length > 0) {
|
|
1376
|
-
errors.push(invalidLabels);
|
|
1377
|
-
}
|
|
1378
|
-
return errors.join('\n');
|
|
1379
|
-
}
|
|
1380
|
-
|
|
1381
|
-
/**
|
|
1382
|
-
* Array of workflows in the project.
|
|
1383
|
-
* @param from Defines where resources are collected from.
|
|
1384
|
-
* @returns array of all workflows in the project.
|
|
1385
|
-
*/
|
|
1386
|
-
public async workflows(
|
|
1387
|
-
from: ResourcesFrom = ResourcesFrom.all,
|
|
1388
|
-
): Promise<Resource[]> {
|
|
1389
|
-
return this.resources.resources('workflows', from);
|
|
1390
|
-
}
|
|
1391
1114
|
}
|