@cyberismo/data-handler 0.0.12 → 0.0.14

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 (130) hide show
  1. package/dist/command-handler.d.ts +24 -42
  2. package/dist/command-handler.js +33 -26
  3. package/dist/command-handler.js.map +1 -1
  4. package/dist/commands/create.d.ts +3 -3
  5. package/dist/commands/create.js +7 -22
  6. package/dist/commands/create.js.map +1 -1
  7. package/dist/commands/edit.d.ts +12 -11
  8. package/dist/commands/edit.js +41 -16
  9. package/dist/commands/edit.js.map +1 -1
  10. package/dist/commands/fetch.js +2 -1
  11. package/dist/commands/fetch.js.map +1 -1
  12. package/dist/commands/import.js +2 -2
  13. package/dist/commands/import.js.map +1 -1
  14. package/dist/commands/remove.js +6 -5
  15. package/dist/commands/remove.js.map +1 -1
  16. package/dist/commands/rename.d.ts +1 -0
  17. package/dist/commands/rename.js +11 -0
  18. package/dist/commands/rename.js.map +1 -1
  19. package/dist/commands/show.d.ts +4 -0
  20. package/dist/commands/show.js +6 -12
  21. package/dist/commands/show.js.map +1 -1
  22. package/dist/commands/update.d.ts +11 -1
  23. package/dist/commands/update.js +14 -2
  24. package/dist/commands/update.js.map +1 -1
  25. package/dist/commands/validate.d.ts +2 -1
  26. package/dist/commands/validate.js +4 -3
  27. package/dist/commands/validate.js.map +1 -1
  28. package/dist/containers/card-container.js +1 -1
  29. package/dist/containers/card-container.js.map +1 -1
  30. package/dist/containers/project/calculation-engine.js +18 -18
  31. package/dist/containers/project/calculation-engine.js.map +1 -1
  32. package/dist/containers/project.d.ts +2 -1
  33. package/dist/containers/project.js +5 -1
  34. package/dist/containers/project.js.map +1 -1
  35. package/dist/index.d.ts +4 -2
  36. package/dist/index.js.map +1 -1
  37. package/dist/interfaces/command-options.d.ts +81 -0
  38. package/dist/interfaces/command-options.js +14 -0
  39. package/dist/interfaces/command-options.js.map +1 -0
  40. package/dist/interfaces/folder-content-interfaces.d.ts +56 -0
  41. package/dist/interfaces/folder-content-interfaces.js +47 -0
  42. package/dist/interfaces/folder-content-interfaces.js.map +1 -0
  43. package/dist/interfaces/project-interfaces.d.ts +11 -9
  44. package/dist/interfaces/project-interfaces.js +10 -8
  45. package/dist/interfaces/project-interfaces.js.map +1 -1
  46. package/dist/interfaces/resource-interfaces.d.ts +37 -10
  47. package/dist/interfaces/resource-interfaces.js.map +1 -1
  48. package/dist/macros/report/index.js +4 -4
  49. package/dist/macros/report/index.js.map +1 -1
  50. package/dist/resources/calculation-resource.d.ts +71 -0
  51. package/dist/resources/calculation-resource.js +130 -0
  52. package/dist/resources/calculation-resource.js.map +1 -0
  53. package/dist/resources/card-type-resource.js +11 -5
  54. package/dist/resources/card-type-resource.js.map +1 -1
  55. package/dist/resources/create-defaults.d.ts +13 -6
  56. package/dist/resources/create-defaults.js +19 -5
  57. package/dist/resources/create-defaults.js.map +1 -1
  58. package/dist/resources/field-type-resource.js +1 -1
  59. package/dist/resources/field-type-resource.js.map +1 -1
  60. package/dist/resources/file-resource.js +9 -3
  61. package/dist/resources/file-resource.js.map +1 -1
  62. package/dist/resources/folder-resource.d.ts +38 -10
  63. package/dist/resources/folder-resource.js +108 -12
  64. package/dist/resources/folder-resource.js.map +1 -1
  65. package/dist/resources/graph-model-resource.d.ts +7 -4
  66. package/dist/resources/graph-model-resource.js +12 -25
  67. package/dist/resources/graph-model-resource.js.map +1 -1
  68. package/dist/resources/graph-view-resource.d.ts +7 -4
  69. package/dist/resources/graph-view-resource.js +12 -26
  70. package/dist/resources/graph-view-resource.js.map +1 -1
  71. package/dist/resources/link-type-resource.js +1 -1
  72. package/dist/resources/link-type-resource.js.map +1 -1
  73. package/dist/resources/report-resource.d.ts +14 -10
  74. package/dist/resources/report-resource.js +41 -45
  75. package/dist/resources/report-resource.js.map +1 -1
  76. package/dist/resources/resource-object.d.ts +7 -0
  77. package/dist/resources/resource-object.js +14 -2
  78. package/dist/resources/resource-object.js.map +1 -1
  79. package/dist/resources/template-resource.d.ts +5 -1
  80. package/dist/resources/template-resource.js +12 -7
  81. package/dist/resources/template-resource.js.map +1 -1
  82. package/dist/resources/workflow-resource.js +6 -0
  83. package/dist/resources/workflow-resource.js.map +1 -1
  84. package/dist/utils/constants.js +1 -0
  85. package/dist/utils/constants.js.map +1 -1
  86. package/dist/utils/error-utils.d.ts +34 -0
  87. package/dist/utils/error-utils.js +56 -0
  88. package/dist/utils/error-utils.js.map +1 -0
  89. package/dist/utils/log-utils.d.ts +0 -27
  90. package/dist/utils/log-utils.js +0 -58
  91. package/dist/utils/log-utils.js.map +1 -1
  92. package/dist/utils/user-preferences.js +6 -3
  93. package/dist/utils/user-preferences.js.map +1 -1
  94. package/package.json +9 -7
  95. package/src/command-handler.ts +74 -59
  96. package/src/commands/create.ts +10 -28
  97. package/src/commands/edit.ts +51 -26
  98. package/src/commands/fetch.ts +2 -1
  99. package/src/commands/import.ts +2 -0
  100. package/src/commands/remove.ts +3 -2
  101. package/src/commands/rename.ts +20 -0
  102. package/src/commands/show.ts +5 -13
  103. package/src/commands/update.ts +20 -2
  104. package/src/commands/validate.ts +7 -3
  105. package/src/containers/card-container.ts +1 -1
  106. package/src/containers/project/calculation-engine.ts +23 -23
  107. package/src/containers/project.ts +4 -1
  108. package/src/index.ts +36 -2
  109. package/src/interfaces/command-options.ts +144 -0
  110. package/src/interfaces/folder-content-interfaces.ts +81 -0
  111. package/src/interfaces/project-interfaces.ts +12 -9
  112. package/src/interfaces/resource-interfaces.ts +51 -12
  113. package/src/macros/report/index.ts +4 -4
  114. package/src/resources/calculation-resource.ts +171 -0
  115. package/src/resources/card-type-resource.ts +12 -6
  116. package/src/resources/create-defaults.ts +21 -5
  117. package/src/resources/field-type-resource.ts +1 -1
  118. package/src/resources/file-resource.ts +9 -3
  119. package/src/resources/folder-resource.ts +150 -20
  120. package/src/resources/graph-model-resource.ts +16 -27
  121. package/src/resources/graph-view-resource.ts +16 -28
  122. package/src/resources/link-type-resource.ts +1 -1
  123. package/src/resources/report-resource.ts +60 -62
  124. package/src/resources/resource-object.ts +30 -7
  125. package/src/resources/template-resource.ts +12 -7
  126. package/src/resources/workflow-resource.ts +4 -0
  127. package/src/utils/constants.ts +1 -0
  128. package/src/utils/error-utils.ts +62 -0
  129. package/src/utils/log-utils.ts +0 -68
  130. package/src/utils/user-preferences.ts +7 -3
