ultravisor 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/.claude/launch.json +11 -0
  2. package/.claude/ultravisor-dev-config.json +3 -0
  3. package/.ultravisor.json +426 -0
  4. package/docs/README.md +63 -0
  5. package/package.json +12 -8
  6. package/source/Ultravisor.cjs +22 -3
  7. package/source/cli/Ultravisor-CLIProgram.cjs +35 -23
  8. package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +29 -18
  9. package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +62 -19
  10. package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +27 -15
  11. package/source/config/Ultravisor-Default-Command-Configuration.cjs +5 -3
  12. package/source/services/Ultravisor-ExecutionEngine.cjs +1039 -0
  13. package/source/services/Ultravisor-ExecutionManifest.cjs +399 -0
  14. package/source/services/Ultravisor-Hypervisor-State.cjs +270 -97
  15. package/source/services/Ultravisor-Hypervisor.cjs +38 -83
  16. package/source/services/Ultravisor-StateManager.cjs +241 -0
  17. package/source/services/Ultravisor-TaskTypeRegistry.cjs +143 -0
  18. package/source/services/tasks/Ultravisor-TaskType-Base.cjs +105 -0
  19. package/source/services/tasks/control/Ultravisor-TaskType-IfConditional.cjs +148 -0
  20. package/source/services/tasks/control/Ultravisor-TaskType-LaunchOperation.cjs +187 -0
  21. package/source/services/tasks/control/Ultravisor-TaskType-SplitExecute.cjs +184 -0
  22. package/source/services/tasks/data/Ultravisor-TaskType-ReplaceString.cjs +82 -0
  23. package/source/services/tasks/data/Ultravisor-TaskType-SetValues.cjs +81 -0
  24. package/source/services/tasks/data/Ultravisor-TaskType-StringAppender.cjs +101 -0
  25. package/source/services/tasks/file-io/Ultravisor-TaskType-ReadFile.cjs +103 -0
  26. package/source/services/tasks/file-io/Ultravisor-TaskType-WriteFile.cjs +117 -0
  27. package/source/services/tasks/interaction/Ultravisor-TaskType-ErrorMessage.cjs +54 -0
  28. package/source/services/tasks/interaction/Ultravisor-TaskType-ValueInput.cjs +62 -0
  29. package/source/web_server/Ultravisor-API-Server.cjs +237 -124
  30. package/test/Ultravisor_browser_tests.js +2226 -0
  31. package/test/Ultravisor_tests.js +1143 -5830
  32. package/webinterface/css/ultravisor.css +23 -0
  33. package/webinterface/package.json +6 -3
  34. package/webinterface/source/Pict-Application-Ultravisor.js +93 -73
  35. package/webinterface/source/cards/FlowCard-CSVTransform.js +43 -0
  36. package/webinterface/source/cards/FlowCard-Command.js +86 -0
  37. package/webinterface/source/cards/FlowCard-ComprehensionIntersect.js +40 -0
  38. package/webinterface/source/cards/FlowCard-Conditional.js +87 -0
  39. package/webinterface/source/cards/FlowCard-CopyFile.js +55 -0
  40. package/webinterface/source/cards/FlowCard-End.js +29 -0
  41. package/webinterface/source/cards/FlowCard-GetJSON.js +55 -0
  42. package/webinterface/source/cards/FlowCard-GetText.js +54 -0
  43. package/webinterface/source/cards/FlowCard-Histogram.js +176 -0
  44. package/webinterface/source/cards/FlowCard-LaunchOperation.js +82 -0
  45. package/webinterface/source/cards/FlowCard-ListFiles.js +55 -0
  46. package/webinterface/source/cards/FlowCard-MeadowCount.js +44 -0
  47. package/webinterface/source/cards/FlowCard-MeadowCreate.js +44 -0
  48. package/webinterface/source/cards/FlowCard-MeadowDelete.js +45 -0
  49. package/webinterface/source/cards/FlowCard-MeadowRead.js +46 -0
  50. package/webinterface/source/cards/FlowCard-MeadowReads.js +46 -0
  51. package/webinterface/source/cards/FlowCard-MeadowUpdate.js +44 -0
  52. package/webinterface/source/cards/FlowCard-ParseCSV.js +85 -0
  53. package/webinterface/source/cards/FlowCard-ReadJSON.js +54 -0
  54. package/webinterface/source/cards/FlowCard-ReadText.js +54 -0
  55. package/webinterface/source/cards/FlowCard-RestRequest.js +59 -0
  56. package/webinterface/source/cards/FlowCard-SendJSON.js +57 -0
  57. package/webinterface/source/cards/FlowCard-Solver.js +77 -0
  58. package/webinterface/source/cards/FlowCard-Start.js +29 -0
  59. package/webinterface/source/cards/FlowCard-TemplateString.js +77 -0
  60. package/webinterface/source/cards/FlowCard-WriteJSON.js +54 -0
  61. package/webinterface/source/cards/FlowCard-WriteText.js +54 -0
  62. package/webinterface/source/data/ExampleFlow-CSVPipeline.js +231 -0
  63. package/webinterface/source/data/ExampleFlow-FileProcessor.js +315 -0
  64. package/webinterface/source/data/ExampleFlow-MeadowPipeline.js +328 -0
  65. package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +8 -8
  66. package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +6 -6
  67. package/webinterface/source/views/PictView-Ultravisor-FlowEditor.js +436 -0
  68. package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +45 -43
  69. package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +34 -89
  70. package/webinterface/source/views/PictView-Ultravisor-OperationList.js +128 -13
  71. package/webinterface/source/views/PictView-Ultravisor-PendingInput.js +314 -0
  72. package/webinterface/source/views/PictView-Ultravisor-Schedule.js +18 -53
  73. package/webinterface/source/views/PictView-Ultravisor-TimingView.js +27 -14
  74. package/webinterface/source/views/PictView-Ultravisor-TopBar.js +2 -1
  75. package/.babelrc +0 -6
  76. package/.browserslistrc +0 -1
  77. package/.browserslistrc-BACKUP +0 -1
  78. package/.gulpfile-quackage-config.json +0 -7
  79. package/.gulpfile-quackage.js +0 -2
  80. package/debug/Harness.js +0 -5
  81. package/source/services/Ultravisor-Operation-Manifest.cjs +0 -160
  82. package/source/services/Ultravisor-Operation.cjs +0 -200
  83. package/source/services/Ultravisor-Task.cjs +0 -349
  84. package/source/services/events/Ultravisor-Hypervisor-Event-Solver.cjs +0 -11
  85. package/source/services/tasks/Ultravisor-Task-Base.cjs +0 -264
  86. package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +0 -188
  87. package/source/services/tasks/Ultravisor-Task-Command.cjs +0 -65
  88. package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +0 -190
  89. package/source/services/tasks/Ultravisor-Task-Conditional.cjs +0 -104
  90. package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +0 -72
  91. package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +0 -336
  92. package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +0 -143
  93. package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +0 -146
  94. package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +0 -158
  95. package/source/services/tasks/Ultravisor-Task-Request.cjs +0 -56
  96. package/source/services/tasks/Ultravisor-Task-Solver.cjs +0 -89
  97. package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +0 -93
  98. package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +0 -127
  99. package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +0 -119
  100. package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +0 -109
  101. package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +0 -112
  102. package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +0 -499
  103. package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +0 -150
  104. package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +0 -110
  105. package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +0 -89
  106. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +0 -87
  107. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +0 -67
  108. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +0 -66
  109. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +0 -69
  110. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +0 -95
  111. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +0 -96
  112. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +0 -99
  113. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +0 -102
  114. package/webinterface/.babelrc +0 -6
  115. package/webinterface/.browserslistrc +0 -1
  116. package/webinterface/.browserslistrc-BACKUP +0 -1
  117. package/webinterface/.gulpfile-quackage-config.json +0 -7
  118. package/webinterface/.gulpfile-quackage.js +0 -2
  119. package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +0 -220
  120. package/webinterface/source/views/PictView-Ultravisor-TaskList.js +0 -248
  121. /package/docs/{cover.md → _cover.md} +0 -0
