@cyberismo/data-handler 0.0.21 → 0.0.22

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 (166) hide show
  1. package/dist/command-handler.js +13 -24
  2. package/dist/command-handler.js.map +1 -1
  3. package/dist/command-manager.d.ts +21 -6
  4. package/dist/command-manager.js +34 -32
  5. package/dist/command-manager.js.map +1 -1
  6. package/dist/commands/calculate.js +101 -46
  7. package/dist/commands/calculate.js.map +1 -1
  8. package/dist/commands/create.js +417 -328
  9. package/dist/commands/create.js.map +1 -1
  10. package/dist/commands/edit.js +117 -68
  11. package/dist/commands/edit.js.map +1 -1
  12. package/dist/commands/export.js +301 -252
  13. package/dist/commands/export.js.map +1 -1
  14. package/dist/commands/fetch.js +205 -156
  15. package/dist/commands/fetch.js.map +1 -1
  16. package/dist/commands/import.js +189 -134
  17. package/dist/commands/import.js.map +1 -1
  18. package/dist/commands/migrate.js +91 -45
  19. package/dist/commands/migrate.js.map +1 -1
  20. package/dist/commands/move.js +347 -267
  21. package/dist/commands/move.js.map +1 -1
  22. package/dist/commands/remove.d.ts +1 -0
  23. package/dist/commands/remove.js +202 -135
  24. package/dist/commands/remove.js.map +1 -1
  25. package/dist/commands/rename.js +233 -187
  26. package/dist/commands/rename.js.map +1 -1
  27. package/dist/commands/show.d.ts +8 -8
  28. package/dist/commands/show.js +477 -372
  29. package/dist/commands/show.js.map +1 -1
  30. package/dist/commands/transition.js +119 -73
  31. package/dist/commands/transition.js.map +1 -1
  32. package/dist/commands/update.js +8 -3
  33. package/dist/commands/update.js.map +1 -1
  34. package/dist/commands/validate.js +1 -1
  35. package/dist/commands/validate.js.map +1 -1
  36. package/dist/containers/project/calculation-engine.js +0 -1
  37. package/dist/containers/project/calculation-engine.js.map +1 -1
  38. package/dist/containers/project/card-cache.js +1 -1
  39. package/dist/containers/project/card-cache.js.map +1 -1
  40. package/dist/containers/project.d.ts +16 -0
  41. package/dist/containers/project.js +59 -1
  42. package/dist/containers/project.js.map +1 -1
  43. package/dist/containers/template.js +1 -1
  44. package/dist/containers/template.js.map +1 -1
  45. package/dist/interfaces/command-options.d.ts +1 -0
  46. package/dist/interfaces/resource-interfaces.d.ts +5 -12
  47. package/dist/interfaces/resource-interfaces.js.map +1 -1
  48. package/dist/macros/base-macro.js +1 -1
  49. package/dist/macros/base-macro.js.map +1 -1
  50. package/dist/macros/graph/index.js +3 -1
  51. package/dist/macros/graph/index.js.map +1 -1
  52. package/dist/macros/index.js +3 -1
  53. package/dist/macros/index.js.map +1 -1
  54. package/dist/macros/report/index.js +1 -1
  55. package/dist/macros/report/index.js.map +1 -1
  56. package/dist/module-manager.js +5 -3
  57. package/dist/module-manager.js.map +1 -1
  58. package/dist/project-settings.js +2 -2
  59. package/dist/project-settings.js.map +1 -1
  60. package/dist/resources/card-type-resource.js +1 -1
  61. package/dist/resources/card-type-resource.js.map +1 -1
  62. package/dist/resources/create-defaults.js +0 -1
  63. package/dist/resources/create-defaults.js.map +1 -1
  64. package/dist/resources/field-type-resource.js +2 -5
  65. package/dist/resources/field-type-resource.js.map +1 -1
  66. package/dist/resources/file-resource.js +4 -1
  67. package/dist/resources/file-resource.js.map +1 -1
  68. package/dist/resources/folder-resource.d.ts +1 -1
  69. package/dist/resources/folder-resource.js +4 -1
  70. package/dist/resources/folder-resource.js.map +1 -1
  71. package/dist/resources/graph-model-resource.d.ts +1 -8
  72. package/dist/resources/graph-model-resource.js +0 -14
  73. package/dist/resources/graph-model-resource.js.map +1 -1
  74. package/dist/resources/graph-view-resource.d.ts +1 -8
  75. package/dist/resources/graph-view-resource.js +0 -14
  76. package/dist/resources/graph-view-resource.js.map +1 -1
  77. package/dist/resources/link-type-resource.js +1 -1
  78. package/dist/resources/link-type-resource.js.map +1 -1
  79. package/dist/resources/report-resource.d.ts +1 -8
  80. package/dist/resources/report-resource.js +0 -14
  81. package/dist/resources/report-resource.js.map +1 -1
  82. package/dist/resources/resource-object.d.ts +11 -1
  83. package/dist/resources/resource-object.js +19 -2
  84. package/dist/resources/resource-object.js.map +1 -1
  85. package/dist/resources/template-resource.d.ts +1 -9
  86. package/dist/resources/template-resource.js +0 -15
  87. package/dist/resources/template-resource.js.map +1 -1
  88. package/dist/resources/workflow-resource.js +1 -1
  89. package/dist/resources/workflow-resource.js.map +1 -1
  90. package/dist/utils/card-utils.js +1 -1
  91. package/dist/utils/card-utils.js.map +1 -1
  92. package/dist/utils/commit-context.d.ts +23 -0
  93. package/dist/utils/commit-context.js +30 -0
  94. package/dist/utils/commit-context.js.map +1 -0
  95. package/dist/utils/file-utils.js +3 -1
  96. package/dist/utils/file-utils.js.map +1 -1
  97. package/dist/utils/git-manager.d.ts +29 -0
  98. package/dist/utils/git-manager.js +76 -0
  99. package/dist/utils/git-manager.js.map +1 -0
  100. package/dist/utils/handlebars-helpers.d.ts +22 -0
  101. package/dist/utils/handlebars-helpers.js +78 -0
  102. package/dist/utils/handlebars-helpers.js.map +1 -0
  103. package/dist/utils/json.js +6 -2
  104. package/dist/utils/json.js.map +1 -1
  105. package/dist/utils/log-utils.d.ts +7 -2
  106. package/dist/utils/log-utils.js +28 -3
  107. package/dist/utils/log-utils.js.map +1 -1
  108. package/dist/utils/report.d.ts +0 -19
  109. package/dist/utils/report.js +4 -67
  110. package/dist/utils/report.js.map +1 -1
  111. package/dist/utils/rw-lock.d.ts +71 -0
  112. package/dist/utils/rw-lock.js +220 -0
  113. package/dist/utils/rw-lock.js.map +1 -0
  114. package/dist/utils/user-preferences.js +3 -3
  115. package/dist/utils/user-preferences.js.map +1 -1
  116. package/package.json +5 -5
  117. package/src/command-handler.ts +14 -22
  118. package/src/command-manager.ts +43 -37
  119. package/src/commands/calculate.ts +8 -1
  120. package/src/commands/create.ts +24 -1
  121. package/src/commands/edit.ts +3 -0
  122. package/src/commands/export.ts +8 -2
  123. package/src/commands/fetch.ts +3 -0
  124. package/src/commands/import.ts +5 -0
  125. package/src/commands/migrate.ts +2 -0
  126. package/src/commands/move.ts +34 -0
  127. package/src/commands/remove.ts +24 -2
  128. package/src/commands/rename.ts +2 -0
  129. package/src/commands/show.ts +63 -34
  130. package/src/commands/transition.ts +2 -0
  131. package/src/commands/update.ts +9 -3
  132. package/src/commands/validate.ts +1 -1
  133. package/src/containers/project/calculation-engine.ts +0 -1
  134. package/src/containers/project/card-cache.ts +1 -0
  135. package/src/containers/project.ts +75 -1
  136. package/src/containers/template.ts +1 -1
  137. package/src/interfaces/command-options.ts +1 -0
  138. package/src/interfaces/resource-interfaces.ts +5 -12
  139. package/src/macros/base-macro.ts +1 -1
  140. package/src/macros/graph/index.ts +3 -0
  141. package/src/macros/index.ts +3 -1
  142. package/src/macros/report/index.ts +1 -0
  143. package/src/module-manager.ts +5 -2
  144. package/src/project-settings.ts +2 -1
  145. package/src/resources/card-type-resource.ts +1 -1
  146. package/src/resources/create-defaults.ts +0 -1
  147. package/src/resources/field-type-resource.ts +2 -4
  148. package/src/resources/file-resource.ts +3 -1
  149. package/src/resources/folder-resource.ts +7 -2
  150. package/src/resources/graph-model-resource.ts +1 -25
  151. package/src/resources/graph-view-resource.ts +1 -25
  152. package/src/resources/link-type-resource.ts +1 -1
  153. package/src/resources/report-resource.ts +1 -25
  154. package/src/resources/resource-object.ts +22 -1
  155. package/src/resources/template-resource.ts +0 -23
  156. package/src/resources/workflow-resource.ts +1 -1
  157. package/src/utils/card-utils.ts +1 -1
  158. package/src/utils/commit-context.ts +45 -0
  159. package/src/utils/file-utils.ts +3 -1
  160. package/src/utils/git-manager.ts +87 -0
  161. package/src/utils/handlebars-helpers.ts +95 -0
  162. package/src/utils/json.ts +6 -2
  163. package/src/utils/log-utils.ts +33 -4
  164. package/src/utils/report.ts +8 -78
  165. package/src/utils/rw-lock.ts +279 -0
  166. package/src/utils/user-preferences.ts +3 -0
