@cyberismo/data-handler 0.0.16 → 0.0.18
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 +5 -7
- package/dist/command-handler.js.map +1 -1
- package/dist/command-manager.js +4 -4
- package/dist/command-manager.js.map +1 -1
- package/dist/commands/create.js +1 -1
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/fetch.d.ts +8 -0
- package/dist/commands/fetch.js +101 -23
- package/dist/commands/fetch.js.map +1 -1
- package/dist/commands/import.d.ts +5 -2
- package/dist/commands/import.js +12 -3
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/remove.d.ts +3 -1
- package/dist/commands/remove.js +7 -1
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/rename.js +5 -0
- package/dist/commands/rename.js.map +1 -1
- package/dist/commands/show.d.ts +4 -2
- package/dist/commands/show.js +8 -2
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/validate.js +3 -5
- package/dist/commands/validate.js.map +1 -1
- package/dist/containers/card-container.d.ts +7 -5
- package/dist/containers/card-container.js +30 -5
- package/dist/containers/card-container.js.map +1 -1
- package/dist/containers/project/project-paths.d.ts +2 -0
- package/dist/containers/project/project-paths.js +6 -0
- package/dist/containers/project/project-paths.js.map +1 -1
- package/dist/containers/project/resource-cache.js +9 -7
- package/dist/containers/project/resource-cache.js.map +1 -1
- package/dist/containers/project.d.ts +11 -2
- package/dist/containers/project.js +54 -8
- package/dist/containers/project.js.map +1 -1
- package/dist/containers/template.js +4 -4
- package/dist/containers/template.js.map +1 -1
- package/dist/interfaces/command-options.d.ts +3 -1
- package/dist/interfaces/project-interfaces.d.ts +5 -5
- package/dist/interfaces/project-interfaces.js.map +1 -1
- package/dist/project-settings.d.ts +5 -0
- package/dist/project-settings.js +12 -0
- package/dist/project-settings.js.map +1 -1
- package/dist/resources/card-type-resource.d.ts +6 -2
- package/dist/resources/card-type-resource.js +68 -86
- package/dist/resources/card-type-resource.js.map +1 -1
- package/dist/resources/field-type-resource.d.ts +5 -1
- package/dist/resources/field-type-resource.js +49 -54
- package/dist/resources/field-type-resource.js.map +1 -1
- package/dist/resources/file-resource.d.ts +14 -1
- package/dist/resources/file-resource.js +29 -0
- package/dist/resources/file-resource.js.map +1 -1
- package/dist/resources/link-type-resource.d.ts +5 -1
- package/dist/resources/link-type-resource.js +28 -30
- package/dist/resources/link-type-resource.js.map +1 -1
- package/dist/resources/resource-object.d.ts +1 -0
- package/dist/resources/resource-object.js +52 -1
- package/dist/resources/resource-object.js.map +1 -1
- package/dist/resources/template-resource.js +5 -26
- package/dist/resources/template-resource.js.map +1 -1
- package/dist/resources/workflow-resource.d.ts +1 -1
- package/dist/resources/workflow-resource.js +79 -76
- package/dist/resources/workflow-resource.js.map +1 -1
- package/dist/utils/configuration-logger.d.ts +91 -0
- package/dist/utils/configuration-logger.js +151 -0
- package/dist/utils/configuration-logger.js.map +1 -0
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.js +5 -3
- package/dist/utils/constants.js.map +1 -1
- package/package.json +4 -4
- package/src/command-handler.ts +17 -9
- package/src/command-manager.ts +4 -4
- package/src/commands/create.ts +1 -1
- package/src/commands/fetch.ts +143 -34
- package/src/commands/import.ts +13 -1
- package/src/commands/remove.ts +10 -1
- package/src/commands/rename.ts +15 -0
- package/src/commands/show.ts +11 -3
- package/src/commands/validate.ts +3 -7
- package/src/containers/card-container.ts +37 -5
- package/src/containers/project/project-paths.ts +8 -0
- package/src/containers/project/resource-cache.ts +12 -9
- package/src/containers/project.ts +76 -9
- package/src/containers/template.ts +4 -4
- package/src/interfaces/command-options.ts +3 -1
- package/src/interfaces/project-interfaces.ts +5 -5
- package/src/project-settings.ts +13 -0
- package/src/resources/card-type-resource.ts +91 -109
- package/src/resources/field-type-resource.ts +60 -64
- package/src/resources/file-resource.ts +43 -1
- package/src/resources/link-type-resource.ts +32 -36
- package/src/resources/resource-object.ts +73 -1
- package/src/resources/template-resource.ts +6 -26
- package/src/resources/workflow-resource.ts +102 -93
- package/src/utils/configuration-logger.ts +206 -0
- package/src/utils/constants.ts +5 -3
|
@@ -22,7 +22,8 @@ import type {
|
|
|
22
22
|
import type { Project } from '../containers/project.js';
|
|
23
23
|
import type { ResourceBaseMetadata } from '../interfaces/resource-interfaces.js';
|
|
24
24
|
import type { ResourceName } from '../utils/resource-utils.js';
|
|
25
|
-
import type { ShowReturnType } from './resource-object.js';
|
|
25
|
+
import type { Operation, ShowReturnType } from './resource-object.js';
|
|
26
|
+
import type { UpdateKey } from '../interfaces/resource-interfaces.js';
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Base class for file based resources (card types, field types, link types, workflows, ...)
|
|
@@ -59,6 +60,13 @@ export abstract class FileResource<
|
|
|
59
60
|
);
|
|
60
61
|
return cards;
|
|
61
62
|
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* For handling name changes.
|
|
66
|
+
* @param previousName The previous name before the change
|
|
67
|
+
*/
|
|
68
|
+
protected abstract onNameChange?(previousName: string): Promise<void>;
|
|
69
|
+
|
|
62
70
|
// Updates resource key to a new prefix
|
|
63
71
|
protected updatePrefixInResourceName(name: string, prefixes: string[]) {
|
|
64
72
|
const { identifier, prefix, type } = resourceName(name);
|
|
@@ -70,6 +78,40 @@ export abstract class FileResource<
|
|
|
70
78
|
: name;
|
|
71
79
|
}
|
|
72
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Updates resource.
|
|
83
|
+
* @param updateKey Key to modify
|
|
84
|
+
* @param op Operation to perform on 'key'
|
|
85
|
+
* @throws if key is unknown.
|
|
86
|
+
*/
|
|
87
|
+
public async update<Type, K extends string>(
|
|
88
|
+
updateKey: UpdateKey<K>,
|
|
89
|
+
op: Operation<Type>,
|
|
90
|
+
) {
|
|
91
|
+
const { key } = updateKey;
|
|
92
|
+
|
|
93
|
+
const nameChange = key === 'name';
|
|
94
|
+
const existingName = this.content.name;
|
|
95
|
+
await super.update(updateKey, op);
|
|
96
|
+
const content = structuredClone(this.content);
|
|
97
|
+
|
|
98
|
+
if (key === 'name') {
|
|
99
|
+
content.name = super.handleScalar(op) as string;
|
|
100
|
+
} else if (key === 'displayName') {
|
|
101
|
+
content.displayName = super.handleScalar(op) as string;
|
|
102
|
+
} else if (key === 'description') {
|
|
103
|
+
content.description = super.handleScalar(op) as string;
|
|
104
|
+
} else {
|
|
105
|
+
throw new Error(`Unknown property '${key}' for folder resource`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
await super.postUpdate(content, updateKey, op);
|
|
109
|
+
|
|
110
|
+
if (nameChange) {
|
|
111
|
+
await this.onNameChange?.(existingName);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
73
115
|
/**
|
|
74
116
|
* Returns the resource metadata content.
|
|
75
117
|
* @returns metadata content
|
|
@@ -32,8 +32,11 @@ export class LinkTypeResource extends FileResource<LinkType> {
|
|
|
32
32
|
this.contentSchema = super.contentSchemaContent(this.contentSchemaId);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* When resource name changes.
|
|
37
|
+
* @param existingName Current resource name.
|
|
38
|
+
*/
|
|
39
|
+
protected async onNameChange(existingName: string) {
|
|
37
40
|
const current = this.content;
|
|
38
41
|
const prefixes = this.project.projectPrefixes();
|
|
39
42
|
if (current.sourceCardTypes) {
|
|
@@ -76,7 +79,7 @@ export class LinkTypeResource extends FileResource<LinkType> {
|
|
|
76
79
|
public async rename(newName: ResourceName) {
|
|
77
80
|
const existingName = this.content.name;
|
|
78
81
|
await super.rename(newName);
|
|
79
|
-
return this.
|
|
82
|
+
return this.onNameChange(existingName);
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
/**
|
|
@@ -89,41 +92,34 @@ export class LinkTypeResource extends FileResource<LinkType> {
|
|
|
89
92
|
op: Operation<Type>,
|
|
90
93
|
) {
|
|
91
94
|
const { key } = updateKey;
|
|
92
|
-
const nameChange = key === 'name';
|
|
93
|
-
const existingName = this.content.name;
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const content = structuredClone(this.content);
|
|
98
|
-
if (key === 'name') {
|
|
99
|
-
content.name = super.handleScalar(op) as string;
|
|
100
|
-
} else if (key === 'destinationCardTypes') {
|
|
101
|
-
content.destinationCardTypes = super.handleArray(
|
|
102
|
-
op,
|
|
103
|
-
key,
|
|
104
|
-
content.destinationCardTypes as Type[],
|
|
105
|
-
) as string[];
|
|
106
|
-
} else if (key === 'enableLinkDescription') {
|
|
107
|
-
content.enableLinkDescription = super.handleScalar(op) as boolean;
|
|
108
|
-
} else if (key === 'inboundDisplayName') {
|
|
109
|
-
content.inboundDisplayName = super.handleScalar(op) as string;
|
|
110
|
-
} else if (key === 'outboundDisplayName') {
|
|
111
|
-
content.outboundDisplayName = super.handleScalar(op) as string;
|
|
112
|
-
} else if (key === 'sourceCardTypes') {
|
|
113
|
-
content.sourceCardTypes = super.handleArray(
|
|
114
|
-
op,
|
|
115
|
-
key,
|
|
116
|
-
content.sourceCardTypes as Type[],
|
|
117
|
-
) as string[];
|
|
96
|
+
if (key === 'name' || key === 'displayName' || key === 'description') {
|
|
97
|
+
await super.update(updateKey, op);
|
|
118
98
|
} else {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
99
|
+
const content = structuredClone(this.content);
|
|
100
|
+
if (key === 'destinationCardTypes') {
|
|
101
|
+
content.destinationCardTypes = super.handleArray(
|
|
102
|
+
op,
|
|
103
|
+
key,
|
|
104
|
+
content.destinationCardTypes as Type[],
|
|
105
|
+
) as string[];
|
|
106
|
+
} else if (key === 'enableLinkDescription') {
|
|
107
|
+
content.enableLinkDescription = super.handleScalar(op) as boolean;
|
|
108
|
+
} else if (key === 'inboundDisplayName') {
|
|
109
|
+
content.inboundDisplayName = super.handleScalar(op) as string;
|
|
110
|
+
} else if (key === 'outboundDisplayName') {
|
|
111
|
+
content.outboundDisplayName = super.handleScalar(op) as string;
|
|
112
|
+
} else if (key === 'sourceCardTypes') {
|
|
113
|
+
content.sourceCardTypes = super.handleArray(
|
|
114
|
+
op,
|
|
115
|
+
key,
|
|
116
|
+
content.sourceCardTypes as Type[],
|
|
117
|
+
) as string[];
|
|
118
|
+
} else {
|
|
119
|
+
throw new Error(`Unknown property '${key}' for LinkType`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
await super.postUpdate(content, updateKey, op);
|
|
127
123
|
}
|
|
128
124
|
}
|
|
129
125
|
|
|
@@ -44,6 +44,11 @@ import type {
|
|
|
44
44
|
} from '../interfaces/resource-interfaces.js';
|
|
45
45
|
import type { Validate } from '../commands/validate.js';
|
|
46
46
|
|
|
47
|
+
import {
|
|
48
|
+
ConfigurationLogger,
|
|
49
|
+
ConfigurationOperation,
|
|
50
|
+
} from '../utils/configuration-logger.js';
|
|
51
|
+
|
|
47
52
|
// Possible operations to perform when doing "update"
|
|
48
53
|
export type UpdateOperations = 'add' | 'change' | 'rank' | 'remove';
|
|
49
54
|
|
|
@@ -308,6 +313,9 @@ export abstract class ResourceObject<
|
|
|
308
313
|
|
|
309
314
|
const resourceString = resourceNameToString(this.resourceName);
|
|
310
315
|
this.project.resources.add(resourceString, this);
|
|
316
|
+
|
|
317
|
+
// Log resource creation to migration log
|
|
318
|
+
await this.logResourceOperation('create');
|
|
311
319
|
}
|
|
312
320
|
|
|
313
321
|
/**
|
|
@@ -408,6 +416,56 @@ export abstract class ResourceObject<
|
|
|
408
416
|
}
|
|
409
417
|
}
|
|
410
418
|
|
|
419
|
+
// Log details
|
|
420
|
+
protected async logResourceOperation<Type>(
|
|
421
|
+
operationType: 'create' | 'delete' | 'update' | 'rename',
|
|
422
|
+
op?: Operation<Type>,
|
|
423
|
+
key?: string,
|
|
424
|
+
): Promise<void> {
|
|
425
|
+
let configOperation: ConfigurationOperation;
|
|
426
|
+
const target = resourceNameToString(this.resourceName);
|
|
427
|
+
const parameters: Record<string, unknown> = { type: this.type };
|
|
428
|
+
|
|
429
|
+
switch (operationType) {
|
|
430
|
+
case 'create':
|
|
431
|
+
configOperation = ConfigurationOperation.RESOURCE_CREATE;
|
|
432
|
+
break;
|
|
433
|
+
case 'delete':
|
|
434
|
+
configOperation = ConfigurationOperation.RESOURCE_DELETE;
|
|
435
|
+
break;
|
|
436
|
+
case 'update':
|
|
437
|
+
configOperation = ConfigurationOperation.RESOURCE_UPDATE;
|
|
438
|
+
if (op) {
|
|
439
|
+
parameters.operation = op.name;
|
|
440
|
+
}
|
|
441
|
+
if (key) {
|
|
442
|
+
parameters.key = key;
|
|
443
|
+
}
|
|
444
|
+
break;
|
|
445
|
+
case 'rename':
|
|
446
|
+
configOperation = ConfigurationOperation.RESOURCE_RENAME;
|
|
447
|
+
if (op && op.name === 'change') {
|
|
448
|
+
const changeOp = op as ChangeOperation<string>;
|
|
449
|
+
parameters.oldName = changeOp.target;
|
|
450
|
+
parameters.newName = changeOp.to;
|
|
451
|
+
}
|
|
452
|
+
break;
|
|
453
|
+
default:
|
|
454
|
+
throw new Error(`Unknown operation type: ${operationType}`);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
await ConfigurationLogger.log(
|
|
458
|
+
this.project.basePath,
|
|
459
|
+
configOperation,
|
|
460
|
+
target,
|
|
461
|
+
{
|
|
462
|
+
parameters,
|
|
463
|
+
},
|
|
464
|
+
);
|
|
465
|
+
|
|
466
|
+
this.logger.info(`Configuration: ${configOperation} - ${target}`);
|
|
467
|
+
}
|
|
468
|
+
|
|
411
469
|
/**
|
|
412
470
|
* Called after inherited class has finished 'update' operation.
|
|
413
471
|
* @param content New content for resource
|
|
@@ -449,6 +507,9 @@ export abstract class ResourceObject<
|
|
|
449
507
|
|
|
450
508
|
this.content = content;
|
|
451
509
|
await this.write();
|
|
510
|
+
|
|
511
|
+
// Log resource update to migration log
|
|
512
|
+
await this.logResourceOperation('update', op, updateKey.key);
|
|
452
513
|
}
|
|
453
514
|
|
|
454
515
|
/**
|
|
@@ -496,9 +557,17 @@ export abstract class ResourceObject<
|
|
|
496
557
|
|
|
497
558
|
this.fileName = newFilename;
|
|
498
559
|
this.content.name = resourceNameToString(newName);
|
|
560
|
+
const newNameString = this.content.name;
|
|
499
561
|
this.resourceName = newName;
|
|
500
562
|
|
|
501
|
-
this.project.resources.rename(oldName,
|
|
563
|
+
this.project.resources.rename(oldName, newNameString);
|
|
564
|
+
|
|
565
|
+
// Log resource rename to migration log
|
|
566
|
+
await this.logResourceOperation('rename', {
|
|
567
|
+
name: 'change',
|
|
568
|
+
target: oldName,
|
|
569
|
+
to: newNameString,
|
|
570
|
+
} as ChangeOperation<string>);
|
|
502
571
|
}
|
|
503
572
|
|
|
504
573
|
/**
|
|
@@ -712,6 +781,9 @@ export abstract class ResourceObject<
|
|
|
712
781
|
await deleteFile(this.fileName);
|
|
713
782
|
this.project.resources.remove(resourceNameToString(this.resourceName));
|
|
714
783
|
this.fileName = '';
|
|
784
|
+
|
|
785
|
+
// Log resource deletion to migration log
|
|
786
|
+
await this.logResourceOperation('delete');
|
|
715
787
|
}
|
|
716
788
|
|
|
717
789
|
/**
|
|
@@ -140,35 +140,15 @@ export class TemplateResource extends FolderResource<TemplateMetadata, never> {
|
|
|
140
140
|
updateKey: UpdateKey<K>,
|
|
141
141
|
op: Operation<Type>,
|
|
142
142
|
) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const existingName = this.content.name;
|
|
146
|
-
|
|
147
|
-
// Only call super.update for keys that base class supports
|
|
148
|
-
if (key === 'name' || key === 'displayName' || key === 'description') {
|
|
149
|
-
await super.update(updateKey, op);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const content = structuredClone(this.content);
|
|
153
|
-
|
|
154
|
-
if (key === 'name') {
|
|
155
|
-
content.name = super.handleScalar(op) as string;
|
|
156
|
-
} else if (key === 'displayName') {
|
|
157
|
-
content.displayName = super.handleScalar(op) as string;
|
|
158
|
-
} else if (key === 'description') {
|
|
159
|
-
content.description = super.handleScalar(op) as string;
|
|
160
|
-
} else if (key === 'category') {
|
|
143
|
+
if (updateKey.key === 'category') {
|
|
144
|
+
const content = structuredClone(this.content);
|
|
161
145
|
content.category = super.handleScalar(op) as string;
|
|
162
|
-
} else {
|
|
163
|
-
throw new Error(`Unknown property '${key}' for Template`);
|
|
164
|
-
}
|
|
165
146
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// Renaming this template causes that references to its name must be updated.
|
|
169
|
-
if (nameChange) {
|
|
170
|
-
await this.onNameChange(existingName);
|
|
147
|
+
await super.postUpdate(content, updateKey, op);
|
|
148
|
+
return;
|
|
171
149
|
}
|
|
150
|
+
|
|
151
|
+
await super.update(updateKey, op);
|
|
172
152
|
}
|
|
173
153
|
|
|
174
154
|
/**
|
|
@@ -56,10 +56,11 @@ export class WorkflowResource extends FileResource<Workflow> {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// When resource name changes.
|
|
59
|
-
|
|
59
|
+
protected async onNameChange(existingName: string) {
|
|
60
60
|
await Promise.all([
|
|
61
61
|
super.updateHandleBars(existingName, this.content.name),
|
|
62
62
|
super.updateCalculations(existingName, this.content.name),
|
|
63
|
+
this.updateCardTypes(existingName),
|
|
63
64
|
]);
|
|
64
65
|
// Finally, write updated content.
|
|
65
66
|
await this.write();
|
|
@@ -193,12 +194,15 @@ export class WorkflowResource extends FileResource<Workflow> {
|
|
|
193
194
|
to: this.content.name,
|
|
194
195
|
} as ChangeOperation<string>;
|
|
195
196
|
for (const cardType of cardTypes) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
197
|
+
// Only update card types that use this workflow
|
|
198
|
+
if (cardType.data?.workflow === oldName) {
|
|
199
|
+
await cardType.update(
|
|
200
|
+
{
|
|
201
|
+
key: 'workflow',
|
|
202
|
+
},
|
|
203
|
+
op,
|
|
204
|
+
);
|
|
205
|
+
}
|
|
202
206
|
}
|
|
203
207
|
}
|
|
204
208
|
|
|
@@ -225,7 +229,7 @@ export class WorkflowResource extends FileResource<Workflow> {
|
|
|
225
229
|
public async rename(newName: ResourceName) {
|
|
226
230
|
const existingName = this.content.name;
|
|
227
231
|
await super.rename(newName);
|
|
228
|
-
return this.
|
|
232
|
+
return this.onNameChange(existingName);
|
|
229
233
|
}
|
|
230
234
|
|
|
231
235
|
/**
|
|
@@ -239,101 +243,106 @@ export class WorkflowResource extends FileResource<Workflow> {
|
|
|
239
243
|
op: Operation<Type>,
|
|
240
244
|
) {
|
|
241
245
|
const { key } = updateKey;
|
|
242
|
-
const nameChange = key === 'name';
|
|
243
|
-
const existingName = this.content.name;
|
|
244
246
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
const content = structuredClone(this.content) as Workflow;
|
|
248
|
-
|
|
249
|
-
if (key === 'name') {
|
|
250
|
-
content.name = super.handleScalar(op) as string;
|
|
251
|
-
} else if (key === 'displayName') {
|
|
252
|
-
content.displayName = super.handleScalar(op) as string;
|
|
253
|
-
} else if (key === 'description') {
|
|
254
|
-
content.description = super.handleScalar(op) as string;
|
|
255
|
-
} else if (key === 'states') {
|
|
256
|
-
content.states = super.handleArray(
|
|
257
|
-
op,
|
|
258
|
-
key,
|
|
259
|
-
content.states as Type[],
|
|
260
|
-
) as WorkflowState[];
|
|
261
|
-
} else if (key === 'transitions') {
|
|
262
|
-
content.transitions = super.handleArray(
|
|
263
|
-
op,
|
|
264
|
-
key,
|
|
265
|
-
content.transitions as WorkflowTransition[] as Type[],
|
|
266
|
-
) as WorkflowTransition[];
|
|
247
|
+
if (key === 'name' || key === 'displayName' || key === 'description') {
|
|
248
|
+
await super.update(updateKey, op);
|
|
267
249
|
} else {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
toState: targetTransition.toState,
|
|
286
|
-
fromState: targetTransition.fromState,
|
|
287
|
-
},
|
|
288
|
-
};
|
|
289
|
-
} else {
|
|
290
|
-
changeOp = op as ChangeOperation<WorkflowTransition>;
|
|
250
|
+
const content = structuredClone(this.content) as Workflow;
|
|
251
|
+
|
|
252
|
+
// Validate state change operations before processing
|
|
253
|
+
if (key === 'states' && op.name === 'change') {
|
|
254
|
+
const changeOp = op as ChangeOperation<WorkflowState>;
|
|
255
|
+
if (
|
|
256
|
+
changeOp.to.name === undefined ||
|
|
257
|
+
changeOp.to.category === undefined
|
|
258
|
+
) {
|
|
259
|
+
const stateName =
|
|
260
|
+
changeOp.target['name' as keyof typeof changeOp.target] ||
|
|
261
|
+
changeOp.target;
|
|
262
|
+
throw new Error(
|
|
263
|
+
`Cannot change state '${stateName}' for workflow '${this.content.name}'.
|
|
264
|
+
Updated state must have 'name' and 'category' properties.`,
|
|
265
|
+
);
|
|
266
|
+
}
|
|
291
267
|
}
|
|
292
|
-
const newTransition = await this.transitionObject(changeOp);
|
|
293
|
-
content.transitions = content.transitions.map((item) =>
|
|
294
|
-
item.name == newTransition.name ? newTransition : item,
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
268
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
269
|
+
if (key === 'states') {
|
|
270
|
+
content.states = super.handleArray(
|
|
271
|
+
op,
|
|
272
|
+
key,
|
|
273
|
+
content.states as Type[],
|
|
274
|
+
) as WorkflowState[];
|
|
275
|
+
} else if (key === 'transitions') {
|
|
276
|
+
content.transitions = super.handleArray(
|
|
277
|
+
op,
|
|
278
|
+
key,
|
|
279
|
+
content.transitions as WorkflowTransition[] as Type[],
|
|
280
|
+
) as WorkflowTransition[];
|
|
309
281
|
} else {
|
|
310
|
-
|
|
282
|
+
throw new Error(`Unknown property '${key}' for Workflow`);
|
|
311
283
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
284
|
+
|
|
285
|
+
// If workflow transition is removed, then above call to 'handleArray' is all that is needed.
|
|
286
|
+
|
|
287
|
+
if (key === 'transitions' && op.name === 'change') {
|
|
288
|
+
// If workflow transition is changed, update to full object and change the content.
|
|
289
|
+
let changeOp: ChangeOperation<WorkflowTransition>;
|
|
290
|
+
if (this.isStringOperation(op)) {
|
|
291
|
+
const targetTransition = (this.content as Workflow).transitions.find(
|
|
292
|
+
(transition) => transition.name === op.target,
|
|
293
|
+
)!;
|
|
294
|
+
changeOp = {
|
|
295
|
+
name: 'change',
|
|
296
|
+
target: targetTransition as WorkflowTransition,
|
|
297
|
+
to: {
|
|
298
|
+
name: op.to,
|
|
299
|
+
toState: targetTransition.toState,
|
|
300
|
+
fromState: targetTransition.fromState,
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
} else {
|
|
304
|
+
changeOp = op as ChangeOperation<WorkflowTransition>;
|
|
305
|
+
}
|
|
306
|
+
const newTransition = await this.transitionObject(changeOp);
|
|
307
|
+
content.transitions = content.transitions.map((item) =>
|
|
308
|
+
item.name == newTransition.name ? newTransition : item,
|
|
319
309
|
);
|
|
320
|
-
changeOp = {
|
|
321
|
-
name: 'change',
|
|
322
|
-
target: toBeChangedState as WorkflowState,
|
|
323
|
-
to: { name: op.to },
|
|
324
|
-
};
|
|
325
|
-
} else {
|
|
326
|
-
changeOp = op as ChangeOperation<WorkflowState>;
|
|
327
310
|
}
|
|
328
|
-
await this.handleStateChange(changeOp);
|
|
329
|
-
}
|
|
330
311
|
|
|
331
|
-
|
|
312
|
+
if (key === 'states' && op.name === 'remove') {
|
|
313
|
+
// If workflow state is removed, remove all transitions "to" and "from" this state.
|
|
314
|
+
let removeOp: RemoveOperation<WorkflowState>;
|
|
315
|
+
if (this.isStringOperation(op)) {
|
|
316
|
+
const toBeRemovedState = this.content.states.find(
|
|
317
|
+
(state) => state.name === op.target,
|
|
318
|
+
);
|
|
319
|
+
removeOp = {
|
|
320
|
+
name: 'remove',
|
|
321
|
+
target: toBeRemovedState as WorkflowState,
|
|
322
|
+
};
|
|
323
|
+
} else {
|
|
324
|
+
removeOp = op as RemoveOperation<WorkflowState>;
|
|
325
|
+
}
|
|
326
|
+
await this.handleStateRemoval(removeOp);
|
|
327
|
+
} else if (key === 'states' && op.name === 'change') {
|
|
328
|
+
// If workflow state is renamed, replace all transitions "to" and "from" the old state with new state.
|
|
329
|
+
let changeOp: ChangeOperation<WorkflowState>;
|
|
330
|
+
if (this.isStringOperation(op)) {
|
|
331
|
+
const toBeChangedState = this.content.states.find(
|
|
332
|
+
(state) => state.name === op.target,
|
|
333
|
+
);
|
|
334
|
+
changeOp = {
|
|
335
|
+
name: 'change',
|
|
336
|
+
target: toBeChangedState as WorkflowState,
|
|
337
|
+
to: { name: op.to },
|
|
338
|
+
};
|
|
339
|
+
} else {
|
|
340
|
+
changeOp = op as ChangeOperation<WorkflowState>;
|
|
341
|
+
}
|
|
342
|
+
await this.handleStateChange(changeOp);
|
|
343
|
+
}
|
|
332
344
|
|
|
333
|
-
|
|
334
|
-
if (nameChange) {
|
|
335
|
-
await this.handleNameChange(existingName);
|
|
336
|
-
await this.updateCardTypes(existingName);
|
|
345
|
+
await super.postUpdate(content, updateKey, op);
|
|
337
346
|
}
|
|
338
347
|
}
|
|
339
348
|
|