@cyberismo/data-handler 0.0.15 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/dist/card-metadata-updater.js +7 -1
  2. package/dist/card-metadata-updater.js.map +1 -1
  3. package/dist/command-handler.d.ts +4 -0
  4. package/dist/command-handler.js +22 -8
  5. package/dist/command-handler.js.map +1 -1
  6. package/dist/command-manager.d.ts +24 -1
  7. package/dist/command-manager.js +31 -7
  8. package/dist/command-manager.js.map +1 -1
  9. package/dist/commands/create.d.ts +1 -1
  10. package/dist/commands/create.js +34 -36
  11. package/dist/commands/create.js.map +1 -1
  12. package/dist/commands/export.d.ts +11 -2
  13. package/dist/commands/export.js +54 -41
  14. package/dist/commands/export.js.map +1 -1
  15. package/dist/commands/fetch.d.ts +8 -0
  16. package/dist/commands/fetch.js +101 -23
  17. package/dist/commands/fetch.js.map +1 -1
  18. package/dist/commands/import.d.ts +14 -3
  19. package/dist/commands/import.js +27 -10
  20. package/dist/commands/import.js.map +1 -1
  21. package/dist/commands/move.js +0 -1
  22. package/dist/commands/move.js.map +1 -1
  23. package/dist/commands/remove.d.ts +11 -2
  24. package/dist/commands/remove.js +15 -5
  25. package/dist/commands/remove.js.map +1 -1
  26. package/dist/commands/rename.d.ts +4 -9
  27. package/dist/commands/rename.js +37 -101
  28. package/dist/commands/rename.js.map +1 -1
  29. package/dist/commands/show.d.ts +20 -12
  30. package/dist/commands/show.js +79 -57
  31. package/dist/commands/show.js.map +1 -1
  32. package/dist/commands/transition.d.ts +9 -2
  33. package/dist/commands/transition.js +25 -17
  34. package/dist/commands/transition.js.map +1 -1
  35. package/dist/commands/update.d.ts +16 -12
  36. package/dist/commands/update.js +19 -17
  37. package/dist/commands/update.js.map +1 -1
  38. package/dist/commands/validate.d.ts +17 -9
  39. package/dist/commands/validate.js +94 -35
  40. package/dist/commands/validate.js.map +1 -1
  41. package/dist/containers/card-container.d.ts +7 -5
  42. package/dist/containers/card-container.js +30 -5
  43. package/dist/containers/card-container.js.map +1 -1
  44. package/dist/containers/project/calculation-engine.d.ts +7 -4
  45. package/dist/containers/project/calculation-engine.js +61 -66
  46. package/dist/containers/project/calculation-engine.js.map +1 -1
  47. package/dist/containers/project/project-paths.d.ts +7 -4
  48. package/dist/containers/project/project-paths.js +22 -12
  49. package/dist/containers/project/project-paths.js.map +1 -1
  50. package/dist/containers/project/resource-cache.d.ts +169 -0
  51. package/dist/containers/project/resource-cache.js +509 -0
  52. package/dist/containers/project/resource-cache.js.map +1 -0
  53. package/dist/containers/project/resource-handler.d.ts +129 -0
  54. package/dist/containers/project/resource-handler.js +206 -0
  55. package/dist/containers/project/resource-handler.js.map +1 -0
  56. package/dist/containers/project.d.ts +46 -152
  57. package/dist/containers/project.js +179 -409
  58. package/dist/containers/project.js.map +1 -1
  59. package/dist/containers/template.d.ts +8 -2
  60. package/dist/containers/template.js +24 -19
  61. package/dist/containers/template.js.map +1 -1
  62. package/dist/interfaces/command-options.d.ts +3 -1
  63. package/dist/interfaces/folder-content-interfaces.d.ts +5 -3
  64. package/dist/interfaces/folder-content-interfaces.js +3 -3
  65. package/dist/interfaces/folder-content-interfaces.js.map +1 -1
  66. package/dist/interfaces/project-interfaces.d.ts +7 -9
  67. package/dist/interfaces/project-interfaces.js.map +1 -1
  68. package/dist/interfaces/resource-interfaces.d.ts +14 -1
  69. package/dist/interfaces/resource-interfaces.js.map +1 -1
  70. package/dist/macros/graph/index.js +12 -26
  71. package/dist/macros/graph/index.js.map +1 -1
  72. package/dist/macros/index.d.ts +1 -1
  73. package/dist/macros/index.js +2 -2
  74. package/dist/macros/index.js.map +1 -1
  75. package/dist/macros/report/index.js +3 -6
  76. package/dist/macros/report/index.js.map +1 -1
  77. package/dist/module-manager.d.ts +16 -3
  78. package/dist/module-manager.js +51 -19
  79. package/dist/module-manager.js.map +1 -1
  80. package/dist/project-settings.d.ts +21 -3
  81. package/dist/project-settings.js +91 -14
  82. package/dist/project-settings.js.map +1 -1
  83. package/dist/resources/calculation-resource.d.ts +4 -3
  84. package/dist/resources/calculation-resource.js +11 -5
  85. package/dist/resources/calculation-resource.js.map +1 -1
  86. package/dist/resources/card-type-resource.d.ts +6 -1
  87. package/dist/resources/card-type-resource.js +34 -23
  88. package/dist/resources/card-type-resource.js.map +1 -1
  89. package/dist/resources/create-defaults.d.ts +3 -2
  90. package/dist/resources/create-defaults.js +3 -2
  91. package/dist/resources/create-defaults.js.map +1 -1
  92. package/dist/resources/field-type-resource.d.ts +4 -1
  93. package/dist/resources/field-type-resource.js +22 -23
  94. package/dist/resources/field-type-resource.js.map +1 -1
  95. package/dist/resources/file-resource.d.ts +5 -9
  96. package/dist/resources/file-resource.js +6 -11
  97. package/dist/resources/file-resource.js.map +1 -1
  98. package/dist/resources/folder-resource.d.ts +29 -32
  99. package/dist/resources/folder-resource.js +59 -78
  100. package/dist/resources/folder-resource.js.map +1 -1
  101. package/dist/resources/graph-model-resource.d.ts +4 -1
  102. package/dist/resources/graph-model-resource.js +11 -4
  103. package/dist/resources/graph-model-resource.js.map +1 -1
  104. package/dist/resources/graph-view-resource.d.ts +5 -2
  105. package/dist/resources/graph-view-resource.js +7 -3
  106. package/dist/resources/graph-view-resource.js.map +1 -1
  107. package/dist/resources/link-type-resource.d.ts +5 -2
  108. package/dist/resources/link-type-resource.js +5 -2
  109. package/dist/resources/link-type-resource.js.map +1 -1
  110. package/dist/resources/report-resource.d.ts +6 -7
  111. package/dist/resources/report-resource.js +14 -23
  112. package/dist/resources/report-resource.js.map +1 -1
  113. package/dist/resources/resource-object.d.ts +94 -8
  114. package/dist/resources/resource-object.js +212 -109
  115. package/dist/resources/resource-object.js.map +1 -1
  116. package/dist/resources/template-resource.d.ts +7 -3
  117. package/dist/resources/template-resource.js +10 -3
  118. package/dist/resources/template-resource.js.map +1 -1
  119. package/dist/resources/workflow-resource.d.ts +5 -2
  120. package/dist/resources/workflow-resource.js +18 -22
  121. package/dist/resources/workflow-resource.js.map +1 -1
  122. package/dist/utils/card-utils.d.ts +2 -2
  123. package/dist/utils/card-utils.js +1 -1
  124. package/dist/utils/clingo-fact-builder.d.ts +25 -14
  125. package/dist/utils/clingo-fact-builder.js +27 -5
  126. package/dist/utils/clingo-fact-builder.js.map +1 -1
  127. package/dist/utils/clingo-facts.js +3 -4
  128. package/dist/utils/clingo-facts.js.map +1 -1
  129. package/dist/utils/configuration-logger.d.ts +91 -0
  130. package/dist/utils/configuration-logger.js +151 -0
  131. package/dist/utils/configuration-logger.js.map +1 -0
  132. package/dist/utils/constants.d.ts +1 -1
  133. package/dist/utils/constants.js +5 -3
  134. package/dist/utils/constants.js.map +1 -1
  135. package/dist/utils/resource-utils.d.ts +1 -0
  136. package/dist/utils/resource-utils.js +2 -1
  137. package/dist/utils/resource-utils.js.map +1 -1
  138. package/package.json +9 -9
  139. package/src/card-metadata-updater.ts +6 -2
  140. package/src/command-handler.ts +39 -12
  141. package/src/command-manager.ts +33 -21
  142. package/src/commands/create.ts +43 -78
  143. package/src/commands/export.ts +63 -52
  144. package/src/commands/fetch.ts +143 -34
  145. package/src/commands/import.ts +37 -15
  146. package/src/commands/move.ts +0 -1
  147. package/src/commands/remove.ts +20 -7
  148. package/src/commands/rename.ts +58 -149
  149. package/src/commands/show.ts +123 -80
  150. package/src/commands/transition.ts +26 -28
  151. package/src/commands/update.ts +25 -22
  152. package/src/commands/validate.ts +104 -67
  153. package/src/containers/card-container.ts +37 -5
  154. package/src/containers/project/calculation-engine.ts +61 -93
  155. package/src/containers/project/project-paths.ts +29 -13
  156. package/src/containers/project/resource-cache.ts +651 -0
  157. package/src/containers/project/resource-handler.ts +265 -0
  158. package/src/containers/project.ts +250 -527
  159. package/src/containers/template.ts +28 -23
  160. package/src/interfaces/command-options.ts +3 -1
  161. package/src/interfaces/folder-content-interfaces.ts +7 -6
  162. package/src/interfaces/project-interfaces.ts +12 -11
  163. package/src/interfaces/resource-interfaces.ts +18 -3
  164. package/src/macros/graph/index.ts +26 -47
  165. package/src/macros/index.ts +2 -2
  166. package/src/macros/report/index.ts +3 -9
  167. package/src/module-manager.ts +74 -17
  168. package/src/project-settings.ts +96 -14
  169. package/src/resources/calculation-resource.ts +18 -18
  170. package/src/resources/card-type-resource.ts +50 -50
  171. package/src/resources/create-defaults.ts +3 -2
  172. package/src/resources/field-type-resource.ts +41 -55
  173. package/src/resources/file-resource.ts +10 -36
  174. package/src/resources/folder-resource.ts +69 -120
  175. package/src/resources/graph-model-resource.ts +20 -22
  176. package/src/resources/graph-view-resource.ts +15 -17
  177. package/src/resources/link-type-resource.ts +10 -13
  178. package/src/resources/report-resource.ts +21 -43
  179. package/src/resources/resource-object.ts +263 -149
  180. package/src/resources/template-resource.ts +17 -16
  181. package/src/resources/workflow-resource.ts +25 -44
  182. package/src/utils/card-utils.ts +2 -2
  183. package/src/utils/clingo-fact-builder.ts +28 -16
  184. package/src/utils/clingo-facts.ts +3 -4
  185. package/src/utils/configuration-logger.ts +206 -0
  186. package/src/utils/constants.ts +5 -3
  187. package/src/utils/resource-utils.ts +2 -1
  188. package/dist/containers/project/resource-collector.d.ts +0 -110
  189. package/dist/containers/project/resource-collector.js +0 -344
  190. package/dist/containers/project/resource-collector.js.map +0 -1
  191. package/src/containers/project/resource-collector.ts +0 -404
