@maxdrellin/xenocline 0.0.1
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/.kodrdriv/config.yaml +10 -0
- package/.kodrdriv/context/content.md +26 -0
- package/LICENSE.md +66 -0
- package/README.md +739 -0
- package/__mocks__/src/execution/event.js +8 -0
- package/dist/aggregator.d.ts +28 -0
- package/dist/aggregator.js +31 -0
- package/dist/aggregator.js.map +1 -0
- package/dist/constants.d.ts +2 -0
- package/dist/context.d.ts +3 -0
- package/dist/event/aggregator.d.ts +16 -0
- package/dist/event/aggregator.js +29 -0
- package/dist/event/aggregator.js.map +1 -0
- package/dist/event/event.d.ts +14 -0
- package/dist/event/event.js +12 -0
- package/dist/event/event.js.map +1 -0
- package/dist/event/handler.d.ts +7 -0
- package/dist/event/handler.js +8 -0
- package/dist/event/handler.js.map +1 -0
- package/dist/event/node.d.ts +40 -0
- package/dist/event/node.js +24 -0
- package/dist/event/node.js.map +1 -0
- package/dist/event/phase.d.ts +15 -0
- package/dist/event/phase.js +12 -0
- package/dist/event/phase.js.map +1 -0
- package/dist/event/process.d.ts +14 -0
- package/dist/event/process.js +15 -0
- package/dist/event/process.js.map +1 -0
- package/dist/event/transition.d.ts +45 -0
- package/dist/event/transition.js +35 -0
- package/dist/event/transition.js.map +1 -0
- package/dist/event.d.ts +30 -0
- package/dist/execution/aggregator.d.ts +23 -0
- package/dist/execution/aggregator.js +81 -0
- package/dist/execution/aggregator.js.map +1 -0
- package/dist/execution/event.d.ts +26 -0
- package/dist/execution/event.js +29 -0
- package/dist/execution/event.js.map +1 -0
- package/dist/execution/next.d.ts +7 -0
- package/dist/execution/next.js +116 -0
- package/dist/execution/next.js.map +1 -0
- package/dist/execution/node.d.ts +4 -0
- package/dist/execution/node.js +170 -0
- package/dist/execution/node.js.map +1 -0
- package/dist/execution/process.d.ts +35 -0
- package/dist/execution/process.js +97 -0
- package/dist/execution/process.js.map +1 -0
- package/dist/input.d.ts +6 -0
- package/dist/input.js +4 -0
- package/dist/input.js.map +1 -0
- package/dist/logger.d.ts +12 -0
- package/dist/node/aggregatornode.d.ts +40 -0
- package/dist/node/aggregatornode.js +41 -0
- package/dist/node/aggregatornode.js.map +1 -0
- package/dist/node/node.d.ts +18 -0
- package/dist/node/node.js +80 -0
- package/dist/node/node.js.map +1 -0
- package/dist/node/phasenode.d.ts +21 -0
- package/dist/node/phasenode.js +35 -0
- package/dist/node/phasenode.js.map +1 -0
- package/dist/output.d.ts +6 -0
- package/dist/phase.d.ts +16 -0
- package/dist/phase.js +23 -0
- package/dist/phase.js.map +1 -0
- package/dist/process.d.ts +15 -0
- package/dist/process.js +106 -0
- package/dist/process.js.map +1 -0
- package/dist/transition/beginning.d.ts +19 -0
- package/dist/transition/beginning.js +31 -0
- package/dist/transition/beginning.js.map +1 -0
- package/dist/transition/connection.d.ts +26 -0
- package/dist/transition/connection.js +80 -0
- package/dist/transition/connection.js.map +1 -0
- package/dist/transition/decision.d.ts +20 -0
- package/dist/transition/decision.js +47 -0
- package/dist/transition/decision.js.map +1 -0
- package/dist/transition/next.d.ts +13 -0
- package/dist/transition/next.js +81 -0
- package/dist/transition/next.js.map +1 -0
- package/dist/transition/termination.d.ts +17 -0
- package/dist/transition/termination.js +50 -0
- package/dist/transition/termination.js.map +1 -0
- package/dist/transition/transition.d.ts +16 -0
- package/dist/transition/transition.js +72 -0
- package/dist/transition/transition.js.map +1 -0
- package/dist/util/general.d.ts +4 -0
- package/dist/util/general.js +6 -0
- package/dist/util/general.js.map +1 -0
- package/dist/utility/event/eventfilter.d.ts +7 -0
- package/dist/utility/event/eventfilter.js +15 -0
- package/dist/utility/event/eventfilter.js.map +1 -0
- package/dist/utility/event/filteredhandler.d.ts +13 -0
- package/dist/utility/event/filteredhandler.js +18 -0
- package/dist/utility/event/filteredhandler.js.map +1 -0
- package/dist/utility/event/logginghandler.d.ts +12 -0
- package/dist/xenocline.d.ts +72 -0
- package/dist/xenocline.js +21 -0
- package/dist/xenocline.js.map +1 -0
- package/eslint.config.mjs +82 -0
- package/package.json +71 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Next } from '../transition/next';
|
|
2
|
+
import { Context } from '../context';
|
|
3
|
+
import { Input } from '../input';
|
|
4
|
+
import { Output } from '../output';
|
|
5
|
+
import { Phase } from '../phase';
|
|
6
|
+
import { Node } from './node';
|
|
7
|
+
export interface PhaseNode<I extends Input = Input, // Input to this phase instance
|
|
8
|
+
O extends Output = Output> extends Node {
|
|
9
|
+
type: 'phase';
|
|
10
|
+
phase: Phase<I, O>;
|
|
11
|
+
}
|
|
12
|
+
export interface PhaseNodeOptions<O extends Output = Output, C extends Context = Context> {
|
|
13
|
+
next?: Next<O, C>;
|
|
14
|
+
}
|
|
15
|
+
export declare const DEFAULT_PHASE_NODE_OPTIONS: PhaseNodeOptions<Output, Context>;
|
|
16
|
+
export declare const createPhaseNode: <I extends Input = Input, O extends Output = Output, C extends Context = Context>(id: string, phase: Phase<I, O>, options?: Partial<PhaseNodeOptions<O, C>>) => Readonly<PhaseNode<I, O>>;
|
|
17
|
+
export declare const isPhaseNode: (obj: any) => obj is PhaseNode<any, any>;
|
|
18
|
+
export declare const validatePhaseNode: (item: any, coordinates?: string[]) => Array<{
|
|
19
|
+
coordinates: string[];
|
|
20
|
+
error: string;
|
|
21
|
+
}>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { isPhase } from '../phase.js';
|
|
2
|
+
import { createNode, isNode } from './node.js';
|
|
3
|
+
import { clean } from '../util/general.js';
|
|
4
|
+
|
|
5
|
+
const DEFAULT_PHASE_NODE_OPTIONS = {};
|
|
6
|
+
const createPhaseNode = (id, phase, options)=>{
|
|
7
|
+
let phaseNodeOptions = {
|
|
8
|
+
...DEFAULT_PHASE_NODE_OPTIONS
|
|
9
|
+
};
|
|
10
|
+
if (options) {
|
|
11
|
+
phaseNodeOptions = {
|
|
12
|
+
...phaseNodeOptions,
|
|
13
|
+
...clean(options)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
...createNode('phase', id, {
|
|
18
|
+
next: phaseNodeOptions.next
|
|
19
|
+
}),
|
|
20
|
+
phase
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
const isPhaseNode = (obj)=>{
|
|
24
|
+
if (!isNode(obj) || obj.type !== 'phase') {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const potentialPhaseNode = obj;
|
|
28
|
+
if (!(potentialPhaseNode.phase && typeof potentialPhaseNode.phase === 'object' && isPhase(potentialPhaseNode.phase))) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export { DEFAULT_PHASE_NODE_OPTIONS, createPhaseNode, isPhaseNode };
|
|
35
|
+
//# sourceMappingURL=phasenode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phasenode.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/output.d.ts
ADDED
package/dist/phase.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Input } from './input';
|
|
2
|
+
import { Output } from './output';
|
|
3
|
+
export type ExecuteMethod<T extends Input = Input, U extends Output = Output> = (input: T) => Promise<U>;
|
|
4
|
+
export interface Phase<T extends Input = Input, U extends Output = Output> {
|
|
5
|
+
name: string;
|
|
6
|
+
execute: (input: T) => Promise<U>;
|
|
7
|
+
}
|
|
8
|
+
export interface PhaseOptions<T extends Input = Input, U extends Output = Output> {
|
|
9
|
+
execute: ExecuteMethod<T, U>;
|
|
10
|
+
}
|
|
11
|
+
export declare const createPhase: <T extends Input = Input, U extends Output = Output>(name: string, options: Partial<PhaseOptions<T, U>>) => Readonly<Phase<T, U>>;
|
|
12
|
+
export declare const isPhase: <T extends Input = Input, U extends Output = Output>(obj: any) => obj is Phase<T, U>;
|
|
13
|
+
export declare const validatePhase: (item: any, coordinates?: string[]) => Array<{
|
|
14
|
+
coordinates: string[];
|
|
15
|
+
error: string;
|
|
16
|
+
}>;
|
package/dist/phase.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { clean } from './util/general.js';
|
|
2
|
+
|
|
3
|
+
const createPhase = (name, options)=>{
|
|
4
|
+
const defaultOptions = {
|
|
5
|
+
execute: async (input)=>{
|
|
6
|
+
return input;
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
const phaseOptions = {
|
|
10
|
+
...defaultOptions,
|
|
11
|
+
...clean(options)
|
|
12
|
+
};
|
|
13
|
+
return {
|
|
14
|
+
name,
|
|
15
|
+
execute: phaseOptions.execute
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
const isPhase = (obj)=>{
|
|
19
|
+
return obj !== undefined && obj !== null && typeof obj === 'object' && typeof obj.name === 'string' && typeof obj.execute === 'function';
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export { createPhase, isPhase };
|
|
23
|
+
//# sourceMappingURL=phase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AggregatorNode } from './node/aggregatornode';
|
|
2
|
+
import { PhaseNode } from './node/phasenode';
|
|
3
|
+
export interface ProcessOptions {
|
|
4
|
+
phases: Record<string, PhaseNode | AggregatorNode>;
|
|
5
|
+
}
|
|
6
|
+
export interface Process {
|
|
7
|
+
name: string;
|
|
8
|
+
phases: Record<string, PhaseNode | AggregatorNode>;
|
|
9
|
+
}
|
|
10
|
+
export declare const createProcess: (name: string, options: Partial<ProcessOptions>) => Readonly<Process>;
|
|
11
|
+
export declare const isProcess: (obj: any) => obj is Process;
|
|
12
|
+
export declare const validateProcess: (item: any, coordinates?: string[]) => Array<{
|
|
13
|
+
coordinates: string[];
|
|
14
|
+
error: string;
|
|
15
|
+
}>;
|
package/dist/process.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { validateNode } from './node/node.js';
|
|
2
|
+
import { isConnection } from './transition/connection.js';
|
|
3
|
+
import { clean } from './util/general.js';
|
|
4
|
+
|
|
5
|
+
//import * as ClassifyPhase from './phases/classify';
|
|
6
|
+
// import * as TranscribePhase from './phases/transcribe';
|
|
7
|
+
// import * as ComposePhase from './phases/compose';
|
|
8
|
+
// import * as CompletePhase from './phases/complete';
|
|
9
|
+
const createProcess = (name, options)=>{
|
|
10
|
+
const defaultOptions = {
|
|
11
|
+
phases: {}
|
|
12
|
+
};
|
|
13
|
+
const processOptions = {
|
|
14
|
+
...defaultOptions,
|
|
15
|
+
...clean(options)
|
|
16
|
+
};
|
|
17
|
+
// Removed: const eventState = createEventState<C>(processOptions.eventHandlers);
|
|
18
|
+
return {
|
|
19
|
+
name,
|
|
20
|
+
phases: processOptions.phases
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
const isProcess = (obj)=>{
|
|
24
|
+
return obj !== undefined && obj !== null && typeof obj === 'object' && typeof obj.name === 'string' && typeof obj.phases === 'object';
|
|
25
|
+
};
|
|
26
|
+
const validateProcess = (item, coordinates)=>{
|
|
27
|
+
const errors = [];
|
|
28
|
+
const currentCoordinates = [
|
|
29
|
+
...[],
|
|
30
|
+
'Process'
|
|
31
|
+
];
|
|
32
|
+
if (item === undefined || item === null) {
|
|
33
|
+
errors.push({
|
|
34
|
+
coordinates: [
|
|
35
|
+
...currentCoordinates
|
|
36
|
+
],
|
|
37
|
+
error: 'Process is undefined or null.'
|
|
38
|
+
});
|
|
39
|
+
return errors;
|
|
40
|
+
}
|
|
41
|
+
if (item.name === undefined || typeof item.name !== 'string') {
|
|
42
|
+
errors.push({
|
|
43
|
+
coordinates: [
|
|
44
|
+
...currentCoordinates
|
|
45
|
+
],
|
|
46
|
+
error: 'Process name is undefined or not a string.'
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const processNameForPath = typeof item.name === 'string' ? item.name : 'UnnamedProcess';
|
|
50
|
+
const basePath = [
|
|
51
|
+
...currentCoordinates,
|
|
52
|
+
`name:${processNameForPath}`
|
|
53
|
+
];
|
|
54
|
+
if (item.phases === undefined || typeof item.phases !== 'object') {
|
|
55
|
+
errors.push({
|
|
56
|
+
coordinates: [
|
|
57
|
+
...basePath,
|
|
58
|
+
'phases'
|
|
59
|
+
],
|
|
60
|
+
error: 'Process phases is undefined or not an object.'
|
|
61
|
+
});
|
|
62
|
+
} else {
|
|
63
|
+
for(const phaseId in item.phases){
|
|
64
|
+
const node = item.phases[phaseId];
|
|
65
|
+
if (Object.prototype.hasOwnProperty.call(item.phases, phaseId)) {
|
|
66
|
+
errors.push(...validateNode(node, [
|
|
67
|
+
...basePath,
|
|
68
|
+
'phases',
|
|
69
|
+
phaseId
|
|
70
|
+
]));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for(const phaseId in item.phases){
|
|
74
|
+
if (Object.prototype.hasOwnProperty.call(item.phases, phaseId)) {
|
|
75
|
+
const node = item.phases[phaseId];
|
|
76
|
+
if (node && typeof node === 'object' && node.next) {
|
|
77
|
+
if (Array.isArray(node.next)) {
|
|
78
|
+
const transitions = node.next;
|
|
79
|
+
if (transitions.length > 0 && transitions.every((t)=>isConnection(t))) {
|
|
80
|
+
transitions.forEach((connection, index)=>{
|
|
81
|
+
if (connection && typeof connection.targetNodeId === 'string') {
|
|
82
|
+
if (!(connection.targetNodeId in item.phases)) {
|
|
83
|
+
errors.push({
|
|
84
|
+
coordinates: [
|
|
85
|
+
...basePath,
|
|
86
|
+
'phases',
|
|
87
|
+
phaseId,
|
|
88
|
+
'next',
|
|
89
|
+
connection.id || `connection-at-index-${index}`
|
|
90
|
+
],
|
|
91
|
+
error: `Node "${phaseId}" has a connection to non-existent targetNodeId "${connection.targetNodeId}".`
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
} else if (!connection || connection.targetNodeId === undefined) ;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return errors;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export { createProcess, isProcess, validateProcess };
|
|
106
|
+
//# sourceMappingURL=process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Context } from '../context';
|
|
2
|
+
import { Input } from '../input';
|
|
3
|
+
import { Transition } from './transition';
|
|
4
|
+
export type BeginFunction<I extends Input = Input, C extends Context = Context> = (input: I, context: C) => Promise<Input>;
|
|
5
|
+
export interface Beginning<I extends Input = Input, C extends Context = Context> extends Transition {
|
|
6
|
+
type: 'beginning';
|
|
7
|
+
targetNodeId: string;
|
|
8
|
+
begin: BeginFunction<I, C>;
|
|
9
|
+
}
|
|
10
|
+
export interface BeginningOptions<I extends Input = Input, C extends Context = Context> {
|
|
11
|
+
begin: BeginFunction<I, C>;
|
|
12
|
+
}
|
|
13
|
+
export declare const DEFAULT_BEGINNING_OPTIONS: BeginningOptions<Input, Context>;
|
|
14
|
+
export declare const createBeginning: <I extends Input = Input, C extends Context = Context>(id: string, targetNodeId: string, options?: Partial<BeginningOptions<I, C>>) => Readonly<Beginning<I, C>>;
|
|
15
|
+
export declare const isBeginning: <I extends Input = Input, C extends Context = Context>(item: any) => item is Beginning<I, C>;
|
|
16
|
+
export declare const validateBeginning: (item: any, coordinates?: string[]) => Array<{
|
|
17
|
+
coordinates: string[];
|
|
18
|
+
error: string;
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { clean } from '../util/general.js';
|
|
2
|
+
import { createTransition, isTransition } from './transition.js';
|
|
3
|
+
|
|
4
|
+
// NEW: Termination type extending Transition
|
|
5
|
+
const DEFAULT_BEGINNING_OPTIONS = {
|
|
6
|
+
begin: async (input)=>{
|
|
7
|
+
return input;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const createBeginning = (id, targetNodeId, options)=>{
|
|
11
|
+
let beginningOptions = {
|
|
12
|
+
...DEFAULT_BEGINNING_OPTIONS
|
|
13
|
+
};
|
|
14
|
+
if (options) {
|
|
15
|
+
beginningOptions = {
|
|
16
|
+
...beginningOptions,
|
|
17
|
+
...clean(options)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
...createTransition('beginning', id),
|
|
22
|
+
targetNodeId,
|
|
23
|
+
begin: beginningOptions.begin
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
const isBeginning = (item)=>{
|
|
27
|
+
return isTransition(item) && item.type === 'beginning' && (item.begin === undefined || typeof item.begin === 'function');
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export { DEFAULT_BEGINNING_OPTIONS, createBeginning, isBeginning };
|
|
31
|
+
//# sourceMappingURL=beginning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"beginning.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Input } from '../input';
|
|
2
|
+
import { Context } from '../context';
|
|
3
|
+
import { Output } from '../output';
|
|
4
|
+
import { Transition } from './transition';
|
|
5
|
+
export type TransformFunction<O extends Output = Output, C extends Context = Context> = (output: O, context: C) => Promise<[Input, C]>;
|
|
6
|
+
export interface Connection<O extends Output = Output, C extends Context = Context> extends Transition {
|
|
7
|
+
type: 'connection';
|
|
8
|
+
targetNodeId: string;
|
|
9
|
+
transform: TransformFunction<O, C>;
|
|
10
|
+
}
|
|
11
|
+
export interface ConnectionOptions<O extends Output = Output, C extends Context = Context> {
|
|
12
|
+
transform: TransformFunction<O, C>;
|
|
13
|
+
}
|
|
14
|
+
export declare const DEFAULT_CONNECTION_OPTIONS: ConnectionOptions;
|
|
15
|
+
export declare const createConnection: <O extends Output = Output, C extends Context = Context>(id: string, targetNodeId: string, options?: Partial<ConnectionOptions<O, C>>) => Readonly<Connection<O, C>>;
|
|
16
|
+
export declare const isConnection: <O extends Output = Output, C extends Context = Context>(item: any) => item is Connection<O, C>;
|
|
17
|
+
export declare const validateConnection: (item: any, coordinates?: string[]) => Array<{
|
|
18
|
+
coordinates: string[];
|
|
19
|
+
error: string;
|
|
20
|
+
}>;
|
|
21
|
+
/**
|
|
22
|
+
* Event emitted specifically for connection transitions.
|
|
23
|
+
*/
|
|
24
|
+
export interface ConnectionEvent extends TransitionEvent {
|
|
25
|
+
transitionType: 'connection';
|
|
26
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createTransition, isTransition, validateTransition } from './transition.js';
|
|
2
|
+
import { clean } from '../util/general.js';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_CONNECTION_OPTIONS = {
|
|
5
|
+
transform: async (output, context)=>{
|
|
6
|
+
return [
|
|
7
|
+
output,
|
|
8
|
+
context
|
|
9
|
+
];
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
const createConnection = (id, targetNodeId, options)=>{
|
|
13
|
+
let connectionOptions = {
|
|
14
|
+
...DEFAULT_CONNECTION_OPTIONS
|
|
15
|
+
};
|
|
16
|
+
if (options) {
|
|
17
|
+
connectionOptions = {
|
|
18
|
+
...connectionOptions,
|
|
19
|
+
...clean(options)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
...createTransition('connection', id),
|
|
24
|
+
targetNodeId,
|
|
25
|
+
transform: connectionOptions.transform
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
const isConnection = (item)=>{
|
|
29
|
+
return isTransition(item) && item.type === 'connection' && item.targetNodeId !== undefined;
|
|
30
|
+
};
|
|
31
|
+
const validateConnection = (item, coordinates)=>{
|
|
32
|
+
const errors = [];
|
|
33
|
+
const connectionBaseCoordinates = [
|
|
34
|
+
...coordinates || [],
|
|
35
|
+
'Connection'
|
|
36
|
+
];
|
|
37
|
+
errors.push(...validateTransition(item, coordinates));
|
|
38
|
+
if (errors.length === 0) {
|
|
39
|
+
if (item && typeof item === 'object') {
|
|
40
|
+
const connectionSpecificErrorPath = [
|
|
41
|
+
...connectionBaseCoordinates,
|
|
42
|
+
`Connection: ${item.id}`
|
|
43
|
+
];
|
|
44
|
+
if (item.type === 'connection') {
|
|
45
|
+
if (typeof item.targetNodeId !== 'string') {
|
|
46
|
+
errors.push({
|
|
47
|
+
coordinates: connectionSpecificErrorPath,
|
|
48
|
+
error: 'Property "targetNodeId" must be a string when type is "connection".'
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// transform is optional, but if present, must be a function.
|
|
52
|
+
if (item.transform !== undefined && typeof item.transform !== 'function') {
|
|
53
|
+
errors.push({
|
|
54
|
+
coordinates: connectionSpecificErrorPath,
|
|
55
|
+
error: 'Optional property "transform" must be a function if present.'
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
// If type is not 'connection', but these properties exist and are malformed.
|
|
60
|
+
// This primarily helps catch if a non-connection object has these fields incorrectly defined.
|
|
61
|
+
if (item.targetNodeId !== undefined && typeof item.targetNodeId !== 'string') {
|
|
62
|
+
errors.push({
|
|
63
|
+
coordinates: connectionSpecificErrorPath,
|
|
64
|
+
error: 'Property "targetNodeId" is present but is not a string.'
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (item.transform !== undefined && typeof item.transform !== 'function') {
|
|
68
|
+
errors.push({
|
|
69
|
+
coordinates: connectionSpecificErrorPath,
|
|
70
|
+
error: 'Property "transform" is present but is not a function.'
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return errors;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export { DEFAULT_CONNECTION_OPTIONS, createConnection, isConnection, validateConnection };
|
|
80
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Termination } from '../xenocline';
|
|
2
|
+
import { Context } from '../context';
|
|
3
|
+
import { Output } from '../output';
|
|
4
|
+
import { Connection } from './connection';
|
|
5
|
+
import { Transition } from './transition';
|
|
6
|
+
export type DecideFunction<O extends Output = Output, C extends Context = Context> = (output: O, context: C) => Promise<Termination<O, C> | Connection<O, C>[]>;
|
|
7
|
+
/**
|
|
8
|
+
* Represents a decision point in the process flow, taking a phase's output and context
|
|
9
|
+
* to determine the next step.
|
|
10
|
+
*/
|
|
11
|
+
export interface Decision<O extends Output = Output, C extends Context = Context> extends Transition {
|
|
12
|
+
type: 'decision';
|
|
13
|
+
decide: DecideFunction<O, C>;
|
|
14
|
+
}
|
|
15
|
+
export declare const createDecision: <O extends Output = Output, C extends Context = Context>(id: string, decide: DecideFunction<O, C>) => Readonly<Decision<O, C>>;
|
|
16
|
+
export declare const isDecision: <O extends Output = Output, C extends Context = Context>(item: any) => item is Decision<O, C>;
|
|
17
|
+
export declare const validateDecision: (item: any, coordinates?: string[]) => Array<{
|
|
18
|
+
coordinates: string[];
|
|
19
|
+
error: string;
|
|
20
|
+
}>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createTransition, isTransition, validateTransition } from './transition.js';
|
|
2
|
+
|
|
3
|
+
const createDecision = (id, decide)=>{
|
|
4
|
+
return {
|
|
5
|
+
...createTransition('decision', id),
|
|
6
|
+
decide
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
const isDecision = (item)=>{
|
|
10
|
+
return isTransition(item) && item.type === 'decision' && typeof item.decide === 'function';
|
|
11
|
+
};
|
|
12
|
+
const validateDecision = (item, coordinates)=>{
|
|
13
|
+
const errors = [];
|
|
14
|
+
const decisionBaseCoordinates = [
|
|
15
|
+
...coordinates || [],
|
|
16
|
+
'Decision'
|
|
17
|
+
];
|
|
18
|
+
errors.push(...validateTransition(item, coordinates));
|
|
19
|
+
if (errors.length === 0) {
|
|
20
|
+
if (item && typeof item === 'object') {
|
|
21
|
+
const decisionSpecificErrorPath = [
|
|
22
|
+
...decisionBaseCoordinates,
|
|
23
|
+
`Decision: ${item.id}`
|
|
24
|
+
];
|
|
25
|
+
if (item.type === 'decision') {
|
|
26
|
+
if (typeof item.decide !== 'function') {
|
|
27
|
+
errors.push({
|
|
28
|
+
coordinates: decisionSpecificErrorPath,
|
|
29
|
+
error: 'Property "decide" must be a function when type is "decision".'
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
// If type is not 'decision', but 'decide' property exists and is malformed.
|
|
34
|
+
if (item.decide !== undefined && typeof item.decide !== 'function') {
|
|
35
|
+
errors.push({
|
|
36
|
+
coordinates: decisionSpecificErrorPath,
|
|
37
|
+
error: 'Property "decide" is present but is not a function.'
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return errors;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { createDecision, isDecision, validateDecision };
|
|
47
|
+
//# sourceMappingURL=decision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Output } from '../output';
|
|
2
|
+
import { Context } from '../context';
|
|
3
|
+
import { Termination } from './termination';
|
|
4
|
+
import { Connection } from './connection';
|
|
5
|
+
import { Decision } from './decision';
|
|
6
|
+
type NonEmptyArray<T> = [T, ...T[]];
|
|
7
|
+
export type Next<O extends Output = Output, C extends Context = Context> = Termination<O, C> | Readonly<NonEmptyArray<Connection<O, C>>> | Readonly<NonEmptyArray<Decision<O, C>>>;
|
|
8
|
+
export declare const isNext: <O extends Output = Output, C extends Context = Context>(item: any) => item is Next<O, C>;
|
|
9
|
+
export declare const validateNext: (item: any, coordinates?: string[]) => Array<{
|
|
10
|
+
coordinates: string[];
|
|
11
|
+
error: string;
|
|
12
|
+
}>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { validateTermination, isTermination } from './termination.js';
|
|
2
|
+
import { isConnection, validateConnection } from './connection.js';
|
|
3
|
+
import { isDecision, validateDecision } from './decision.js';
|
|
4
|
+
|
|
5
|
+
const isNext = (item)=>{
|
|
6
|
+
if (isTermination(item)) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
if (!Array.isArray(item)) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
if (item.length === 0) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
const firstElement = item[0];
|
|
16
|
+
if (isConnection(firstElement)) {
|
|
17
|
+
return item.every((el)=>isConnection(el));
|
|
18
|
+
}
|
|
19
|
+
if (isDecision(firstElement)) {
|
|
20
|
+
return item.every((el)=>isDecision(el));
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
};
|
|
24
|
+
const validateDecisionOrConnectionArray = (item, coordinates)=>{
|
|
25
|
+
const errors = [];
|
|
26
|
+
const currentCoordinates = [
|
|
27
|
+
...coordinates || []
|
|
28
|
+
];
|
|
29
|
+
if (item.length === 0) {
|
|
30
|
+
errors.push({
|
|
31
|
+
coordinates: [
|
|
32
|
+
...currentCoordinates
|
|
33
|
+
],
|
|
34
|
+
error: 'Next Array is empty.'
|
|
35
|
+
});
|
|
36
|
+
return errors;
|
|
37
|
+
}
|
|
38
|
+
const firstElement = item[0];
|
|
39
|
+
if (isConnection(firstElement)) {
|
|
40
|
+
for (const element of item){
|
|
41
|
+
errors.push(...validateConnection(element, currentCoordinates));
|
|
42
|
+
}
|
|
43
|
+
} else if (isDecision(firstElement)) {
|
|
44
|
+
for (const element of item){
|
|
45
|
+
errors.push(...validateDecision(element, currentCoordinates));
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
errors.push({
|
|
49
|
+
coordinates: [
|
|
50
|
+
...currentCoordinates
|
|
51
|
+
],
|
|
52
|
+
error: 'Next Array contains invalid element types. Expected all Connections or all Decisions.'
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return errors;
|
|
56
|
+
};
|
|
57
|
+
const validateNext = (item, coordinates)=>{
|
|
58
|
+
const errors = [];
|
|
59
|
+
const currentCoordinates = [
|
|
60
|
+
...coordinates || [],
|
|
61
|
+
'Next'
|
|
62
|
+
];
|
|
63
|
+
if (item === undefined || item === null) {
|
|
64
|
+
errors.push({
|
|
65
|
+
coordinates: [
|
|
66
|
+
...currentCoordinates
|
|
67
|
+
],
|
|
68
|
+
error: 'Next is undefined or null.'
|
|
69
|
+
});
|
|
70
|
+
return errors;
|
|
71
|
+
}
|
|
72
|
+
if (Array.isArray(item)) {
|
|
73
|
+
errors.push(...validateDecisionOrConnectionArray(item, currentCoordinates));
|
|
74
|
+
} else {
|
|
75
|
+
errors.push(...validateTermination(item, currentCoordinates));
|
|
76
|
+
}
|
|
77
|
+
return errors;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export { isNext, validateNext };
|
|
81
|
+
//# sourceMappingURL=next.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Context } from '../context';
|
|
2
|
+
import { Output } from '../output';
|
|
3
|
+
import { Transition } from './transition';
|
|
4
|
+
export type TerminateFunction<O extends Output = Output, C extends Context = Context> = (output: O, context: C) => Promise<Output>;
|
|
5
|
+
export interface Termination<O extends Output = Output, C extends Context = Context> extends Transition {
|
|
6
|
+
type: 'termination';
|
|
7
|
+
terminate: TerminateFunction<O, C>;
|
|
8
|
+
}
|
|
9
|
+
export interface TerminationOptions<O extends Output = Output, C extends Context = Context> {
|
|
10
|
+
terminate: TerminateFunction<O, C>;
|
|
11
|
+
}
|
|
12
|
+
export declare const createTermination: <O extends Output = Output, C extends Context = Context>(id: string, options?: Partial<TerminationOptions<O, C>>) => Readonly<Termination<O, C>>;
|
|
13
|
+
export declare const isTermination: <O extends Output = Output, C extends Context = Context>(item: any) => item is Termination<O, C>;
|
|
14
|
+
export declare const validateTermination: (item: any, coordinates?: string[]) => Array<{
|
|
15
|
+
coordinates: string[];
|
|
16
|
+
error: string;
|
|
17
|
+
}>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { clean } from '../util/general.js';
|
|
2
|
+
import { createTransition, isTransition, validateTransition } from './transition.js';
|
|
3
|
+
|
|
4
|
+
// NEW: Termination type extending Transition
|
|
5
|
+
const createTermination = (id, options)=>{
|
|
6
|
+
const defaultOptions = {
|
|
7
|
+
terminate: async (output)=>{
|
|
8
|
+
return output;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
let terminationOptions = {
|
|
12
|
+
...defaultOptions
|
|
13
|
+
};
|
|
14
|
+
if (options) {
|
|
15
|
+
terminationOptions = {
|
|
16
|
+
...terminationOptions,
|
|
17
|
+
...clean(options)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
...createTransition('termination', id),
|
|
22
|
+
terminate: terminationOptions.terminate
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
const isTermination = (item)=>{
|
|
26
|
+
return isTransition(item) && item.type === 'termination' && (item.terminate === undefined || typeof item.terminate === 'function');
|
|
27
|
+
};
|
|
28
|
+
const validateTermination = (item, coordinates)=>{
|
|
29
|
+
const errors = [];
|
|
30
|
+
const currentCoordinates = [
|
|
31
|
+
...coordinates || [],
|
|
32
|
+
'Termination'
|
|
33
|
+
];
|
|
34
|
+
errors.push(...validateTransition(item, currentCoordinates));
|
|
35
|
+
if (errors.length === 0) {
|
|
36
|
+
currentCoordinates.push(`Termination: ${item.id}`);
|
|
37
|
+
if (item.terminate !== undefined && typeof item.terminate !== 'function') {
|
|
38
|
+
errors.push({
|
|
39
|
+
coordinates: [
|
|
40
|
+
...currentCoordinates
|
|
41
|
+
],
|
|
42
|
+
error: 'terminate is not a function.'
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return errors;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export { createTermination, isTermination, validateTermination };
|
|
50
|
+
//# sourceMappingURL=termination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"termination.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|