@@ -1,143 +0,0 @@
1
- const libUltravisorTaskBase = require('./Ultravisor-Task-Base.cjs');
2
-
3
- class UltravisorTaskLaunchOperation extends libUltravisorTaskBase
4
- {
5
- constructor(pFable)
6
- {
7
- super(pFable);
8
- }
9
-
10
- /**
11
- * Asynchronously launch another operation.
12
- *
13
- * The parent task completes immediately without waiting for the
14
- * child operation to finish. The child runs in the background
15
- * and its result is logged when it completes.
16
- *
17
- * Task definition fields:
18
- * - TargetOperation (required): GUID of the operation to launch.
19
- * - InitialState (optional): JSON object or dot-notation address
20
- * string to resolve from the parent's GlobalState. Used as
21
- * the child operation's initial GlobalState.
22
- * - MergeParentState (optional, default false): if true, the
23
- * parent's GlobalState is deep-cloned as the base and
24
- * InitialState is merged on top.
25
- */
26
- execute(pTaskDefinition, pContext, pManifestEntry, fCallback)
27
- {
28
- let tmpTargetGUID = pTaskDefinition.TargetOperation;
29
-
30
- if (!tmpTargetGUID || typeof(tmpTargetGUID) !== 'string' || tmpTargetGUID.length === 0)
31
- {
32
- pManifestEntry.StopTime = new Date().toISOString();
33
- pManifestEntry.Status = 'Error';
34
- pManifestEntry.Log.push(`LaunchOperation: TargetOperation is required.`);
35
- return fCallback(null, pManifestEntry);
36
- }
37
-
38
- let tmpStateService = this.fable['Ultravisor-Hypervisor-State'];
39
- let tmpOperationService = this.fable['Ultravisor-Operation'];
40
-
41
- tmpStateService.getOperation(tmpTargetGUID,
42
- (pError, pOperationDefinition) =>
43
- {
44
- if (pError || !pOperationDefinition)
45
- {
46
- pManifestEntry.StopTime = new Date().toISOString();
47
- pManifestEntry.Status = 'Error';
48
- pManifestEntry.Log.push(`LaunchOperation: could not find operation "${tmpTargetGUID}": ${pError ? pError.message : 'not found'}.`);
49
- return fCallback(null, pManifestEntry);
50
- }
51
-
52
- // Build child GlobalState
53
- let tmpChildState = this.buildChildState(pTaskDefinition, pContext, pManifestEntry);
54
-
55
- // Clone the operation definition so we don't mutate the original
56
- let tmpChildOperationDef = JSON.parse(JSON.stringify(pOperationDefinition));
57
- tmpChildOperationDef.GlobalState = tmpChildState;
58
-
59
- pManifestEntry.Log.push(`LaunchOperation: launching operation "${tmpTargetGUID}" asynchronously.`);
60
-
61
- // Fire and forget -- launch the operation but do not wait for it
62
- tmpOperationService.executeOperation(tmpChildOperationDef,
63
- (pExecError, pChildManifest) =>
64
- {
65
- if (pExecError)
66
- {
67
- this.log.error(`LaunchOperation: async operation "${tmpTargetGUID}" errored: ${pExecError.message}`);
68
- }
69
- else
70
- {
71
- this.log.info(`LaunchOperation: async operation "${tmpTargetGUID}" completed. Status: ${pChildManifest.Status}, Success: ${pChildManifest.Success}`);
72
- }
73
- });
74
-
75
- // Complete the parent task immediately
76
- pManifestEntry.StopTime = new Date().toISOString();
77
- pManifestEntry.Status = 'Complete';
78
- pManifestEntry.Success = true;
79
- pManifestEntry.Output = JSON.stringify({
80
- TargetOperation: tmpTargetGUID,
81
- Async: true
82
- });
83
-
84
- return fCallback(null, pManifestEntry);
85
- });
86
- }
87
-
88
- /**
89
- * Build the child GlobalState from InitialState and MergeParentState.
90
- *
91
- * @param {object} pTaskDefinition - Task definition with InitialState / MergeParentState.
92
- * @param {object} pContext - Parent execution context.
93
- * @param {object} pManifestEntry - For logging.
94
- * @returns {object} The assembled child GlobalState.
95
- */
96
- buildChildState(pTaskDefinition, pContext, pManifestEntry)
97
- {
98
- let tmpChildState = {};
99
-
100
- // Optionally start from a deep clone of the parent's GlobalState
101
- if (pTaskDefinition.MergeParentState)
102
- {
103
- try
104
- {
105
- tmpChildState = JSON.parse(JSON.stringify(pContext.GlobalState || {}));
106
- pManifestEntry.Log.push(`LaunchOperation: merged parent GlobalState into child.`);
107
- }
108
- catch (pCloneError)
109
- {
110
- pManifestEntry.Log.push(`LaunchOperation: warning: could not clone parent GlobalState: ${pCloneError.message}`);
111
- }
112
- }
113
-
114
- // Resolve InitialState
115
- let tmpInitialState = pTaskDefinition.InitialState;
116
-
117
- if (typeof(tmpInitialState) === 'string' && tmpInitialState.length > 0)
118
- {
119
- // Resolve from GlobalState address
120
- let tmpResolved = this.resolveAddress(tmpInitialState, pContext);
121
- if (typeof(tmpResolved) === 'object' && tmpResolved !== null)
122
- {
123
- tmpInitialState = tmpResolved;
124
- pManifestEntry.Log.push(`LaunchOperation: resolved InitialState from address "${pTaskDefinition.InitialState}".`);
125
- }
126
- else
127
- {
128
- pManifestEntry.Log.push(`LaunchOperation: warning: InitialState address "${pTaskDefinition.InitialState}" did not resolve to an object.`);
129
- tmpInitialState = null;
130
- }
131
- }
132
-
133
- if (typeof(tmpInitialState) === 'object' && tmpInitialState !== null)
134
- {
135
- Object.assign(tmpChildState, tmpInitialState);
136
- pManifestEntry.Log.push(`LaunchOperation: applied InitialState to child GlobalState.`);
137
- }
138
-
139
- return tmpChildState;
140
- }
141
- }
142
-
143
- module.exports = UltravisorTaskLaunchOperation;
@@ -1,146 +0,0 @@
1
- const libUltravisorTaskBase = require('./Ultravisor-Task-Base.cjs');
2
-
3
- class UltravisorTaskLaunchTask extends libUltravisorTaskBase
4
- {
5
- constructor(pFable)
6
- {
7
- super(pFable);
8
- }
9
-
10
- /**
11
- * Asynchronously launch an isolated task.
12
- *
13
- * The parent task completes immediately without waiting for the
14
- * child task to finish. The child runs in the background and
15
- * its result is logged when it completes.
16
- *
17
- * Task definition fields:
18
- * - TargetTask (required): GUID of the task to launch.
19
- * - InitialState (optional): JSON object or dot-notation address
20
- * string to resolve from the parent's GlobalState. Used as
21
- * the child task's GlobalState.
22
- * - MergeParentState (optional, default false): if true, the
23
- * parent's GlobalState is deep-cloned as the base and
24
- * InitialState is merged on top.
25
- */
26
- execute(pTaskDefinition, pContext, pManifestEntry, fCallback)
27
- {
28
- let tmpTargetGUID = pTaskDefinition.TargetTask;
29
-
30
- if (!tmpTargetGUID || typeof(tmpTargetGUID) !== 'string' || tmpTargetGUID.length === 0)
31
- {
32
- pManifestEntry.StopTime = new Date().toISOString();
33
- pManifestEntry.Status = 'Error';
34
- pManifestEntry.Log.push(`LaunchTask: TargetTask is required.`);
35
- return fCallback(null, pManifestEntry);
36
- }
37
-
38
- let tmpStateService = this.fable['Ultravisor-Hypervisor-State'];
39
- let tmpTaskService = this.fable['Ultravisor-Task'];
40
-
41
- tmpStateService.getTask(tmpTargetGUID,
42
- (pError, pTargetTaskDefinition) =>
43
- {
44
- if (pError || !pTargetTaskDefinition)
45
- {
46
- pManifestEntry.StopTime = new Date().toISOString();
47
- pManifestEntry.Status = 'Error';
48
- pManifestEntry.Log.push(`LaunchTask: could not find task "${tmpTargetGUID}": ${pError ? pError.message : 'not found'}.`);
49
- return fCallback(null, pManifestEntry);
50
- }
51
-
52
- // Build child GlobalState
53
- let tmpChildState = this.buildChildState(pTaskDefinition, pContext, pManifestEntry);
54
-
55
- // Build an isolated execution context for the child task
56
- let tmpChildContext = {
57
- GlobalState: tmpChildState,
58
- NodeState: {},
59
- StagingPath: pContext.StagingPath || ''
60
- };
61
-
62
- pManifestEntry.Log.push(`LaunchTask: launching task "${tmpTargetGUID}" asynchronously.`);
63
-
64
- // Fire and forget -- launch the task but do not wait for it
65
- tmpTaskService.executeTask(pTargetTaskDefinition, tmpChildContext,
66
- (pExecError, pChildManifestEntry) =>
67
- {
68
- if (pExecError)
69
- {
70
- this.log.error(`LaunchTask: async task "${tmpTargetGUID}" errored: ${pExecError.message}`);
71
- }
72
- else
73
- {
74
- this.log.info(`LaunchTask: async task "${tmpTargetGUID}" completed. Status: ${pChildManifestEntry.Status}, Success: ${pChildManifestEntry.Success}`);
75
- }
76
- });
77
-
78
- // Complete the parent task immediately
79
- pManifestEntry.StopTime = new Date().toISOString();
80
- pManifestEntry.Status = 'Complete';
81
- pManifestEntry.Success = true;
82
- pManifestEntry.Output = JSON.stringify({
83
- TargetTask: tmpTargetGUID,
84
- Async: true
85
- });
86
-
87
- return fCallback(null, pManifestEntry);
88
- });
89
- }
90
-
91
- /**
92
- * Build the child GlobalState from InitialState and MergeParentState.
93
- *
94
- * @param {object} pTaskDefinition - Task definition with InitialState / MergeParentState.
95
- * @param {object} pContext - Parent execution context.
96
- * @param {object} pManifestEntry - For logging.
97
- * @returns {object} The assembled child GlobalState.
98
- */
99
- buildChildState(pTaskDefinition, pContext, pManifestEntry)
100
- {
101
- let tmpChildState = {};
102
-
103
- // Optionally start from a deep clone of the parent's GlobalState
104
- if (pTaskDefinition.MergeParentState)
105
- {
106
- try
107
- {
108
- tmpChildState = JSON.parse(JSON.stringify(pContext.GlobalState || {}));
109
- pManifestEntry.Log.push(`LaunchTask: merged parent GlobalState into child.`);
110
- }
111
- catch (pCloneError)
112
- {
113
- pManifestEntry.Log.push(`LaunchTask: warning: could not clone parent GlobalState: ${pCloneError.message}`);
114
- }
115
- }
116
-
117
- // Resolve InitialState
118
- let tmpInitialState = pTaskDefinition.InitialState;
119
-
120
- if (typeof(tmpInitialState) === 'string' && tmpInitialState.length > 0)
121
- {
122
- // Resolve from GlobalState address
123
- let tmpResolved = this.resolveAddress(tmpInitialState, pContext);
124
- if (typeof(tmpResolved) === 'object' && tmpResolved !== null)
125
- {
126
- tmpInitialState = tmpResolved;
127
- pManifestEntry.Log.push(`LaunchTask: resolved InitialState from address "${pTaskDefinition.InitialState}".`);
128
- }
129
- else
130
- {
131
- pManifestEntry.Log.push(`LaunchTask: warning: InitialState address "${pTaskDefinition.InitialState}" did not resolve to an object.`);
132
- tmpInitialState = null;
133
- }
134
- }
135
-
136
- if (typeof(tmpInitialState) === 'object' && tmpInitialState !== null)
137
- {
138
- Object.assign(tmpChildState, tmpInitialState);
139
- pManifestEntry.Log.push(`LaunchTask: applied InitialState to child GlobalState.`);
140
- }
141
-
142
- return tmpChildState;
143
- }
144
- }
145
-
146
- module.exports = UltravisorTaskLaunchTask;
@@ -1,158 +0,0 @@
1
- const libUltravisorTaskBase = require('./Ultravisor-Task-Base.cjs');
2
-
3
- class UltravisorTaskLineMatch extends libUltravisorTaskBase
4
- {
5
- constructor(pFable)
6
- {
7
- super(pFable);
8
- }
9
-
10
- /**
11
- * Split a string on a separator and apply a regex to each line,
12
- * producing a JSON array of match result objects.
13
- *
14
- * The input string is resolved from either:
15
- * - Address: a manyfest address into pContext.GlobalState
16
- * - Data: an inline string literal
17
- *
18
- * Task definition fields:
19
- * - Address: dot-notation path into GlobalState for the input string
20
- * - Data: inline string to process (used when Address is not set)
21
- * - Pattern: regular expression string to apply to each line
22
- * - Flags (optional): regex flags (default: "")
23
- * - Separator (optional): string to split on (default: "\n")
24
- * - Destination (optional): manyfest address in GlobalState
25
- * where the result array is stored (default: "Output")
26
- */
27
- execute(pTaskDefinition, pContext, pManifestEntry, fCallback)
28
- {
29
- // --- Resolve the input string ---
30
- let tmpInput = undefined;
31
-
32
- if (pTaskDefinition.Address && typeof(pTaskDefinition.Address) === 'string')
33
- {
34
- tmpInput = this.resolveAddress(pTaskDefinition.Address, pContext);
35
- pManifestEntry.Log.push(`LineMatch: resolved Address "${pTaskDefinition.Address}".`);
36
- }
37
- else if (pTaskDefinition.hasOwnProperty('Data'))
38
- {
39
- tmpInput = pTaskDefinition.Data;
40
- pManifestEntry.Log.push(`LineMatch: using inline Data.`);
41
- }
42
- else
43
- {
44
- pManifestEntry.StopTime = new Date().toISOString();
45
- pManifestEntry.Status = 'Error';
46
- pManifestEntry.Log.push(`LineMatch: task requires an Address or Data field.`);
47
- return fCallback(null, pManifestEntry);
48
- }
49
-
50
- if (tmpInput === undefined || tmpInput === null)
51
- {
52
- pManifestEntry.StopTime = new Date().toISOString();
53
- pManifestEntry.Status = 'Error';
54
- pManifestEntry.Log.push(`LineMatch: input resolved to null or undefined.`);
55
- return fCallback(null, pManifestEntry);
56
- }
57
-
58
- // Coerce non-string input to a string
59
- if (typeof(tmpInput) !== 'string')
60
- {
61
- tmpInput = String(tmpInput);
62
- }
63
-
64
- // --- Validate the pattern ---
65
- let tmpPatternString = pTaskDefinition.Pattern;
66
-
67
- if (!tmpPatternString || typeof(tmpPatternString) !== 'string' || tmpPatternString.length === 0)
68
- {
69
- pManifestEntry.StopTime = new Date().toISOString();
70
- pManifestEntry.Status = 'Error';
71
- pManifestEntry.Log.push(`LineMatch: missing or empty Pattern field.`);
72
- return fCallback(null, pManifestEntry);
73
- }
74
-
75
- let tmpFlags = (pTaskDefinition.Flags && typeof(pTaskDefinition.Flags) === 'string')
76
- ? pTaskDefinition.Flags
77
- : '';
78
-
79
- let tmpRegex;
80
- try
81
- {
82
- tmpRegex = new RegExp(tmpPatternString, tmpFlags);
83
- }
84
- catch (pError)
85
- {
86
- pManifestEntry.StopTime = new Date().toISOString();
87
- pManifestEntry.Status = 'Error';
88
- pManifestEntry.Log.push(`LineMatch: invalid regex "${tmpPatternString}": ${pError.message}`);
89
- return fCallback(null, pManifestEntry);
90
- }
91
-
92
- // --- Split on separator ---
93
- let tmpSeparator = (pTaskDefinition.hasOwnProperty('Separator') && typeof(pTaskDefinition.Separator) === 'string')
94
- ? pTaskDefinition.Separator
95
- : '\n';
96
-
97
- let tmpLines = tmpInput.split(tmpSeparator);
98
-
99
- pManifestEntry.Log.push(`LineMatch: split input into ${tmpLines.length} line(s) using separator ${JSON.stringify(tmpSeparator)}.`);
100
- pManifestEntry.Log.push(`LineMatch: applying pattern /${tmpPatternString}/${tmpFlags}.`);
101
-
102
- // --- Apply regex to each line ---
103
- let tmpResults = [];
104
-
105
- for (let i = 0; i < tmpLines.length; i++)
106
- {
107
- let tmpLine = tmpLines[i];
108
- let tmpMatch = tmpRegex.exec(tmpLine);
109
-
110
- let tmpEntry = {
111
- Index: i,
112
- Line: tmpLine,
113
- Match: (tmpMatch !== null)
114
- };
115
-
116
- if (tmpMatch)
117
- {
118
- tmpEntry.FullMatch = tmpMatch[0];
119
-
120
- // Collect numbered capture groups
121
- let tmpGroups = [];
122
- for (let g = 1; g < tmpMatch.length; g++)
123
- {
124
- tmpGroups.push(tmpMatch[g]);
125
- }
126
- tmpEntry.Groups = tmpGroups;
127
-
128
- // Include named groups if present
129
- if (tmpMatch.groups)
130
- {
131
- tmpEntry.NamedGroups = tmpMatch.groups;
132
- }
133
- }
134
- else
135
- {
136
- tmpEntry.FullMatch = null;
137
- tmpEntry.Groups = [];
138
- }
139
-
140
- tmpResults.push(tmpEntry);
141
- }
142
-
143
- let tmpMatchCount = tmpResults.filter((pEntry) => { return pEntry.Match; }).length;
144
-
145
- pManifestEntry.StopTime = new Date().toISOString();
146
- pManifestEntry.Status = 'Complete';
147
- pManifestEntry.Success = true;
148
- pManifestEntry.Output = JSON.stringify(tmpResults);
149
- pManifestEntry.Log.push(`LineMatch: ${tmpMatchCount} of ${tmpLines.length} line(s) matched.`);
150
-
151
- // Store via Destination
152
- this.storeDestination(pTaskDefinition, pContext, pManifestEntry, tmpResults);
153
-
154
- return fCallback(null, pManifestEntry);
155
- }
156
- }
157
-
158
- module.exports = UltravisorTaskLineMatch;
@@ -1,56 +0,0 @@
1
- const libUltravisorTaskBase = require('./Ultravisor-Task-Base.cjs');
2
- const libUltravisorTaskCommand = require('./Ultravisor-Task-Command.cjs');
3
-
4
- class UltravisorTaskRequest extends libUltravisorTaskBase
5
- {
6
- constructor(pFable)
7
- {
8
- super(pFable);
9
- }
10
-
11
- /**
12
- * Execute an HTTP request task.
13
- *
14
- * Task definition fields:
15
- * - URL: the endpoint to request
16
- * - Method (optional): HTTP method (defaults to GET)
17
- * - Persist (optional): where to store the response body
18
- * string -- manyfest address into GlobalState
19
- * { Address: "..." } -- same as string form
20
- * { File: "..." } -- writes response to a staging file
21
- */
22
- execute(pTaskDefinition, pContext, pManifestEntry, fCallback)
23
- {
24
- let tmpURL = pTaskDefinition.URL || pTaskDefinition.Parameters || '';
25
-
26
- if (!tmpURL || tmpURL.length === 0)
27
- {
28
- pManifestEntry.StopTime = new Date().toISOString();
29
- pManifestEntry.Status = 'Error';
30
- pManifestEntry.Log.push(`Request task has no URL to request.`);
31
- return fCallback(null, pManifestEntry);
32
- }
33
-
34
- let tmpMethod = (pTaskDefinition.Method || 'GET').toUpperCase();
35
-
36
- pManifestEntry.Log.push(`Executing ${tmpMethod} request to: ${tmpURL}`);
37
-
38
- // Use curl for HTTP requests, delegating to the Command task type
39
- let tmpCurlCommand = `curl -s -X ${tmpMethod} "${tmpURL}"`;
40
- let tmpCommandTask = new libUltravisorTaskCommand(this.fable);
41
- tmpCommandTask.execute(
42
- Object.assign({}, pTaskDefinition, { Command: tmpCurlCommand }),
43
- pContext, pManifestEntry,
44
- (pError, pResult) =>
45
- {
46
- // Persist the response output
47
- if (pManifestEntry.Success && pTaskDefinition.Persist && pManifestEntry.Output)
48
- {
49
- this.storeResult(pTaskDefinition, pContext, pManifestEntry, pManifestEntry.Output);
50
- }
51
- return fCallback(pError, pResult);
52
- });
53
- }
54
- }
55
-
56
- module.exports = UltravisorTaskRequest;
@@ -1,89 +0,0 @@
1
- const libUltravisorTaskBase = require('./Ultravisor-Task-Base.cjs');
2
-
3
- class UltravisorTaskSolver extends libUltravisorTaskBase
4
- {
5
- constructor(pFable)
6
- {
7
- super(pFable);
8
- }
9
-
10
- /**
11
- * Evaluate an expression using the fable ExpressionParser.
12
- *
13
- * The solver runs pTaskDefinition.Expression through
14
- * ExpressionParser.solve(), using pContext.GlobalState as the
15
- * Record (data source object). This means any address accessible
16
- * via AppData.GlobalState is also available inside expressions.
17
- *
18
- * Task definition fields:
19
- * - Expression: the expression string to solve
20
- * - Destination (optional): manyfest address in GlobalState
21
- * where the result is stored (defaults to "Output")
22
- */
23
- execute(pTaskDefinition, pContext, pManifestEntry, fCallback)
24
- {
25
- let tmpExpression = pTaskDefinition.Expression || '';
26
-
27
- if (!tmpExpression || typeof(tmpExpression) !== 'string' || tmpExpression.length === 0)
28
- {
29
- pManifestEntry.StopTime = new Date().toISOString();
30
- pManifestEntry.Status = 'Error';
31
- pManifestEntry.Log.push(`Solver: missing or empty Expression field.`);
32
- return fCallback(null, pManifestEntry);
33
- }
34
-
35
- pManifestEntry.Log.push(`Solver: evaluating expression: ${tmpExpression}`);
36
-
37
- try
38
- {
39
- // Get or create an ExpressionParser instance
40
- let tmpParser = this.fable.instantiateServiceProviderIfNotExists('ExpressionParser');
41
-
42
- // Build the record from GlobalState so the expression can
43
- // reference any value in the operation's shared state.
44
- if (!pContext.GlobalState || typeof(pContext.GlobalState) !== 'object')
45
- {
46
- pContext.GlobalState = {};
47
- }
48
-
49
- let tmpRecord = pContext.GlobalState;
50
- let tmpResultObject = {};
51
- let tmpDestinationObject = {};
52
-
53
- let tmpResult = tmpParser.solve(tmpExpression, tmpRecord, tmpResultObject, false, tmpDestinationObject);
54
-
55
- pManifestEntry.StopTime = new Date().toISOString();
56
- pManifestEntry.Status = 'Complete';
57
- pManifestEntry.Success = true;
58
- pManifestEntry.Output = (typeof(tmpResult) === 'string') ? tmpResult : JSON.stringify(tmpResult);
59
- pManifestEntry.Log.push(`Solver: result = ${pManifestEntry.Output}`);
60
-
61
- // Store the raw result at the Destination address
62
- this.storeDestination(pTaskDefinition, pContext, pManifestEntry, tmpResult);
63
-
64
- // If the expression contained assignments (e.g. "Area = X * Y"),
65
- // merge assigned values from the destination object back into
66
- // GlobalState so subsequent tasks can use them.
67
- let tmpDestKeys = Object.keys(tmpDestinationObject);
68
- if (tmpDestKeys.length > 0)
69
- {
70
- for (let i = 0; i < tmpDestKeys.length; i++)
71
- {
72
- let tmpKey = tmpDestKeys[i];
73
- this._Manyfest.setValueAtAddress(pContext.GlobalState, tmpKey, tmpDestinationObject[tmpKey]);
74
- }
75
- pManifestEntry.Log.push(`Solver: merged ${tmpDestKeys.length} assigned value(s) into GlobalState: ${tmpDestKeys.join(', ')}`);
76
- }
77
- }
78
- catch (pError)
79
- {
80
- pManifestEntry.StopTime = new Date().toISOString();
81
- pManifestEntry.Status = 'Error';
82
- pManifestEntry.Log.push(`Solver: ${pError.message}`);
83
- }
84
-
85
- return fCallback(null, pManifestEntry);
86
- }
87
- }
88
-
89
- module.exports = UltravisorTaskSolver;
@@ -1,93 +0,0 @@
1
- const libUltravisorTaskBase = require('./Ultravisor-Task-Base.cjs');
2
-
3
- class UltravisorTaskTemplateString extends libUltravisorTaskBase
4
- {
5
- constructor(pFable)
6
- {
7
- super(pFable);
8
- }
9
-
10
- /**
11
- * Build a string by resolving {Address} placeholders from GlobalState.
12
- *
13
- * Scans the Template string for patterns like {Some.Address} and
14
- * replaces each one with the value found at that address in
15
- * GlobalState (or NodeState). Useful for constructing URLs,
16
- * filter strings, or any dynamic text from operation state.
17
- *
18
- * Task definition fields:
19
- * - Template (required): the template string with {Address}
20
- * placeholders. Placeholders use dot-notation addresses
21
- * into GlobalState (e.g. {DateWindow.WindowStart}).
22
- * - Destination (optional): manyfest address in GlobalState
23
- * where the resolved string is stored (defaults to "Output")
24
- *
25
- * Unresolved placeholders (where the address resolves to undefined)
26
- * are left in place and logged as warnings.
27
- */
28
- execute(pTaskDefinition, pContext, pManifestEntry, fCallback)
29
- {
30
- let tmpTemplate = pTaskDefinition.Template || '';
31
-
32
- if (!tmpTemplate || typeof(tmpTemplate) !== 'string' || tmpTemplate.length === 0)
33
- {
34
- pManifestEntry.StopTime = new Date().toISOString();
35
- pManifestEntry.Status = 'Error';
36
- pManifestEntry.Log.push(`TemplateString: missing or empty Template field.`);
37
- return fCallback(null, pManifestEntry);
38
- }
39
-
40
- pManifestEntry.Log.push(`TemplateString: template="${tmpTemplate}"`);
41
-
42
- // Find all {Address} placeholders
43
- let tmpResult = tmpTemplate;
44
- let tmpPattern = /\{([^}]+)\}/g;
45
- let tmpMatch;
46
- let tmpResolvedCount = 0;
47
- let tmpUnresolvedCount = 0;
48
-
49
- // Collect all matches first, then replace (to avoid regex state issues)
50
- let tmpMatches = [];
51
- while ((tmpMatch = tmpPattern.exec(tmpTemplate)) !== null)
52
- {
53
- tmpMatches.push({ full: tmpMatch[0], address: tmpMatch[1] });
54
- }
55
-
56
- for (let i = 0; i < tmpMatches.length; i++)
57
- {
58
- let tmpAddress = tmpMatches[i].address;
59
- let tmpValue = this.resolveAddress(tmpAddress, pContext);
60
-
61
- if (tmpValue !== undefined && tmpValue !== null)
62
- {
63
- let tmpStringValue = String(tmpValue);
64
- // Replace all occurrences of this placeholder
65
- while (tmpResult.indexOf(tmpMatches[i].full) !== -1)
66
- {
67
- tmpResult = tmpResult.replace(tmpMatches[i].full, tmpStringValue);
68
- }
69
- tmpResolvedCount++;
70
- pManifestEntry.Log.push(`TemplateString: {${tmpAddress}} = "${tmpStringValue.substring(0, 100)}"`);
71
- }
72
- else
73
- {
74
- tmpUnresolvedCount++;
75
- pManifestEntry.Log.push(`TemplateString: WARNING {${tmpAddress}} could not be resolved, left in place.`);
76
- }
77
- }
78
-
79
- pManifestEntry.StopTime = new Date().toISOString();
80
- pManifestEntry.Status = 'Complete';
81
- pManifestEntry.Success = true;
82
- pManifestEntry.Output = tmpResult;
83
-
84
- pManifestEntry.Log.push(`TemplateString: resolved ${tmpResolvedCount} placeholder(s)${tmpUnresolvedCount > 0 ? `, ${tmpUnresolvedCount} unresolved` : ''}.`);
85
- pManifestEntry.Log.push(`TemplateString: result="${tmpResult.substring(0, 500)}"`);
86
-
87
- this.storeDestination(pTaskDefinition, pContext, pManifestEntry, tmpResult);
88
-
89
- return fCallback(null, pManifestEntry);
90
- }
91
- }
92
-
93
- module.exports = UltravisorTaskTemplateString;