@cyberismo/data-handler 0.0.15 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/card-metadata-updater.js +7 -1
- package/dist/card-metadata-updater.js.map +1 -1
- package/dist/command-handler.d.ts +4 -0
- package/dist/command-handler.js +19 -3
- package/dist/command-handler.js.map +1 -1
- package/dist/command-manager.d.ts +24 -1
- package/dist/command-manager.js +27 -3
- 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/import.d.ts +9 -1
- package/dist/commands/import.js +15 -7
- 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 +8 -1
- package/dist/commands/remove.js +8 -4
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/rename.d.ts +4 -9
- package/dist/commands/rename.js +32 -101
- package/dist/commands/rename.js.map +1 -1
- package/dist/commands/show.d.ts +16 -10
- package/dist/commands/show.js +71 -55
- 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 +96 -35
- package/dist/commands/validate.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 +5 -4
- package/dist/containers/project/project-paths.js +16 -12
- package/dist/containers/project/project-paths.js.map +1 -1
- package/dist/containers/project/resource-cache.d.ts +169 -0
- package/dist/containers/project/resource-cache.js +507 -0
- package/dist/containers/project/resource-cache.js.map +1 -0
- package/dist/containers/project/resource-handler.d.ts +129 -0
- package/dist/containers/project/resource-handler.js +206 -0
- package/dist/containers/project/resource-handler.js.map +1 -0
- package/dist/containers/project.d.ts +38 -153
- package/dist/containers/project.js +129 -405
- package/dist/containers/project.js.map +1 -1
- package/dist/containers/template.d.ts +8 -2
- package/dist/containers/template.js +20 -15
- package/dist/containers/template.js.map +1 -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 +2 -4
- 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 +16 -3
- package/dist/project-settings.js +79 -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 +93 -8
- package/dist/resources/resource-object.js +162 -110
- 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/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 +8 -8
- package/src/card-metadata-updater.ts +6 -2
- package/src/command-handler.ts +24 -5
- package/src/command-manager.ts +29 -17
- package/src/commands/create.ts +43 -78
- package/src/commands/export.ts +63 -52
- package/src/commands/import.ts +24 -14
- package/src/commands/move.ts +0 -1
- package/src/commands/remove.ts +11 -7
- package/src/commands/rename.ts +43 -149
- package/src/commands/show.ts +113 -78
- package/src/commands/transition.ts +26 -28
- package/src/commands/update.ts +25 -22
- package/src/commands/validate.ts +108 -67
- package/src/containers/project/calculation-engine.ts +61 -93
- package/src/containers/project/project-paths.ts +21 -13
- package/src/containers/project/resource-cache.ts +648 -0
- package/src/containers/project/resource-handler.ts +265 -0
- package/src/containers/project.ts +178 -522
- package/src/containers/template.ts +24 -19
- package/src/interfaces/folder-content-interfaces.ts +7 -6
- package/src/interfaces/project-interfaces.ts +7 -6
- 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 +83 -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 +194 -152
- 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/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
|
@@ -23,9 +23,7 @@ import {
|
|
|
23
23
|
type Card,
|
|
24
24
|
type CardAttachment,
|
|
25
25
|
CardNameRegEx,
|
|
26
|
-
type Resource,
|
|
27
26
|
} from '../interfaces/project-interfaces.js';
|
|
28
|
-
import type { CardType, Workflow } from '../interfaces/resource-interfaces.js';
|
|
29
27
|
import { pathExists, stripExtension } from '../utils/file-utils.js';
|
|
30
28
|
import { DefaultContent } from '../resources/create-defaults.js';
|
|
31
29
|
|
|
@@ -42,6 +40,9 @@ import { resourceName } from '../utils/resource-utils.js';
|
|
|
42
40
|
|
|
43
41
|
import { ROOT } from '../utils/constants.js';
|
|
44
42
|
|
|
43
|
+
// @todo: Fix the constructor to not use Resource.
|
|
44
|
+
import type { Resource } from './project/resource-cache.js';
|
|
45
|
+
|
|
45
46
|
// creates template instance based on a project path and name
|
|
46
47
|
export class Template extends CardContainer {
|
|
47
48
|
private templateName: string;
|
|
@@ -55,6 +56,12 @@ export class Template extends CardContainer {
|
|
|
55
56
|
});
|
|
56
57
|
}
|
|
57
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Creates an instance of Template container that holds template related cards.
|
|
61
|
+
* @param project Project in which template is.
|
|
62
|
+
* @param template Template resource that this container is connected to.
|
|
63
|
+
*/
|
|
64
|
+
// @todo: Fix the constructor to not use Resource, but resource full path
|
|
58
65
|
constructor(project: Project, template: Resource) {
|
|
59
66
|
// Templates might come from modules. Remove module name from template name.
|
|
60
67
|
const templateName = stripExtension(basename(template.name));
|
|
@@ -199,18 +206,14 @@ export class Template extends CardContainer {
|
|
|
199
206
|
// Process metadata
|
|
200
207
|
const processMetadata = async (card: Card, parentCards: Card[]) => {
|
|
201
208
|
if (!card.metadata) return card;
|
|
209
|
+
const cardType = this.project.resources
|
|
210
|
+
.byType(card.metadata?.cardType, 'cardTypes')
|
|
211
|
+
.show();
|
|
202
212
|
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
`Card type '${card.metadata?.cardType}' of card ${card.key} cannot be found`,
|
|
207
|
-
);
|
|
208
|
-
}
|
|
213
|
+
const workflow = this.project.resources
|
|
214
|
+
.byType(cardType.workflow, 'workflows')
|
|
215
|
+
.show();
|
|
209
216
|
|
|
210
|
-
const workflow = this.project.resource<Workflow>(cardType.workflow);
|
|
211
|
-
if (!workflow) {
|
|
212
|
-
throw new Error(`Workflow '${cardType.workflow}' cannot be found`);
|
|
213
|
-
}
|
|
214
217
|
const initialWorkflowState = workflow.transitions.find(
|
|
215
218
|
(item) => item.fromState.includes('') || item.fromState.length === 0,
|
|
216
219
|
);
|
|
@@ -268,7 +271,7 @@ export class Template extends CardContainer {
|
|
|
268
271
|
await mkdir(processedCard.path, { recursive: true });
|
|
269
272
|
|
|
270
273
|
await Promise.all([
|
|
271
|
-
|
|
274
|
+
this.saveCardMetadata(processedCard),
|
|
272
275
|
writeFile(
|
|
273
276
|
join(processedCard.path, Project.cardContentFile),
|
|
274
277
|
processedAttachments.content || '',
|
|
@@ -389,18 +392,19 @@ export class Template extends CardContainer {
|
|
|
389
392
|
parentCard?: Card,
|
|
390
393
|
): Promise<string> {
|
|
391
394
|
const destinationCardPath = parentCard
|
|
392
|
-
? join(
|
|
395
|
+
? join(this.cardFolder(parentCard.key), 'c')
|
|
393
396
|
: this.templateCardsPath;
|
|
394
397
|
let newCardKey = '';
|
|
395
398
|
|
|
396
399
|
try {
|
|
400
|
+
// todo: to use cache instead of file access
|
|
397
401
|
if (!pathExists(this.templateFolder())) {
|
|
398
402
|
throw new Error(`Template '${this.containerName}' does not exist`);
|
|
399
403
|
}
|
|
400
|
-
const cardType = this.project.
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
+
const cardType = this.project.resources
|
|
405
|
+
.byType(cardTypeName, 'cardTypes')
|
|
406
|
+
.show();
|
|
407
|
+
|
|
404
408
|
if (parentCard && !this.hasTemplateCard(parentCard.key)) {
|
|
405
409
|
throw new Error(
|
|
406
410
|
`Card '${parentCard.key}' does not exist in template '${this.containerName}'`,
|
|
@@ -522,7 +526,7 @@ export class Template extends CardContainer {
|
|
|
522
526
|
/**
|
|
523
527
|
* Checks if a specific card key exists in a template.
|
|
524
528
|
* @param cardKey Card key to find from template.
|
|
525
|
-
* @
|
|
529
|
+
* @returns true if card with a given card key exists in the template, false otherwise.
|
|
526
530
|
*/
|
|
527
531
|
public hasTemplateCard(cardKey: string): boolean {
|
|
528
532
|
return this.project.hasTemplateCard(cardKey);
|
|
@@ -533,6 +537,7 @@ export class Template extends CardContainer {
|
|
|
533
537
|
* @returns true, if template is exists in project; false otherwise
|
|
534
538
|
*/
|
|
535
539
|
public isCreated(): boolean {
|
|
540
|
+
// todo: to use cache instead of file access
|
|
536
541
|
return pathExists(this.templateCardsPath);
|
|
537
542
|
}
|
|
538
543
|
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
import type { Schema } from 'jsonschema';
|
|
15
15
|
|
|
16
|
+
export type { Schema };
|
|
17
|
+
|
|
16
18
|
// All file mappings for lookup (filename -> property name)
|
|
17
19
|
export const ALL_FILE_MAPPINGS = {
|
|
18
20
|
'calculation.lp': 'calculation',
|
|
@@ -24,7 +26,7 @@ export const ALL_FILE_MAPPINGS = {
|
|
|
24
26
|
} as const;
|
|
25
27
|
|
|
26
28
|
// Reverse mappings from property names to filenames
|
|
27
|
-
export const
|
|
29
|
+
export const CONTENT_FILES = {
|
|
28
30
|
calculation: 'calculation.lp',
|
|
29
31
|
contentTemplate: 'index.adoc.hbs',
|
|
30
32
|
model: 'model.lp',
|
|
@@ -34,7 +36,7 @@ export const REVERSE_FILE_MAPPINGS = {
|
|
|
34
36
|
} as const;
|
|
35
37
|
|
|
36
38
|
// Union type of all valid content property names
|
|
37
|
-
export type ContentPropertyName = keyof typeof
|
|
39
|
+
export type ContentPropertyName = keyof typeof CONTENT_FILES;
|
|
38
40
|
|
|
39
41
|
// Content interface for Calculation resources
|
|
40
42
|
export interface CalculationContent {
|
|
@@ -49,6 +51,7 @@ export interface GraphModelContent {
|
|
|
49
51
|
// Content interface for Graph View resources
|
|
50
52
|
export interface GraphViewContent {
|
|
51
53
|
viewTemplate?: string;
|
|
54
|
+
schema?: Schema;
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
// Content interface for Report resources
|
|
@@ -70,9 +73,7 @@ export type FolderResourceContent =
|
|
|
70
73
|
* @returns filename that matches property name
|
|
71
74
|
*/
|
|
72
75
|
export function filename(propertyName: string): string | undefined {
|
|
73
|
-
return
|
|
74
|
-
propertyName as keyof typeof REVERSE_FILE_MAPPINGS
|
|
75
|
-
];
|
|
76
|
+
return CONTENT_FILES[propertyName as keyof typeof CONTENT_FILES];
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
/**
|
|
@@ -80,7 +81,7 @@ export function filename(propertyName: string): string | undefined {
|
|
|
80
81
|
* @param filename Filename.
|
|
81
82
|
* @returns property name that matches filename
|
|
82
83
|
*/
|
|
83
|
-
export function
|
|
84
|
+
export function contentPropertyName(
|
|
84
85
|
filename: string,
|
|
85
86
|
): ContentPropertyName | undefined {
|
|
86
87
|
return ALL_FILE_MAPPINGS[filename as keyof typeof ALL_FILE_MAPPINGS];
|
|
@@ -178,6 +178,7 @@ export interface ProjectMetadata {
|
|
|
178
178
|
|
|
179
179
|
// Project's settings (=cardsConfig.json).
|
|
180
180
|
export interface ProjectSettings {
|
|
181
|
+
schemaVersion?: number;
|
|
181
182
|
cardKeyPrefix: string;
|
|
182
183
|
name: string;
|
|
183
184
|
modules: ModuleSetting[];
|
|
@@ -228,12 +229,9 @@ export type RemovableResourceTypes =
|
|
|
228
229
|
| 'workflow'
|
|
229
230
|
| 'label';
|
|
230
231
|
|
|
231
|
-
//
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
path: string;
|
|
235
|
-
}
|
|
236
|
-
|
|
232
|
+
// TODO: fix terminology. In DH, modules are not resources.
|
|
233
|
+
// Also, this contains non-folder resources
|
|
234
|
+
// This was done likely like this, because on the CLI, they act similarly to resources
|
|
237
235
|
// Resources that have own folders.
|
|
238
236
|
export type ResourceFolderType =
|
|
239
237
|
| 'calculations'
|
|
@@ -247,6 +245,9 @@ export type ResourceFolderType =
|
|
|
247
245
|
| 'templates'
|
|
248
246
|
| 'workflows';
|
|
249
247
|
|
|
248
|
+
// This covers all 'true' resources
|
|
249
|
+
export type ResourceType = Exclude<ResourceFolderType, 'modules'>;
|
|
250
|
+
|
|
250
251
|
// All resource types; both singular and plural.
|
|
251
252
|
export type ResourceTypes =
|
|
252
253
|
| RemovableResourceTypes
|
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
GraphViewContent,
|
|
18
18
|
ReportContent,
|
|
19
19
|
} from './folder-content-interfaces.js';
|
|
20
|
+
import type { ResourceType } from './project-interfaces.js';
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Each resource represents a file (or a folder in some cases) with metadata stored
|
|
@@ -140,17 +141,31 @@ export interface ResourceBaseMetadata {
|
|
|
140
141
|
}
|
|
141
142
|
|
|
142
143
|
// All resources metadata content.
|
|
143
|
-
export type
|
|
144
|
-
|
|
|
144
|
+
export type AnyResourceContent =
|
|
145
|
+
| Calculation
|
|
145
146
|
| CardType
|
|
146
147
|
| FieldType
|
|
147
148
|
| GraphModel
|
|
148
149
|
| GraphView
|
|
149
150
|
| LinkType
|
|
150
|
-
|
|
|
151
|
+
| Report
|
|
151
152
|
| TemplateMetadata
|
|
152
153
|
| Workflow;
|
|
153
154
|
|
|
155
|
+
export type ResourceContent<T extends ResourceType> = ResourceContentMap[T];
|
|
156
|
+
|
|
157
|
+
export type ResourceContentMap = {
|
|
158
|
+
calculations: Calculation;
|
|
159
|
+
cardTypes: CardType;
|
|
160
|
+
fieldTypes: FieldType;
|
|
161
|
+
graphModels: GraphModel;
|
|
162
|
+
graphViews: GraphView;
|
|
163
|
+
linkTypes: LinkType;
|
|
164
|
+
reports: Report;
|
|
165
|
+
templates: TemplateMetadata;
|
|
166
|
+
workflows: Workflow;
|
|
167
|
+
};
|
|
168
|
+
|
|
154
169
|
// Template configuration details.
|
|
155
170
|
export interface TemplateConfiguration extends TemplateMetadata {
|
|
156
171
|
path: string;
|
|
@@ -12,19 +12,14 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import BaseMacro from '../base-macro.js';
|
|
15
|
-
import type { GraphOptions } from './types.js';
|
|
16
15
|
import { createImage, validateMacroContent } from '../index.js';
|
|
17
16
|
import Handlebars from 'handlebars';
|
|
18
|
-
import type { MacroGenerationContext } from '../../interfaces/macros.js';
|
|
19
17
|
import macroMetadata from './metadata.js';
|
|
20
|
-
import { pathExists } from '../../utils/file-utils.js';
|
|
21
|
-
import { readFile } from 'node:fs/promises';
|
|
22
|
-
import { readFileSync } from 'node:fs';
|
|
23
|
-
import type { Schema } from 'jsonschema';
|
|
24
|
-
import type TaskQueue from '../task-queue.js';
|
|
25
18
|
import { ClingoError } from '@cyberismo/node-clingo';
|
|
26
|
-
|
|
27
|
-
import {
|
|
19
|
+
|
|
20
|
+
import type { GraphOptions } from './types.js';
|
|
21
|
+
import type { MacroGenerationContext } from '../../interfaces/macros.js';
|
|
22
|
+
import type TaskQueue from '../task-queue.js';
|
|
28
23
|
|
|
29
24
|
class GraphMacro extends BaseMacro {
|
|
30
25
|
constructor(tasksQueue: TaskQueue) {
|
|
@@ -38,40 +33,35 @@ class GraphMacro extends BaseMacro {
|
|
|
38
33
|
handleStatic = async (context: MacroGenerationContext, input: unknown) => {
|
|
39
34
|
const options = this.parseOptions(input, context);
|
|
40
35
|
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
'model.lp',
|
|
45
|
-
);
|
|
46
|
-
const viewLocation = resourceFilePath(
|
|
47
|
-
context.project,
|
|
48
|
-
resourceName(options.view),
|
|
49
|
-
'view.lp.hbs',
|
|
36
|
+
const modelResource = context.project.resources.byType(
|
|
37
|
+
options.model,
|
|
38
|
+
'graphModels',
|
|
50
39
|
);
|
|
40
|
+
const modelContent = modelResource.contentData();
|
|
51
41
|
|
|
52
|
-
|
|
53
|
-
|
|
42
|
+
const viewResource = context.project.resources.byType(
|
|
43
|
+
options.view,
|
|
44
|
+
'graphViews',
|
|
45
|
+
);
|
|
46
|
+
const viewContent = viewResource.contentData();
|
|
47
|
+
if (!viewContent.viewTemplate) {
|
|
48
|
+
throw new Error(`Graph: View ${options.view} has no view template`);
|
|
54
49
|
}
|
|
55
50
|
|
|
56
|
-
let viewContent = '';
|
|
57
|
-
try {
|
|
58
|
-
viewContent = await readFile(viewLocation, { encoding: 'utf-8' });
|
|
59
|
-
} catch {
|
|
60
|
-
throw new Error(`Graph: View ${options.view} does not exist`);
|
|
61
|
-
}
|
|
62
51
|
const handlebarsContext = {
|
|
63
52
|
cardKey: context.cardKey,
|
|
64
53
|
...options,
|
|
65
54
|
};
|
|
66
55
|
|
|
67
56
|
const handlebars = Handlebars.create();
|
|
68
|
-
const view = handlebars.compile(viewContent)(
|
|
57
|
+
const view = handlebars.compile(viewContent.viewTemplate)(
|
|
58
|
+
handlebarsContext,
|
|
59
|
+
);
|
|
69
60
|
|
|
70
|
-
const modelContent = await readFile(modelLocation, { encoding: 'utf-8' });
|
|
71
61
|
let result: string;
|
|
72
62
|
try {
|
|
73
63
|
result = await context.project.calculationEngine.runGraph(
|
|
74
|
-
modelContent,
|
|
64
|
+
modelContent.model,
|
|
75
65
|
view,
|
|
76
66
|
context.context,
|
|
77
67
|
);
|
|
@@ -98,24 +88,13 @@ class GraphMacro extends BaseMacro {
|
|
|
98
88
|
): GraphOptions {
|
|
99
89
|
const options = validateMacroContent<GraphOptions>(this.metadata, input);
|
|
100
90
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
'parameterSchema.json',
|
|
109
|
-
),
|
|
110
|
-
{ encoding: 'utf-8' },
|
|
111
|
-
),
|
|
112
|
-
);
|
|
113
|
-
} catch (err) {
|
|
114
|
-
this.logger.trace(
|
|
115
|
-
err,
|
|
116
|
-
'Graph schema not found or failed to read, skipping validation',
|
|
117
|
-
);
|
|
118
|
-
}
|
|
91
|
+
// Get schema from view resource content if available
|
|
92
|
+
const resource = context.project.resources.byType(
|
|
93
|
+
options.view,
|
|
94
|
+
'graphViews',
|
|
95
|
+
);
|
|
96
|
+
const content = resource.contentData();
|
|
97
|
+
const schema = content.schema;
|
|
119
98
|
|
|
120
99
|
if (schema) {
|
|
121
100
|
validateMacroContent(this.metadata, input, schema);
|
package/src/macros/index.ts
CHANGED
|
@@ -186,7 +186,7 @@ export function validateMacroContent<T>(
|
|
|
186
186
|
* @param tasks - Tasks to register
|
|
187
187
|
* @returns macro instances
|
|
188
188
|
*/
|
|
189
|
-
export function registerMacros(
|
|
189
|
+
export async function registerMacros(
|
|
190
190
|
instance: typeof Handlebars,
|
|
191
191
|
context: MacroGenerationContext,
|
|
192
192
|
tasks: TaskQueue,
|
|
@@ -242,7 +242,7 @@ export async function evaluateMacros(
|
|
|
242
242
|
) {
|
|
243
243
|
const handlebars = Handlebars.create();
|
|
244
244
|
const tasks = new TaskQueue();
|
|
245
|
-
registerMacros(handlebars, context, tasks);
|
|
245
|
+
await registerMacros(handlebars, context, tasks);
|
|
246
246
|
let result = content;
|
|
247
247
|
while ((context.maxTries ?? 10) > 0) {
|
|
248
248
|
await tasks.reset();
|
|
@@ -18,8 +18,6 @@ import macroMetadata from './metadata.js';
|
|
|
18
18
|
import BaseMacro from '../base-macro.js';
|
|
19
19
|
import { validateJson } from '../../utils/validate.js';
|
|
20
20
|
import type TaskQueue from '../task-queue.js';
|
|
21
|
-
import { ReportResource } from '../../resources/report-resource.js';
|
|
22
|
-
import { resourceName } from '../../utils/resource-utils.js';
|
|
23
21
|
import { generateReportContent } from '../../utils/report.js';
|
|
24
22
|
import { ClingoError } from '@cyberismo/node-clingo';
|
|
25
23
|
import type { ReportOptions } from './types.js';
|
|
@@ -34,13 +32,9 @@ class ReportMacro extends BaseMacro {
|
|
|
34
32
|
|
|
35
33
|
handleStatic = async (context: MacroGenerationContext, data: unknown) => {
|
|
36
34
|
const options = this.validate(data);
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
);
|
|
41
|
-
const report = await resource.show();
|
|
42
|
-
|
|
43
|
-
if (!report) throw new Error(`Report ${options.name} does not exist`);
|
|
35
|
+
const report = context.project.resources
|
|
36
|
+
.byType(options.name, 'reports')
|
|
37
|
+
.show();
|
|
44
38
|
|
|
45
39
|
if (report.content.schema) {
|
|
46
40
|
validateJson(options, {
|
package/src/module-manager.ts
CHANGED
|
@@ -26,7 +26,7 @@ import { Project } from './containers/project.js';
|
|
|
26
26
|
import type { ProjectConfiguration } from './project-settings.js';
|
|
27
27
|
import { ProjectPaths } from './containers/project/project-paths.js';
|
|
28
28
|
import { readJsonFile } from './utils/json.js';
|
|
29
|
-
import { Validate } from './commands/
|
|
29
|
+
import { Validate } from './commands/validate.js';
|
|
30
30
|
|
|
31
31
|
const FILE_PROTOCOL = 'file:';
|
|
32
32
|
const HTTPS_PROTOCOL = 'https:';
|
|
@@ -54,7 +54,7 @@ export class ModuleManager {
|
|
|
54
54
|
await copyDir(sourcePath, destinationPath);
|
|
55
55
|
|
|
56
56
|
// Update the resources.
|
|
57
|
-
|
|
57
|
+
this.project.resources.changedModules();
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
// Creates a map of what dependencies each module depend from.
|
|
@@ -213,13 +213,11 @@ export class ModuleManager {
|
|
|
213
213
|
|
|
214
214
|
// Fetches direct dependencies of a module.
|
|
215
215
|
private async dependencies(moduleName: string): Promise<Set<string>> {
|
|
216
|
-
const
|
|
217
|
-
if (!allModules) return new Set();
|
|
218
|
-
const module = allModules.find((m) => m.name === moduleName);
|
|
216
|
+
const module = await this.project.module(moduleName);
|
|
219
217
|
if (!module) {
|
|
220
218
|
throw new Error(`Module '${moduleName}' not found`);
|
|
221
219
|
}
|
|
222
|
-
const modulePath = join(module.path,
|
|
220
|
+
const modulePath = join(module.path, 'cardsConfig.json');
|
|
223
221
|
const moduleConfiguration = (await readJsonFile(
|
|
224
222
|
modulePath,
|
|
225
223
|
)) as ProjectConfiguration;
|
|
@@ -287,7 +285,7 @@ export class ModuleManager {
|
|
|
287
285
|
|
|
288
286
|
// Imports from a given folder. Is used both for .temp/<module name> and file locations.
|
|
289
287
|
private async importFromFolder(path: string, name: string) {
|
|
290
|
-
await this.importFileModule(path);
|
|
288
|
+
await this.importFileModule(path, undefined, true); // Skip validation during updates
|
|
291
289
|
console.log(
|
|
292
290
|
`... Imported module '${name}' to '${this.project.configuration.name}'`,
|
|
293
291
|
);
|
|
@@ -361,6 +359,9 @@ export class ModuleManager {
|
|
|
361
359
|
try {
|
|
362
360
|
await this.removeModuleFiles(module.name);
|
|
363
361
|
console.log(`... Removed imported module '${module.name}'`);
|
|
362
|
+
|
|
363
|
+
// Refresh module resources in cache after filesystem removal to avoid stale prefixes
|
|
364
|
+
this.project.resources.changedModules();
|
|
364
365
|
} catch (error) {
|
|
365
366
|
if (error instanceof Error)
|
|
366
367
|
console.error(
|
|
@@ -479,7 +480,11 @@ export class ModuleManager {
|
|
|
479
480
|
}
|
|
480
481
|
|
|
481
482
|
// Updates modules in the project.
|
|
482
|
-
private async update(
|
|
483
|
+
private async update(
|
|
484
|
+
module?: ModuleSetting,
|
|
485
|
+
credentials?: Credentials,
|
|
486
|
+
skipModules?: Set<string>,
|
|
487
|
+
) {
|
|
483
488
|
// Prints dots every half second so that user knows that something is ongoing
|
|
484
489
|
function start() {
|
|
485
490
|
console.log('... Collecting unique modules. This takes a moment.');
|
|
@@ -514,22 +519,46 @@ export class ModuleManager {
|
|
|
514
519
|
uniqueModules.map((item) => item.name),
|
|
515
520
|
);
|
|
516
521
|
|
|
522
|
+
// Filter out modules that are already imported
|
|
523
|
+
const modulesToImport = skipModules
|
|
524
|
+
? uniqueModules.filter((module) => !skipModules.has(module.name))
|
|
525
|
+
: uniqueModules;
|
|
526
|
+
|
|
527
|
+
if (
|
|
528
|
+
skipModules &&
|
|
529
|
+
skipModules.size > 0 &&
|
|
530
|
+
modulesToImport.length < uniqueModules.length
|
|
531
|
+
) {
|
|
532
|
+
const skippedModules = uniqueModules
|
|
533
|
+
.filter((module) => skipModules.has(module.name))
|
|
534
|
+
.map((m) => m.name)
|
|
535
|
+
.join(', ');
|
|
536
|
+
console.log(
|
|
537
|
+
`... Skipping already imported module(s): ${skippedModules}`,
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
|
|
517
541
|
// Update modules parallel.
|
|
518
542
|
const promises: Promise<void>[] = [];
|
|
519
|
-
|
|
543
|
+
modulesToImport.forEach((module) =>
|
|
520
544
|
promises.push(this.handleModule(module)),
|
|
521
545
|
);
|
|
522
546
|
await Promise.all(promises);
|
|
523
547
|
await deleteDir(this.tempModulesDir);
|
|
524
|
-
|
|
548
|
+
this.project.resources.changedModules();
|
|
525
549
|
}
|
|
526
550
|
}
|
|
527
551
|
|
|
528
552
|
// Checks that module prefix is not in use in the project
|
|
529
|
-
|
|
553
|
+
// Optionally skip check for modules that are already imported (during updates)
|
|
554
|
+
private validatePrefix(modulePrefix: string, skipIfExists = false) {
|
|
530
555
|
// Do not allow modules with same prefixes.
|
|
531
|
-
const currentlyUsedPrefixes =
|
|
556
|
+
const currentlyUsedPrefixes = this.project.projectPrefixes();
|
|
532
557
|
if (currentlyUsedPrefixes.includes(modulePrefix)) {
|
|
558
|
+
// If skipIfExists is true, allow re-importing modules that are already present
|
|
559
|
+
if (skipIfExists) {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
533
562
|
throw new Error(
|
|
534
563
|
`Imported project has a prefix '${modulePrefix}' that is already used in the project. Cannot import from module.`,
|
|
535
564
|
);
|
|
@@ -540,8 +569,14 @@ export class ModuleManager {
|
|
|
540
569
|
* Imports module from local file path.
|
|
541
570
|
* @param source Path to import from.
|
|
542
571
|
* @param destination is this really needed???
|
|
572
|
+
* @param skipValidation Skip prefix validation (used during updates)
|
|
573
|
+
* @returns Module prefix of the imported module.
|
|
543
574
|
*/
|
|
544
|
-
public async importFileModule(
|
|
575
|
+
public async importFileModule(
|
|
576
|
+
source: string,
|
|
577
|
+
destination?: string,
|
|
578
|
+
skipValidation = false,
|
|
579
|
+
) {
|
|
545
580
|
if (!Validate.validateFolder(source)) {
|
|
546
581
|
throw new Error(
|
|
547
582
|
`Input validation error: folder name is invalid '${source}'`,
|
|
@@ -566,7 +601,7 @@ export class ModuleManager {
|
|
|
566
601
|
);
|
|
567
602
|
const sourcePath = sourceProject.paths.resourcesFolder;
|
|
568
603
|
|
|
569
|
-
|
|
604
|
+
this.validatePrefix(modulePrefix, skipValidation);
|
|
570
605
|
|
|
571
606
|
// Copy files.
|
|
572
607
|
await this.addFileContents(sourcePath, destinationPath);
|
|
@@ -578,12 +613,14 @@ export class ModuleManager {
|
|
|
578
613
|
* @param source Git URL to import from.
|
|
579
614
|
* @param options Modules setting options.
|
|
580
615
|
* @param credentials Credentials for private repositories.
|
|
616
|
+
* @param skipValidation Skip prefix validation (used during updates)
|
|
581
617
|
* @returns module prefix as defined in its CardsConfig.json
|
|
582
618
|
*/
|
|
583
619
|
public async importGitModule(
|
|
584
620
|
source: string,
|
|
585
621
|
options?: ModuleSettingOptions,
|
|
586
622
|
credentials?: Credentials,
|
|
623
|
+
skipValidation = false,
|
|
587
624
|
) {
|
|
588
625
|
const clonedName = await this.clone(
|
|
589
626
|
{
|
|
@@ -596,7 +633,7 @@ export class ModuleManager {
|
|
|
596
633
|
);
|
|
597
634
|
const clonePath = join(this.tempModulesDir, clonedName);
|
|
598
635
|
const modulePrefix = (await this.configuration(clonePath)).cardKeyPrefix;
|
|
599
|
-
|
|
636
|
+
this.validatePrefix(modulePrefix, skipValidation);
|
|
600
637
|
|
|
601
638
|
const sourcePath = new ProjectPaths(clonePath).resourcesFolder;
|
|
602
639
|
const destinationPath = join(
|
|
@@ -612,6 +649,7 @@ export class ModuleManager {
|
|
|
612
649
|
* If module is not used by any other modules, then will remove the module from disk as well.
|
|
613
650
|
* Otherwise, only updates project configuration.
|
|
614
651
|
* @param moduleName Name of the module to remove
|
|
652
|
+
* @throws If module was not found.
|
|
615
653
|
*/
|
|
616
654
|
public async removeModule(moduleName: string) {
|
|
617
655
|
const projectModules = this.project.configuration.modules;
|
|
@@ -639,14 +677,33 @@ export class ModuleManager {
|
|
|
639
677
|
await this.project.removeModule(moduleName);
|
|
640
678
|
}
|
|
641
679
|
|
|
680
|
+
/**
|
|
681
|
+
* Updates dependencies for a module without re-importing the module itself.
|
|
682
|
+
* Used during module import to fetch dependencies after the main module is already imported.
|
|
683
|
+
* @param module Module whose dependencies should be updated.
|
|
684
|
+
* @param credentials Optional credentials for private repositories.
|
|
685
|
+
* @returns Module prefix as defined in its CardsConfig.json
|
|
686
|
+
*/
|
|
687
|
+
public async updateDependencies(
|
|
688
|
+
module: ModuleSetting,
|
|
689
|
+
credentials?: Credentials,
|
|
690
|
+
) {
|
|
691
|
+
return this.update(module, credentials, new Set([module.name]));
|
|
692
|
+
}
|
|
693
|
+
|
|
642
694
|
/**
|
|
643
695
|
* Imports module from a local file path or a git URL.
|
|
644
696
|
* @param module Module to update. If not provided, updates all modules.
|
|
645
697
|
* @param credentials Optional credentials for private repositories.
|
|
698
|
+
* @param skipModules Optional set of module names to skip during import.
|
|
646
699
|
* @returns Module prefix as defined in its CardsConfig.json
|
|
647
700
|
*/
|
|
648
|
-
public async updateModule(
|
|
649
|
-
|
|
701
|
+
public async updateModule(
|
|
702
|
+
module: ModuleSetting,
|
|
703
|
+
credentials?: Credentials,
|
|
704
|
+
skipModules?: Set<string>,
|
|
705
|
+
) {
|
|
706
|
+
return this.update(module, credentials, skipModules);
|
|
650
707
|
}
|
|
651
708
|
|
|
652
709
|
/**
|