@@ -1,13 +1,14 @@
1
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/>.
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2024
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/>.
11
12
  */
12
13
 
13
14
  // node
@@ -16,18 +17,19 @@ import { homedir } from 'node:os';
16
17
  import { spawnSync } from 'node:child_process';
17
18
 
18
19
  import { ActionGuard } from '../permissions/action-guard.js';
20
+ import { CalculationResource } from '../resources/calculation-resource.js';
21
+ import { FolderResource } from '../resources/folder-resource.js';
22
+ import { Project } from '../containers/project.js';
23
+ import { propertyName } from '../interfaces/folder-content-interfaces.js';
24
+ import { resourceNameToString } from '../utils/resource-utils.js';
25
+ import { UserPreferences } from '../utils/user-preferences.js';
26
+
27
+ import type { ContentPropertyName } from '../interfaces/folder-content-interfaces.js';
19
28
  import type {
20
29
  MetadataContent,
21
30
  ResourceFolderType,
22
31
  } from '../interfaces/project-interfaces.js';
23
- import { Project } from '../containers/project.js';
24
- import { UserPreferences } from '../utils/user-preferences.js';
25
- import {
26
- type ResourceName,
27
- resourceNameToString,
28
- } from '../utils/resource-utils.js';
29
- import { FolderResource } from '../resources/folder-resource.js';
30
- import { writeFile } from 'node:fs/promises';
32
+ import type { ResourceName } from '../utils/resource-utils.js';
31
33
 
