@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,378 @@
|
|
|
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
|
+
|
|
15
|
+
// node
|
|
16
|
+
import { basename, join, sep } from 'node:path';
|
|
17
|
+
import type { Dirent } from 'node:fs';
|
|
18
|
+
import { readdir, readFile, writeFile } from 'node:fs/promises';
|
|
19
|
+
|
|
20
|
+
import { writeJsonFile } from '../utils/json.js';
|
|
21
|
+
import { getFilesSync } from '../utils/file-utils.js';
|
|
22
|
+
|
|
23
|
+
// interfaces
|
|
24
|
+
import {
|
|
25
|
+
type CardAttachment,
|
|
26
|
+
type Card,
|
|
27
|
+
CardNameRegEx,
|
|
28
|
+
type FetchCardDetails,
|
|
29
|
+
} from '../interfaces/project-interfaces.js';
|
|
30
|
+
|
|
31
|
+
// asciidoctor
|
|
32
|
+
import asciidoctor from '@asciidoctor/core';
|
|
33
|
+
|
|
34
|
+
import mime from 'mime-types';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Card container base class. Used for both Project and Template.
|
|
38
|
+
* Contains common card-related functionality.
|
|
39
|
+
*/
|
|
40
|
+
export class CardContainer {
|
|
41
|
+
public basePath: string;
|
|
42
|
+
protected containerName: string;
|
|
43
|
+
|
|
44
|
+
static projectConfigFileName = 'cardsConfig.json';
|
|
45
|
+
static cardMetadataFile = 'index.json';
|
|
46
|
+
static cardContentFile = 'index.adoc';
|
|
47
|
+
static schemaContentFile = '.schema';
|
|
48
|
+
|
|
49
|
+
constructor(path: string, name: string) {
|
|
50
|
+
this.basePath = path;
|
|
51
|
+
this.containerName = name;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Lists all direct children.
|
|
55
|
+
private async childrenCards(cardPath: string, details?: FetchCardDetails) {
|
|
56
|
+
const containerCards: Card[] = [];
|
|
57
|
+
await this.doCollectCards(cardPath, containerCards, details, true);
|
|
58
|
+
return containerCards;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Function collects attachments from all cards in one folder.
|
|
62
|
+
private async doCollectAttachments(
|
|
63
|
+
folder: string,
|
|
64
|
+
attachments: CardAttachment[],
|
|
65
|
+
): Promise<CardAttachment[]> {
|
|
66
|
+
const currentPaths: string[] = [];
|
|
67
|
+
let entries: Dirent[] = [];
|
|
68
|
+
try {
|
|
69
|
+
entries = (await readdir(folder, { withFileTypes: true })).filter(
|
|
70
|
+
(item) => item.isDirectory(),
|
|
71
|
+
);
|
|
72
|
+
} catch {
|
|
73
|
+
// ignore throws, if currentPaths does not have more values, recursion will stop
|
|
74
|
+
}
|
|
75
|
+
for (const entry of entries) {
|
|
76
|
+
// Investigate the content of card folders' attachment folders, but do not continue to children cards.
|
|
77
|
+
// For each attachment folder, collect all files.
|
|
78
|
+
if (CardNameRegEx.test(entry.name)) {
|
|
79
|
+
currentPaths.push(join(entry.parentPath, entry.name));
|
|
80
|
+
} else if (entry.name === 'c') {
|
|
81
|
+
continue;
|
|
82
|
+
} else if (entry.name === 'a') {
|
|
83
|
+
const attachmentFolder = join(entry.parentPath, entry.name);
|
|
84
|
+
const cardItem = basename(entry.parentPath) || '';
|
|
85
|
+
let entryAttachments: Dirent[] = [];
|
|
86
|
+
try {
|
|
87
|
+
entryAttachments = await readdir(attachmentFolder, {
|
|
88
|
+
withFileTypes: true,
|
|
89
|
+
});
|
|
90
|
+
} catch {
|
|
91
|
+
// ignore readdir errors
|
|
92
|
+
}
|
|
93
|
+
entryAttachments.forEach((attachment) =>
|
|
94
|
+
attachments.push({
|
|
95
|
+
card: cardItem,
|
|
96
|
+
fileName: attachment.name,
|
|
97
|
+
path: attachment.parentPath,
|
|
98
|
+
mimeType: mime.lookup(attachment.name) || null,
|
|
99
|
+
}),
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (currentPaths) {
|
|
105
|
+
const promises = currentPaths.map((item) =>
|
|
106
|
+
this.doCollectAttachments(item, attachments),
|
|
107
|
+
);
|
|
108
|
+
await Promise.all(promises);
|
|
109
|
+
}
|
|
110
|
+
return attachments;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Collects all cards from container.
|
|
114
|
+
private async doCollectCards(
|
|
115
|
+
path: string,
|
|
116
|
+
cards: Card[],
|
|
117
|
+
details: FetchCardDetails = {},
|
|
118
|
+
directChildrenOnly: boolean = false,
|
|
119
|
+
): Promise<Card[]> {
|
|
120
|
+
let entries = [];
|
|
121
|
+
try {
|
|
122
|
+
entries = await readdir(path, { withFileTypes: true });
|
|
123
|
+
} catch {
|
|
124
|
+
return cards;
|
|
125
|
+
}
|
|
126
|
+
let finish = false;
|
|
127
|
+
const currentPaths: string[] = [];
|
|
128
|
+
|
|
129
|
+
for (const entry of entries) {
|
|
130
|
+
if (entry.isDirectory()) {
|
|
131
|
+
const currentPath = join(entry.parentPath, entry.name);
|
|
132
|
+
currentPaths.push(currentPath);
|
|
133
|
+
if (CardNameRegEx.test(entry.name)) {
|
|
134
|
+
if (directChildrenOnly) {
|
|
135
|
+
// Make recursion stop on the level where first children cards are found.
|
|
136
|
+
finish = true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const attachmentFiles: CardAttachment[] = [];
|
|
140
|
+
const promiseContainer = [
|
|
141
|
+
this.getContent(currentPath, details.content),
|
|
142
|
+
this.getMetadata(currentPath, details.metadata),
|
|
143
|
+
this.getChildren(currentPath, details),
|
|
144
|
+
this.getAttachments(
|
|
145
|
+
currentPath,
|
|
146
|
+
attachmentFiles,
|
|
147
|
+
details.attachments,
|
|
148
|
+
),
|
|
149
|
+
];
|
|
150
|
+
const [cardContent, cardMetadata, cardChildren] =
|
|
151
|
+
await Promise.all(promiseContainer);
|
|
152
|
+
|
|
153
|
+
cards.push({
|
|
154
|
+
key: entry.name,
|
|
155
|
+
path: currentPath,
|
|
156
|
+
children: details.children ? (cardChildren as Card[]) : [],
|
|
157
|
+
attachments: details.attachments ? [...attachmentFiles] : [],
|
|
158
|
+
...(details.content && { content: cardContent as string }),
|
|
159
|
+
...(details.metadata && {
|
|
160
|
+
metadata: JSON.parse(cardMetadata as string),
|
|
161
|
+
}),
|
|
162
|
+
...(details.parent && { parent: this.parentCard(currentPath) }),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Continue collecting cards from children
|
|
169
|
+
if (!finish && currentPaths) {
|
|
170
|
+
const promises = currentPaths.map((item) =>
|
|
171
|
+
this.doCollectCards(item, cards, details, directChildrenOnly),
|
|
172
|
+
);
|
|
173
|
+
await Promise.all(promises);
|
|
174
|
+
}
|
|
175
|
+
return cards;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Find specific card
|
|
179
|
+
private async doFindCard(
|
|
180
|
+
path: string,
|
|
181
|
+
cardKey: string,
|
|
182
|
+
details: FetchCardDetails = {},
|
|
183
|
+
foundCards: Card[],
|
|
184
|
+
): Promise<Card[]> {
|
|
185
|
+
const entries = await readdir(path, { withFileTypes: true });
|
|
186
|
+
let asciiDocProcessor;
|
|
187
|
+
// optimization: do not create AsciiDoctor Processor, unless it is needed.
|
|
188
|
+
if (details.contentType && details.contentType === 'html') {
|
|
189
|
+
asciiDocProcessor = asciidoctor();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
for (const entry of entries) {
|
|
193
|
+
if (entry.isDirectory()) {
|
|
194
|
+
const currentPath = join(entry.parentPath, entry.name);
|
|
195
|
+
if (entry.name === cardKey) {
|
|
196
|
+
const attachmentFiles: CardAttachment[] = [];
|
|
197
|
+
const promiseContainer = [
|
|
198
|
+
this.getContent(currentPath, details.content),
|
|
199
|
+
this.getMetadata(currentPath, details.metadata),
|
|
200
|
+
this.getChildren(currentPath, details),
|
|
201
|
+
this.getAttachments(
|
|
202
|
+
currentPath,
|
|
203
|
+
attachmentFiles,
|
|
204
|
+
details.attachments,
|
|
205
|
+
),
|
|
206
|
+
];
|
|
207
|
+
const [cardContent, cardMetadata, cardChildren] =
|
|
208
|
+
await Promise.all(promiseContainer);
|
|
209
|
+
|
|
210
|
+
const content =
|
|
211
|
+
details.contentType && details.contentType === 'html'
|
|
212
|
+
? asciiDocProcessor?.convert(cardContent as string)
|
|
213
|
+
: cardContent;
|
|
214
|
+
|
|
215
|
+
foundCards.push({
|
|
216
|
+
key: entry.name,
|
|
217
|
+
path: currentPath,
|
|
218
|
+
children: details.children ? (cardChildren as Card[]) : [],
|
|
219
|
+
attachments: details.attachments ? [...attachmentFiles] : [],
|
|
220
|
+
...(details.content && { content: content as string }),
|
|
221
|
+
...(details.metadata && {
|
|
222
|
+
metadata: JSON.parse(cardMetadata as string),
|
|
223
|
+
}),
|
|
224
|
+
...(details.parent && { parent: this.parentCard(currentPath) }),
|
|
225
|
+
...(details.calculations && { calculations: [] }),
|
|
226
|
+
});
|
|
227
|
+
break; //optimization - there can only be one.
|
|
228
|
+
}
|
|
229
|
+
// Only continue, if the card has not been found.
|
|
230
|
+
if (foundCards.length === 0) {
|
|
231
|
+
await this.doFindCard(currentPath, cardKey, details, foundCards);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return foundCards;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Gets conditionally attachments
|
|
239
|
+
private async getAttachments(
|
|
240
|
+
currentPath: string,
|
|
241
|
+
files: CardAttachment[],
|
|
242
|
+
include?: boolean,
|
|
243
|
+
): Promise<string | CardAttachment[] | Card[]> {
|
|
244
|
+
return include ? this.doCollectAttachments(currentPath, files) : [];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Gets conditionally children
|
|
248
|
+
private async getChildren(
|
|
249
|
+
currentPath: string,
|
|
250
|
+
details: FetchCardDetails = {},
|
|
251
|
+
): Promise<string | CardAttachment[] | Card[]> {
|
|
252
|
+
return details.children ? this.childrenCards(currentPath, details) : [];
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Gets conditionally content
|
|
256
|
+
private async getContent(
|
|
257
|
+
currentPath: string,
|
|
258
|
+
include?: boolean,
|
|
259
|
+
): Promise<string | CardAttachment[] | Card[]> {
|
|
260
|
+
return include
|
|
261
|
+
? readFile(join(currentPath, CardContainer.cardContentFile), {
|
|
262
|
+
encoding: 'utf-8',
|
|
263
|
+
})
|
|
264
|
+
: '';
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Gets conditionally metadata
|
|
268
|
+
private async getMetadata(
|
|
269
|
+
currentPath: string,
|
|
270
|
+
include?: boolean,
|
|
271
|
+
): Promise<string> {
|
|
272
|
+
let metadata = include
|
|
273
|
+
? await readFile(join(currentPath, CardContainer.cardMetadataFile), {
|
|
274
|
+
encoding: 'utf-8',
|
|
275
|
+
})
|
|
276
|
+
: '';
|
|
277
|
+
metadata = this.injectLinksIfMissing(metadata);
|
|
278
|
+
return metadata;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Injects 'links' member - if it is missing - to a string representation of a card.
|
|
282
|
+
private injectLinksIfMissing(metadata: string): string {
|
|
283
|
+
if (metadata !== '' && !metadata.includes('"links":')) {
|
|
284
|
+
const end = metadata.lastIndexOf('}');
|
|
285
|
+
metadata = metadata.slice(0, end - 1) + ',\n "links": []\n' + '}';
|
|
286
|
+
}
|
|
287
|
+
return metadata;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Finds parent
|
|
291
|
+
private parentCard(cardPath: string) {
|
|
292
|
+
const pathParts = cardPath.split(sep);
|
|
293
|
+
if (
|
|
294
|
+
pathParts.at(pathParts.length - 2) === 'cardRoot' ||
|
|
295
|
+
(pathParts.length > 3 &&
|
|
296
|
+
pathParts.at(pathParts.length - 4) === 'templates')
|
|
297
|
+
) {
|
|
298
|
+
return 'root';
|
|
299
|
+
} else {
|
|
300
|
+
return pathParts.at(pathParts.length - 3);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Lists all attachments from container.
|
|
305
|
+
protected async attachments(path: string): Promise<CardAttachment[]> {
|
|
306
|
+
const attachments: CardAttachment[] = [];
|
|
307
|
+
const cards: Card[] = [];
|
|
308
|
+
await this.doCollectCards(path, cards, { attachments: true });
|
|
309
|
+
|
|
310
|
+
cards.forEach((card) => {
|
|
311
|
+
if (card.attachments) {
|
|
312
|
+
attachments.push(...card.attachments.flat());
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
return attachments;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Lists all cards from container.
|
|
320
|
+
protected async cards(
|
|
321
|
+
path: string,
|
|
322
|
+
details: FetchCardDetails = {},
|
|
323
|
+
directChildrenOnly: boolean = false,
|
|
324
|
+
): Promise<Card[]> {
|
|
325
|
+
const containerCards: Card[] = [];
|
|
326
|
+
await this.doCollectCards(
|
|
327
|
+
path,
|
|
328
|
+
containerCards,
|
|
329
|
+
details,
|
|
330
|
+
directChildrenOnly,
|
|
331
|
+
);
|
|
332
|
+
return containerCards;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Finds a specific card.
|
|
336
|
+
protected async findCard(
|
|
337
|
+
path: string,
|
|
338
|
+
cardKey: string,
|
|
339
|
+
details: FetchCardDetails = {},
|
|
340
|
+
): Promise<Card | undefined> {
|
|
341
|
+
const foundCards: Card[] = [];
|
|
342
|
+
await this.doFindCard(path, cardKey, details, foundCards);
|
|
343
|
+
return foundCards.at(0);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Checks if container has the specified card.
|
|
347
|
+
protected hasCard(cardKey: string, path: string): boolean {
|
|
348
|
+
const allFiles = getFilesSync(path);
|
|
349
|
+
const cardIndexJsonFile = join(cardKey, CardContainer.cardMetadataFile);
|
|
350
|
+
const found = allFiles.findIndex((file) =>
|
|
351
|
+
file.includes(cardIndexJsonFile),
|
|
352
|
+
);
|
|
353
|
+
return found !== -1;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Persists card content.
|
|
357
|
+
protected async saveCard(card: Card) {
|
|
358
|
+
await this.saveCardContent(card);
|
|
359
|
+
await this.saveCardMetadata(card);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Persists card metadata.
|
|
363
|
+
protected async saveCardContent(card: Card) {
|
|
364
|
+
if (card.content != null) {
|
|
365
|
+
const contentFile = join(card.path, CardContainer.cardContentFile);
|
|
366
|
+
await writeFile(contentFile, card.content);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Persists card metadata.
|
|
371
|
+
protected async saveCardMetadata(card: Card) {
|
|
372
|
+
if (card.metadata != null) {
|
|
373
|
+
const metadataFile = join(card.path, CardContainer.cardMetadataFile);
|
|
374
|
+
card.metadata!.lastUpdated = new Date().toISOString();
|
|
375
|
+
await writeJsonFile(metadataFile, card.metadata);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Cyberismo
|
|
3
|
+
Copyright © Cyberismo Ltd and contributors 2025
|
|
4
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
5
|
+
the terms of the GNU Affero General Public License version 3 as published by
|
|
6
|
+
the Free Software Foundation. This program is distributed in the hope that it
|
|
7
|
+
will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
8
|
+
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
9
|
+
See the GNU Affero General Public License for more details.
|
|
10
|
+
You should have received a copy of the GNU Affero General Public
|
|
11
|
+
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
|
|
16
|
+
import type { ResourceFolderType } from '../../interfaces/project-interfaces.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Handles paths for a project.
|
|
20
|
+
*/
|
|
21
|
+
export class ProjectPaths {
|
|
22
|
+
private pathMap: Map<ResourceFolderType, string>;
|
|
23
|
+
|
|
24
|
+
constructor(private path: string) {
|
|
25
|
+
this.pathMap = new Map([
|
|
26
|
+
['calculations', this.calculationProjectFolder],
|
|
27
|
+
['cardTypes', this.cardTypesFolder],
|
|
28
|
+
['fieldTypes', this.fieldTypesFolder],
|
|
29
|
+
['graphModels', this.graphModelsFolder],
|
|
30
|
+
['graphViews', this.graphViewsFolder],
|
|
31
|
+
['linkTypes', this.linkTypesFolder],
|
|
32
|
+
['modules', this.modulesFolder],
|
|
33
|
+
['reports', this.reportsFolder],
|
|
34
|
+
['templates', this.templatesFolder],
|
|
35
|
+
['workflows', this.workflowsFolder],
|
|
36
|
+
]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public get calculationCardsFolder(): string {
|
|
40
|
+
return join(this.calculationFolder, 'cards');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public get calculationFolder(): string {
|
|
44
|
+
return join(this.path, '.calc');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public get calculationProjectFolder(): string {
|
|
48
|
+
return join(this.resourcesFolder, 'calculations');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public get calculationResourcesFolder(): string {
|
|
52
|
+
return join(this.calculationFolder, 'resources');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public get cardRootFolder(): string {
|
|
56
|
+
return join(this.path, 'cardRoot');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public get cardTypesFolder(): string {
|
|
60
|
+
return join(this.resourcesFolder, 'cardTypes');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public get configurationFile(): string {
|
|
64
|
+
return join(this.resourcesFolder, 'cardsConfig.json');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public get fieldTypesFolder(): string {
|
|
68
|
+
return join(this.resourcesFolder, 'fieldTypes');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public get graphModelsFolder(): string {
|
|
72
|
+
return join(this.resourcesFolder, 'graphModels');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public get graphViewsFolder(): string {
|
|
76
|
+
return join(this.resourcesFolder, 'graphViews');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public get linkTypesFolder(): string {
|
|
80
|
+
return join(this.resourcesFolder, 'linkTypes');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public get logPath(): string {
|
|
84
|
+
return join(this.resourcesFolder, 'dh.log');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public get modulesFolder(): string {
|
|
88
|
+
return join(this.path, '.cards', 'modules');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public get resourcesFolder(): string {
|
|
92
|
+
return join(this.path, '.cards', 'local');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public get reportsFolder(): string {
|
|
96
|
+
return join(this.resourcesFolder, 'reports');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public get tempCardFolder(): string {
|
|
100
|
+
return join(this.tempFolder, 'cards');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public get tempFolder(): string {
|
|
104
|
+
return join(this.path, '.temp');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public get templatesFolder(): string {
|
|
108
|
+
return join(this.resourcesFolder, 'templates');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public get workflowsFolder(): string {
|
|
112
|
+
return join(this.resourcesFolder, 'workflows');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Return path to a resource type folder.
|
|
117
|
+
* @param resourceType Type of resource
|
|
118
|
+
* @returns path to a resources folder (e.g. '.cards/local/cardTypes')
|
|
119
|
+
*/
|
|
120
|
+
public resourcePath(resourceType: ResourceFolderType): string {
|
|
121
|
+
const resourcePath = this.pathMap.get(resourceType);
|
|
122
|
+
if (!resourcePath) {
|
|
123
|
+
throw new Error(`unknown resourceType: ${resourceType}`);
|
|
124
|
+
}
|
|
125
|
+
return resourcePath;
|
|
126
|
+
}
|
|
127
|
+
}
|