@cyberismo/data-handler 0.0.6 → 0.0.8

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 (175) hide show
  1. package/README.md +1 -0
  2. package/dist/card-metadata-updater.d.ts +1 -0
  3. package/dist/card-metadata-updater.js +7 -2
  4. package/dist/card-metadata-updater.js.map +1 -1
  5. package/dist/command-handler.d.ts +6 -1
  6. package/dist/command-handler.js +16 -15
  7. package/dist/command-handler.js.map +1 -1
  8. package/dist/command-manager.d.ts +15 -4
  9. package/dist/command-manager.js +41 -9
  10. package/dist/command-manager.js.map +1 -1
  11. package/dist/commands/calculate.d.ts +4 -10
  12. package/dist/commands/calculate.js +67 -78
  13. package/dist/commands/calculate.js.map +1 -1
  14. package/dist/commands/create.d.ts +1 -1
  15. package/dist/commands/create.js +15 -10
  16. package/dist/commands/create.js.map +1 -1
  17. package/dist/commands/export.js +3 -3
  18. package/dist/commands/export.js.map +1 -1
  19. package/dist/commands/import.d.ts +3 -8
  20. package/dist/commands/import.js +17 -15
  21. package/dist/commands/import.js.map +1 -1
  22. package/dist/commands/index.d.ts +1 -2
  23. package/dist/commands/index.js +1 -2
  24. package/dist/commands/index.js.map +1 -1
  25. package/dist/commands/remove.d.ts +1 -1
  26. package/dist/commands/remove.js +4 -10
  27. package/dist/commands/remove.js.map +1 -1
  28. package/dist/commands/show.d.ts +6 -3
  29. package/dist/commands/show.js +8 -5
  30. package/dist/commands/show.js.map +1 -1
  31. package/dist/commands/validate.d.ts +0 -8
  32. package/dist/commands/validate.js +6 -36
  33. package/dist/commands/validate.js.map +1 -1
  34. package/dist/containers/project/project-content-watcher.d.ts +28 -0
  35. package/dist/containers/project/project-content-watcher.js +54 -0
  36. package/dist/containers/project/project-content-watcher.js.map +1 -0
  37. package/dist/containers/project/project-paths.js +1 -1
  38. package/dist/containers/project/project-paths.js.map +1 -1
  39. package/dist/containers/project/resource-collector.d.ts +2 -1
  40. package/dist/containers/project/resource-collector.js +33 -23
  41. package/dist/containers/project/resource-collector.js.map +1 -1
  42. package/dist/containers/project.d.ts +9 -7
  43. package/dist/containers/project.js +58 -18
  44. package/dist/containers/project.js.map +1 -1
  45. package/dist/containers/template.d.ts +1 -0
  46. package/dist/containers/template.js +7 -2
  47. package/dist/containers/template.js.map +1 -1
  48. package/dist/exceptions/index.d.ts +20 -0
  49. package/dist/exceptions/index.js +16 -0
  50. package/dist/exceptions/index.js.map +1 -1
  51. package/dist/index.d.ts +2 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/interfaces/macros.d.ts +5 -1
  54. package/dist/interfaces/project-interfaces.d.ts +5 -0
  55. package/dist/interfaces/project-interfaces.js.map +1 -1
  56. package/dist/interfaces/resource-interfaces.d.ts +14 -22
  57. package/dist/interfaces/resource-interfaces.js +10 -9
  58. package/dist/interfaces/resource-interfaces.js.map +1 -1
  59. package/dist/macros/base-macro.d.ts +2 -0
  60. package/dist/macros/base-macro.js +66 -19
  61. package/dist/macros/base-macro.js.map +1 -1
  62. package/dist/macros/graph/index.d.ts +0 -1
  63. package/dist/macros/graph/index.js +16 -12
  64. package/dist/macros/graph/index.js.map +1 -1
  65. package/dist/macros/index.d.ts +30 -3
  66. package/dist/macros/index.js +36 -6
  67. package/dist/macros/index.js.map +1 -1
  68. package/dist/macros/report/index.d.ts +13 -10
  69. package/dist/macros/report/index.js +35 -38
  70. package/dist/macros/report/index.js.map +1 -1
  71. package/dist/module-manager.d.ts +32 -11
  72. package/dist/module-manager.js +301 -147
  73. package/dist/module-manager.js.map +1 -1
  74. package/dist/project-settings.js +8 -8
  75. package/dist/project-settings.js.map +1 -1
  76. package/dist/resources/array-handler.js +6 -1
  77. package/dist/resources/array-handler.js.map +1 -1
  78. package/dist/resources/card-type-resource.d.ts +13 -9
  79. package/dist/resources/card-type-resource.js +47 -23
  80. package/dist/resources/card-type-resource.js.map +1 -1
  81. package/dist/resources/create-defaults.d.ts +10 -9
  82. package/dist/resources/create-defaults.js +15 -12
  83. package/dist/resources/create-defaults.js.map +1 -1
  84. package/dist/resources/field-type-resource.d.ts +0 -1
  85. package/dist/resources/field-type-resource.js +2 -10
  86. package/dist/resources/field-type-resource.js.map +1 -1
  87. package/dist/resources/file-resource.d.ts +7 -7
  88. package/dist/resources/file-resource.js +32 -7
  89. package/dist/resources/file-resource.js.map +1 -1
  90. package/dist/resources/folder-resource.d.ts +10 -9
  91. package/dist/resources/folder-resource.js +10 -9
  92. package/dist/resources/folder-resource.js.map +1 -1
  93. package/dist/resources/report-resource.d.ts +5 -6
  94. package/dist/resources/report-resource.js +16 -7
  95. package/dist/resources/report-resource.js.map +1 -1
  96. package/dist/resources/template-resource.d.ts +5 -6
  97. package/dist/resources/template-resource.js +7 -6
  98. package/dist/resources/template-resource.js.map +1 -1
  99. package/dist/resources/workflow-resource.d.ts +15 -8
  100. package/dist/resources/workflow-resource.js +124 -8
  101. package/dist/resources/workflow-resource.js.map +1 -1
  102. package/dist/types/queries.d.ts +11 -10
  103. package/dist/types/queries.js +10 -9
  104. package/dist/types/queries.js.map +1 -1
  105. package/dist/utils/clingo-fact-builder.d.ts +1 -0
  106. package/dist/utils/clingo-fact-builder.js +8 -3
  107. package/dist/utils/clingo-fact-builder.js.map +1 -1
  108. package/dist/utils/clingo-facts.js +15 -11
  109. package/dist/utils/clingo-facts.js.map +1 -1
  110. package/dist/utils/constants.d.ts +18 -12
  111. package/dist/utils/constants.js +18 -11
  112. package/dist/utils/constants.js.map +1 -1
  113. package/dist/utils/log-utils.d.ts +15 -2
  114. package/dist/utils/log-utils.js +20 -37
  115. package/dist/utils/log-utils.js.map +1 -1
  116. package/dist/utils/report.d.ts +27 -0
  117. package/dist/utils/report.js +60 -0
  118. package/dist/utils/report.js.map +1 -0
  119. package/dist/utils/resource-utils.js +3 -0
  120. package/dist/utils/resource-utils.js.map +1 -1
  121. package/dist/utils/sanitize-svg.d.ts +3 -4
  122. package/dist/utils/sanitize-svg.js +4 -7
  123. package/dist/utils/sanitize-svg.js.map +1 -1
  124. package/dist/utils/validate.js +2 -1
  125. package/dist/utils/validate.js.map +1 -1
  126. package/package.json +9 -11
  127. package/src/card-metadata-updater.ts +7 -2
  128. package/src/command-handler.ts +23 -13
  129. package/src/command-manager.ts +54 -13
  130. package/src/commands/calculate.ts +90 -106
  131. package/src/commands/create.ts +18 -10
  132. package/src/commands/export.ts +3 -2
  133. package/src/commands/import.ts +30 -17
  134. package/src/commands/index.ts +0 -2
  135. package/src/commands/remove.ts +7 -12
  136. package/src/commands/show.ts +13 -5
  137. package/src/commands/validate.ts +14 -44
  138. package/src/containers/project/project-content-watcher.ts +65 -0
  139. package/src/containers/project/project-paths.ts +1 -1
  140. package/src/containers/project/resource-collector.ts +33 -14
  141. package/src/containers/project.ts +96 -19
  142. package/src/containers/template.ts +7 -2
  143. package/src/exceptions/index.ts +36 -0
  144. package/src/index.ts +2 -0
  145. package/src/interfaces/macros.ts +5 -1
  146. package/src/interfaces/project-interfaces.ts +8 -0
  147. package/src/interfaces/resource-interfaces.ts +15 -22
  148. package/src/macros/base-macro.ts +89 -25
  149. package/src/macros/graph/index.ts +22 -12
  150. package/src/macros/index.ts +61 -8
  151. package/src/macros/report/index.ts +42 -43
  152. package/src/module-manager.ts +383 -177
  153. package/src/project-settings.ts +9 -11
  154. package/src/resources/array-handler.ts +7 -2
  155. package/src/resources/card-type-resource.ts +61 -46
  156. package/src/resources/create-defaults.ts +15 -12
  157. package/src/resources/field-type-resource.ts +2 -17
  158. package/src/resources/file-resource.ts +46 -8
  159. package/src/resources/folder-resource.ts +11 -10
  160. package/src/resources/report-resource.ts +19 -7
  161. package/src/resources/template-resource.ts +7 -6
  162. package/src/resources/workflow-resource.ts +155 -8
  163. package/src/types/queries.ts +11 -10
  164. package/src/utils/clingo-fact-builder.ts +8 -3
  165. package/src/utils/clingo-facts.ts +18 -12
  166. package/src/utils/constants.ts +20 -12
  167. package/src/utils/log-utils.ts +24 -45
  168. package/src/utils/report.ts +86 -0
  169. package/src/utils/resource-utils.ts +4 -0
  170. package/src/utils/sanitize-svg.ts +4 -9
  171. package/src/utils/validate.ts +3 -2
  172. package/dist/commands/export-site.d.ts +0 -45
  173. package/dist/commands/export-site.js +0 -301
  174. package/dist/commands/export-site.js.map +0 -1
  175. package/src/commands/export-site.ts +0 -356
