@cyberismo/data-handler 0.0.20 → 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.
- package/dist/command-handler.js +13 -24
- package/dist/command-handler.js.map +1 -1
- package/dist/command-manager.d.ts +21 -6
- package/dist/command-manager.js +34 -32
- package/dist/command-manager.js.map +1 -1
- package/dist/commands/calculate.js +101 -46
- package/dist/commands/calculate.js.map +1 -1
- package/dist/commands/create.js +420 -320
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/edit.js +117 -68
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/export.js +301 -252
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/fetch.js +205 -156
- package/dist/commands/fetch.js.map +1 -1
- package/dist/commands/import.js +189 -134
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/migrate.js +91 -45
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/move.js +347 -267
- package/dist/commands/move.js.map +1 -1
- package/dist/commands/remove.d.ts +1 -0
- package/dist/commands/remove.js +202 -135
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/rename.js +233 -187
- package/dist/commands/rename.js.map +1 -1
- package/dist/commands/show.d.ts +8 -8
- package/dist/commands/show.js +477 -372
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/transition.js +119 -73
- package/dist/commands/transition.js.map +1 -1
- package/dist/commands/update.js +8 -3
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +1 -1
- package/dist/commands/validate.js.map +1 -1
- package/dist/containers/project/calculation-engine.js +0 -1
- package/dist/containers/project/calculation-engine.js.map +1 -1
- package/dist/containers/project/card-cache.js +1 -1
- package/dist/containers/project/card-cache.js.map +1 -1
- package/dist/containers/project.d.ts +16 -0
- package/dist/containers/project.js +59 -1
- package/dist/containers/project.js.map +1 -1
- package/dist/containers/template.js +1 -1
- package/dist/containers/template.js.map +1 -1
- package/dist/interfaces/command-options.d.ts +1 -0
- package/dist/interfaces/resource-interfaces.d.ts +5 -12
- package/dist/interfaces/resource-interfaces.js.map +1 -1
- package/dist/macros/base-macro.js +1 -1
- package/dist/macros/base-macro.js.map +1 -1
- package/dist/macros/graph/index.js +3 -1
- package/dist/macros/graph/index.js.map +1 -1
- package/dist/macros/include/index.js +16 -1
- package/dist/macros/include/index.js.map +1 -1
- package/dist/macros/include/types.d.ts +15 -12
- package/dist/macros/index.js +4 -1
- package/dist/macros/index.js.map +1 -1
- package/dist/macros/report/index.js +1 -1
- package/dist/macros/report/index.js.map +1 -1
- package/dist/module-manager.js +5 -3
- package/dist/module-manager.js.map +1 -1
- package/dist/project-settings.js +2 -2
- package/dist/project-settings.js.map +1 -1
- package/dist/resources/card-type-resource.js +1 -1
- package/dist/resources/card-type-resource.js.map +1 -1
- package/dist/resources/create-defaults.js +0 -1
- package/dist/resources/create-defaults.js.map +1 -1
- package/dist/resources/field-type-resource.js +2 -5
- package/dist/resources/field-type-resource.js.map +1 -1
- package/dist/resources/file-resource.js +4 -1
- package/dist/resources/file-resource.js.map +1 -1
- package/dist/resources/folder-resource.d.ts +1 -1
- package/dist/resources/folder-resource.js +4 -1
- package/dist/resources/folder-resource.js.map +1 -1
- package/dist/resources/graph-model-resource.d.ts +1 -8
- package/dist/resources/graph-model-resource.js +0 -14
- package/dist/resources/graph-model-resource.js.map +1 -1
- package/dist/resources/graph-view-resource.d.ts +1 -8
- package/dist/resources/graph-view-resource.js +0 -14
- package/dist/resources/graph-view-resource.js.map +1 -1
- package/dist/resources/link-type-resource.js +1 -1
- package/dist/resources/link-type-resource.js.map +1 -1
- package/dist/resources/report-resource.d.ts +1 -8
- package/dist/resources/report-resource.js +0 -14
- package/dist/resources/report-resource.js.map +1 -1
- package/dist/resources/resource-object.d.ts +11 -1
- package/dist/resources/resource-object.js +19 -2
- package/dist/resources/resource-object.js.map +1 -1
- package/dist/resources/template-resource.d.ts +1 -9
- package/dist/resources/template-resource.js +0 -15
- package/dist/resources/template-resource.js.map +1 -1
- package/dist/resources/workflow-resource.d.ts +6 -0
- package/dist/resources/workflow-resource.js +29 -13
- package/dist/resources/workflow-resource.js.map +1 -1
- package/dist/utils/card-utils.js +1 -1
- package/dist/utils/card-utils.js.map +1 -1
- package/dist/utils/commit-context.d.ts +23 -0
- package/dist/utils/commit-context.js +30 -0
- package/dist/utils/commit-context.js.map +1 -0
- package/dist/utils/csv.d.ts +8 -0
- package/dist/utils/csv.js +11 -0
- package/dist/utils/csv.js.map +1 -1
- package/dist/utils/file-utils.js +3 -1
- package/dist/utils/file-utils.js.map +1 -1
- package/dist/utils/git-manager.d.ts +29 -0
- package/dist/utils/git-manager.js +76 -0
- package/dist/utils/git-manager.js.map +1 -0
- package/dist/utils/handlebars-helpers.d.ts +22 -0
- package/dist/utils/handlebars-helpers.js +78 -0
- package/dist/utils/handlebars-helpers.js.map +1 -0
- package/dist/utils/json.d.ts +17 -10
- package/dist/utils/json.js +27 -14
- package/dist/utils/json.js.map +1 -1
- package/dist/utils/log-utils.d.ts +7 -2
- package/dist/utils/log-utils.js +28 -3
- package/dist/utils/log-utils.js.map +1 -1
- package/dist/utils/report.d.ts +0 -19
- package/dist/utils/report.js +4 -63
- package/dist/utils/report.js.map +1 -1
- package/dist/utils/rw-lock.d.ts +71 -0
- package/dist/utils/rw-lock.js +220 -0
- package/dist/utils/rw-lock.js.map +1 -0
- package/dist/utils/user-preferences.js +3 -3
- package/dist/utils/user-preferences.js.map +1 -1
- package/package.json +10 -10
- package/src/command-handler.ts +14 -22
- package/src/command-manager.ts +43 -37
- package/src/commands/calculate.ts +8 -1
- package/src/commands/create.ts +39 -6
- package/src/commands/edit.ts +3 -0
- package/src/commands/export.ts +8 -2
- package/src/commands/fetch.ts +3 -0
- package/src/commands/import.ts +5 -0
- package/src/commands/migrate.ts +2 -0
- package/src/commands/move.ts +34 -0
- package/src/commands/remove.ts +24 -2
- package/src/commands/rename.ts +2 -0
- package/src/commands/show.ts +63 -34
- package/src/commands/transition.ts +2 -0
- package/src/commands/update.ts +9 -3
- package/src/commands/validate.ts +1 -1
- package/src/containers/project/calculation-engine.ts +0 -1
- package/src/containers/project/card-cache.ts +1 -0
- package/src/containers/project.ts +75 -1
- package/src/containers/template.ts +1 -1
- package/src/interfaces/command-options.ts +1 -0
- package/src/interfaces/resource-interfaces.ts +5 -12
- package/src/macros/base-macro.ts +1 -1
- package/src/macros/graph/index.ts +3 -0
- package/src/macros/include/index.ts +19 -1
- package/src/macros/include/types.ts +15 -12
- package/src/macros/index.ts +4 -1
- package/src/macros/report/index.ts +1 -0
- package/src/module-manager.ts +5 -2
- package/src/project-settings.ts +2 -1
- package/src/resources/card-type-resource.ts +1 -1
- package/src/resources/create-defaults.ts +0 -1
- package/src/resources/field-type-resource.ts +2 -4
- package/src/resources/file-resource.ts +3 -1
- package/src/resources/folder-resource.ts +7 -2
- package/src/resources/graph-model-resource.ts +1 -25
- package/src/resources/graph-view-resource.ts +1 -25
- package/src/resources/link-type-resource.ts +1 -1
- package/src/resources/report-resource.ts +1 -25
- package/src/resources/resource-object.ts +22 -1
- package/src/resources/template-resource.ts +0 -23
- package/src/resources/workflow-resource.ts +45 -16
- package/src/utils/card-utils.ts +1 -1
- package/src/utils/commit-context.ts +45 -0
- package/src/utils/csv.ts +12 -0
- package/src/utils/file-utils.ts +3 -1
- package/src/utils/git-manager.ts +87 -0
- package/src/utils/handlebars-helpers.ts +95 -0
- package/src/utils/json.ts +29 -15
- package/src/utils/log-utils.ts +33 -4
- package/src/utils/report.ts +8 -74
- package/src/utils/rw-lock.ts +279 -0
- package/src/utils/user-preferences.ts +3 -0
package/src/commands/show.ts
CHANGED
|
@@ -48,6 +48,7 @@ import type { ResourceName } from '../utils/resource-utils.js';
|
|
|
48
48
|
import type { ResourceMap } from '../containers/project/resource-cache.js';
|
|
49
49
|
|
|
50
50
|
import { UserPreferences } from '../utils/user-preferences.js';
|
|
51
|
+
import { read, write } from '../utils/rw-lock.js';
|
|
51
52
|
import ReportMacro from '../macros/report/index.js';
|
|
52
53
|
import TaskQueue from '../macros/task-queue.js';
|
|
53
54
|
import { evaluateMacros } from '../macros/index.js';
|
|
@@ -146,10 +147,13 @@ export class Show {
|
|
|
146
147
|
* Shows all template cards in a project.
|
|
147
148
|
* @returns all template cards in a project.
|
|
148
149
|
*/
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
@read
|
|
151
|
+
public async showAllTemplateCards(): Promise<
|
|
152
|
+
{
|
|
153
|
+
name: string;
|
|
154
|
+
cards: CardWithChildrenCards[];
|
|
155
|
+
}[]
|
|
156
|
+
> {
|
|
153
157
|
return this.project.resources.templates().map((template) => {
|
|
154
158
|
const cards = template.templateObject().listCards();
|
|
155
159
|
const buildCards = buildCardHierarchy(cards);
|
|
@@ -165,6 +169,7 @@ export class Show {
|
|
|
165
169
|
* Shows all attachments (either template or project attachments) from a project.
|
|
166
170
|
* @returns array of card attachments
|
|
167
171
|
*/
|
|
172
|
+
@read
|
|
168
173
|
public async showAttachments(): Promise<CardAttachment[]> {
|
|
169
174
|
const attachments = this.project.attachments();
|
|
170
175
|
const templateAttachments = await this.attachmentsFromTemplates();
|
|
@@ -178,7 +183,11 @@ export class Show {
|
|
|
178
183
|
* @param filename attachment filename
|
|
179
184
|
* @returns attachment details
|
|
180
185
|
*/
|
|
181
|
-
|
|
186
|
+
@read
|
|
187
|
+
public async showAttachment(
|
|
188
|
+
cardKey: string,
|
|
189
|
+
filename: string,
|
|
190
|
+
): Promise<attachmentPayload> {
|
|
182
191
|
if (!cardKey) {
|
|
183
192
|
throw new Error(`Mandatory parameter 'cardKey' missing`);
|
|
184
193
|
}
|
|
@@ -203,6 +212,7 @@ export class Show {
|
|
|
203
212
|
* @param waitDelay amount of time to wait for the application to open the attachment
|
|
204
213
|
* @todo: Move away from Show.
|
|
205
214
|
*/
|
|
215
|
+
@read
|
|
206
216
|
public async openAttachment(
|
|
207
217
|
cardKey: string,
|
|
208
218
|
filename: string,
|
|
@@ -259,10 +269,11 @@ export class Show {
|
|
|
259
269
|
* @param contentType Content format in which content is to be shown
|
|
260
270
|
* @returns card details
|
|
261
271
|
*/
|
|
262
|
-
|
|
272
|
+
@read
|
|
273
|
+
public async showCardDetails(
|
|
263
274
|
cardKey?: string,
|
|
264
275
|
contentType?: FileContentType,
|
|
265
|
-
): Card {
|
|
276
|
+
): Promise<Card> {
|
|
266
277
|
if (!cardKey) {
|
|
267
278
|
throw new Error(`Mandatory parameter 'cardKey' missing`);
|
|
268
279
|
}
|
|
@@ -285,6 +296,7 @@ export class Show {
|
|
|
285
296
|
* @param cardsFrom - The location from which to look for cards. Either from the project, templates or both.
|
|
286
297
|
* @returns cards list array
|
|
287
298
|
*/
|
|
299
|
+
@read
|
|
288
300
|
public async showCards(
|
|
289
301
|
cardsFrom?: CardLocation,
|
|
290
302
|
): Promise<CardListContainer[]> {
|
|
@@ -296,6 +308,7 @@ export class Show {
|
|
|
296
308
|
* @param cardKey The key of the card.
|
|
297
309
|
* @returns the content of the logic program.
|
|
298
310
|
*/
|
|
311
|
+
@read
|
|
299
312
|
public async showCardLogicProgram(cardKey: string) {
|
|
300
313
|
return this.project.calculationEngine.cardLogicProgram(cardKey);
|
|
301
314
|
}
|
|
@@ -304,6 +317,7 @@ export class Show {
|
|
|
304
317
|
* Shows all card types in a project.
|
|
305
318
|
* @returns array of card type details
|
|
306
319
|
*/
|
|
320
|
+
@read
|
|
307
321
|
public async showCardTypesWithDetails(): Promise<(CardType | undefined)[]> {
|
|
308
322
|
const container = [];
|
|
309
323
|
for (const cardType of this.project.resources.cardTypes()) {
|
|
@@ -324,6 +338,7 @@ export class Show {
|
|
|
324
338
|
* with 'showAll' true, the list consists of all modules in the hubs, even if they have already been imported
|
|
325
339
|
* Note that the two boolean options can be combined.
|
|
326
340
|
*/
|
|
341
|
+
@write()
|
|
327
342
|
public async showImportableModules(
|
|
328
343
|
showAll?: boolean,
|
|
329
344
|
showDetails?: boolean,
|
|
@@ -368,7 +383,8 @@ export class Show {
|
|
|
368
383
|
* Returns all unique labels in a project
|
|
369
384
|
* @returns labels in a list
|
|
370
385
|
*/
|
|
371
|
-
|
|
386
|
+
@read
|
|
387
|
+
public async showLabels(): Promise<string[]> {
|
|
372
388
|
const cards = flattenCardArray(
|
|
373
389
|
this.project.showProjectCards(),
|
|
374
390
|
this.project,
|
|
@@ -384,6 +400,7 @@ export class Show {
|
|
|
384
400
|
* @param resource Name of the resource.
|
|
385
401
|
* @returns the content of the logic program.
|
|
386
402
|
*/
|
|
403
|
+
@read
|
|
387
404
|
public async showLogicProgram(resource: ResourceName) {
|
|
388
405
|
return this.project.calculationEngine.resourceLogicProgram(resource);
|
|
389
406
|
}
|
|
@@ -393,6 +410,7 @@ export class Show {
|
|
|
393
410
|
* @param moduleName name of a module
|
|
394
411
|
* @returns details of a module.
|
|
395
412
|
*/
|
|
413
|
+
@read
|
|
396
414
|
public async showModule(moduleName: string): Promise<ModuleContent> {
|
|
397
415
|
const moduleDetails = await this.project.module(moduleName);
|
|
398
416
|
if (!moduleDetails) {
|
|
@@ -405,6 +423,7 @@ export class Show {
|
|
|
405
423
|
* Shows hubs of the project.
|
|
406
424
|
* @returns list of hubs.
|
|
407
425
|
*/
|
|
426
|
+
@write()
|
|
408
427
|
public async showHubs(): Promise<HubSetting[]> {
|
|
409
428
|
// Ensure module list is up to date before showing
|
|
410
429
|
await this.fetchCmd.ensureModuleListUpToDate();
|
|
@@ -415,7 +434,8 @@ export class Show {
|
|
|
415
434
|
* Returns all project cards in the project. Cards don't have content and nor metadata.
|
|
416
435
|
* @returns array of cards
|
|
417
436
|
*/
|
|
418
|
-
|
|
437
|
+
@read
|
|
438
|
+
public async showProjectCards(): Promise<Card[]> {
|
|
419
439
|
return this.project.showProjectCards();
|
|
420
440
|
}
|
|
421
441
|
|
|
@@ -423,7 +443,8 @@ export class Show {
|
|
|
423
443
|
* Shows all modules (if any) in a project.
|
|
424
444
|
* @returns all modules in a project.
|
|
425
445
|
*/
|
|
426
|
-
|
|
446
|
+
@read
|
|
447
|
+
public async showModules(): Promise<string[]> {
|
|
427
448
|
return this.project.resources.moduleNames().sort();
|
|
428
449
|
}
|
|
429
450
|
|
|
@@ -431,6 +452,7 @@ export class Show {
|
|
|
431
452
|
* Shows details of a particular project.
|
|
432
453
|
* @returns project information
|
|
433
454
|
*/
|
|
455
|
+
@read
|
|
434
456
|
public async showProject(): Promise<ProjectMetadata> {
|
|
435
457
|
return this.project.show();
|
|
436
458
|
}
|
|
@@ -445,6 +467,7 @@ export class Show {
|
|
|
445
467
|
* @returns Report results as a string
|
|
446
468
|
* @throws Error if the report does not exist
|
|
447
469
|
*/
|
|
470
|
+
@read
|
|
448
471
|
public async showReportResults(
|
|
449
472
|
reportName: string,
|
|
450
473
|
cardKey: string,
|
|
@@ -487,6 +510,7 @@ export class Show {
|
|
|
487
510
|
if (error instanceof Error) {
|
|
488
511
|
throw new Error(
|
|
489
512
|
`Failed to write report to ${outputPath}: ${error.message}`,
|
|
513
|
+
{ cause: error },
|
|
490
514
|
);
|
|
491
515
|
}
|
|
492
516
|
}
|
|
@@ -515,29 +539,31 @@ export class Show {
|
|
|
515
539
|
arg2?: boolean | ResourceType,
|
|
516
540
|
arg3?: boolean,
|
|
517
541
|
): Promise<AnyResourceContent> {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
542
|
+
return this.project.lock.read(async () => {
|
|
543
|
+
const hasResourceType = typeof arg2 === 'string';
|
|
544
|
+
const resourceType = hasResourceType ? arg2 : null;
|
|
545
|
+
const showUse = hasResourceType ? arg3 : arg2;
|
|
546
|
+
|
|
547
|
+
const type = this.project.resources.extractType(name);
|
|
548
|
+
if (resourceType !== null && resourceType !== type) {
|
|
549
|
+
throw new Error(
|
|
550
|
+
`While fetching '${name}': Expected type '${resourceType}', but got '${type}' instead`,
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
const resource = this.project.resources.byType(name, type);
|
|
554
|
+
const [details, usage] = await Promise.all([
|
|
555
|
+
resource?.show(),
|
|
556
|
+
showUse ? resource?.usage() : [],
|
|
557
|
+
]);
|
|
558
|
+
if (showUse) {
|
|
559
|
+
return {
|
|
560
|
+
...details,
|
|
561
|
+
usedIn: [...usage],
|
|
562
|
+
};
|
|
563
|
+
} else {
|
|
564
|
+
return details;
|
|
565
|
+
}
|
|
566
|
+
});
|
|
541
567
|
}
|
|
542
568
|
|
|
543
569
|
/**
|
|
@@ -545,6 +571,7 @@ export class Show {
|
|
|
545
571
|
* @param type Name of resources to return (in plural form, e.g. 'templates')
|
|
546
572
|
* @returns sorted array of resources
|
|
547
573
|
*/
|
|
574
|
+
@read
|
|
548
575
|
public async showResources(type: string): Promise<string[]> {
|
|
549
576
|
const func = this.resourceFunctions[type];
|
|
550
577
|
if (!func) return [];
|
|
@@ -555,6 +582,7 @@ export class Show {
|
|
|
555
582
|
* Shows all templates with full details in a project.
|
|
556
583
|
* @returns all templates in a project.
|
|
557
584
|
*/
|
|
585
|
+
@read
|
|
558
586
|
public async showTemplatesWithDetails(): Promise<TemplateConfiguration[]> {
|
|
559
587
|
const templates = [];
|
|
560
588
|
for (const template of this.project.resources.templates()) {
|
|
@@ -567,7 +595,8 @@ export class Show {
|
|
|
567
595
|
* Shows all workflows with full details in a project.
|
|
568
596
|
* @returns workflows with full details
|
|
569
597
|
*/
|
|
570
|
-
|
|
598
|
+
@read
|
|
599
|
+
public async showWorkflowsWithDetails(): Promise<(Workflow | undefined)[]> {
|
|
571
600
|
const workflows = [];
|
|
572
601
|
for (const workflow of this.project.resources.workflows()) {
|
|
573
602
|
workflows.push(workflow.data);
|
|
@@ -15,6 +15,7 @@ import { ActionGuard } from '../permissions/action-guard.js';
|
|
|
15
15
|
import { CardMetadataUpdater } from '../card-metadata-updater.js';
|
|
16
16
|
import type { Project } from '../containers/project.js';
|
|
17
17
|
import type { WorkflowState } from '../interfaces/resource-interfaces.js';
|
|
18
|
+
import { write } from '../utils/rw-lock.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Handles transitions.
|
|
@@ -40,6 +41,7 @@ export class Transition {
|
|
|
40
41
|
* @param cardKey card key
|
|
41
42
|
* @param transition which transition to do
|
|
42
43
|
*/
|
|
44
|
+
@write((cardKey) => `Transition card ${cardKey}`)
|
|
43
45
|
public async cardTransition(cardKey: string, transition: WorkflowState) {
|
|
44
46
|
const card = this.project.findCard(cardKey);
|
|
45
47
|
|
package/src/commands/update.ts
CHANGED
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
} from '../resources/resource-object.js';
|
|
22
22
|
import type { Project } from '../containers/project.js';
|
|
23
23
|
import type { UpdateKey } from '../interfaces/resource-interfaces.js';
|
|
24
|
+
import { runWithDefaultCommitMessage } from '../utils/commit-context.js';
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Class that handles 'update' commands.
|
|
@@ -47,9 +48,13 @@ export class Update {
|
|
|
47
48
|
T extends UpdateOperations,
|
|
48
49
|
K extends string,
|
|
49
50
|
>(name: string, updateKey: UpdateKey<K>, operation: OperationFor<Type, T>) {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const run = () =>
|
|
52
|
+
this.project.lock.write(async () => {
|
|
53
|
+
const type = this.project.resources.extractType(name);
|
|
54
|
+
const resource = this.project.resources.byType(name, type);
|
|
55
|
+
await resource?.update(updateKey, operation);
|
|
56
|
+
});
|
|
57
|
+
return runWithDefaultCommitMessage('Apply resource operation', run);
|
|
53
58
|
}
|
|
54
59
|
|
|
55
60
|
/**
|
|
@@ -69,6 +74,7 @@ export class Update {
|
|
|
69
74
|
optionalDetail?: Type, // todo: for 'rank' it might be reasonable to accept also 'number'
|
|
70
75
|
mappingTable?: { stateMapping: Record<string, string> },
|
|
71
76
|
) {
|
|
77
|
+
// Safe to not have lock here, this is just a wrapper to applyResourceOperation
|
|
72
78
|
const op: Operation<Type> = {
|
|
73
79
|
name: operation,
|
|
74
80
|
target: '' as Type,
|
package/src/commands/validate.ts
CHANGED
|
@@ -240,7 +240,7 @@ export class Validate {
|
|
|
240
240
|
const result = await Promise.all(promises);
|
|
241
241
|
message.push(...result.flat(1));
|
|
242
242
|
} catch (error) {
|
|
243
|
-
throw new Error(errorFunction(error));
|
|
243
|
+
throw new Error(errorFunction(error), { cause: error });
|
|
244
244
|
}
|
|
245
245
|
return message;
|
|
246
246
|
}
|
|
@@ -56,6 +56,9 @@ import { Validate } from '../commands/validate.js';
|
|
|
56
56
|
import { ContentWatcher } from './project/project-content-watcher.js';
|
|
57
57
|
import { getChildLogger } from '../utils/log-utils.js';
|
|
58
58
|
import { MigrationExecutor } from '../migrations/migration-executor.js';
|
|
59
|
+
import { RWLock } from '../utils/rw-lock.js';
|
|
60
|
+
import { GitManager } from '../utils/git-manager.js';
|
|
61
|
+
import { getCommitContext } from '../utils/commit-context.js';
|
|
59
62
|
|
|
60
63
|
import type { MigrationResult } from '@cyberismo/migrations';
|
|
61
64
|
import type { Template } from './template.js';
|
|
@@ -78,13 +81,16 @@ export { ResourcesFrom };
|
|
|
78
81
|
export interface ProjectOptions {
|
|
79
82
|
autoSave?: boolean;
|
|
80
83
|
watchResourceChanges?: boolean;
|
|
84
|
+
autocommit?: boolean;
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
/**
|
|
84
88
|
* Represents project folder.
|
|
85
89
|
*/
|
|
86
90
|
export class Project extends CardContainer {
|
|
91
|
+
public readonly lock = new RWLock();
|
|
87
92
|
public calculationEngine: CalculationEngine;
|
|
93
|
+
private gitManager?: GitManager;
|
|
88
94
|
private logger = getChildLogger({ module: 'Project' });
|
|
89
95
|
private projectPaths: ProjectPaths;
|
|
90
96
|
private resourceHandler: ResourceHandler;
|
|
@@ -140,6 +146,28 @@ export class Project extends CardContainer {
|
|
|
140
146
|
},
|
|
141
147
|
);
|
|
142
148
|
}
|
|
149
|
+
|
|
150
|
+
if (this.options.autocommit) {
|
|
151
|
+
this.gitManager = new GitManager(path);
|
|
152
|
+
|
|
153
|
+
// Commit after successful writes
|
|
154
|
+
this.lock.onAfterWrite(async () => {
|
|
155
|
+
const context = getCommitContext();
|
|
156
|
+
await this.gitManager!.commit(
|
|
157
|
+
context.message ?? 'Autocommit',
|
|
158
|
+
context.author,
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Rollback on failed writes
|
|
163
|
+
this.lock.onWriteError(async () => {
|
|
164
|
+
await this.gitManager!.rollback();
|
|
165
|
+
// Invalidate caches after rollback since filesystem state changed
|
|
166
|
+
this.cardCache.clear();
|
|
167
|
+
await this.populateCardsCache();
|
|
168
|
+
this.resources.changed();
|
|
169
|
+
});
|
|
170
|
+
}
|
|
143
171
|
}
|
|
144
172
|
|
|
145
173
|
// Changes a card's parent in the cache and updates all relationships.
|
|
@@ -868,6 +896,15 @@ export class Project extends CardContainer {
|
|
|
868
896
|
return this.projectPaths;
|
|
869
897
|
}
|
|
870
898
|
|
|
899
|
+
/**
|
|
900
|
+
* Initialize git repo for autocommit mode. No-op if autocommit is disabled.
|
|
901
|
+
*/
|
|
902
|
+
public async initializeGit(): Promise<void> {
|
|
903
|
+
if (this.gitManager) {
|
|
904
|
+
await this.gitManager.initialize(getCommitContext().author);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
|
|
871
908
|
/**
|
|
872
909
|
* Populates the card cache, if it has not been populated.
|
|
873
910
|
*/
|
|
@@ -939,7 +976,7 @@ export class Project extends CardContainer {
|
|
|
939
976
|
await unlink(attachmentPath);
|
|
940
977
|
} catch (error) {
|
|
941
978
|
this.logger.error({ error }, 'Removing card attachment');
|
|
942
|
-
throw new Error(`Attachment not found: ${fileName}
|
|
979
|
+
throw new Error(`Attachment not found: ${fileName}`, { cause: error });
|
|
943
980
|
}
|
|
944
981
|
await this.handleAttachmentChange(cardKey, 'removed', fileName);
|
|
945
982
|
}
|
|
@@ -1134,6 +1171,43 @@ export class Project extends CardContainer {
|
|
|
1134
1171
|
}
|
|
1135
1172
|
}
|
|
1136
1173
|
|
|
1174
|
+
/**
|
|
1175
|
+
* Updates descendant card paths in the cache after a parent card has been moved.
|
|
1176
|
+
* This ensures cached paths reflect the actual filesystem locations.
|
|
1177
|
+
* @param cardKey The card whose descendants need path updates
|
|
1178
|
+
* @param oldBasePath The old base path before the move
|
|
1179
|
+
* @param newBasePath The new base path after the move
|
|
1180
|
+
*/
|
|
1181
|
+
public updateDescendantPathsAfterMove(
|
|
1182
|
+
cardKey: string,
|
|
1183
|
+
oldBasePath: string,
|
|
1184
|
+
newBasePath: string,
|
|
1185
|
+
): void {
|
|
1186
|
+
const card = this.cardCache.getCard(cardKey);
|
|
1187
|
+
if (!card) return;
|
|
1188
|
+
|
|
1189
|
+
if (card.path.startsWith(oldBasePath)) {
|
|
1190
|
+
card.path = card.path.replace(oldBasePath, newBasePath);
|
|
1191
|
+
|
|
1192
|
+
if (card.attachments && card.attachments.length > 0) {
|
|
1193
|
+
for (const attachment of card.attachments) {
|
|
1194
|
+
if (attachment.path.startsWith(oldBasePath)) {
|
|
1195
|
+
attachment.path = attachment.path.replace(oldBasePath, newBasePath);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
this.cardCache.updateCard(card.key, card);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
// Recursively update children
|
|
1204
|
+
if (card.children && card.children.length > 0) {
|
|
1205
|
+
for (const childKey of card.children) {
|
|
1206
|
+
this.updateDescendantPathsAfterMove(childKey, oldBasePath, newBasePath);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1137
1211
|
/**
|
|
1138
1212
|
* Updates the entire card in the card cache and handles any path/parent changes.
|
|
1139
1213
|
* Also persists changes to content and metadata files.
|
|
@@ -399,7 +399,7 @@ export class Template extends CardContainer {
|
|
|
399
399
|
const destinationCardPath = parentCard
|
|
400
400
|
? join(this.cardFolder(parentCard.key), 'c')
|
|
401
401
|
: this.templateCardsPath;
|
|
402
|
-
let newCardKey
|
|
402
|
+
let newCardKey: string;
|
|
403
403
|
|
|
404
404
|
try {
|
|
405
405
|
// todo: to use cache instead of file access
|
|
@@ -92,6 +92,7 @@ export interface ShowCommandOptions extends BaseCommandOptions {
|
|
|
92
92
|
export interface StartCommandOptions extends BaseCommandOptions {
|
|
93
93
|
forceStart?: boolean;
|
|
94
94
|
watchResourceChanges?: boolean;
|
|
95
|
+
autocommit?: boolean;
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
// Options for 'transition' command
|
|
@@ -83,18 +83,14 @@ export interface FieldType extends ResourceBaseMetadata {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// Graph model content.
|
|
86
|
-
export
|
|
87
|
-
category?: string;
|
|
88
|
-
}
|
|
86
|
+
export type GraphModelMetadata = ResourceBaseMetadata;
|
|
89
87
|
export interface GraphModel extends GraphModelMetadata {
|
|
90
88
|
content: GraphModelContent;
|
|
91
89
|
}
|
|
92
90
|
export type GraphModelContentPropertyName = 'model';
|
|
93
91
|
|
|
94
92
|
// Graph view content.
|
|
95
|
-
export
|
|
96
|
-
category?: string;
|
|
97
|
-
}
|
|
93
|
+
export type GraphViewMetadata = ResourceBaseMetadata;
|
|
98
94
|
export type GraphViewContentPropertyName = 'viewTemplate';
|
|
99
95
|
export interface GraphView extends GraphViewMetadata {
|
|
100
96
|
content: GraphViewContent;
|
|
@@ -128,13 +124,12 @@ export type ReportContentPropertyName =
|
|
|
128
124
|
| 'schema';
|
|
129
125
|
|
|
130
126
|
// Metadata for report
|
|
131
|
-
export
|
|
132
|
-
category: string;
|
|
133
|
-
}
|
|
127
|
+
export type ReportMetadata = ResourceBaseMetadata;
|
|
134
128
|
|
|
135
129
|
// Base interface for all resources.
|
|
136
130
|
export interface ResourceBaseMetadata {
|
|
137
131
|
name: string;
|
|
132
|
+
category?: string;
|
|
138
133
|
description?: string;
|
|
139
134
|
displayName: string;
|
|
140
135
|
usedIn?: string[];
|
|
@@ -173,9 +168,7 @@ export interface TemplateConfiguration extends TemplateMetadata {
|
|
|
173
168
|
}
|
|
174
169
|
|
|
175
170
|
// Template configuration content details.
|
|
176
|
-
export
|
|
177
|
-
category?: string;
|
|
178
|
-
}
|
|
171
|
+
export type TemplateMetadata = ResourceBaseMetadata;
|
|
179
172
|
type ContentUpdateKey = { key: 'content'; subKey: string };
|
|
180
173
|
type PropertyUpdateKey<K extends string = string> = {
|
|
181
174
|
key: Exclude<K, 'content'>;
|
package/src/macros/base-macro.ts
CHANGED
|
@@ -134,7 +134,7 @@ abstract class BaseMacro {
|
|
|
134
134
|
} catch (error) {
|
|
135
135
|
if (error instanceof Error) {
|
|
136
136
|
const errorMessage = `From card '${context.cardKey}' a macro validation error:\n\n${error.message}.\n\nCard content:\n ${input}`;
|
|
137
|
-
throw new Error(errorMessage);
|
|
137
|
+
throw new Error(errorMessage, { cause: error });
|
|
138
138
|
}
|
|
139
139
|
throw error;
|
|
140
140
|
}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import BaseMacro from '../base-macro.js';
|
|
15
15
|
import { createImage, validateMacroContent } from '../index.js';
|
|
16
|
+
import { registerComparisonHelpers } from '../../utils/handlebars-helpers.js';
|
|
16
17
|
import Handlebars from 'handlebars';
|
|
17
18
|
import macroMetadata from './metadata.js';
|
|
18
19
|
import { ClingoError } from '@cyberismo/node-clingo';
|
|
@@ -54,6 +55,7 @@ class GraphMacro extends BaseMacro {
|
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
const handlebars = Handlebars.create();
|
|
58
|
+
registerComparisonHelpers(handlebars);
|
|
57
59
|
const view = handlebars.compile(viewContent.viewTemplate)(
|
|
58
60
|
handlebarsContext,
|
|
59
61
|
);
|
|
@@ -69,6 +71,7 @@ class GraphMacro extends BaseMacro {
|
|
|
69
71
|
if (error instanceof ClingoError) {
|
|
70
72
|
throw new Error(
|
|
71
73
|
`Error running graph in view '${options.view}' in model '${options.model}': ${error.details.errors.join('\n')}`,
|
|
74
|
+
{ cause: error },
|
|
72
75
|
);
|
|
73
76
|
}
|
|
74
77
|
throw error;
|
|
@@ -19,6 +19,8 @@ import macroMetadata from './metadata.js';
|
|
|
19
19
|
import BaseMacro from '../base-macro.js';
|
|
20
20
|
import type TaskQueue from '../task-queue.js';
|
|
21
21
|
import { MAX_LEVEL_OFFSET } from '../../utils/constants.js';
|
|
22
|
+
import { escapeCsvField } from '../../utils/csv.js';
|
|
23
|
+
import { escapeJsonString } from '../../utils/json.js';
|
|
22
24
|
|
|
23
25
|
export default class IncludeMacro extends BaseMacro {
|
|
24
26
|
constructor(tasksQueue: TaskQueue) {
|
|
@@ -40,6 +42,14 @@ export default class IncludeMacro extends BaseMacro {
|
|
|
40
42
|
if (!options.pageTitles) {
|
|
41
43
|
options.pageTitles = 'normal';
|
|
42
44
|
}
|
|
45
|
+
|
|
46
|
+
// Validate incompatible option combinations
|
|
47
|
+
if (options.escape && options.title !== 'exclude') {
|
|
48
|
+
throw new Error(
|
|
49
|
+
'The "escape" option can only be used with "title": "exclude". ' +
|
|
50
|
+
'Escaping is meant for embedding raw content in JSON/CSV documents, not for generating AsciiDoc output.',
|
|
51
|
+
);
|
|
52
|
+
}
|
|
43
53
|
const newContext = {
|
|
44
54
|
...context,
|
|
45
55
|
cardKey: options.cardKey,
|
|
@@ -52,6 +62,8 @@ export default class IncludeMacro extends BaseMacro {
|
|
|
52
62
|
card.content,
|
|
53
63
|
newContext,
|
|
54
64
|
);
|
|
65
|
+
|
|
66
|
+
// Skip the leading newlines if trim is enabled
|
|
55
67
|
const content = `\n\n${anchor}${title}${cardContent}`;
|
|
56
68
|
|
|
57
69
|
let levelOffset = 0;
|
|
@@ -102,7 +114,13 @@ export default class IncludeMacro extends BaseMacro {
|
|
|
102
114
|
context: MacroGenerationContext,
|
|
103
115
|
): Promise<string> {
|
|
104
116
|
if (options.title !== 'only') {
|
|
105
|
-
|
|
117
|
+
let content = await evaluateMacros(cardContent ?? '', context, true);
|
|
118
|
+
if (options.escape === 'json') {
|
|
119
|
+
content = escapeJsonString(content);
|
|
120
|
+
} else if (options.escape === 'csv') {
|
|
121
|
+
content = escapeCsvField(content);
|
|
122
|
+
}
|
|
123
|
+
return content;
|
|
106
124
|
}
|
|
107
125
|
return '';
|
|
108
126
|
}
|
|
@@ -12,21 +12,23 @@
|
|
|
12
12
|
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Include macro options.
|
|
17
|
+
* @param cardKey Card key of the card being included
|
|
18
|
+
* @param levelOffset A positive number will increase the level of headings.
|
|
19
|
+
* A negative value will decrease the level of headings in the included content.
|
|
20
|
+
* @param title Determines behaviour with the title that is in card metadata
|
|
21
|
+
* include --> includes the title
|
|
22
|
+
* exclude --> excludes the title
|
|
23
|
+
* only --> includes title but does not import content
|
|
24
|
+
* @param whitespace Whether to trim leading and trailing whitespace
|
|
25
|
+
* @param escape Type of escaping to apply to the included content
|
|
26
|
+
* json --> escapes for JSON strings
|
|
27
|
+
* csv --> escapes for CSV fields
|
|
28
|
+
*/
|
|
15
29
|
export interface IncludeMacroOptions {
|
|
16
|
-
/**
|
|
17
|
-
* Card key of the card being included
|
|
18
|
-
*/
|
|
19
30
|
cardKey: string;
|
|
20
|
-
/**
|
|
21
|
-
* A positive number wil increase the level of headings and a negative alue will the level of headings in the included content
|
|
22
|
-
*/
|
|
23
31
|
levelOffset?: string;
|
|
24
|
-
/**
|
|
25
|
-
* Determines behaviour with the title that is in card metadata
|
|
26
|
-
* include --> includes the title
|
|
27
|
-
* exclude --> excludes the title
|
|
28
|
-
* only --> includes title but does not import content
|
|
29
|
-
*/
|
|
30
32
|
title?: 'include' | 'exclude' | 'only';
|
|
31
33
|
pageTitles?: 'normal' | 'discrete';
|
|
32
34
|
/**
|
|
@@ -35,4 +37,5 @@ export interface IncludeMacroOptions {
|
|
|
35
37
|
* Default is 'keep'.
|
|
36
38
|
*/
|
|
37
39
|
whitespace?: 'keep' | 'trim';
|
|
40
|
+
escape?: 'json' | 'csv';
|
|
38
41
|
}
|
package/src/macros/index.ts
CHANGED
|
@@ -175,7 +175,9 @@ export function validateMacroContent<T>(
|
|
|
175
175
|
if (error instanceof DHValidationError) {
|
|
176
176
|
message = `${error.errors?.map((e) => e.message).join(', ')}`;
|
|
177
177
|
}
|
|
178
|
-
throw new Error(`${macro.name} macro JSON validation error: ${message}
|
|
178
|
+
throw new Error(`${macro.name} macro JSON validation error: ${message}`, {
|
|
179
|
+
cause: error,
|
|
180
|
+
});
|
|
179
181
|
}
|
|
180
182
|
}
|
|
181
183
|
|
|
@@ -249,6 +251,7 @@ export async function evaluateMacros(
|
|
|
249
251
|
try {
|
|
250
252
|
const compiled = handlebars.compile(preprocessRawBlocks(result), {
|
|
251
253
|
strict: true,
|
|
254
|
+
ignoreStandalone: true,
|
|
252
255
|
});
|
|
253
256
|
result = compiled({ cardKey: context.cardKey });
|
|
254
257
|
|