32
34
  export class Edit {
33
35
  private project: Project;
@@ -61,15 +63,21 @@ export class Edit {
61
63
  `Resource '${resourceNameString}' does not exist in the project`,
62
64
  );
63
65
  }
64
- await writeFile(
65
- join(
66
- this.project.paths.calculationProjectFolder,
67
- resourceName.identifier + '.lp',
68
- ),
69
- changedContent,
66
+ const calculationResource = new CalculationResource(
67
+ this.project,
68
+ resourceName,
69
+ );
70
+ const contentUpdateKey = {
71
+ key: 'content',
72
+ subKey: 'calculation',
73
+ };
74
+ await calculationResource.update(
75
+ // TODO: Let's fix this while we get rid of updating filenames directly a bit later.
76
+ contentUpdateKey as unknown as ContentPropertyName,
70
77
  {
71
- encoding: 'utf-8',
72
- flag: 'r+',
78
+ name: 'change',
79
+ target: resourceNameString,
80
+ to: changedContent,
73
81
  },
74
82
  );
75
83
  }
@@ -201,6 +209,23 @@ export class Edit {
201
209
  `Resource '${resourceNameString}' is not a folder resource`,
202
210
  );
203
211
  }
204
- return resource.updateFile(fileName, changedContent);
212
+
213
+ // TODO: The caller should not pass filename, but content type
214
+ // Once that is in place, this check can be removed
215
+ const propName: ContentPropertyName | undefined = propertyName(fileName);
216
+ if (!propName) {
217
+ throw new Error(`File '${fileName}' is not allowed`);
218
+ }
219
+
220
+ const contentUpdateKey = {
221
+ key: 'content',
222
+ subKey: propName,
223
+ };
224
+ // TODO: Let's fix this while we get rid of updating filenames directly a bit later.
225
+ return resource.update(contentUpdateKey as unknown as ContentPropertyName, {
226
+ name: 'change',
227
+ target: '',
228
+ to: changedContent,
229
+ });
205
230
  }
206
231
  }
@@ -18,7 +18,8 @@ import type { Project } from '../containers/project.js';
18
18
  import { writeJsonFile } from '../utils/json.js';
19
19
  import { validateJson } from '../utils/validate.js';
20
20
  import { type ModuleSetting } from '../interfaces/project-interfaces.js';
21
- import { errorFunction, getChildLogger } from '../utils/log-utils.js';
21
+ import { errorFunction } from '../utils/error-utils.js';
22
+ import { getChildLogger } from '../utils/log-utils.js';
22
23
 
23
24
  const FETCH_TIMEOUT = 30000; // 30s timeout for fetching a hub file.
24
25
  const MAX_RESPONSE_SIZE = 1024 * 1024; // 1MB limit for safety