@@ -72,15 +72,20 @@ export class Create {
72
72
  },
73
73
  ];
74
74
 
75
- static gitIgnoreContent: string = `.calc\n
76
- .asciidoctor\n
77
- .vscode\n
78
- *.html\n
79
- *.pdf\n
80
- *.puml\n
81
- **/.DS_Store\n
82
- *-debug.log\n
83
- *-error.log\n`;
75
+ static gitIgnoreContent: string[] = [
76
+ '.calc',
77
+ '.asciidoctor',
78
+ '.vscode',
79
+ '*.html',
80
+ '*.pdf',
81
+ '*.puml',
82
+ '**/.DS_Store',
83
+ '*-debug.log',
84
+ '*-error.log',
85
+ '.temp',
86
+ '.logs',
87
+ '.cache',
88
+ ];
84
89
 
85
90
  /**
86
91
  * Adds new cards to a template.
@@ -510,7 +515,10 @@ export class Create {
510
515
  });
511
516
 
512
517
  try {
513
- await writeFile(join(projectPath, '.gitignore'), this.gitIgnoreContent);
518
+ await writeFile(
519
+ join(projectPath, '.gitignore'),
520
+ this.gitIgnoreContent.join('\n') + '\n',
521
+ );
514
522
  } catch {
515
523
  console.error('Failed to create project');
516
524
  }
@@ -196,16 +196,17 @@ export class Export {
196
196
  );
197
197
 
198
198
  let asciiDocContent = '';
199
- const projectPath = this.project.basePath;
199
+ const project = this.project;
200
200
  try {
201
201
  const { evaluateMacros } = await import('../macros/index.js');
202
202
  asciiDocContent = await evaluateMacros(
203
203
  cardDetailsResponse.content || '',
204
204
  {
205
205
  mode: 'static',
206
- projectPath,
206
+ project,
207
207
  cardKey: card.key,
208
208
  },
209
+ this.calculateCmd,
209
210
  );
210
211
  } catch (error) {
211
212
  asciiDocContent = `Macro error: ${error instanceof Error ? error.message : 'Unknown error'}\n\n${asciiDocContent}`;
@@ -14,7 +14,10 @@
14
14
  import type { CardType } from '../interfaces/resource-interfaces.js';
15
15
  import { type Create, Validate } from './index.js';
16
16
  import { ModuleManager } from '../module-manager.js';
17
- import type { ModuleSettingOptions } from '../interfaces/project-interfaces.js';
17
+ import type {
18
+ Credentials,
19
+ ModuleSettingOptions,
20
+ } from '../interfaces/project-interfaces.js';
18
21
  import type { Project } from '../containers/project.js';
19
22
  import { readCsvFile } from '../utils/csv.js';
20
23
  import { resourceName } from '../utils/resource-utils.js';
@@ -26,7 +29,7 @@ export class Import {
26
29
  private project: Project,
27
30
  private createCmd: Create,
28
31
  ) {
29
- this.moduleManager = new ModuleManager(this.project, this);
32
+ this.moduleManager = new ModuleManager(this.project);
30
33
  }
31
34
 
32
35
  /**
@@ -131,7 +134,10 @@ export class Import {
131
134
  destination?: string,
132
135
  options?: ModuleSettingOptions,
133
136
  ) {
134
- const gitModule = source.startsWith('https');
137
+ const beforeImportValidateErrors = await Validate.getInstance().validate(
138
+ this.project.basePath,
139
+ );
140
+ const gitModule = source.startsWith('https') || source.startsWith('git@');
135
141
  const modulePrefix = gitModule
136
142
  ? await this.moduleManager.importGitModule(source, options)
137
143
  : await this.moduleManager.importFileModule(source, destination);
@@ -142,28 +148,35 @@ export class Import {
142
148
  );
143
149
  }
144
150
 
145
- // Add module as a dependency.
146
- return this.project.importModule({
151
+ const moduleSettings = {
147
152
  name: modulePrefix,
148
153
  branch: options ? options.branch : undefined,
149
154
  private: options ? options.private : undefined,
150
155
  location: gitModule ? source : `file:${source}`,
151
- });
152
- }
156
+ };
153
157
 
154
- /**
155
- * Updates all imported modules.
156
- */
157
- public async updateAllModules() {
158
- return this.moduleManager.update();
158
+ // Fetch module dependencies.
159
+ await this.moduleManager.updateModule(moduleSettings, options?.credentials);
160
+
161
+ // Add module as a dependency.
162
+ await this.project.importModule(moduleSettings);
163
+
164
+ // Validate the project after module has been imported
165
+ const afterImportValidateErrors = await Validate.getInstance().validate(
166
+ this.project.basePath,
167
+ );
168
+ if (afterImportValidateErrors.length > beforeImportValidateErrors.length) {
169
+ console.error(
170
+ `There are new validations errors after importing the module. Check the project`,
171
+ );
172
+ }
159
173
  }