@@ -12,6 +12,7 @@
12
12
  */
13
13
 
14
14
  import { writeJsonFile as atomicWrite } from 'write-json-file';
15
+ import { writeFileSync } from 'node:fs';
15
16
 
16
17
  import { resolve } from 'node:path';
17
18
  import { URL } from 'node:url';
@@ -21,40 +22,44 @@ import type {
21
22
  ModuleSetting,
22
23
  ProjectSettings,
23
24
  } from './interfaces/project-interfaces.js';
25
+ import { formatJson } from './utils/json.js';
26
+ import { getChildLogger } from './utils/log-utils.js';
24
27
  import { readJsonFileSync } from './utils/json.js';
25
- import { Validate } from './commands/index.js';
28
+ import { Validate } from './commands/validate.js';
29
+ import { SCHEMA_VERSION } from '@cyberismo/assets';
26
30
 
27
31
  /**
28
32
  * Represents Project's cardsConfig.json file.
29
33
  */
30
34
  export class ProjectConfiguration implements ProjectSettings {
31
- private static instance: ProjectConfiguration;
32
-
35
+ schemaVersion?: number;
33
36
  name: string;
34
37
  cardKeyPrefix: string;
35
38
  modules: ModuleSetting[];
36
39
  hubs: HubSetting[];
40
+ private logger = getChildLogger({ module: 'Project' });
37
41
  private settingPath: string;
42
+ private autoSave: boolean = false;
38
43
 
39
- constructor(path: string) {
44
+ constructor(path: string, autoSave: boolean = true) {
40
45
  this.name = '';
41
46
  this.settingPath = path;
42
47
  this.cardKeyPrefix = '';
43
48
  this.modules = [];
44
49
  this.hubs = [];
50
+ this.autoSave = autoSave;
45
51
  this.readSettings();
52
+ this.ensureSchemaVersionAndSave();
46
53
  }
47
54
 
48
- // Persists configuration file to disk.
49
- public async save() {
50
- if (this.cardKeyPrefix === '') {
51
- throw new Error('wrong configuration');
52
- }
53
- try {
54
- await atomicWrite(this.settingPath, this.toJSON(), { indent: 4 });
55
- } catch (error) {
56
- if (error instanceof Error) {
57
- console.error(error.message);
55
+ // Ensures that schemaVersion is set in the project configuration.
56
+ // If missing, sets it to the current SCHEMA_VERSION and marks for auto-save.
57
+ private ensureSchemaVersionAndSave() {
58
+ if (this.schemaVersion === undefined) {
59
+ this.schemaVersion = SCHEMA_VERSION;
60
+ // Auto-saves the configuration, if schema version was updated.
61
+ if (this.autoSave) {
62
+ this.saveSync();
58
63
  }
59
64
  }
60
65
  }
@@ -71,6 +76,7 @@ export class ProjectConfiguration implements ProjectSettings {
71
76
  Object.prototype.hasOwnProperty.call(settings, 'name');
72
77
 
73
78
  if (valid) {
79
+ this.schemaVersion = settings.schemaVersion;
74
80
  this.cardKeyPrefix = settings.cardKeyPrefix;
75
81
  this.name = settings.name;
76
82
  this.modules = settings.modules || [];
@@ -80,9 +86,24 @@ export class ProjectConfiguration implements ProjectSettings {
80
86
  }
81
87
  }
82
88
 
89
+ // Synchronously persists configuration file to disk.
90
+ private saveSync() {
91
+ if (this.cardKeyPrefix === '') {
92
+ throw new Error('wrong configuration');
93
+ }
94
+ try {
95
+ writeFileSync(this.settingPath, formatJson(this.toJSON()), 'utf-8');
96
+ } catch (error) {
97
+ if (error instanceof Error) {
98
+ this.logger.error({ error }, 'Cannot write project configuration');
99
+ }
100
+ }
101
+ }
102
+
83
103
  // Return the configuration as object
84
104
  private toJSON(): ProjectSettings {
85
105
  return {
106
+ schemaVersion: this.schemaVersion,
86
107
  cardKeyPrefix: this.cardKeyPrefix,
87
108
  name: this.name,
88
109
  modules: this.modules,
@@ -152,6 +173,39 @@ export class ProjectConfiguration implements ProjectSettings {
152
173
  return this.save();
153
174
  }
154
175
 
176
+ /**
177
+ * Checks schema version compatibility.
178
+ * @returns Compatibility state (true - compatible; false - not) and optional message related to it.
179
+ */
180
+ public checkSchemaVersion(): { isCompatible: boolean; message: string } {
181
+ if (this.schemaVersion === undefined) {
182
+ return {
183
+ isCompatible: true,
184
+ message: '',
185
+ };
186
+ }
187
+
188
+ if (this.schemaVersion < SCHEMA_VERSION) {
189
+ return {
190
+ isCompatible: false,
191
+ message: `Schema version mismatch: Project schema version (${this.schemaVersion}) is older than the application schema version (${SCHEMA_VERSION}). A migration is needed.`,
192
+ };
193
+ }
194
+
195
+ if (this.schemaVersion > SCHEMA_VERSION) {
196
+ return {
197
+ isCompatible: false,
198
+ message: `Schema version mismatch: Project schema version (${this.schemaVersion}) is newer than the application schema version (${SCHEMA_VERSION}). Please update the application.`,
199
+ };
200
+ }
201
+
202
+ // Schema versions are equal
203
+ return {
204
+ isCompatible: true,
205
+ message: '',
206
+ };
207
+ }
208
+
155
209
  /**
156
210
  * Removes a hub.
157
211
  * @param hubName Name of the hub to remove.
@@ -169,6 +223,7 @@ export class ProjectConfiguration implements ProjectSettings {
169
223
  /**
170
224
  * Removes module from imported modules property.
171
225
  * @param moduleName Name of the module to remove.
226
+ * @throws If Module name is empty, or not imported to the project.
172
227
  */
173
228
  public async removeModule(moduleName: string) {
174
229
  if (!moduleName) {
@@ -182,6 +237,20 @@ export class ProjectConfiguration implements ProjectSettings {
182
237
  return this.save();
183
238
  }
184
239
 
240
+ // Persists configuration file to disk.
241
+ public async save() {
242
+ if (this.cardKeyPrefix === '') {
243
+ throw new Error('wrong configuration');
244
+ }
245
+ try {
246
+ await atomicWrite(this.settingPath, this.toJSON(), { indent: 4 });
247
+ } catch (error) {
248
+ if (error instanceof Error) {
249
+ this.logger.error({ error }, 'Could not write project configuration');
250
+ }
251
+ }
252
+ }
253
+
185
254
  /**
186
255
  * Changes project prefix.
187
256
  * @param newPrefix New prefix to use in the project
@@ -196,4 +265,17 @@ export class ProjectConfiguration implements ProjectSettings {
196
265
  `Prefix '${newPrefix}' is not valid prefix. Prefix should be in lowercase and contain letters from a to z (max length 10).`,
197
266
  );
198
267
  }
268
+
269
+ /**
270
+ * Changes project name.
271
+ * @param newName New project name
272
+ */
273
+ public async setProjectName(newName: string) {
274
+ const isValid = Validate.isValidProjectName(newName);
275
+ if (isValid) {
276
+ this.name = newName;
277
+ return this.save();
278
+ }
279
+ throw new Error(`Project name '${newName}' is not valid.`);
280
+ }
199
281
  }
@@ -14,17 +14,18 @@
14
14
 
15
15
  import { join } from 'node:path';
16
16
 
17
- import {
18
- DefaultContent,
19
- FolderResource,
20
- resourceNameToString,
21
- sortCards,
22
- } from './folder-resource.js';
17
+ import { CONTENT_FILES } from '../interfaces/folder-content-interfaces.js';
18
+ import { DefaultContent } from '../resources/create-defaults.js';
19
+ import { FolderResource } from './folder-resource.js';
20
+ import { resourceNameToString } from '../utils/resource-utils.js';
21
+ import { sortCards } from '../utils/card-utils.js';
23
22
  import { writeFileSafe } from '../utils/file-utils.js';
24
23
 
25
- import { type CalculationMetadata } from '../interfaces/resource-interfaces.js';
26
24
  import type { CalculationContent } from '../interfaces/folder-content-interfaces.js';
27
- import type { Card, Project, ResourceName } from './file-resource.js';
25
+ import type { CalculationMetadata } from '../interfaces/resource-interfaces.js';
26
+ import type { Card } from '../interfaces/project-interfaces.js';
27
+ import type { Project } from '../containers/project.js';
28
+ import type { ResourceName } from '../utils/resource-utils.js';
28
29
 
29
30
  /**
30
31
  * Calculation resource class.
@@ -33,7 +34,6 @@ export class CalculationResource extends FolderResource<
33
34
  CalculationMetadata,
34
35
  CalculationContent
35
36
  > {
36
- private calculationsFile = 'calculation.lp';
37
37
  constructor(project: Project, name: ResourceName) {
38
38
  super(project, name, 'calculations');
39
39
 
@@ -61,14 +61,14 @@ export class CalculationResource extends FolderResource<
61
61
  }
62
62
  await super.create(newContent);
63
63
 
64
- const calculationsFile = join(this.internalFolder, this.calculationsFile);
65
- await writeFileSafe(
66
- calculationsFile,
67
- `% add your calculations here for '${this.resourceName.identifier}'`,
68
- {
69
- flag: 'wx',
70
- },
71
- );
64
+ const calculationContent = `% add your calculations here for '${this.resourceName.identifier}'`;
65
+ const calculationFile = CONTENT_FILES.calculation;
66
+ const calculationsFile = join(this.internalFolder, calculationFile);
67
+ await writeFileSafe(calculationsFile, calculationContent, {
68
+ flag: 'wx',
69
+ });
70
+
71
+ await this.loadContentFiles();
72
72
  }
73
73
  /**
74
74
  * Renames resource metadata file and renames memory resident object 'name'.
@@ -88,7 +88,7 @@ export class CalculationResource extends FolderResource<
88
88
  * @returns array of card keys and calculation filenames that refer this resource.
89
89
  */
90
90
  public async usage(cards?: Card[]): Promise<string[]> {
91
- const allCards = cards || (await super.cards());
91
+ const allCards = cards || super.cards();
92
92
 
93
93
  const [cardContentReferences, calculations] = await Promise.all([
94
94
  super.usage(allCards),
@@ -12,31 +12,28 @@
12
12
  License along with this program. If not, see <https://www.gnu.org/licenses/>.
13
13
  */
14
14
 
15
+ import { DefaultContent } from './create-defaults.js';
16
+ import { FileResource } from './file-resource.js';
17
+ import { resourceName, resourceNameToString } from '../utils/resource-utils.js';
18
+ import { ResourcesFrom } from '../containers/project.js';
19
+ import { sortCards } from '../utils/card-utils.js';
20
+ import { Validate } from '../commands/validate.js';
21
+
22
+ import type {
23
+ AddOperation,
24
+ ChangeOperation,
25
+ Operation,
26
+ RemoveOperation,
27
+ } from './resource-object.js';
28
+ import type { Card } from '../interfaces/project-interfaces.js';
15
29
  import type {
16
30
  CardType,
17
31
  CustomField,
18
32
  LinkType,
19
33
  UpdateKey,
20
- Workflow,
21
34
  } from '../interfaces/resource-interfaces.js';
22
- import { FieldTypeResource } from './field-type-resource.js';
23
- import {
24
- type AddOperation,
25
- type Card,
26
- type ChangeOperation,
27
- DefaultContent,
28
- FileResource,
29
- type Operation,
30
- type Project,
31
- type RemoveOperation,
32
- ResourcesFrom,
33
- type ResourceName,
34
- resourceName,
35
- resourceNameToString,
36
- sortCards,
37
- } from './file-resource.js';
38
- import { LinkTypeResource } from './link-type-resource.js';
39
- import { Validate } from '../commands/index.js';
35
+ import type { Project } from '../containers/project.js';
36
+ import type { ResourceName } from '../utils/resource-utils.js';
40
37
 
41
38
  /**
42
39
  * Card type resource class.
@@ -62,7 +59,7 @@ export class CardTypeResource extends FileResource<CardType> {
62
59
  // Checks if field type exists in the project.
63
60
  private async fieldTypeExists(field: Partial<CustomField>) {
64
61
  return field && field.name
65
- ? this.project.resourceExists('fieldTypes', field.name)
62
+ ? this.project.resources.exists(field.name)
66
63
  : false;
67
64
  }
68
65
 
@@ -108,7 +105,7 @@ export class CardTypeResource extends FileResource<CardType> {
108
105
  // When resource name changes.
109
106
  private async handleNameChange(existingName: string) {
110
107
  const current = this.content;
111
- const prefixes = await this.project.projectPrefixes();
108
+ const prefixes = this.project.projectPrefixes();
112
109
  if (current.customFields) {
113
110
  current.customFields.map(
114
111
  (field) =>
@@ -202,24 +199,25 @@ export class CardTypeResource extends FileResource<CardType> {
202
199
  }
203
200
 
204
201
  // Return link types that use this card type.
205
- private async relevantLinkTypes(): Promise<string[]> {
202
+ private relevantLinkTypes(): string[] {
206
203
  const resourceName = resourceNameToString(this.resourceName);
207
- const allLinkTypes = await this.project.linkTypes(ResourcesFrom.all);
204
+ const allLinkTypes = this.project.resources.linkTypes();
205
+ const references: string[] = [];
208
206
 
209
- const linkTypeNames = await Promise.all(
210
- allLinkTypes.map(async (linkType) => {
211
- const metadata = await this.project.resource<LinkType>(linkType.name);
212
- if (!metadata) return null;
207
+ for (const linkType of allLinkTypes) {
208
+ const metadata = linkType.data;
209
+ if (!metadata) continue;
213
210
 
214
- const isRelevant =
215
- metadata.destinationCardTypes.includes(resourceName) ||
216
- metadata.sourceCardTypes.includes(resourceName);
211
+ const isRelevant =
212
+ metadata.destinationCardTypes.includes(resourceName) ||
213
+ metadata.sourceCardTypes.includes(resourceName);
217
214
 
218
- return isRelevant ? linkType.name : null;
219
- }),
220
- );
215
+ if (isRelevant) {
216
+ references.push(metadata.name);
217
+ }
218
+ }
221
219
 
222
- return linkTypeNames.filter((name): name is string => name !== null);
220
+ return references;
223
221
  }
224
222
 
225
223
  // If value from 'customFields' is removed, remove it also from 'optionallyVisible' and 'alwaysVisible' arrays.
@@ -250,9 +248,9 @@ export class CardTypeResource extends FileResource<CardType> {
250
248
  }
251
249
  // Fetch "displayName" from field type if it is missing.
252
250
  if (item.name && item.displayName === undefined) {
253
- const fieldType = new FieldTypeResource(
254
- this.project,
255
- resourceName(item.name),
251
+ const fieldType = this.project.resources.byType(
252
+ item.name,
253
+ 'fieldTypes',
256
254
  );
257
255
  const fieldTypeContent = fieldType.data;
258
256
  if (fieldTypeContent) {
@@ -279,14 +277,9 @@ export class CardTypeResource extends FileResource<CardType> {
279
277
 
280
278
  // Updates dependent link types.
281
279
  private async updateLinkTypes(oldName: string): Promise<void> {
282
- const linkTypes = await this.project.linkTypes(ResourcesFrom.localOnly);
283
-
284
- const updatePromises = linkTypes.map(async (linkType) => {
285
- const object = new LinkTypeResource(
286
- this.project,
287
- resourceName(linkType.name),
288
- );
280
+ const linkTypes = this.project.resources.linkTypes(ResourcesFrom.localOnly);
289
281
 
282
+ const updatePromises = linkTypes.map(async (object) => {
290
283
  const data = object.data;
291
284
  const updates: Promise<void>[] = [];
292
285
 
@@ -343,7 +336,7 @@ export class CardTypeResource extends FileResource<CardType> {
343
336
  }
344
337
  // Check that field type is defined in card type.
345
338
  if (key === 'alwaysVisibleFields' || key === 'optionallyVisibleFields') {
346
- const hasField = await this.hasFieldType(field);
339
+ const hasField = this.hasFieldType(field);
347
340
  if (!hasField) {
348
341
  throw new Error(
349
342
  `Field type '${field.name}' is not defined in card type '${this.content.name}'`,
@@ -360,15 +353,19 @@ export class CardTypeResource extends FileResource<CardType> {
360
353
  op: ChangeOperation<Type>,
361
354
  ) {
362
355
  const currentWorkflowName = op.target as string;
363
- const currentWorkflow =
364
- await this.project.resource<Workflow>(currentWorkflowName);
356
+ const currentWorkflow = this.project.resources
357
+ .byType(currentWorkflowName, 'workflows')
358
+ .show();
365
359
  if (!currentWorkflow) {
366
360
  throw new Error(
367
361
  `Workflow '${currentWorkflowName}' does not exist in the project`,
368
362
  );
369
363
  }
370
364
 
371
- const newWorkflow = await this.project.resource<Workflow>(op.to as string);
365
+ const newWorkflow = this.project.resources
366
+ .byType(op.to as string, 'workflows')
367
+ .show();
368
+
372
369
  if (!newWorkflow) {
373
370
  throw new Error(`Workflow '${op.to}' does not exist in the project`);
374
371
  }
@@ -406,6 +403,7 @@ export class CardTypeResource extends FileResource<CardType> {
406
403
  /**
407
404
  * Creates a new card type object. Base class writes the object to disk automatically.
408
405
  * @param workflowName Workflow name that this card type uses.
406
+ * @throws when workflow is empty, or does not exist in the project.
409
407
  */
410
408
  public async createCardType(workflowName: string) {
411
409
  if (!workflowName) {
@@ -416,9 +414,11 @@ export class CardTypeResource extends FileResource<CardType> {
416
414
  const validWorkflowName = Validate.getInstance().validResourceName(
417
415
  'workflows',
418
416
  resourceNameToString(resourceName(workflowName)),
419
- await this.project.projectPrefixes(),
417
+ this.project.projectPrefixes(),
420
418
  );
421
- const workflow = await this.project.resource<Workflow>(workflowName);
419
+ const workflow = this.project.resources
420
+ .byType(workflowName, 'workflows')
421
+ .show();
422
422
  if (!workflow) {
423
423
  throw new Error(
424
424
  `Workflow '${workflowName}' does not exist in the project`,
@@ -189,7 +189,8 @@ export abstract class DefaultContent {
189
189
  }
190
190
 
191
191
  /**
192
- * Default template content
192
+ * Default template content.
193
+ * @param templateName Template name
193
194
  * @returns Default template content
194
195
  */
195
196
  public static template(templateName: string): TemplateMetadata {
@@ -201,7 +202,7 @@ export abstract class DefaultContent {
201
202
 
202
203
  /**
203
204
  * Default content for workflow JSON values.
204
- * @param {string} workflowName workflow name
205
+ * @param workflowName workflow name
205
206
  * @returns Default content for workflow JSON values.
206
207
  */
207
208
  public static workflow(workflowName: string): Workflow {
@@ -11,38 +11,33 @@
11
11
  License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
12
  */
13
13
 
14
+ import {
15
+ allowed,
16
+ fromDate,
17
+ fromNumber,
18
+ fromString,
19
+ } from '../utils/value-utils.js';
20
+ import { DefaultContent } from './create-defaults.js';
21
+ import { FileResource } from './file-resource.js';
22
+ import { resourceNameToString } from '../utils/resource-utils.js';
23
+ import { sortCards } from '../utils/card-utils.js';
24
+
25
+ import * as EmailValidator from 'email-validator';
26
+
14
27
  import type {
15
- Card,
16
28
  ChangeOperation,
17
29
  Operation,
18
- Project,
19
30
  RemoveOperation,
20
- ResourceName,
21
- } from './file-resource.js';
22
- import {
23
- DefaultContent,
24
- FileResource,
25
- ResourcesFrom,
26
- resourceName,
27
- resourceNameToString,
28
- sortCards,
29
- } from './file-resource.js';
30
-
31
+ } from './resource-object.js';
32
+ import type { Card } from '../interfaces/project-interfaces.js';
31
33
  import type {
32
- CardType,
33
34
  DataType,
34
35
  EnumDefinition,
35
36
  FieldType,
36
37
  UpdateKey,
37
38
  } from '../interfaces/resource-interfaces.js';
38
- import { CardTypeResource } from './card-type-resource.js';
39
- import {
40
- allowed,
41
- fromDate,
42
- fromNumber,
43
- fromString,
44
- } from '../utils/value-utils.js';
45
- import * as EmailValidator from 'email-validator';
39
+ import type { Project } from '../containers/project.js';
40
+ import type { ResourceName } from '../utils/resource-utils.js';
46
41
 
47
42
  const SHORT_TEXT_MAX_LENGTH = 80;
48
43
 
@@ -134,7 +129,7 @@ export class FieldTypeResource extends FileResource<FieldType> {
134
129
  }
135
130
 
136
131
  // First collect the cardTypes that need to be updated.
137
- const cardTypes = await this.relevantCardTypes(ResourcesFrom.localOnly);
132
+ const cardTypes = this.relevantCardTypes();
138
133
  cardTypesThatUseThisFieldType.push(...cardTypes);
139
134
 
140
135
  // Then collect cards (both project and local template) that use those card types.
@@ -209,7 +204,7 @@ export class FieldTypeResource extends FileResource<FieldType> {
209
204
  if (!newValue) return;
210
205
 
211
206
  const removedValue = (op.target as EnumDefinition).enumValue;
212
- const cardTypes = await this.relevantCardTypes(ResourcesFrom.localOnly);
207
+ const cardTypes = this.relevantCardTypes();
213
208
  const allCards = await Promise.all(
214
209
  cardTypes.map((cardType) => this.collectCards(cardType)),
215
210
  );
@@ -255,44 +250,35 @@ export class FieldTypeResource extends FileResource<FieldType> {
255
250
  }
256
251
 
257
252
  // Card types that use field type.
258
- private async relevantCardTypes(from: ResourcesFrom): Promise<string[]> {
253
+ private relevantCardTypes(): string[] {
259
254
  const resourceName = resourceNameToString(this.resourceName);
260
- const cardTypes = await this.project.cardTypes(from);
261
-
262
- const references = await Promise.all(
263
- cardTypes.map(async (cardType) => {
264
- const metadata = await this.project.resource<CardType>(cardType.name);
265
- return metadata?.customFields.some(
266
- (field) => field.name === resourceName,
267
- )
268
- ? cardType.name
269
- : '';
270
- }),
271
- );
272
- // Remove empty values.
273
- return references.filter(Boolean);
255
+ const cardTypes = this.project.resources.cardTypes();
256
+ const references = [];
257
+ for (const cardType of cardTypes) {
258
+ const found = cardType.data?.customFields.filter(
259
+ (field) => field.name === resourceName,
260
+ );
261
+ if (found && found.length > 0 && cardType.data)
262
+ references.push(cardType.data?.name);
263
+ }
264
+ return references;
274
265
  }
275
266
 
276
267
  // Update dependant card types
277
268
  private async updateCardTypes(oldName: string) {
278
- const cardTypes = await this.project.cardTypes(ResourcesFrom.localOnly);
269
+ const cardTypes = this.project.resources.cardTypes();
279
270
  const op = {
280
271
  name: 'change',
281
272
  target: oldName,
282
273
  to: this.content.name,
283
274
  } as ChangeOperation<string>;
284
275
  for (const cardType of cardTypes) {
285
- const object = new CardTypeResource(
286
- this.project,
287
- resourceName(cardType.name),
288
- );
289
- const data = object.data;
290
- if (data) {
291
- const found = data.customFields
292
- ? data.customFields.find((item) => item.name === oldName)
276
+ if (cardType.data?.customFields) {
277
+ const found = cardType.data.customFields
278
+ ? cardType.data.customFields.find((item) => item.name === oldName)
293
279
  : undefined;
294
280
  if (found) {
295
- await object.update({ key: 'customFields' }, op);
281
+ await cardType.update({ key: 'customFields' }, op);
296
282
  }
297
283
  }
298
284
  }
@@ -474,12 +460,12 @@ export class FieldTypeResource extends FileResource<FieldType> {
474
460
  public async usage(cards?: Card[]): Promise<string[]> {
475
461
  const allCards = cards ?? super.cards();
476
462
 
477
- const [cardContentReferences, relevantLinkTypes, calculations] =
478
- await Promise.all([
479
- super.usage(allCards),
480
- this.relevantCardTypes(ResourcesFrom.all),
481
- super.calculations(),
482
- ]);
463
+ const relevantLinkTypes = this.relevantCardTypes();
464
+
465
+ const [cardContentReferences, calculations] = await Promise.all([
466
+ super.usage(allCards),
467
+ super.calculations(),
468
+ ]);
483
469
 
484
470
  const cardReferences = [
485
471
  ...this.cardsWithFieldType(allCards),
@@ -11,43 +11,18 @@
11
11
  License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
12
  */
13
13
 
14
+ import { resourceName } from '../utils/resource-utils.js';
15
+ import { ResourceObject } from './resource-object.js';
16
+ import { ResourcesFrom } from '../containers/project.js';
17
+
14
18
  import type {
15
19
  Card,
16
20
  ResourceFolderType,
17
21
  } from '../interfaces/project-interfaces.js';
18
- import type { ShowReturnType } from './resource-object.js';
19
- import {
20
- type AddOperation,
21
- type ChangeOperation,
22
- type Operation,
23
- type RemoveOperation,
24
- ResourceObject,
25
- } from './resource-object.js';
26
- import { DefaultContent } from './create-defaults.js';
27
- import { Project, ResourcesFrom } from '../containers/project.js';
22
+ import type { Project } from '../containers/project.js';
28
23
  import type { ResourceBaseMetadata } from '../interfaces/resource-interfaces.js';
29
- import {
30
- type ResourceName,
31
- resourceName,
32
- resourceNameToString,
33
- } from '../utils/resource-utils.js';
34
- import { sortCards } from '../utils/card-utils.js';
35
- import { Template } from '../containers/template.js';
36
-
37
- export {
38
- type AddOperation,
39
- type Card,
40
- type ChangeOperation,
41
- DefaultContent,
42
- type Operation,
43
- Project,
44
- RemoveOperation,
45
- ResourcesFrom,
46
- resourceName,
47
- type ResourceName,
48
- resourceNameToString,
49
- sortCards,
50
- };
24
+ import type { ResourceName } from '../utils/resource-utils.js';
25
+ import type { ShowReturnType } from './resource-object.js';
51
26
 
52
27
  /**
53
28
  * Base class for file based resources (card types, field types, link types, workflows, ...)
@@ -72,9 +47,9 @@ export abstract class FileResource<
72
47
  cardTypeName,
73
48
  );
74
49
  // ... and cards from each template that would be affected.
75
- const templates = await this.project.templates(ResourcesFrom.localOnly);
50
+ const templates = this.project.resources.templates(ResourcesFrom.localOnly);
76
51
  const templateCards = templates.map((template) => {
77
- const templateObject = new Template(this.project, template);
52
+ const templateObject = template.templateObject();
78
53
  return filteredCards(templateObject.cards(), cardTypeName);
79
54
  });
80
55
  // Return all affected cards
@@ -98,9 +73,8 @@ export abstract class FileResource<
98
73
  /**
99
74
  * Returns the resource metadata content.
100
75
  * @returns metadata content
101
- * @throws if resource does not exist.
102
76
  */
103
- public async show(): Promise<ShowReturnType<T>> {
77
+ public show(): ShowReturnType<T> {
104
78
  this.assertResourceExists();
105
79
  return this.content;
106
80
  }