@@ -1 +1 @@
1
- {"version":3,"file":"user-preferences.js","sourceRoot":"","sources":["../../src/utils/user-preferences.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"user-preferences.js","sourceRoot":"","sources":["../../src/utils/user-preferences.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cyberismo/data-handler",
3
3
  "description": "Command handler for cards and web service",
4
- "version": "0.0.21",
4
+ "version": "0.0.22",
5
5
  "author": "sami.merila@cyberismo.com",
6
6
  "license": "AGPL-3.0",
7
7
  "homepage": "https://github.com/CyberismoCom/cyberismo",
@@ -21,9 +21,9 @@
21
21
  "@types/jsdom": "^21.1.7",
22
22
  "@types/json-schema": "^7.0.15",
23
23
  "@types/sinon": "^21.0.0",
24
- "c8": "^10.1.3",
24
+ "c8": "^11.0.0",
25
25
  "pino-pretty": "^13.1.3",
26
- "sinon": "^21.0.0"
26
+ "sinon": "^21.0.1"
27
27
  },
28
28
  "dependencies": {
29
29
  "@asciidoctor/core": "^3.0.4",
@@ -46,9 +46,9 @@
46
46
  "vega": "^6.2.0",
47
47
  "vega-lite": "^6.4.2",
48
48
  "write-json-file": "^7.0.0",
49
- "@cyberismo/assets": "0.0.21",
49
+ "@cyberismo/migrations": "0.0.22",
50
50
  "@cyberismo/node-clingo": "1.3.4",
51
- "@cyberismo/migrations": "0.0.21"
51
+ "@cyberismo/assets": "0.0.22"
52
52
  },
53
53
  "type": "module",
54
54
  "files": [
@@ -163,12 +163,10 @@ export class Commands {
163
163
  const path = options.projectPath || '';
164
164
  this.projectPath = resolveTilde(await this.setProjectPath(path));
165
165
  if (!Validate.validateFolder(this.projectPath)) {
166
- let errorMessage = '';
167
- if (path === '' || path === undefined) {
168
- errorMessage = `No 'cardRoot' in the current folder`;
169
- } else {
170
- errorMessage = `Input validation error: folder name '${path}' is invalid`;
171
- }
166
+ const errorMessage =
167
+ path === '' || path === undefined
168
+ ? `No 'cardRoot' in the current folder`
169
+ : `Input validation error: folder name '${path}' is invalid`;
172
170
  throw new Error(errorMessage);
173
171
  }
174
172
 
@@ -180,6 +178,7 @@ export class Commands {
180
178
  logLevel: options.logLevel,
181
179
  watchResourceChanges: (options as StartCommandOptions)
182
180
  .watchResourceChanges,
181
+ autocommit: (options as StartCommandOptions).autocommit,
183
182
  });
184
183
  if (!this.commands) {
185
184
  throw new Error('Cannot get instance of CommandManager');
@@ -426,6 +425,7 @@ export class Commands {
426
425
  } catch (error) {
427
426
  throw new Error(
428
427
  `Failed to read mapping file: ${errorFunction(error)}`,
428
+ { cause: error },
429
429
  );
430
430
  }
431
431
  }
@@ -574,7 +574,7 @@ export class Commands {
574
574
  return { statusCode: 500 };
575
575
  }
576
576
  process.env.EXPORT_FORMAT = format;
577
- let message = '';
577
+ let message: string;
578
578
  if (format === 'pdf') {
579
579
  const options = {
580
580
  title: pdfOptions?.title || 'Title',
@@ -717,7 +717,7 @@ export class Commands {
717
717
  }
718
718
 
719
719
  const { name, parameters } = parametersFile;
720
- let result: string | undefined = '';
720
+ let result: string | undefined;
721
721
  try {
722
722
  result = await this.commands?.showCmd.showReportResults(
723
723
  name,
@@ -758,12 +758,9 @@ export class Commands {
758
758
  case 'attachments':
759
759
  promise = this.commands!.showCmd.showAttachments();
760
760
  break;
761
- case 'card': {
762
- return {
763
- statusCode: 200,
764
- payload: this.commands!.showCmd.showCardDetails(detail),
765
- };
766
- }
761
+ case 'card':
762
+ promise = this.commands!.showCmd.showCardDetails(detail);
763
+ break;
767
764
  case 'cards':
768
765
  promise = this.commands!.showCmd.showCards();
769
766
  break;
@@ -796,10 +793,8 @@ export class Commands {
796
793
  );
797
794
  break;
798
795
  case 'labels':
799
- return {
800
- statusCode: 200,
801
- payload: this.commands!.showCmd.showLabels(),
802
- };
796
+ promise = this.commands!.showCmd.showLabels();
797
+ break;
803
798
  case 'module':
804
799
  promise = this.commands!.showCmd.showModule(detail);
805
800
  break;
@@ -807,10 +802,7 @@ export class Commands {
807
802
  promise = this.commands!.showCmd.showHubs();
808
803
  break;
809
804
  case 'modules':
810
- return {
811
- statusCode: 200,
812
- payload: this.commands!.showCmd.showModules(),
813
- };
805
+ promise = this.commands!.showCmd.showModules();
814
806
  break;
815
807
  case 'project':
816
808
  promise = this.commands!.showCmd.showProject();
@@ -25,14 +25,16 @@ import { Transition } from './commands/transition.js';
25
25
  import { Update } from './commands/update.js';
26
26
  import { Validate } from './commands/validate.js';
27
27
  import { Project } from './containers/project.js';
28
- import { ProjectPaths } from './containers/project/project-paths.js';
29
- import pino, { type Level, type TransportTargetOptions } from 'pino';
30
- import { setLogger } from './utils/log-utils.js';
28
+ import { runWithCommitContext } from './utils/commit-context.js';
29
+ import { type Level } from 'pino';
30
+ import { join } from 'node:path';
31
+ import { initLogger } from './utils/log-utils.js';
31
32
 
32
33
  export interface CommandManagerOptions {
33
34
  watchResourceChanges?: boolean;
34
35
  autoSaveConfiguration?: boolean;
35
36
  logLevel?: Level;
37
+ autocommit?: boolean;
36
38
  }
37
39
 
38
40
  // Handles commands and ensures that no extra instances are created.
@@ -55,12 +57,11 @@ export class CommandManager {
55
57
  public updateCmd: Update;
56
58
  public validateCmd: Validate;
57
59
 
58
- private pathHandler: ProjectPaths;
59
-
60
60
  constructor(path: string, options?: CommandManagerOptions) {
61
61
  this.project = new Project(path, {
62
62
  autoSave: options?.autoSaveConfiguration,
63
63
  watchResourceChanges: options?.watchResourceChanges,
64
+ autocommit: options?.autocommit,
64
65
  });
65
66
  this.validateCmd = Validate.getInstance();
66
67
 
@@ -77,7 +78,6 @@ export class CommandManager {
77
78
  this.renameCmd = new Rename(this.project);
78
79
  this.transitionCmd = new Transition(this.project);
79
80
  this.updateCmd = new Update(this.project);
80
- this.pathHandler = new ProjectPaths(path);
81
81
  }
82
82
 
83
83
  /**
@@ -90,6 +90,36 @@ export class CommandManager {
90
90
  return this.project.configuration.checkSchemaVersion();
91
91
  }
92
92
 
93
+ /**
94
+ * Run a function with the given author set in async-local context.
95
+ * Git commits made during the function will use this author.
96
+ */
97
+ public runAsAuthor<T>(
98
+ author: { name: string; email: string },
99
+ fn: () => Promise<T>,
100
+ ): Promise<T> {
101
+ return runWithCommitContext({ author }, fn);
102
+ }
103
+
104
+ /**
105
+ * Execute multiple commands as a single atomic write transaction.
106
+ * All inner @write/@read calls reuse the same lock context.
107
+ * Git commit fires once on success; rollback on any error.
108
+ */
109
+ public async atomic<T>(fn: () => Promise<T>, message: string): Promise<T> {
110
+ const run = () => this.project.lock.write(fn);
111
+ return runWithCommitContext({ message }, run);
112
+ }
113
+
114
+ /**
115
+ * Execute multiple commands under a consistent read snapshot.
116
+ * All inner @read calls reuse the same lock context.
117
+ * Writers are blocked for the duration.
118
+ */
119
+ public async consistent<T>(fn: () => Promise<T>): Promise<T> {
120
+ return this.project.lock.read(fn);
121
+ }
122
+
93
123
  /**
94
124
  * Some commands needs initialization that cannot be performed inside constructor.
95
125
  * Add such calls here.
@@ -97,34 +127,7 @@ export class CommandManager {
97
127
  public async initialize() {
98
128
  this.project.resources.changedModules();
99
129
  await this.project.populateCaches();
100
- }
101
-
102
- /**
103
- * Sets the logger for the command manager.
104
- * @param level Log level.
105
- */
106
- public setLogger(level: Level) {
107
- const all: TransportTargetOptions[] = [
108
- {
109
- target: 'pino/file',
110
- level: 'trace',
111
- options: { destination: this.pathHandler.logPath, mkdir: true },
112
- },
113
- {
114
- target: 'pino/file',
115
- level: level,
116
- options: { destination: 1 }, // stdout
117
- },
118
- ];
119
-
120
- setLogger(
121
- pino({
122
- level: 'trace',
123
- transport: {
124
- targets: all,
125
- },
126
- }),
127
- );
130
+ await this.project.initializeGit();
128
131
  }
129
132
 
130
133
  /**
@@ -138,6 +141,12 @@ export class CommandManager {
138
141
  path: string,
139
142
  options?: CommandManagerOptions,
140
143
  ): Promise<CommandManager> {
144
+ // Set up logger before constructing anything so eager child loggers work
145
+ if (options?.logLevel) {
146
+ const logPath = join(path, '.logs', 'cyberismo_data-handler.log');
147
+ initLogger(options.logLevel, logPath);
148
+ }
149
+
141
150
  if (
142
151
  CommandManager.instance &&
143
152
  CommandManager.instance.project.basePath !== path
@@ -151,9 +160,6 @@ export class CommandManager {
151
160
  await CommandManager.instance.initialize();
152
161
  }
153
162
 
154
- if (options?.logLevel) {
155
- CommandManager.instance.setLogger(options?.logLevel);
156
- }
157
163
  return CommandManager.instance;
158
164
  }
159
165
  }
@@ -14,6 +14,7 @@
14
14
  import type { Context } from '../interfaces/project-interfaces.js';
15
15
  import type { Project } from '../containers/project.js';
16
16
  import type { QueryName, QueryResult } from '../types/queries.js';
17
+ import { read } from '../utils/rw-lock.js';
17
18
 
18
19
  // Class that calculates with logic program card / project level calculations.
19
20
  export class Calculate {
@@ -25,6 +26,7 @@ export class Calculate {
25
26
  * @param programs Programs or categories to export
26
27
  * @param query Query to export, if not provided, all programs will be exported
27
28
  */
29
+ @read
28
30
  public async exportLogicProgram(
29
31
  destination: string,
30
32
  programs: string[] = ['all'],
@@ -40,6 +42,7 @@ export class Calculate {
40
42
  /**
41
43
  * Generates a logic program.
42
44
  */
45
+ @read
43
46
  public async generate() {
44
47
  return this.project.calculationEngine.generate();
45
48
  }
@@ -50,6 +53,7 @@ export class Calculate {
50
53
  * @param timeout Maximum amount of milliseconds clingraph is allowed to run
51
54
  * @returns a base64 encoded image as a string
52
55
  */
56
+ @read
53
57
  public async runGraph(model: string, view: string, context: Context) {
54
58
  return this.project.calculationEngine.runGraph(model, view, context);
55
59
  }
@@ -59,6 +63,7 @@ export class Calculate {
59
63
  * @param query Logic program to be run
60
64
  * @returns parsed program output
61
65
  */
66
+ @read
62
67
  public async runLogicProgram(query: string, context: Context = 'localApp') {
63
68
  return this.project.calculationEngine.runLogicProgram(query, context);
64
69
  }
@@ -74,6 +79,8 @@ export class Calculate {
74
79
  context: Context = 'localApp',
75
80
  options?: unknown,
76
81
  ): Promise<QueryResult<T>[]> {
77
- return this.project.calculationEngine.runQuery(queryName, context, options);
82
+ return this.project.lock.read(async () =>
83
+ this.project.calculationEngine.runQuery(queryName, context, options),
84
+ );
78
85
  }
79
86
  }
@@ -26,6 +26,7 @@ import { isModulePath } from '../utils/card-utils.js';
26
26
  import type { DataType } from '../interfaces/resource-interfaces.js';
27
27
  import type { Card, ProjectFile } from '../interfaces/project-interfaces.js';
28
28
  import { resourceName, resourceNameToString } from '../utils/resource-utils.js';
29
+ import { write } from '../utils/rw-lock.js';
29
30
  import { writeJsonFile } from '../utils/json.js';
30
31
 
31
32
  // todo: Is there a easy to way to make JSON schema into a TypeScript interface/type?
@@ -80,6 +81,10 @@ export class Create {
80
81
  * @param count How many cards to add. By default one.
81
82
  * @returns non-empty string array with ids of added cards
82
83
  */
84
+ @write(
85
+ (cardTypeName, templateName) =>
86
+ `Add cards of type ${cardTypeName} to template ${templateName}`,
87
+ )
83
88
  public async addCards(
84
89
  cardTypeName: string,
85
90
  templateName: string,
@@ -140,6 +145,7 @@ export class Create {
140
145
  * Adds a new hub location.
141
146
  * @param hubUrl URL of the hub
142
147
  */
148
+ @write((hubUrl) => `Add hub ${hubUrl}`)
143
149
  public async addHubLocation(hubUrl: string) {
144
150
  return this.project.configuration.addHub(hubUrl);
145
151
  }
@@ -150,6 +156,7 @@ export class Create {
150
156
  * @param attachment path to an attachment file or attachment name if buffer is defined
151
157
  * @param buffer (Optional) attachment buffer
152
158
  */
159
+ @write((cardKey, attachment) => `Add attachment ${attachment} to ${cardKey}`)
153
160
  public async createAttachment(
154
161
  cardKey: string,
155
162
  attachment: string,
@@ -162,7 +169,7 @@ export class Create {
162
169
  buffer || attachment,
163
170
  );
164
171
  } catch (error) {
165
- throw new Error(errorFunction(error));
172
+ throw new Error(errorFunction(error), { cause: error });
166
173
  }
167
174
  }
168
175
 
@@ -170,6 +177,7 @@ export class Create {
170
177
  * Creates a calculation resource.
171
178
  * @param calculationName name for the calculation resource
172
179
  */
180
+ @write((calculationName) => `Create calculation ${calculationName}`)
173
181
  public async createCalculation(calculationName: string) {
174
182
  return this.project.resources
175
183
  .byType(calculationName, 'calculations')
@@ -182,6 +190,7 @@ export class Create {
182
190
  * @param parentCardKey (Optional) card-key of a parent card. If missing, cards are added to the card root.
183
191
  * @returns array of card keys that were created. Cards are sorted by their parent key and rank. Template root cards are first but the order between other card groups is not guaranteed. However, the order of cards within a group is guaranteed to be ordered by rank.
184
192
  */
193
+ @write((templateName) => `Create card from template ${templateName}`)
185
194
  public async createCard(
186
195
  templateName: string,
187
196
  parentCardKey?: string,
@@ -232,6 +241,7 @@ export class Create {
232
241
  * @param cardTypeName name for the card type.
233
242
  * @param workflowName workflow name to use in the card type.
234
243
  */
244
+ @write((cardTypeName) => `Create card type ${cardTypeName}`)
235
245
  public async createCardType(cardTypeName: string, workflowName: string) {
236
246
  return this.project.resources
237
247
  .byType(cardTypeName, 'cardTypes')
@@ -243,6 +253,7 @@ export class Create {
243
253
  * @param fieldTypeName name for the field type.
244
254
  * @param dataType data type for the field type
245
255
  */
256
+ @write((fieldTypeName) => `Create field type ${fieldTypeName}`)
246
257
  public async createFieldType(fieldTypeName: string, dataType: DataType) {
247
258
  return this.project.resources
248
259
  .byType(fieldTypeName, 'fieldTypes')
@@ -253,6 +264,7 @@ export class Create {
253
264
  * Creates a new graph model.
254
265
  * @param graphModelName name for the graph model.
255
266
  */
267
+ @write((graphModelName) => `Create graph model ${graphModelName}`)
256
268
  public async createGraphModel(graphModelName: string) {
257
269
  return this.project.resources
258
270
  .byType(graphModelName, 'graphModels')
@@ -263,6 +275,7 @@ export class Create {
263
275
  * Creates a new graph view.
264
276
  * @param graphViewName name for the graph view.
265
277
  */
278
+ @write((graphViewName) => `Create graph view ${graphViewName}`)
266
279
  public async createGraphView(graphViewName: string) {
267
280
  return this.project.resources.byType(graphViewName, 'graphViews').create();
268
281
  }
@@ -272,6 +285,7 @@ export class Create {
272
285
  * @param cardKey The card to which the label is added to
273
286
  * @param label The label being added
274
287
  */
288
+ @write((cardKey, label) => `Add label ${label} to ${cardKey}`)
275
289
  public async createLabel(cardKey: string, label: string) {
276
290
  if (!Validate.isValidLabelName(label)) {
277
291
  throw new Error(`Not a valid label name'`);
@@ -292,6 +306,7 @@ export class Create {
292
306
  * Creates a new link type.
293
307
  * @param linkTypeName name for the link type.
294
308
  */
309
+ @write((linkTypeName) => `Create link type ${linkTypeName}`)
295
310
  public async createLinkType(linkTypeName: string) {
296
311
  return this.project.resources.byType(linkTypeName, 'linkTypes').create();
297
312
  }
@@ -303,6 +318,10 @@ export class Create {
303
318
  * @param linkType The type of link to add
304
319
  * @param linkDescription Optional description of the link
305
320
  */
321
+ @write(
322
+ (cardKey, destinationCardKey, linkType) =>
323
+ `Create ${linkType} link from ${cardKey} to ${destinationCardKey}`,
324
+ )
306
325
  public async createLink(
307
326
  cardKey: string,
308
327
  destinationCardKey: string,
@@ -393,6 +412,7 @@ export class Create {
393
412
  projectCategory: string,
394
413
  projectDescription: string,
395
414
  ) {
415
+ // No lock required, since we are creating a new project
396
416
  projectPath = resolve(projectPath);
397
417
 
398
418
  if (!projectPath) {
@@ -482,6 +502,7 @@ export class Create {
482
502
  * Creates a report
483
503
  * @param name name of the report
484
504
  */
505
+ @write((name) => `Create report ${name}`)
485
506
  public async createReport(name: string) {
486
507
  return this.project.resources.byType(name, 'reports').createReport();
487
508
  }
@@ -491,6 +512,7 @@ export class Create {
491
512
  * @param templateName Name of the template.
492
513
  * @param templateContent JSON content for the template file.
493
514
  */
515
+ @write((templateName) => `Create template ${templateName}`)
494
516
  public async createTemplate(templateName: string, templateContent: string) {
495
517
  return this.project.resources
496
518
  .byType(templateName, 'templates')
@@ -502,6 +524,7 @@ export class Create {
502
524
  * @param workflowName workflow name
503
525
  * @param workflowContent workflow content JSON
504
526
  */
527
+ @write((workflowName) => `Create workflow ${workflowName}`)
505
528
  public async createWorkflow(workflowName: string, workflowContent: string) {
506
529
  return this.project.resources
507
530
  .byType(workflowName, 'workflows')
@@ -19,6 +19,7 @@ import { spawnSync } from 'node:child_process';
19
19
  import { ActionGuard } from '../permissions/action-guard.js';
20
20
  import { Project } from '../containers/project.js';
21
21
  import { UserPreferences } from '../utils/user-preferences.js';
22
+ import { write } from '../utils/rw-lock.js';
22
23
 
23
24
  import type { MetadataContent } from '../interfaces/project-interfaces.js';
24
25
 
@@ -76,6 +77,7 @@ export class Edit {
76
77
  * @param cardKey The card to update.
77
78
  * @param changedContent New content for the card.
78
79
  */
80
+ @write((cardKey) => `Edit content of ${cardKey}`)
79
81
  public async editCardContent(cardKey: string, changedContent: string) {
80
82
  if (this.project.hasTemplateCard(cardKey)) {
81
83
  return this.project.updateCardContent(cardKey, changedContent);
@@ -93,6 +95,7 @@ export class Edit {
93
95
  * @param changedKey Which metadata property was changed
94
96
  * @param newValue New value for the metadata property
95
97
  */
98
+ @write((cardKey) => `Edit metadata of ${cardKey}`)
96
99
  public async editCardMetadata(
97
100
  cardKey: string,
98
101
  changedKey: string,
@@ -31,6 +31,7 @@ import { generateReportContent } from '../utils/report.js';
31
31
  import { getStaticDirectoryPath, pdfReport } from '@cyberismo/assets';
32
32
  import { Project } from '../containers/project.js';
33
33
  import type { QueryResult } from '../types/queries.js';
34
+ import { read } from '../utils/rw-lock.js';
34
35
  import type { Show } from './show.js';
35
36
  import { sortItems } from '../utils/lexorank.js';
36
37
 
@@ -246,7 +247,10 @@ export class Export {
246
247
  children: [],
247
248
  attachments: [],
248
249
  };
249
- const cardDetailsResponse = this.showCmd.showCardDetails(card.key, 'adoc');
250
+ const cardDetailsResponse = await this.showCmd.showCardDetails(
251
+ card.key,
252
+ 'adoc',
253
+ );
250
254
  let asciiDocContent = '';
251
255
  const project = this.project;
252
256
  try {
@@ -283,6 +287,7 @@ export class Export {
283
287
  * @param options Export options.
284
288
  * @returns status message
285
289
  */
290
+ @read
286
291
  public async exportPdf(
287
292
  destination: string,
288
293
  options: ExportPdfOptions,
@@ -320,6 +325,7 @@ export class Export {
320
325
  * @param cardKey If not exporting the whole card tree, card key of parent card.
321
326
  * @returns status message
322
327
  */
328
+ @read
323
329
  public async exportToADoc(
324
330
  destination: string,
325
331
  cardKey?: string,
@@ -365,7 +371,7 @@ export class Export {
365
371
  destination,
366
372
  Project.cardContentFile,
367
373
  );
368
- let message = '';
374
+ let message: string;
369
375
  try {
370
376
  await truncate(resultDocumentPath, 0);
371
377
  message = `Using existing output file '${resultDocumentPath}'`;
@@ -17,6 +17,7 @@ import { resolve, sep } from 'node:path';
17
17
  import { getChildLogger } from '../utils/log-utils.js';
18
18
  import { readJsonFile, writeJsonFile } from '../utils/json.js';
19
19
  import { validateJson } from '../utils/validate.js';
20
+ import { write } from '../utils/rw-lock.js';
20
21
 
21
22
  import type { ModuleSetting } from '../interfaces/project-interfaces.js';
22
23
  import type { Project } from '../containers/project.js';
@@ -203,6 +204,7 @@ export class Fetch {
203
204
  /**
204
205
  * Ensures the module list is up to date by fetching if needed.
205
206
  */
207
+ @write()
206
208
  public async ensureModuleListUpToDate() {
207
209
  await this.fetchHubs();
208
210
  }
@@ -211,6 +213,7 @@ export class Fetch {
211
213
  * Fetches modules from modules hub(s) and writes them to a file.
212
214
  * Only fetches if the remote version is newer than the local version.
213
215
  */
216
+ @write(() => 'Fetch hubs')
214
217
  public async fetchHubs() {
215
218
  const needsFetch = await this.fetchModuleList();
216
219
  if (!needsFetch) {
@@ -14,6 +14,7 @@
14
14
  import { ModuleManager } from '../module-manager.js';
15
15
  import { readCsvFile } from '../utils/csv.js';
16
16
  import { Validate } from './validate.js';
17
+ import { write } from '../utils/rw-lock.js';
17
18
 
18
19
  import type { Create } from './create.js';
19
20
  import type {
@@ -48,6 +49,7 @@ export class Import {
48
49
  * @param parentCardKey the cards in the csv file will be created under this card
49
50
  * @returns card keys of the imported cards
50
51
  */
52
+ @write((csvFilePath) => `Import cards from CSV ${csvFilePath}`)
51
53
  public async importCsv(
52
54
  csvFilePath: string,
53
55
  parentCardKey?: string,
@@ -137,6 +139,7 @@ export class Import {
137
139
  * private: If true, uses credentials to clone the repository
138
140
  * @param skipMigrationLog If true, skip logging to migration log (used during project creation)
139
141
  */
142
+ @write((source) => `Import module ${source}`)
140
143
  public async importModule(
141
144
  source: string,
142
145
  destination?: string,
@@ -195,6 +198,7 @@ export class Import {
195
198
  * @param credentials Optional credentials for a private module.
196
199
  * @throws if module is not part of the project
197
200
  */
201
+ @write((moduleName) => `Update module ${moduleName}`)
198
202
  public async updateModule(moduleName: string, credentials?: Credentials) {
199
203
  // Ensure module list is up to date before updating
200
204
  await this.fetchCmd.ensureModuleListUpToDate();
@@ -212,6 +216,7 @@ export class Import {
212
216
  * Updates all imported modules.
213
217
  * @param credentials Optional credentials for private modules.
214
218
  */
219
+ @write(() => 'Update all modules')
215
220
  public async updateAllModules(credentials?: Credentials) {
216
221
  // Ensure module list is up to date before updating all modules
217
222
  await this.fetchCmd.ensureModuleListUpToDate();
@@ -14,6 +14,7 @@
14
14
  import { SCHEMA_VERSION } from '@cyberismo/assets';
15
15
  import type { MigrationResult } from '@cyberismo/migrations';
16
16
  import type { Project } from '../containers/project.js';
17
+ import { write } from '../utils/rw-lock.js';
17
18
 
18
19
  /**
19
20
  * Command that handles schema migration operations.
@@ -32,6 +33,7 @@ export class Migrate {
32
33
  * @param timeoutMilliSeconds Optional timeout in milliseconds (defaults to 2 minutes)
33
34
  * @returns Migration result
34
35
  */
36
+ @write(() => 'Migrate project')
35
37
  public async migrate(
36
38
  toVersion?: number,
37
39
  backupDir?: string,