@@ -136,6 +136,7 @@ export class Import {
136
136
  ) {
137
137
  const beforeImportValidateErrors = await Validate.getInstance().validate(
138
138
  this.project.basePath,
139
+ () => this.project,
139
140
  );
140
141
  const gitModule = source.startsWith('https') || source.startsWith('git@');
141
142
  const modulePrefix = gitModule
@@ -164,6 +165,7 @@ export class Import {
164
165
  // Validate the project after module has been imported
165
166
  const afterImportValidateErrors = await Validate.getInstance().validate(
166
167
  this.project.basePath,
168
+ () => this.project,
167
169
  );
168
170
  if (afterImportValidateErrors.length > beforeImportValidateErrors.length) {
169
171
  console.error(
@@ -35,6 +35,7 @@ export class Remove {
35
35
  // True, if resource is a project resource
36
36
  private projectResource(type: RemovableResourceTypes): boolean {
37
37
  return (
38
+ type === 'calculation' ||
38
39
  type === 'cardType' ||
39
40
  type === 'fieldType' ||
40
41
  type === 'graphModel' ||
@@ -229,12 +230,12 @@ export class Remove {
229
230
  if (type === 'attachment')
230
231
  return this.removeAttachment(targetName, rest[0]);
231
232
  else if (type === 'card') return this.removeCard(targetName);
233
+ else if (type === 'hub') return this.removeHubLocation(targetName);
234
+ else if (type === 'label') return this.removeLabel(targetName, rest[0]);
232
235
  else if (type === 'link')
233
236
  return this.removeLink(targetName, rest[0], rest[1], rest.at(2));
234
237
  else if (type === 'module')
235
238
  return this.moduleManager.removeModule(targetName);
236
- else if (type === 'label') return this.removeLabel(targetName, rest[0]);
237
- else if (type === 'hub') return this.removeHubLocation(targetName);
238
239
  }
239
240
  throw new Error(`Unknown resource type '${type}'`);
240
241
  }
@@ -22,6 +22,7 @@ import { type Project, ResourcesFrom } from '../containers/project.js';
22
22
  import { resourceName } from '../utils/resource-utils.js';
23
23
  import { Template } from '../containers/template.js';
24
24
 
25
+ import { CalculationResource } from '../resources/calculation-resource.js';
25
26
  import { CardTypeResource } from '../resources/card-type-resource.js';
26
27
  import { FieldTypeResource } from '../resources/field-type-resource.js';
27
28
  import { GraphModelResource } from '../resources/graph-model-resource.js';
@@ -192,6 +193,17 @@ export class Rename {
192
193
  return cardType.rename(resourceName(this.updateResourceName(cardTypeName)));
193
194
  }
194
195
 
196
+ // Rename calculations.
197
+ private async updateCalculation(calculationName: string) {
198
+ const calculation = new CalculationResource(
199
+ this.project,
200
+ resourceName(calculationName),
201
+ );
202
+ return calculation.rename(
203
+ resourceName(this.updateResourceName(calculationName)),
204
+ );
205
+ }
206
+
195
207
  // Updates field type's metadata.
196
208
  private async updateFieldTypeMetadata(fieldTypeName: string) {
197
209
  const fieldType = new FieldTypeResource(
@@ -341,6 +353,14 @@ export class Rename {
341
353
  }
342
354
  console.info('Updated templates');
343
355
 
356
+ const calculations = await this.project.calculations(
357
+ ResourcesFrom.localOnly,
358
+ );
359
+ for (const calculation of calculations) {
360
+ await this.updateCalculation(calculation.name);
361
+ }
362
+ console.info('Updated calculations');
363
+
344
364
  // Rename all local template cards.
345
365
  templates = await this.project.templates(ResourcesFrom.localOnly);
346
366
  for (const template of templates) {
@@ -16,7 +16,7 @@ import { existsSync, readFileSync } from 'node:fs';
16
16
  import { homedir } from 'node:os';
17
17
  import { join, resolve } from 'node:path';
18
18
  import { spawn } from 'node:child_process';
19
- import { readFile, writeFile } from 'node:fs/promises';
19
+ import { writeFile } from 'node:fs/promises';
20
20
 
21
21
  import { MODULE_LIST_FULL_PATH } from './fetch.js';
22
22
 
@@ -47,7 +47,6 @@ import { Project, type ResourcesFrom } from '../containers/project.js';
47
47
  import {
48
48
  type ResourceName,
49
49
  resourceName,
50
- resourceNameToPath,
51
50
  resourceNameToString,
52
51
  } from '../utils/resource-utils.js';
53
52
  import { TemplateResource } from '../resources/template-resource.js';
@@ -332,6 +331,8 @@ export class Show {
332
331
 
333
332
  /**
334
333
  * Shows the content of a file in a resource.
334
+ * TODO: To be removed
335
+ * @deprecated
335
336
  * @param resourceName Name of the resource.
336
337
  * @param fileName Name of the file to show.
337
338
  * @returns the content of the file.
@@ -360,6 +361,8 @@ export class Show {
360
361
 
361
362
  /**
362
363
  * Shows all file names in a folder resource.
364
+ * TODO: To be removed
365
+ * @deprecated
363
366
  * @param resourceName Name of the resource.
364
367
  * @returns all file names in the resource.
365
368
  */
@@ -567,17 +570,6 @@ export class Show {
567
570
  name: string,
568
571
  showUse: boolean = false,
569
572
  ): Promise<ResourceContent | undefined> {
570
- // TODO: remove this workaround once calculations are implemented as a resource class
571
- if (resourceName(name).type === 'calculations') {
572
- const nameObj = resourceName(name);
573
- const path = resourceNameToPath(this.project, nameObj, '.lp');
574
- return {
575
- name,
576
- displayName: nameObj.identifier,
577
- calculation: await readFile(path, 'utf-8'),
578
- };
579
- }
580
-
581
573
  const strictNameCheck = true;
582
574
  const resource = Project.resourceObject(
583
575
  this.project,
@@ -14,6 +14,7 @@ import type {
14
14
  AddOperation,
15
15
  ChangeOperation,
16
16
  Operation,
17
+ OperationFor,
17
18
  RankOperation,
18
19
  RemoveOperation,
19
20
  UpdateOperations,
@@ -44,7 +45,6 @@ export class Update {
44
45
  optionalDetail?: Type, // todo: for 'rank' it might be reasonable to accept also 'number'
45
46
  mappingTable?: { stateMapping: Record<string, string> },
46
47
  ) {
47
- const resource = Project.resourceObject(this.project, resourceName(name));
48
48
  const op: Operation<Type> = {
49
49
  name: operation,
50
50
  target: '' as Type,
@@ -76,7 +76,25 @@ export class Update {
76
76
  : undefined;
77
77
  }
78
78
 
79
- await resource?.update(key, op);
79
+ await this.applyResourceOperation(name, key, op);
80
+ }
81
+
82
+ /**
83
+ * Update single resource property
84
+ * This is similar to updateValue, but allows the operation to be fully specified
85
+ * @param name Name of the resource to operate on.
86
+ * @param key Property to change in resource JSON
87
+ * @param operation The full operation object
88
+ * @template Type Type of the target of the operation
89
+ * @template T Type of operation ('add', 'remove', 'change', 'rank')
90
+ */
91
+ public async applyResourceOperation<Type, T extends UpdateOperations>(
92
+ name: string,
93
+ key: string,
94
+ operation: OperationFor<Type, T>,
95
+ ) {
96
+ const resource = Project.resourceObject(this.project, resourceName(name));
97
+ await resource?.update(key, operation);
80
98
  this.project.collectLocalResources();
81
99
  }
82
100
  }
@@ -36,7 +36,7 @@ import type {
36
36
  ResourceContent,
37
37
  Workflow,
38
38
  } from '../interfaces/resource-interfaces.js';
39
- import { errorFunction } from '../utils/log-utils.js';
39
+ import { errorFunction } from '../utils/error-utils.js';
40
40
  import { isTemplateCard } from '../utils/card-utils.js';
41
41
  import { pathExists } from '../utils/file-utils.js';
42
42
  import { Project } from '../containers/project.js';
@@ -521,9 +521,13 @@ export class Validate {
521
521
  * Validates that a given directory path (and its children) conform to a JSON schema.
522
522
  * @note Validates also content in the directory tree, if .schema file is found.
523
523
  * @param projectPath path to validate.
524
+ * @param projectFn function that returns a Project instance.
524
525
  * @returns string containing all validation errors
525
526
  */
526
- public async validate(projectPath: string): Promise<string> {
527
+ public async validate(
528
+ projectPath: string,
529
+ projectFn: () => Project,
530
+ ): Promise<string> {
527
531
  let validationErrors = '';
528
532
  this.validatedFieldTypes.clear();
529
533
  this.validatedWorkflows.clear();
@@ -545,7 +549,7 @@ export class Validate {
545
549
  return validationErrors;
546
550
  } else {
547
551
  const errorMsg: string[] = [];
548
- const project = new Project(projectPath);
552
+ const project = projectFn();
549
553
 
550
554
  // Then, validate that each 'contentSchema' children as well.
551
555
  const result = await this.readAndValidateContentFiles(
@@ -18,9 +18,9 @@ import type { Dirent } from 'node:fs';
18
18
  import { readdir, readFile, writeFile } from 'node:fs/promises';
19
19
 
20
20
  import { findParentPath } from '../utils/card-utils.js';
21
+ import { getFilesSync } from '../utils/file-utils.js';
21
22
  import { readJsonFile } from '../utils/json.js';
22
23
  import { writeJsonFile } from '../utils/json.js';
23
- import { getFilesSync } from '../utils/file-utils.js';
24
24
 
25
25
  // interfaces
26
26
  import {
@@ -12,8 +12,7 @@
12
12
  */
13
13
 
14
14
  // node
15
- import { basename, join, resolve } from 'node:path';
16
- import { readFile, writeFile } from 'node:fs/promises';
15
+ import { writeFile } from 'node:fs/promises';
17
16
 
18
17
  import { sanitizeSvgBase64 } from '../../utils/sanitize-svg.js';
19
18
  import { instance } from '@viz-js/viz';
@@ -26,7 +25,6 @@ import type {
26
25
  } from '../../types/queries.js';
27
26
  import type { Card, Context } from '../../interfaces/project-interfaces.js';
28
27
  import ClingoParser from '../../utils/clingo-parser.js';
29
- import { pathExists } from '../../utils/file-utils.js';
30
28
  import { Mutex } from 'async-mutex';
31
29
  import Handlebars from 'handlebars';
32
30
  import { type Project, ResourcesFrom } from '../../containers/project.js';
@@ -52,6 +50,7 @@ import type {
52
50
  TemplateMetadata,
53
51
  Workflow,
54
52
  } from '../../interfaces/resource-interfaces.js';
53
+ import { CalculationResource } from '../../resources/calculation-resource.js';
55
54
  import {
56
55
  removeAllPrograms,
57
56
  solve,
@@ -62,6 +61,7 @@ import {
62
61
  import { generateReportContent } from '../../utils/report.js';
63
62
  import { lpFiles, graphvizReport } from '@cyberismo/assets';
64
63
  import {
64
+ resourceName,
65
65
  type ResourceName,
66
66
  resourceNameToString,
67
67
  } from '../../utils/resource-utils.js';
@@ -123,7 +123,7 @@ export class CalculationEngine {
123
123
  query?: QueryName,
124
124
  ) {
125
125
  let logicProgram = query ? this.queryContent(query) : '';
126
- logicProgram += await buildProgram('', programs);
126
+ logicProgram += buildProgram('', programs);
127
127
  await writeFile(destination, logicProgram);
128
128
  }
129
129
 
@@ -259,26 +259,28 @@ export class CalculationEngine {
259
259
  const calculations = await this.project.calculations(ResourcesFrom.all);
260
260
 
261
261
  for (const calculationFile of calculations) {
262
- if (calculationFile.path) {
263
- const moduleLogicFile = resolve(
264
- join(calculationFile.path, basename(calculationFile.name)),
262
+ try {
263
+ const calculationResource = new CalculationResource(
264
+ this.project,
265
+ resourceName(calculationFile.name),
265
266
  );
266
-
267
- const filePath = moduleLogicFile.endsWith('.lp')
268
- ? moduleLogicFile
269
- : moduleLogicFile + '.lp';
270
-
271
- if (pathExists(filePath)) {
272
- try {
273
- const moduleContent = await readFile(filePath, 'utf-8');
274
- setProgram(calculationFile.name, moduleContent, [ALL_CATEGORY]);
275
- } catch (error) {
276
- this.logger.warn(
277
- error,
278
- `Failed to read calculation ${calculationFile.name}`,
267
+ if (calculationResource) {
268
+ const resource = await calculationResource.show();
269
+ if (!resource?.content.calculation) {
270
+ this.logger.info(
271
+ `Calculation resource '${resource.name}' does not have calculation file`,
279
272
  );
273
+ continue;
280
274
  }
275
+ setProgram(calculationFile.name, resource.content.calculation, [
276
+ ALL_CATEGORY,
277
+ ]);
281
278
  }
279
+ } catch (error) {
280
+ this.logger.warn(
281
+ error,
282
+ `Failed to read calculation ${calculationFile.name}`,
283
+ );
282
284
  }
283
285
  }
284
286
  }
@@ -466,9 +468,7 @@ export class CalculationEngine {
466
468
  case 'templates':
467
469
  return createTemplateFacts(resource as TemplateMetadata);
468
470
  default:
469
- throw new Error(
470
- `Resource ${resourceNameToString(resourceName)} does not have a logic program`,
471
- );
471
+ return '';
472
472
  }
473
473
  }
474
474
 
@@ -53,6 +53,7 @@ import {
53
53
  import type { Template } from './template.js';
54
54
  import { Validate } from '../commands/validate.js';
55
55
 
56
+ import { CalculationResource } from '../resources/calculation-resource.js';
56
57
  import { CardTypeResource } from '../resources/card-type-resource.js';
57
58
  import { FieldTypeResource } from '../resources/field-type-resource.js';
58
59
  import { GraphModelResource } from '../resources/graph-model-resource.js';
@@ -977,7 +978,9 @@ export class Project extends CardContainer {
977
978
  * @returns Created resource.
978
979
  */
979
980
  public static resourceObject(project: Project, name: ResourceName) {
980
- if (name.type === 'cardTypes') {
981
+ if (name.type === 'calculations') {
982
+ return new CalculationResource(project, name);
983
+ } else if (name.type === 'cardTypes') {
981
984
  return new CardTypeResource(project, name);
982
985
  } else if (name.type === 'fieldTypes') {
983
986
  return new FieldTypeResource(project, name);
package/src/index.ts CHANGED
@@ -11,8 +11,9 @@
11
11
  */
12
12
 
13
13
  import {
14
- CardsOptions,
15
14
  Cmd,
15
+ CmdKey,
16
+ CmdValue,
16
17
  Commands,
17
18
  CommandManager,
18
19
  ExportFormats,
@@ -21,6 +22,14 @@ import { Validate } from './commands/validate.js';
21
22
  export * from './interfaces/project-interfaces.js';
22
23
  import { requestStatus } from './interfaces/request-status-interfaces.js';
23
24
  import { UpdateOperations } from './resources/resource-object.js';
25
+ export type {
26
+ Operation,
27
+ OperationFor,
28
+ AddOperation,
29
+ ChangeOperation,
30
+ RankOperation,
31
+ RemoveOperation,
32
+ } from './resources/resource-object.js';
24
33
  import { evaluateMacros } from './macros/index.js';
25
34
  import {
26
35
  isResourceFolderType,
@@ -30,8 +39,9 @@ import {
30
39
  import { moduleNameFromCardKey } from './utils/card-utils.js';
31
40
 
32
41
  export {
33
- CardsOptions,
34
42
  Cmd,
43
+ CmdKey,
44
+ CmdValue,
35
45
  CommandManager,
36
46
  Commands,
37
47
  ExportFormats,
@@ -44,3 +54,27 @@ export {
44
54
  Validate,
45
55
  evaluateMacros,
46
56
  };
57
+
58
+ // Export command-specific option interfaces
59
+ export type {
60
+ CommandOptions,
61
+ AllCommandOptions,
62
+ AddCommandOptions,
63
+ CalcCommandOptions,
64
+ CreateCommandOptions,
65
+ EditCommandOptions,
66
+ ExportCommandOptions,
67
+ FetchCommandOptions,
68
+ ImportCommandOptions,
69
+ MoveCommandOptions,
70
+ RankCommandOptions,
71
+ RemoveCommandOptions,
72
+ RenameCommandOptions,
73
+ ReportCommandOptions,
74
+ ShowCommandOptions,
75
+ StartCommandOptions,
76
+ TransitionCommandOptions,
77
+ UpdateCommandOptions,
78
+ UpdateModulesCommandOptions,
79
+ ValidateCommandOptions,
80
+ } from './interfaces/command-options.js';
@@ -0,0 +1,144 @@
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 { Level } from 'pino';
15
+ import type { Context } from './project-interfaces.js';
16
+ import type { CmdKey } from '../command-handler.js';
17
+
18
+ // Base options shared across multiple commands
19
+ export interface BaseCommandOptions {
20
+ projectPath?: string;
21
+ logLevel?: Level;
22
+ }
23
+
24
+ // Options for commands that need context
25
+ export interface ContextualCommandOptions extends BaseCommandOptions {
26
+ context?: Context;
27
+ }
28
+
29
+ // Options for 'add' command
30
+ export interface AddCommandOptions extends BaseCommandOptions {
31
+ repeat?: number;
32
+ }
33
+
34
+ // Options for 'calc' command
35
+ export type CalcCommandOptions = ContextualCommandOptions;
36
+
37
+ // Options for 'create' command
38
+ export interface CreateCommandOptions extends BaseCommandOptions {
39
+ skipModuleImport?: boolean;
40
+ }
41
+
42
+ // Options for 'edit' command
43
+ export type EditCommandOptions = BaseCommandOptions;
44
+
45
+ // Options for the 'export' command
46
+ export interface ExportCommandOptions extends BaseCommandOptions {
47
+ recursive?: boolean;
48
+ title?: string;
49
+ name?: string;
50
+ version?: string;
51
+ date?: string;
52
+ revremark?: string;
53
+ }
54
+
55
+ // Options for 'fetch' command
56
+ export type FetchCommandOptions = BaseCommandOptions;
57
+
58
+ // Options for 'import' command
59
+ export type ImportCommandOptions = BaseCommandOptions;
60
+
61
+ // Options for 'move' command
62
+ export type MoveCommandOptions = BaseCommandOptions;
63
+
64
+ // Options for 'rank' command
65
+ export type RankCommandOptions = BaseCommandOptions;
66
+
67
+ // Options for 'remove' command
68
+ export type RemoveCommandOptions = BaseCommandOptions;
69
+
70
+ // Options for 'rename' command
71
+ export type RenameCommandOptions = BaseCommandOptions;
72
+
73
+ // Options for 'report' command
74
+ export type ReportCommandOptions = ContextualCommandOptions;
75
+
76
+ // Options for 'show' command
77
+ export interface ShowCommandOptions extends BaseCommandOptions {
78
+ details?: boolean;
79
+ showAll?: boolean;
80
+ showUse?: boolean;
81
+ }
82
+
83
+ // Options for 'start' command
84
+ export interface StartCommandOptions extends BaseCommandOptions {
85
+ forceStart?: boolean;
86
+ watchResourceChanges?: boolean;
87
+ }
88
+
89
+ // Options for 'transition' command
90
+ export type TransitionCommandOptions = BaseCommandOptions;
91
+
92
+ // Options for 'update' command
93
+ export interface UpdateCommandOptions extends BaseCommandOptions {
94
+ mappingFile?: string;
95
+ }
96
+
97
+ // Options for 'updateModules' command
98
+ export type UpdateModulesCommandOptions = BaseCommandOptions;
99
+
100
+ // Options for 'validate' command
101
+ export type ValidateCommandOptions = BaseCommandOptions;
102
+
103
+ // All possible command options
104
+ export type AllCommandOptions =
105
+ | AddCommandOptions
106
+ | CalcCommandOptions
107
+ | CreateCommandOptions
108
+ | EditCommandOptions
109
+ | ExportCommandOptions
110
+ | FetchCommandOptions
111
+ | ImportCommandOptions
112
+ | MoveCommandOptions
113
+ | RankCommandOptions
114
+ | RemoveCommandOptions
115
+ | RenameCommandOptions
116
+ | ReportCommandOptions
117
+ | ShowCommandOptions
118
+ | StartCommandOptions
119
+ | TransitionCommandOptions
120
+ | UpdateCommandOptions
121
+ | UpdateModulesCommandOptions
122
+ | ValidateCommandOptions;
123
+
124
+ // Map command keys to their option types
125
+ export type CommandOptions<T extends CmdKey> = {
126
+ add: AddCommandOptions;
127
+ calc: CalcCommandOptions;
128
+ create: CreateCommandOptions;
129
+ edit: EditCommandOptions;
130
+ export: ExportCommandOptions;
131
+ fetch: FetchCommandOptions;
132
+ import: ImportCommandOptions;
133
+ move: MoveCommandOptions;
134
+ rank: RankCommandOptions;
135
+ remove: RemoveCommandOptions;
136
+ rename: RenameCommandOptions;
137
+ report: ReportCommandOptions;
138
+ show: ShowCommandOptions;
139
+ start: StartCommandOptions;
140
+ transition: TransitionCommandOptions;
141
+ update: UpdateCommandOptions;
142
+ updateModules: UpdateModulesCommandOptions;
143
+ validate: ValidateCommandOptions;
144
+ }[T];