160
174
 
161
175
  /**
162
- * Updates 'moduleName' module from its source.
163
- * Modules using gitUrl, are first copied to .temp
164
- * @param moduleName module name (prefix) to update
176
+ * Updates all imported modules.
177
+ * @param credentials Optional credentials for private modules.
165
178
  */
166
- public async updateExistingModule(moduleName: string) {
167
- await this.moduleManager.importFileModule(moduleName);
179
+ public async updateAllModules(credentials?: Credentials) {
180
+ return this.moduleManager.updateModules(credentials);
168
181
  }
169
182
  }
@@ -15,7 +15,6 @@ import { Calculate } from './calculate.js';
15
15
  import { Create } from './create.js';
16
16
  import { Edit } from './edit.js';
17
17
  import { Export } from './export.js';
18
- import { ExportSite } from './export-site.js';
19
18
  import { Import } from './import.js';
20
19
  import { Move } from './move.js';
21
20
  import { Remove } from './remove.js';
@@ -30,7 +29,6 @@ export {
30
29
  Create,
31
30
  Edit,
32
31
  Export,
33
- ExportSite,
34
32
  Import,
35
33
  Move,
36
34
  Remove,
@@ -17,6 +17,7 @@ import { join, sep } from 'node:path';
17
17
  import { ActionGuard } from '../permissions/action-guard.js';
18
18
  import type { Calculate } from './index.js';
19
19
  import { deleteDir, deleteFile } from '../utils/file-utils.js';
20
+ import { ModuleManager } from '../module-manager.js';
20
21
  import { Project } from '../containers/project.js';
21
22
  import type { RemovableResourceTypes } from '../interfaces/project-interfaces.js';
22
23
  import { resourceName } from '../utils/resource-utils.js';
@@ -27,10 +28,13 @@ const MODULES_PATH = `${sep}modules${sep}`;
27
28
  * Remove command.
28
29
  */
29
30
  export class Remove {
31
+ private moduleManager: ModuleManager;
30
32
  constructor(
31
33
  private project: Project,
32
34
  private calculateCmd: Calculate,
33
- ) {}
35
+ ) {
36
+ this.moduleManager = new ModuleManager(this.project);
37
+ }
34
38
 
35
39
  // True, if resource is a project resource
36
40
  private projectResource(type: RemovableResourceTypes): boolean {
@@ -182,16 +186,6 @@ export class Remove {
182
186
  await this.project.updateCardMetadataKey(sourceCardKey, 'links', newLinks);
183
187
  }
184
188
 
185
- // Removes modules from project
186
- private async removeModule(moduleName: string) {
187
- const module = await this.project.module(moduleName);
188
- if (!module) {
189
- throw new Error(`Module '${moduleName}' not found`);
190
- }
191
- await deleteDir(module.path);
192
- await this.project.removeModule(moduleName);
193
- }
194
-
195
189
  /**
196
190
  * Removes either attachment, card, imported module, link or resource from project.
197
191
  * @param type Type of resource
@@ -236,7 +230,8 @@ export class Remove {
236
230
  else if (type == 'card') return this.removeCard(targetName);
237
231
  else if (type == 'link')
238
232
  return this.removeLink(targetName, rest[0], rest[1], rest.at(2));
239
- else if (type == 'module') return this.removeModule(targetName);
233
+ else if (type == 'module')
234
+ return this.moduleManager.removeModule(targetName);
240
235
  else if (type == 'label') return this.removeLabel(targetName, rest[0]);
241
236
  }
242
237
  throw new Error(`Unknown resource type '${type}'`);
@@ -29,6 +29,7 @@ import type {
29
29
  ProjectFetchCardDetails,
30
30
  ProjectMetadata,
31
31
  Resource,
32
+ CardLocation,
32
33
  } from '../interfaces/project-interfaces.js';
33
34
  import type {
34
35
  CardType,
@@ -43,6 +44,7 @@ import { UserPreferences } from '../utils/user-preferences.js';
43
44
 
44
45
  import ReportMacro from '../macros/report/index.js';
45
46
  import TaskQueue from '../macros/task-queue.js';
47
+ import type { Calculate } from './calculate.js';
46
48
 
47
49
  /**
48
50
  * Show command.
@@ -52,7 +54,10 @@ export class Show {
52
54
  string,
53
55
  (from?: ResourcesFrom) => Promise<Resource[]>
54
56
  >;
55
- constructor(private project: Project) {
57
+ constructor(
58
+ private project: Project,
59
+ private calculate: Calculate,
60
+ ) {
56
61
  this.resourceFunction = new Map([
57
62
  ['cardTypes', this.project.cardTypes.bind(this.project)],
58
63
  ['fieldTypes', this.project.fieldTypes.bind(this.project)],
@@ -250,10 +255,13 @@ export class Show {
250
255
 
251
256
  /**
252
257
  * Shows all cards (either template or project cards) from a project.
258
+ * @param cardsFrom - The location from which to look for cards. Either from the project, templates or both.
253
259
  * @returns cards list array
254
260
  */
255
- public async showCards(): Promise<CardListContainer[]> {
256
- return this.project.listCards();
261
+ public async showCards(
262
+ cardsFrom?: CardLocation,
263
+ ): Promise<CardListContainer[]> {
264
+ return this.project.listCards(cardsFrom);
257
265
  }
258
266
 
259
267
  /**
@@ -351,10 +359,10 @@ export class Show {
351
359
  throw new Error(`Report '${reportName}' does not exist`);
352
360
  }
353
361
 
354
- const reportMacro = new ReportMacro(new TaskQueue());
362
+ const reportMacro = new ReportMacro(new TaskQueue(), this.calculate);
355
363
  const result = await reportMacro.handleInject(
356
364
  {
357
- projectPath: this.project.basePath,
365
+ project: this.project,
358
366
  cardKey: cardKey,
359
367
  mode: 'static',
360
368
  },
@@ -20,7 +20,7 @@ import { readdir } from 'node:fs/promises';
20
20
  // dependencies
21
21
  import { Validator as JSONValidator, type Schema } from 'jsonschema';
22
22
  import { Validator as DirectoryValidator } from 'directory-schema-validator';
23
- import { parentSchema, schemas } from '@cyberismo/resources';
23
+ import { parentSchema, schemas } from '@cyberismo/assets';
24
24
 
25
25
  // data-handler
26
26
  import type {
@@ -52,7 +52,7 @@ const SHORT_TEXT_MAX_LENGTH = 80;
52
52
 
53
53
  import * as EmailValidator from 'email-validator';
54
54
  import { evaluateMacros } from '../macros/index.js';
55
-
55
+ import { Calculate } from './calculate.js';
56
56
  const baseDir = dirname(fileURLToPath(import.meta.url));
57
57
  const subFoldersToValidate = ['.cards', 'cardRoot'];
58
58
 
@@ -111,7 +111,7 @@ export class Validate {
111
111
  // Loads child schemas to validator.
112
112
  private addChildSchemas() {
113
113
  schemas.forEach((schema) => {
114
- this.validator.addSchema(schema, schema.$id);
114
+ this.validator.addSchema(schema as Schema, schema.$id);
115
115
  });
116
116
  }
117
117
 
@@ -355,7 +355,7 @@ export class Validate {
355
355
  }
356
356
  const result = this.validator.validate(content, schema);
357
357
  for (const error of result.errors) {
358
- const msg = `Validation error from '${fullPath}': ${error.message}.`;
358
+ const msg = `Validation error from '${fullPath}': ${error.property} ${error.message}.`;
359
359
  messages.push(msg);
360
360
  }
361
361
  }
@@ -547,6 +547,7 @@ export class Validate {
547
547
  } else {
548
548
  const errorMsg: string[] = [];
549
549
  const project = new Project(projectPath);
550
+ const calculate = new Calculate(project);
550
551
 
551
552
  // Then, validate that each 'contentSchema' children as well.
552
553
  const result = await this.readAndValidateContentFiles(
@@ -590,11 +591,15 @@ export class Validate {
590
591
 
591
592
  // Validate macros in content
592
593
  if (card.content) {
593
- await evaluateMacros(card.content, {
594
- mode: 'validate',
595
- projectPath,
596
- cardKey: card.key,
597
- });
594
+ await evaluateMacros(
595
+ card.content,
596
+ {
597
+ mode: 'validate',
598
+ project,
599
+ cardKey: card.key,
600
+ },
601
+ calculate,
602
+ );
598
603
  }
599
604
  }
600
605
  if (errorMsg.length) {
@@ -699,41 +704,6 @@ export class Validate {
699
704
  return contentValidated && lengthValidated;
700
705
  }
701
706
 
702
- /**
703
- * Validate schema that matches schemaId from path.
704
- * @param projectPath path to schema
705
- * @param schemaId schema's id
706
- * @returns string containing all validation errors
707
- * @todo - unused; remove?
708
- */
709
- public async validateSchema(
710
- projectPath: string,
711
- schemaId: string,
712
- ): Promise<string> {
713
- const validationErrors: string[] = [];
714
- if (!schemaId.startsWith('/')) {
715
- schemaId = '/' + schemaId;
716
- }
717
- const activeJsonSchema = this.validator.schemas[schemaId];
718
- if (activeJsonSchema === undefined) {
719
- throw new Error(`Unknown schema '${schemaId}'`);
720
- } else {
721
- let contentFile = '';
722
- try {
723
- contentFile = await readJsonFile(projectPath);
724
- } catch {
725
- throw new Error(`Path is not valid ${projectPath}`);
726
- }
727
-
728
- const result = this.validator.validate(contentFile, activeJsonSchema);
729
- for (const error of result.errors) {
730
- const msg = `Schema '${schemaId}' validation Error: ${error.message}\n`;
731
- validationErrors.push(msg);
732
- }
733
- }
734
- return validationErrors.join('\n');
735
- }
736
-
737
707
  /**
738
708
  * Validates that card's custom fields are according to schema and have correct data in them.
739
709
  * @param project currently used Project
@@ -0,0 +1,65 @@
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 { watch } from 'node:fs';
15
+
16
+ import { getChildLogger } from '../../utils/log-utils.js';
17
+
18
+ /**
19
+ * Class that starts watching certain path for changes.
20
+ * Generally we are not interested for file renames, as they are handled
21
+ * through rename command, thus there is an option to ignore those.
22
+ */
23
+ export class ContentWatcher {
24
+ private watcher;
25
+ private abortController = new AbortController();
26
+
27
+ constructor(
28
+ ignoreRenames: boolean,
29
+ private watchPath: string,
30
+ callback: (fileName: string) => void,
31
+ ) {
32
+ this.watcher = watch(
33
+ this.watchPath,
34
+ {
35
+ persistent: true,
36
+ recursive: true,
37
+ signal: this.abortController.signal,
38
+ },
39
+ (eventType, filename) => {
40
+ if ((ignoreRenames && eventType === 'rename') || !filename) {
41
+ return;
42
+ }
43
+ callback(filename);
44
+ },
45
+ ).on('error', (error) => {
46
+ ContentWatcher.logger.error(error, 'Watch error');
47
+ this.close();
48
+ });
49
+ this.watcher.unref();
50
+ }
51
+
52
+ // Returns instance of logger.
53
+ private static get logger() {
54
+ return getChildLogger({
55
+ module: 'contentWatcher',
56
+ });
57
+ }
58
+
59
+ /**
60
+ * Close content watcher. Removes watcher.
61
+ */
62
+ public close() {
63
+ this.abortController.abort();
64
+ }
65
+ }
@@ -81,7 +81,7 @@ export class ProjectPaths {
81
81
  }
82
82
 
83
83
  public get logPath(): string {
84
- return join(this.resourcesFolder, 'dh.log');
84
+ return join(this.path, '.logs', 'cyberismo_data-handler.log');
85
85
  }
86
86
 
87
87
  public get modulesFolder(): string {
@@ -55,17 +55,31 @@ class ResourceCollection {
55
55
  * @param type Resource array type to return.
56
56
  * @returns resource array of a give type.
57
57
  */
58
- public resourceArray(type: ResourceFolderType): Resource[] {
59
- if (type === 'calculations') return this.calculations;
60
- if (type === 'cardTypes') return this.cardTypes;
61
- if (type === 'fieldTypes') return this.fieldTypes;
62
- if (type === 'graphViews') return this.graphViews;
63
- if (type === 'graphModels') return this.graphModels;
64
- if (type === 'linkTypes') return this.linkTypes;
65
- if (type === 'reports') return this.reports;
66
- if (type === 'templates') return this.templates;
67
- if (type === 'workflows') return this.workflows;
68
- throw new Error(`Unknown resource type '${type}'`);
58
+ public resourceArray(
59
+ type: ResourceFolderType,
60
+ moduleName?: string,
61
+ ): Resource[] {
62
+ let resources: Resource[] = [];
63
+
64
+ if (type === 'calculations') resources = this.calculations;
65
+ else if (type === 'cardTypes') resources = this.cardTypes;
66
+ else if (type === 'fieldTypes') resources = this.fieldTypes;
67
+ else if (type === 'graphViews') resources = this.graphViews;
68
+ else if (type === 'graphModels') resources = this.graphModels;
69
+ else if (type === 'linkTypes') resources = this.linkTypes;
70
+ else if (type === 'reports') resources = this.reports;
71
+ else if (type === 'templates') resources = this.templates;
72
+ else if (type === 'workflows') resources = this.workflows;
73
+ else throw new Error(`Unknown resource type '${type}'`);
74
+
75
+ if (moduleName) {
76
+ resources = resources.filter((item) => {
77
+ const { prefix } = resourceName(item.name);
78
+ return moduleName === prefix;
79
+ });
80
+ }
81
+
82
+ return resources;
69
83
  }
70
84
  }
71
85
 
@@ -162,6 +176,7 @@ export class ResourceCollector {
162
176
  // Adds a resource type from all modules.
163
177
  private async addResourcesFromModules(
164
178
  type: ResourceFolderType,
179
+ moduleName?: string,
165
180
  ): Promise<Resource[]> {
166
181
  try {
167
182
  // 'modules' is a bit special; it is collected separately from actual resources.
@@ -174,7 +189,7 @@ export class ResourceCollector {
174
189
  }
175
190
 
176
191
  await this.addModuleResources();
177
- return this.modules.resourceArray(type);
192
+ return this.modules.resourceArray(type, moduleName);
178
193
  } catch {
179
194
  return [];
180
195
  }
@@ -261,10 +276,14 @@ export class ResourceCollector {
261
276
  /**
262
277
  * Collect specific resource from modules.
263
278
  * @param type Type of resource (e.g. 'templates').
279
+ * @param moduleName Name of the module to collect resources from
264
280
  * @returns array of collected items.
265
281
  */
266
- public async collectResourcesFromModules(type: ResourceFolderType) {
267
- return (await this.addResourcesFromModules(type)).map((item) =>
282
+ public async collectResourcesFromModules(
283
+ type: ResourceFolderType,
284
+ moduleName?: string,
285
+ ) {
286
+ return (await this.addResourcesFromModules(type, moduleName)).map((item) =>
268
287
  stripExtension(item.name),
269
288
  );
270
289
  }