@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,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Cyberismo
|
|
3
|
+
Copyright © Cyberismo Ltd and contributors 2024
|
|
4
|
+
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
5
|
+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
6
|
+
You should have received a copy of the GNU Affero General Public
|
|
7
|
+
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// node
|
|
11
|
+
import { join, parse, sep } from 'node:path';
|
|
12
|
+
|
|
13
|
+
import type { Project } from '../containers/project.js';
|
|
14
|
+
import { stripExtension } from './file-utils.js';
|
|
15
|
+
|
|
16
|
+
// Resource name parts are:
|
|
17
|
+
// - prefix; name of the project this resource is part of
|
|
18
|
+
// - type; type of resource; in plural
|
|
19
|
+
// - identifier; unique name (within a project/module) for the resource
|
|
20
|
+
export interface ResourceName {
|
|
21
|
+
prefix: string;
|
|
22
|
+
type: string; // todo: should be a ResourceFolderType
|
|
23
|
+
identifier: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Indexes of resource name parts
|
|
27
|
+
const PREFIX_INDEX = 0;
|
|
28
|
+
const TYPE_INDEX = 1;
|
|
29
|
+
const IDENTIFIER_INDEX = 2;
|
|
30
|
+
// Valid resource name has three parts
|
|
31
|
+
const RESOURCE_NAME_PARTS = 3;
|
|
32
|
+
|
|
33
|
+
// Checks if name is valid (3 parts, separated by '/').
|
|
34
|
+
export function isResourceName(name: string): boolean {
|
|
35
|
+
const partsCount = name.split('/').length;
|
|
36
|
+
return partsCount === RESOURCE_NAME_PARTS;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Returns resource name parts (project prefix, type in plural, name of the resource).
|
|
41
|
+
* @param resourceName Name of the resource (e.g. <prefix>/<type>/<name>)
|
|
42
|
+
* @param strict If true, does not allow names without 'prefix' and 'type'.
|
|
43
|
+
* @throws if 'resourceName' is not valid resource name.
|
|
44
|
+
* @returns resource name parts: project or module prefix, resource type (plural) and actual name of the resource.
|
|
45
|
+
* @todo: In the future, switch the default value of 'strict' to true. Only in certain cases should we accept names with just 'identifier'.
|
|
46
|
+
*/
|
|
47
|
+
export function resourceName(
|
|
48
|
+
resourceName: string,
|
|
49
|
+
strict: boolean = false,
|
|
50
|
+
): ResourceName {
|
|
51
|
+
const parts = resourceName.split('/');
|
|
52
|
+
// just resource identifier - type and prefix are unknown
|
|
53
|
+
if (parts.length === 1 && parts.at(0) !== '') {
|
|
54
|
+
if (strict) {
|
|
55
|
+
throw new Error(`Name '${resourceName}' is not valid resource name`);
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
prefix: '',
|
|
59
|
+
type: '',
|
|
60
|
+
identifier: resourceName,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// resource name
|
|
64
|
+
if (parts.length === RESOURCE_NAME_PARTS) {
|
|
65
|
+
return {
|
|
66
|
+
prefix: parts[PREFIX_INDEX],
|
|
67
|
+
type: parts[TYPE_INDEX],
|
|
68
|
+
identifier: parse(parts[IDENTIFIER_INDEX]).name,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// other formats are not accepted
|
|
72
|
+
if (resourceName === '') {
|
|
73
|
+
throw new Error('Must define resource name to query its details');
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`Name '${resourceName}' is not valid resource name`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Converts resource name to path.
|
|
80
|
+
* @param project Project
|
|
81
|
+
* @param resourceName Name of the resource (e.g. <prefix>/<type>/<name>)
|
|
82
|
+
* @returns path to resource metadata file
|
|
83
|
+
*/
|
|
84
|
+
export function resourceNameToPath(
|
|
85
|
+
project: Project,
|
|
86
|
+
resourceName: ResourceName,
|
|
87
|
+
): string {
|
|
88
|
+
if (project.projectPrefix === resourceName.prefix) {
|
|
89
|
+
return join(
|
|
90
|
+
project.paths.resourcesFolder,
|
|
91
|
+
resourceName.type,
|
|
92
|
+
resourceName.identifier + '.json',
|
|
93
|
+
);
|
|
94
|
+
} else if (resourceName.prefix !== '') {
|
|
95
|
+
return join(
|
|
96
|
+
project.paths.modulesFolder,
|
|
97
|
+
resourceName.prefix,
|
|
98
|
+
resourceName.type,
|
|
99
|
+
resourceName.identifier + '.json',
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
throw new Error('resourceName does not contain prefix');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Resource metadata file path to resource name (e.g. <prefix>/<type>/<name>)
|
|
107
|
+
* @param project Project where resource is in
|
|
108
|
+
* @param path Path to resource metadata file
|
|
109
|
+
* @returns Resource name (<prefix>/<type>/<name>)
|
|
110
|
+
*/
|
|
111
|
+
export function pathToResourceName(
|
|
112
|
+
project: Project,
|
|
113
|
+
path: string,
|
|
114
|
+
): ResourceName {
|
|
115
|
+
const parts = path.split(sep);
|
|
116
|
+
const modulesIndex = parts.lastIndexOf('modules');
|
|
117
|
+
const localIndex = parts.lastIndexOf('local');
|
|
118
|
+
// Check that either 'local' or 'modules' is included in path (but not both).
|
|
119
|
+
// And after that there is required amount of parts.
|
|
120
|
+
if (
|
|
121
|
+
(modulesIndex === -1 && localIndex === -1) ||
|
|
122
|
+
(modulesIndex !== -1 && localIndex !== -1) ||
|
|
123
|
+
(modulesIndex !== -1 &&
|
|
124
|
+
localIndex === 1 &&
|
|
125
|
+
parts.length === modulesIndex + 3) ||
|
|
126
|
+
(modulesIndex === -1 &&
|
|
127
|
+
localIndex !== -1 &&
|
|
128
|
+
parts.length === localIndex + 2)
|
|
129
|
+
) {
|
|
130
|
+
throw new Error(`invalid path: ${path}`);
|
|
131
|
+
}
|
|
132
|
+
// Finally check that all relevant parts are defined.
|
|
133
|
+
const prefix =
|
|
134
|
+
modulesIndex !== -1 ? parts.at(modulesIndex + 1) : project.projectPrefix;
|
|
135
|
+
const typeIndex = modulesIndex !== -1 ? modulesIndex + 2 : localIndex + 1;
|
|
136
|
+
const identifierIndex =
|
|
137
|
+
modulesIndex !== -1 ? modulesIndex + 3 : localIndex + 2;
|
|
138
|
+
const type = parts.at(typeIndex);
|
|
139
|
+
const identifier = stripExtension(parts.at(identifierIndex)!);
|
|
140
|
+
if (!identifier || !type || !prefix) {
|
|
141
|
+
throw new Error(`invalid path: ${path}`);
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
prefix: prefix,
|
|
145
|
+
type: type,
|
|
146
|
+
identifier: identifier,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Returns ResourceName as a single string.
|
|
152
|
+
* @param resourceName Resource name to convert.
|
|
153
|
+
* @returns resource name as a single string.
|
|
154
|
+
* @note that valid resource names are: empty string, identifier alone and prefix/type/identifier combination.
|
|
155
|
+
*/
|
|
156
|
+
export function resourceNameToString(resourceName: ResourceName): string {
|
|
157
|
+
if (!resourceName.prefix && !resourceName.type && !resourceName.identifier) {
|
|
158
|
+
return '';
|
|
159
|
+
}
|
|
160
|
+
if (resourceName.identifier === '') {
|
|
161
|
+
throw new Error(`Not a valid resource name. Identifier is missing.`);
|
|
162
|
+
}
|
|
163
|
+
if (
|
|
164
|
+
resourceName.prefix &&
|
|
165
|
+
resourceName.identifier &&
|
|
166
|
+
resourceName.type === ''
|
|
167
|
+
) {
|
|
168
|
+
throw new Error(`Not a valid resource name. Type is missing.`);
|
|
169
|
+
}
|
|
170
|
+
if (
|
|
171
|
+
resourceName.prefix === '' &&
|
|
172
|
+
resourceName.identifier &&
|
|
173
|
+
resourceName.type
|
|
174
|
+
) {
|
|
175
|
+
throw new Error(`Not a valid resource name. Prefix is missing.`);
|
|
176
|
+
}
|
|
177
|
+
return resourceName.prefix && resourceName.type && resourceName.prefix
|
|
178
|
+
? `${resourceName.prefix}/${resourceName.type}/${resourceName.identifier}`
|
|
179
|
+
: `${resourceName.identifier}`;
|
|
180
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
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 the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
6
|
+
|
|
7
|
+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
8
|
+
|
|
9
|
+
You should have received a copy of the GNU Affero General Public
|
|
10
|
+
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import createDOMPurify, { type WindowLike } from 'dompurify';
|
|
14
|
+
import { Buffer } from 'buffer';
|
|
15
|
+
import { JSDOM } from 'jsdom';
|
|
16
|
+
|
|
17
|
+
const window = new JSDOM('').window as unknown as Window;
|
|
18
|
+
|
|
19
|
+
// Remove SVG size to make it scale in the application properly
|
|
20
|
+
const removeSvgWidthAndHeight = (node: Element) => {
|
|
21
|
+
if (node.nodeName === 'svg') {
|
|
22
|
+
node.removeAttribute('width');
|
|
23
|
+
node.removeAttribute('height');
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Sanitize an SVG Buffer and return a base64-encoded string
|
|
29
|
+
* @param buffer - SVG content as a Buffer
|
|
30
|
+
* @returns base64-encoded sanitized SVG string
|
|
31
|
+
*/
|
|
32
|
+
export function sanitizeSvgBase64(buffer: Buffer): string {
|
|
33
|
+
const DOMPurify = createDOMPurify(window as unknown as WindowLike);
|
|
34
|
+
|
|
35
|
+
const dirty = buffer.toString('utf-8');
|
|
36
|
+
|
|
37
|
+
DOMPurify.setConfig({ USE_PROFILES: { svg: true } });
|
|
38
|
+
DOMPurify.addHook('afterSanitizeAttributes', removeSvgWidthAndHeight);
|
|
39
|
+
|
|
40
|
+
let cleaned = DOMPurify.sanitize(dirty);
|
|
41
|
+
|
|
42
|
+
// Remove link titles, quick fix for Clingraph/Graphviz generated titles for links that are quite strange
|
|
43
|
+
cleaned = cleaned.replace(/\s*xlink:title=(["']).*?\1/g, '');
|
|
44
|
+
|
|
45
|
+
return Buffer.from(cleaned, 'utf-8').toString('base64');
|
|
46
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
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 the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
6
|
+
|
|
7
|
+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
8
|
+
|
|
9
|
+
You should have received a copy of the GNU Affero General Public
|
|
10
|
+
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
14
|
+
import { formatJson } from './json.js';
|
|
15
|
+
import { dirname } from 'path';
|
|
16
|
+
|
|
17
|
+
export interface UserPreferencesObject {
|
|
18
|
+
editCommand: {
|
|
19
|
+
[platform: string]: {
|
|
20
|
+
command: string;
|
|
21
|
+
args: string[];
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
attachmentEditors: {
|
|
25
|
+
[platform: string]: {
|
|
26
|
+
mimeType: string;
|
|
27
|
+
command: string;
|
|
28
|
+
}[];
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The class checks if the preferences file exists when instantiated, and if not, creates it with a default JSON object.
|
|
33
|
+
* The getPreferences() method simply reads and parses the file to return the preferences object.
|
|
34
|
+
*/
|
|
35
|
+
export class UserPreferences {
|
|
36
|
+
// If preferences do not exist, they are initialised
|
|
37
|
+
// with these defaults.
|
|
38
|
+
static defaults = {
|
|
39
|
+
editCommand: {
|
|
40
|
+
darwin: {
|
|
41
|
+
command: 'code',
|
|
42
|
+
args: ['{{cardContentPath}}', '{{cardJsonPath}}'],
|
|
43
|
+
},
|
|
44
|
+
linux: {
|
|
45
|
+
command: 'vi',
|
|
46
|
+
args: ['{{cardContentPath}}', '{{cardJsonPath}}'],
|
|
47
|
+
},
|
|
48
|
+
win32: {
|
|
49
|
+
command: 'notepad.exe',
|
|
50
|
+
args: ['{{cardContentPath}}', '{{cardJsonPath}}'],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
attachmentEditors: {
|
|
54
|
+
darwin: [
|
|
55
|
+
{
|
|
56
|
+
mimeType: 'image/png',
|
|
57
|
+
command: "open -a draw.io '{{attachmentPath}}'",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
mimeType: 'image/svg+xml',
|
|
61
|
+
command: "open -a draw.io '{{attachmentPath}}'",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
mimeType: 'application/pdf',
|
|
65
|
+
command: 'open -a Preview "{{attachmentPath}}"',
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
linux: [
|
|
69
|
+
{
|
|
70
|
+
mimeType: 'image/png',
|
|
71
|
+
command: 'drawio {{attachmentPath}}',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
mimeType: 'image/svg+xml',
|
|
75
|
+
command: 'drawio {{attachmentPath}}',
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
win32: [
|
|
79
|
+
{
|
|
80
|
+
mimeType: 'text/plain',
|
|
81
|
+
command: 'notepad.exe {{attachmentPath}}',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
mimeType: 'image/png',
|
|
85
|
+
command:
|
|
86
|
+
'"C:\\Program Files\\draw.io\\draw.io.exe" "{{attachmentPath}}"',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
mimeType: 'image/svg+xml',
|
|
90
|
+
command:
|
|
91
|
+
'"C:\\Program Files\\draw.io\\draw.io.exe" "{{attachmentPath}}"',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
constructor(private prefsFilePath: string) {
|
|
98
|
+
if (!existsSync(this.prefsFilePath)) {
|
|
99
|
+
// Create the preferences directory based on prefsFilePath dirname
|
|
100
|
+
const prefsDir = dirname(this.prefsFilePath);
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
if (!existsSync(prefsDir)) {
|
|
104
|
+
mkdirSync(prefsDir, { recursive: true });
|
|
105
|
+
}
|
|
106
|
+
// File does not exist, create it with default content
|
|
107
|
+
writeFileSync(this.prefsFilePath, formatJson(UserPreferences.defaults));
|
|
108
|
+
} catch (error) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`Error creating preferences file '${this.prefsFilePath}': ${error}`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public getPreferences(): UserPreferencesObject {
|
|
117
|
+
// Read and parse the preferences file
|
|
118
|
+
try {
|
|
119
|
+
return JSON.parse(readFileSync(this.prefsFilePath, 'utf8'));
|
|
120
|
+
} catch (error) {
|
|
121
|
+
throw new Error(
|
|
122
|
+
`Error reading preferences file '${this.prefsFilePath}': ${error}`,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
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 the terms of the GNU Affero General Public License version 3 as published by the Free Software Foundation.
|
|
6
|
+
|
|
7
|
+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
8
|
+
|
|
9
|
+
You should have received a copy of the GNU Affero General Public
|
|
10
|
+
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
11
|
+
*/
|
|
12
|
+
import { type Schema, Validator } from 'jsonschema';
|
|
13
|
+
import { DHValidationError, SchemaNotFound } from '../exceptions/index.js';
|
|
14
|
+
import { schemas } from '@cyberismo/resources';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Validates a JSON object against a schema
|
|
18
|
+
* @param object The object to validate
|
|
19
|
+
* @param schemaId The id of the schema to validate against
|
|
20
|
+
* @param validator An optional validator to use. If validator is not provided or does not contain any schemas, project schemas will be used
|
|
21
|
+
* @returns The object casted to the type T if it is valid
|
|
22
|
+
* @throws DHValidationError if the object is not valid
|
|
23
|
+
* @throws SchemaNotFound if the schema with the given id is not found
|
|
24
|
+
*/
|
|
25
|
+
export function validateJson<T>(
|
|
26
|
+
object: unknown,
|
|
27
|
+
options: {
|
|
28
|
+
schemaId?: string;
|
|
29
|
+
schema?: Schema;
|
|
30
|
+
validator?: Validator;
|
|
31
|
+
},
|
|
32
|
+
): T {
|
|
33
|
+
const { schemaId, schema } = options;
|
|
34
|
+
let validator = options.validator;
|
|
35
|
+
|
|
36
|
+
if (!schema && !schemaId) {
|
|
37
|
+
throw new Error('Must either specify schema or schemaId');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!validator) {
|
|
41
|
+
validator = new Validator();
|
|
42
|
+
for (const schema of schemas) {
|
|
43
|
+
validator.addSchema(schema, schema.$id);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let jsonSchema: Schema | undefined;
|
|
48
|
+
|
|
49
|
+
if (schema) {
|
|
50
|
+
jsonSchema = schema;
|
|
51
|
+
} else {
|
|
52
|
+
jsonSchema = Object.values(validator.schemas).find(
|
|
53
|
+
(s) => s.$id === schemaId,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!jsonSchema) {
|
|
58
|
+
throw new SchemaNotFound(`Schema with id ${schemaId} not found`);
|
|
59
|
+
}
|
|
60
|
+
const result = validator.validate(object, jsonSchema);
|
|
61
|
+
if (!result.valid) {
|
|
62
|
+
throw new DHValidationError('Validation failed', result.errors);
|
|
63
|
+
}
|
|
64
|
+
// we know that the object is valid, so we can safely cast it to T
|
|
65
|
+
return object as T;
|
|
66
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
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.
|
|
7
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
8
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
9
|
+
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
10
|
+
details. 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 type { DataType } from '../interfaces/resource-interfaces.js';
|
|
15
|
+
import { isBigInt } from '../utils/common-utils.js';
|
|
16
|
+
import * as EmailValidator from 'email-validator';
|
|
17
|
+
|
|
18
|
+
const SHORT_TEXT_MAX_LENGTH = 80;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Checks if conversion 'from' 'to' can be done.
|
|
22
|
+
* @param from Data type to convert from
|
|
23
|
+
* @param to Data type to convert to
|
|
24
|
+
* @returns true if conversion can be done, false otherwise.
|
|
25
|
+
*/
|
|
26
|
+
export function allowed(from: DataType, to: DataType) {
|
|
27
|
+
// Converting from strings is fine, except to enum.
|
|
28
|
+
if (from === 'longText' || from === 'shortText') {
|
|
29
|
+
switch (to) {
|
|
30
|
+
case 'boolean':
|
|
31
|
+
case 'date':
|
|
32
|
+
case 'dateTime':
|
|
33
|
+
case 'integer':
|
|
34
|
+
case 'list':
|
|
35
|
+
case 'longText':
|
|
36
|
+
case 'number':
|
|
37
|
+
case 'person':
|
|
38
|
+
case 'shortText':
|
|
39
|
+
return true;
|
|
40
|
+
default:
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Converting from<->to number formats is fine
|
|
45
|
+
if (
|
|
46
|
+
(from === 'number' && to === 'integer') ||
|
|
47
|
+
(from === 'integer' && to === 'number')
|
|
48
|
+
) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Converting to strings is fine
|
|
53
|
+
if (to === 'shortText' || to === 'longText') {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Converting from<->to date formats is fine
|
|
58
|
+
if (
|
|
59
|
+
(from === 'dateTime' && to === 'date') ||
|
|
60
|
+
(from === 'date' && to === 'dateTime')
|
|
61
|
+
) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
// Everything else is forbidden.
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Converts number value to other data types.
|
|
70
|
+
* @param value Value to convert
|
|
71
|
+
* @param to Date type to which value is converted to
|
|
72
|
+
* @returns converted value, or null if cannot convert
|
|
73
|
+
* Allowed conversions are
|
|
74
|
+
* date -> dateTime
|
|
75
|
+
* dateTime -> date
|
|
76
|
+
* date/dateTime -> shortText/longText
|
|
77
|
+
*/
|
|
78
|
+
export function fromDate<T>(value: T, to: DataType) {
|
|
79
|
+
if (to === 'date') {
|
|
80
|
+
const tempDate = new Date(value as Date);
|
|
81
|
+
return new Date(tempDate).toISOString().slice(0, 10);
|
|
82
|
+
}
|
|
83
|
+
if (to === 'dateTime') {
|
|
84
|
+
const tempDate = new Date(value as Date);
|
|
85
|
+
return new Date(tempDate).toISOString();
|
|
86
|
+
}
|
|
87
|
+
if (to === 'longText' || to === 'shortText') {
|
|
88
|
+
return String(value);
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Converts number value to other data types.
|
|
95
|
+
* @param value Value to convert
|
|
96
|
+
* @param to Date type to which value is converted to
|
|
97
|
+
* @returns converted value, or null if cannot convert
|
|
98
|
+
* Allowed conversions are
|
|
99
|
+
* integer -> number
|
|
100
|
+
* number -> integer
|
|
101
|
+
* number/integer -> shortText
|
|
102
|
+
* number/integer -> longText
|
|
103
|
+
*/
|
|
104
|
+
export function fromNumber<T>(value: T, to: DataType) {
|
|
105
|
+
if (to === 'integer') {
|
|
106
|
+
return Math.trunc(value as number);
|
|
107
|
+
}
|
|
108
|
+
if (to === 'longText') {
|
|
109
|
+
return String(value);
|
|
110
|
+
}
|
|
111
|
+
if (to === 'number') {
|
|
112
|
+
return Number(value);
|
|
113
|
+
}
|
|
114
|
+
if (to === 'shortText') {
|
|
115
|
+
const tempString = String(value);
|
|
116
|
+
return tempString.length > SHORT_TEXT_MAX_LENGTH ? null : tempString;
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Converts string value to other data types.
|
|
123
|
+
* @param value Value to convert
|
|
124
|
+
* @param to Date type to which value is converted to
|
|
125
|
+
* @returns converted value, or null if cannot convert
|
|
126
|
+
* Allowed conversions are
|
|
127
|
+
* longText -> shortText
|
|
128
|
+
* shortText -> longText
|
|
129
|
+
* longText/shortText -> integer
|
|
130
|
+
* longText/shortText -> number
|
|
131
|
+
* longText/shortText -> list
|
|
132
|
+
* longText/shortText -> date/dateTime
|
|
133
|
+
* longText/shortText -> boolean
|
|
134
|
+
*/
|
|
135
|
+
export function fromString<T>(value: T, to: DataType) {
|
|
136
|
+
switch (to) {
|
|
137
|
+
case 'boolean': {
|
|
138
|
+
if (value === 'true') return true;
|
|
139
|
+
if (value === 'false') return false;
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
case 'date': {
|
|
143
|
+
try {
|
|
144
|
+
const tempDate = new Date((value as string) + 'Z').toUTCString();
|
|
145
|
+
return new Date(tempDate).toISOString().slice(0, 10);
|
|
146
|
+
} catch {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
case 'dateTime': {
|
|
151
|
+
try {
|
|
152
|
+
const tempDate = new Date((value as string) + 'Z').toUTCString();
|
|
153
|
+
return new Date(tempDate).toISOString();
|
|
154
|
+
} catch {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
case 'integer': {
|
|
159
|
+
if (isBigInt(value as string)) {
|
|
160
|
+
return BigInt(value as string);
|
|
161
|
+
}
|
|
162
|
+
const tempInt = parseInt(value as string);
|
|
163
|
+
return isNaN(tempInt) ? null : tempInt;
|
|
164
|
+
}
|
|
165
|
+
case 'list': {
|
|
166
|
+
return (value as string).split(',');
|
|
167
|
+
}
|
|
168
|
+
case 'longText': {
|
|
169
|
+
return value;
|
|
170
|
+
}
|
|
171
|
+
case 'number': {
|
|
172
|
+
if (isBigInt(value as string)) {
|
|
173
|
+
return BigInt(value as string);
|
|
174
|
+
}
|
|
175
|
+
const tempNumber = parseFloat(value as string);
|
|
176
|
+
return isNaN(tempNumber) ? null : tempNumber;
|
|
177
|
+
}
|
|
178
|
+
case 'person': {
|
|
179
|
+
if (EmailValidator.validate(value as string)) {
|
|
180
|
+
return String(value);
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
case 'shortText': {
|
|
185
|
+
return (value as string).length > SHORT_TEXT_MAX_LENGTH ? null : value;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
}
|