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.
- package/.claude/launch.json +11 -0
- package/.claude/ultravisor-dev-config.json +3 -0
- package/.ultravisor.json +426 -0
- package/docs/README.md +63 -0
- package/package.json +12 -8
- package/source/Ultravisor.cjs +22 -3
- package/source/cli/Ultravisor-CLIProgram.cjs +35 -23
- package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +29 -18
- package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +62 -19
- package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +27 -15
- package/source/config/Ultravisor-Default-Command-Configuration.cjs +5 -3
- package/source/services/Ultravisor-ExecutionEngine.cjs +1039 -0
- package/source/services/Ultravisor-ExecutionManifest.cjs +399 -0
- package/source/services/Ultravisor-Hypervisor-State.cjs +270 -97
- package/source/services/Ultravisor-Hypervisor.cjs +38 -83
- package/source/services/Ultravisor-StateManager.cjs +241 -0
- package/source/services/Ultravisor-TaskTypeRegistry.cjs +143 -0
- package/source/services/tasks/Ultravisor-TaskType-Base.cjs +105 -0
- package/source/services/tasks/control/Ultravisor-TaskType-IfConditional.cjs +148 -0
- package/source/services/tasks/control/Ultravisor-TaskType-LaunchOperation.cjs +187 -0
- package/source/services/tasks/control/Ultravisor-TaskType-SplitExecute.cjs +184 -0
- package/source/services/tasks/data/Ultravisor-TaskType-ReplaceString.cjs +82 -0
- package/source/services/tasks/data/Ultravisor-TaskType-SetValues.cjs +81 -0
- package/source/services/tasks/data/Ultravisor-TaskType-StringAppender.cjs +101 -0
- package/source/services/tasks/file-io/Ultravisor-TaskType-ReadFile.cjs +103 -0
- package/source/services/tasks/file-io/Ultravisor-TaskType-WriteFile.cjs +117 -0
- package/source/services/tasks/interaction/Ultravisor-TaskType-ErrorMessage.cjs +54 -0
- package/source/services/tasks/interaction/Ultravisor-TaskType-ValueInput.cjs +62 -0
- package/source/web_server/Ultravisor-API-Server.cjs +237 -124
- package/test/Ultravisor_browser_tests.js +2226 -0
- package/test/Ultravisor_tests.js +1143 -5830
- package/webinterface/css/ultravisor.css +23 -0
- package/webinterface/package.json +6 -3
- package/webinterface/source/Pict-Application-Ultravisor.js +93 -73
- package/webinterface/source/cards/FlowCard-CSVTransform.js +43 -0
- package/webinterface/source/cards/FlowCard-Command.js +86 -0
- package/webinterface/source/cards/FlowCard-ComprehensionIntersect.js +40 -0
- package/webinterface/source/cards/FlowCard-Conditional.js +87 -0
- package/webinterface/source/cards/FlowCard-CopyFile.js +55 -0
- package/webinterface/source/cards/FlowCard-End.js +29 -0
- package/webinterface/source/cards/FlowCard-GetJSON.js +55 -0
- package/webinterface/source/cards/FlowCard-GetText.js +54 -0
- package/webinterface/source/cards/FlowCard-Histogram.js +176 -0
- package/webinterface/source/cards/FlowCard-LaunchOperation.js +82 -0
- package/webinterface/source/cards/FlowCard-ListFiles.js +55 -0
- package/webinterface/source/cards/FlowCard-MeadowCount.js +44 -0
- package/webinterface/source/cards/FlowCard-MeadowCreate.js +44 -0
- package/webinterface/source/cards/FlowCard-MeadowDelete.js +45 -0
- package/webinterface/source/cards/FlowCard-MeadowRead.js +46 -0
- package/webinterface/source/cards/FlowCard-MeadowReads.js +46 -0
- package/webinterface/source/cards/FlowCard-MeadowUpdate.js +44 -0
- package/webinterface/source/cards/FlowCard-ParseCSV.js +85 -0
- package/webinterface/source/cards/FlowCard-ReadJSON.js +54 -0
- package/webinterface/source/cards/FlowCard-ReadText.js +54 -0
- package/webinterface/source/cards/FlowCard-RestRequest.js +59 -0
- package/webinterface/source/cards/FlowCard-SendJSON.js +57 -0
- package/webinterface/source/cards/FlowCard-Solver.js +77 -0
- package/webinterface/source/cards/FlowCard-Start.js +29 -0
- package/webinterface/source/cards/FlowCard-TemplateString.js +77 -0
- package/webinterface/source/cards/FlowCard-WriteJSON.js +54 -0
- package/webinterface/source/cards/FlowCard-WriteText.js +54 -0
- package/webinterface/source/data/ExampleFlow-CSVPipeline.js +231 -0
- package/webinterface/source/data/ExampleFlow-FileProcessor.js +315 -0
- package/webinterface/source/data/ExampleFlow-MeadowPipeline.js +328 -0
- package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +8 -8
- package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +6 -6
- package/webinterface/source/views/PictView-Ultravisor-FlowEditor.js +436 -0
- package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +45 -43
- package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +34 -89
- package/webinterface/source/views/PictView-Ultravisor-OperationList.js +128 -13
- package/webinterface/source/views/PictView-Ultravisor-PendingInput.js +314 -0
- package/webinterface/source/views/PictView-Ultravisor-Schedule.js +18 -53
- package/webinterface/source/views/PictView-Ultravisor-TimingView.js +27 -14
- package/webinterface/source/views/PictView-Ultravisor-TopBar.js +2 -1
- package/.babelrc +0 -6
- package/.browserslistrc +0 -1
- package/.browserslistrc-BACKUP +0 -1
- package/.gulpfile-quackage-config.json +0 -7
- package/.gulpfile-quackage.js +0 -2
- package/debug/Harness.js +0 -5
- package/source/services/Ultravisor-Operation-Manifest.cjs +0 -160
- package/source/services/Ultravisor-Operation.cjs +0 -200
- package/source/services/Ultravisor-Task.cjs +0 -349
- package/source/services/events/Ultravisor-Hypervisor-Event-Solver.cjs +0 -11
- package/source/services/tasks/Ultravisor-Task-Base.cjs +0 -264
- package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +0 -188
- package/source/services/tasks/Ultravisor-Task-Command.cjs +0 -65
- package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +0 -190
- package/source/services/tasks/Ultravisor-Task-Conditional.cjs +0 -104
- package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +0 -72
- package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +0 -336
- package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +0 -143
- package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +0 -146
- package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +0 -158
- package/source/services/tasks/Ultravisor-Task-Request.cjs +0 -56
- package/source/services/tasks/Ultravisor-Task-Solver.cjs +0 -89
- package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +0 -93
- package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +0 -127
- package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +0 -119
- package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +0 -109
- package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +0 -112
- package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +0 -499
- package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +0 -150
- package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +0 -110
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +0 -89
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +0 -87
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +0 -67
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +0 -66
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +0 -69
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +0 -95
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +0 -96
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +0 -99
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +0 -102
- package/webinterface/.babelrc +0 -6
- package/webinterface/.browserslistrc +0 -1
- package/webinterface/.browserslistrc-BACKUP +0 -1
- package/webinterface/.gulpfile-quackage-config.json +0 -7
- package/webinterface/.gulpfile-quackage.js +0 -2
- package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +0 -220
- package/webinterface/source/views/PictView-Ultravisor-TaskList.js +0 -248
- /package/docs/{cover.md → _cover.md} +0 -0
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
const libUltravisorTaskBase = require('./Ultravisor-Task-Base.cjs');
|
|
2
|
-
|
|
3
|
-
const libChildProcess = require('child_process');
|
|
4
|
-
|
|
5
|
-
class UltravisorTaskCommandEach extends libUltravisorTaskBase
|
|
6
|
-
{
|
|
7
|
-
constructor(pFable)
|
|
8
|
-
{
|
|
9
|
-
super(pFable);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Execute a templated shell command once for each value in an array.
|
|
14
|
-
*
|
|
15
|
-
* Takes an array from GlobalState and runs a shell command for each
|
|
16
|
-
* element, substituting interpolation variables into the command
|
|
17
|
-
* template. Commands run sequentially (one at a time).
|
|
18
|
-
*
|
|
19
|
-
* Task definition fields:
|
|
20
|
-
* - Address: manyfest address in GlobalState pointing to the
|
|
21
|
-
* source array of values (e.g. "ObservationIDs").
|
|
22
|
-
* - Command: the shell command template. Supports interpolation
|
|
23
|
-
* variables:
|
|
24
|
-
* {Value} -- the current array element (stringified)
|
|
25
|
-
* {Index} -- the zero-based index of the current element
|
|
26
|
-
* {Count} -- total number of elements in the array
|
|
27
|
-
* Example: "curl https://api.example.com/obs/{Value} -o obs_{Value}.json"
|
|
28
|
-
* - ContinueOnError (optional, default true): if true, continue
|
|
29
|
-
* executing remaining commands when one fails. If false,
|
|
30
|
-
* stop at the first failure.
|
|
31
|
-
* - Destination (optional): manyfest address in GlobalState
|
|
32
|
-
* where the results array is stored (default: "Output").
|
|
33
|
-
* Each result contains: { Value, Index, ExitCode, StdOut,
|
|
34
|
-
* StdErr, Success, Command }.
|
|
35
|
-
* - Persist (optional): standard persist options (file or address).
|
|
36
|
-
*/
|
|
37
|
-
execute(pTaskDefinition, pContext, pManifestEntry, fCallback)
|
|
38
|
-
{
|
|
39
|
-
// --- Validate required fields ---
|
|
40
|
-
if (!pTaskDefinition.Address || typeof(pTaskDefinition.Address) !== 'string' || pTaskDefinition.Address.length === 0)
|
|
41
|
-
{
|
|
42
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
43
|
-
pManifestEntry.Status = 'Error';
|
|
44
|
-
pManifestEntry.Log.push(`CommandEach: missing or empty Address field.`);
|
|
45
|
-
return fCallback(null, pManifestEntry);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (!pTaskDefinition.Command || typeof(pTaskDefinition.Command) !== 'string' || pTaskDefinition.Command.length === 0)
|
|
49
|
-
{
|
|
50
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
51
|
-
pManifestEntry.Status = 'Error';
|
|
52
|
-
pManifestEntry.Log.push(`CommandEach: missing or empty Command field.`);
|
|
53
|
-
return fCallback(null, pManifestEntry);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// --- Resolve source array ---
|
|
57
|
-
let tmpSource = this.resolveAddress(pTaskDefinition.Address, pContext);
|
|
58
|
-
|
|
59
|
-
if (tmpSource === undefined || tmpSource === null)
|
|
60
|
-
{
|
|
61
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
62
|
-
pManifestEntry.Status = 'Complete';
|
|
63
|
-
pManifestEntry.Success = true;
|
|
64
|
-
pManifestEntry.Output = '[]';
|
|
65
|
-
pManifestEntry.Log.push(`CommandEach: Address "${pTaskDefinition.Address}" resolved to null or undefined; nothing to execute.`);
|
|
66
|
-
this.storeDestination(pTaskDefinition, pContext, pManifestEntry, []);
|
|
67
|
-
return fCallback(null, pManifestEntry);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (!Array.isArray(tmpSource))
|
|
71
|
-
{
|
|
72
|
-
// Wrap a single value into an array for uniform processing
|
|
73
|
-
tmpSource = [tmpSource];
|
|
74
|
-
pManifestEntry.Log.push(`CommandEach: source is not an array; wrapped in array.`);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (tmpSource.length === 0)
|
|
78
|
-
{
|
|
79
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
80
|
-
pManifestEntry.Status = 'Complete';
|
|
81
|
-
pManifestEntry.Success = true;
|
|
82
|
-
pManifestEntry.Output = '[]';
|
|
83
|
-
pManifestEntry.Log.push(`CommandEach: source array is empty, nothing to execute.`);
|
|
84
|
-
this.storeDestination(pTaskDefinition, pContext, pManifestEntry, []);
|
|
85
|
-
return fCallback(null, pManifestEntry);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
let tmpContinueOnError = (pTaskDefinition.ContinueOnError !== false);
|
|
89
|
-
let tmpCommandTemplate = pTaskDefinition.Command;
|
|
90
|
-
let tmpTimeout = (this.fable?.ProgramConfiguration?.UltravisorCommandTimeoutMilliseconds) || 300000;
|
|
91
|
-
let tmpMaxBuffer = (this.fable?.ProgramConfiguration?.UltravisorCommandMaxBufferBytes) || 10485760;
|
|
92
|
-
let tmpCount = tmpSource.length;
|
|
93
|
-
|
|
94
|
-
pManifestEntry.Log.push(`CommandEach: executing command template for ${tmpCount} value(s).`);
|
|
95
|
-
|
|
96
|
-
let tmpResults = [];
|
|
97
|
-
let tmpSuccessCount = 0;
|
|
98
|
-
let tmpFailCount = 0;
|
|
99
|
-
let tmpIndex = 0;
|
|
100
|
-
|
|
101
|
-
let fRunNext = () =>
|
|
102
|
-
{
|
|
103
|
-
if (tmpIndex >= tmpCount)
|
|
104
|
-
{
|
|
105
|
-
// All commands have been executed
|
|
106
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
107
|
-
pManifestEntry.Status = (tmpFailCount === 0) ? 'Complete' : 'Complete';
|
|
108
|
-
pManifestEntry.Success = (tmpFailCount === 0);
|
|
109
|
-
pManifestEntry.Output = JSON.stringify({
|
|
110
|
-
Total: tmpCount,
|
|
111
|
-
Succeeded: tmpSuccessCount,
|
|
112
|
-
Failed: tmpFailCount
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
pManifestEntry.Log.push(`CommandEach: finished. ${tmpSuccessCount} succeeded, ${tmpFailCount} failed out of ${tmpCount}.`);
|
|
116
|
-
|
|
117
|
-
this.storeDestination(pTaskDefinition, pContext, pManifestEntry, tmpResults);
|
|
118
|
-
this.storeResult(pTaskDefinition, pContext, pManifestEntry, tmpResults);
|
|
119
|
-
|
|
120
|
-
return fCallback(null, pManifestEntry);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
let tmpValue = tmpSource[tmpIndex];
|
|
124
|
-
let tmpValueString = (tmpValue === null || tmpValue === undefined) ? '' : String(tmpValue);
|
|
125
|
-
|
|
126
|
-
// Interpolate the command template
|
|
127
|
-
let tmpCommand = tmpCommandTemplate;
|
|
128
|
-
tmpCommand = tmpCommand.split('{Value}').join(tmpValueString);
|
|
129
|
-
tmpCommand = tmpCommand.split('{Index}').join(String(tmpIndex));
|
|
130
|
-
tmpCommand = tmpCommand.split('{Count}').join(String(tmpCount));
|
|
131
|
-
|
|
132
|
-
let tmpCurrentIndex = tmpIndex;
|
|
133
|
-
tmpIndex++;
|
|
134
|
-
|
|
135
|
-
pManifestEntry.Log.push(`CommandEach [${tmpCurrentIndex}/${tmpCount}]: ${tmpCommand}`);
|
|
136
|
-
|
|
137
|
-
libChildProcess.exec(tmpCommand, { timeout: tmpTimeout, maxBuffer: tmpMaxBuffer },
|
|
138
|
-
(pError, pStdOut, pStdErr) =>
|
|
139
|
-
{
|
|
140
|
-
let tmpResult = {
|
|
141
|
-
Value: tmpValue,
|
|
142
|
-
Index: tmpCurrentIndex,
|
|
143
|
-
Command: tmpCommand,
|
|
144
|
-
ExitCode: pError ? (pError.code || 1) : 0,
|
|
145
|
-
StdOut: pStdOut || '',
|
|
146
|
-
StdErr: pStdErr || '',
|
|
147
|
-
Success: !pError
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
tmpResults.push(tmpResult);
|
|
151
|
-
|
|
152
|
-
if (pError)
|
|
153
|
-
{
|
|
154
|
-
tmpFailCount++;
|
|
155
|
-
pManifestEntry.Log.push(`CommandEach [${tmpCurrentIndex}]: failed - ${pError.message}`);
|
|
156
|
-
|
|
157
|
-
if (!tmpContinueOnError)
|
|
158
|
-
{
|
|
159
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
160
|
-
pManifestEntry.Status = 'Error';
|
|
161
|
-
pManifestEntry.Success = false;
|
|
162
|
-
pManifestEntry.Output = JSON.stringify({
|
|
163
|
-
Total: tmpCount,
|
|
164
|
-
Succeeded: tmpSuccessCount,
|
|
165
|
-
Failed: tmpFailCount,
|
|
166
|
-
StoppedAtIndex: tmpCurrentIndex
|
|
167
|
-
});
|
|
168
|
-
pManifestEntry.Log.push(`CommandEach: stopping at index ${tmpCurrentIndex} due to ContinueOnError=false.`);
|
|
169
|
-
|
|
170
|
-
this.storeDestination(pTaskDefinition, pContext, pManifestEntry, tmpResults);
|
|
171
|
-
this.storeResult(pTaskDefinition, pContext, pManifestEntry, tmpResults);
|
|
172
|
-
|
|
173
|
-
return fCallback(null, pManifestEntry);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
else
|
|
177
|
-
{
|
|
178
|
-
tmpSuccessCount++;
|
|
179
|
-
pManifestEntry.Log.push(`CommandEach [${tmpCurrentIndex}]: succeeded.`);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
fRunNext();
|
|
183
|
-
});
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
fRunNext();
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
module.exports = UltravisorTaskCommandEach;
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
const libUltravisorTaskBase = require('./Ultravisor-Task-Base.cjs');
|
|
2
|
-
|
|
3
|
-
class UltravisorTaskConditional extends libUltravisorTaskBase
|
|
4
|
-
{
|
|
5
|
-
constructor(pFable)
|
|
6
|
-
{
|
|
7
|
-
super(pFable);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Evaluate an address and execute one task if truthy, another if falsy.
|
|
12
|
-
*
|
|
13
|
-
* The "Address" field is resolved from pContext.GlobalState (dot-notation).
|
|
14
|
-
* Alternatively, the "Value" field can provide a literal to test.
|
|
15
|
-
*
|
|
16
|
-
* Task definition fields:
|
|
17
|
-
* - Address: dot-notation path into pContext.GlobalState
|
|
18
|
-
* - Value (optional): literal value to evaluate instead of Address
|
|
19
|
-
* - TrueTask: GUID of the task to run when the value is truthy
|
|
20
|
-
* - FalseTask: GUID of the task to run when the value is falsy
|
|
21
|
-
*/
|
|
22
|
-
execute(pTaskDefinition, pContext, pManifestEntry, fCallback)
|
|
23
|
-
{
|
|
24
|
-
let tmpValue = undefined;
|
|
25
|
-
|
|
26
|
-
// Resolve the value to test
|
|
27
|
-
if (pTaskDefinition.hasOwnProperty('Value'))
|
|
28
|
-
{
|
|
29
|
-
tmpValue = pTaskDefinition.Value;
|
|
30
|
-
pManifestEntry.Log.push(`Conditional: evaluating literal Value: ${JSON.stringify(tmpValue)}`);
|
|
31
|
-
}
|
|
32
|
-
else if (pTaskDefinition.Address && typeof(pTaskDefinition.Address) === 'string')
|
|
33
|
-
{
|
|
34
|
-
tmpValue = this.resolveAddress(pTaskDefinition.Address, pContext);
|
|
35
|
-
pManifestEntry.Log.push(`Conditional: resolved Address "${pTaskDefinition.Address}" to: ${JSON.stringify(tmpValue)}`);
|
|
36
|
-
}
|
|
37
|
-
else
|
|
38
|
-
{
|
|
39
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
40
|
-
pManifestEntry.Status = 'Error';
|
|
41
|
-
pManifestEntry.Log.push(`Conditional: task requires an Address or Value field.`);
|
|
42
|
-
return fCallback(null, pManifestEntry);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
let tmpIsTruthy = !!tmpValue;
|
|
46
|
-
let tmpTargetGUID = tmpIsTruthy ? pTaskDefinition.TrueTask : pTaskDefinition.FalseTask;
|
|
47
|
-
|
|
48
|
-
pManifestEntry.Log.push(`Conditional: value is ${tmpIsTruthy ? 'truthy' : 'falsy'}, selected ${tmpIsTruthy ? 'TrueTask' : 'FalseTask'}: ${tmpTargetGUID || '(none)'}`);
|
|
49
|
-
|
|
50
|
-
if (!tmpTargetGUID || typeof(tmpTargetGUID) !== 'string' || tmpTargetGUID.length === 0)
|
|
51
|
-
{
|
|
52
|
-
// No task to execute for this branch -- that is a valid no-op
|
|
53
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
54
|
-
pManifestEntry.Status = 'Complete';
|
|
55
|
-
pManifestEntry.Success = true;
|
|
56
|
-
pManifestEntry.Output = JSON.stringify({ Branch: tmpIsTruthy ? 'true' : 'false', Task: null });
|
|
57
|
-
pManifestEntry.Log.push(`Conditional: no task defined for this branch; completing as no-op.`);
|
|
58
|
-
return fCallback(null, pManifestEntry);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Look up and execute the selected task
|
|
62
|
-
let tmpStateService = this.fable['Ultravisor-Hypervisor-State'];
|
|
63
|
-
let tmpTaskOrchestrator = this.fable['Ultravisor-Task'];
|
|
64
|
-
|
|
65
|
-
tmpStateService.getTask(tmpTargetGUID,
|
|
66
|
-
(pError, pBranchTaskDefinition) =>
|
|
67
|
-
{
|
|
68
|
-
if (pError)
|
|
69
|
-
{
|
|
70
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
71
|
-
pManifestEntry.Status = 'Error';
|
|
72
|
-
pManifestEntry.Log.push(`Conditional: could not find task ${tmpTargetGUID}: ${pError.message}`);
|
|
73
|
-
return fCallback(null, pManifestEntry);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
tmpTaskOrchestrator.executeCoreTaskStandalone(pBranchTaskDefinition, pContext,
|
|
77
|
-
(pExecError, pResult) =>
|
|
78
|
-
{
|
|
79
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
80
|
-
|
|
81
|
-
if (pExecError)
|
|
82
|
-
{
|
|
83
|
-
pManifestEntry.Status = 'Error';
|
|
84
|
-
pManifestEntry.Log.push(`Conditional: error executing branch task ${tmpTargetGUID}: ${pExecError.message}`);
|
|
85
|
-
return fCallback(null, pManifestEntry);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
pManifestEntry.Status = pResult.Status;
|
|
89
|
-
pManifestEntry.Success = pResult.Success;
|
|
90
|
-
pManifestEntry.Output = JSON.stringify(
|
|
91
|
-
{
|
|
92
|
-
Branch: tmpIsTruthy ? 'true' : 'false',
|
|
93
|
-
Task: tmpTargetGUID,
|
|
94
|
-
Result: pResult
|
|
95
|
-
});
|
|
96
|
-
pManifestEntry.Log.push(`Conditional: branch task ${tmpTargetGUID} completed with status ${pResult.Status}.`);
|
|
97
|
-
|
|
98
|
-
return fCallback(null, pManifestEntry);
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
module.exports = UltravisorTaskConditional;
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
const libUltravisorTaskBase = require('./Ultravisor-Task-Base.cjs');
|
|
2
|
-
|
|
3
|
-
class UltravisorTaskDateWindow extends libUltravisorTaskBase
|
|
4
|
-
{
|
|
5
|
-
constructor(pFable)
|
|
6
|
-
{
|
|
7
|
-
super(pFable);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Compute the last completed time-aligned window.
|
|
12
|
-
*
|
|
13
|
-
* Calculates the most recent completed N-minute window aligned to
|
|
14
|
-
* clock boundaries (e.g. :00, :10, :20 for 10-minute windows).
|
|
15
|
-
*
|
|
16
|
-
* Examples for a 10-minute interval:
|
|
17
|
-
* Current time 10:13 → window is 10:00 – 10:09:59.999
|
|
18
|
-
* Current time 10:07 → window is 09:50 – 09:59:59.999
|
|
19
|
-
* Current time 10:30 → window is 10:20 – 10:29:59.999
|
|
20
|
-
*
|
|
21
|
-
* Task definition fields:
|
|
22
|
-
* - IntervalMinutes (optional, default 10): window size in minutes
|
|
23
|
-
* - Destination (optional): manyfest address in GlobalState for
|
|
24
|
-
* the result object (defaults to "Output")
|
|
25
|
-
*
|
|
26
|
-
* Result object:
|
|
27
|
-
* {
|
|
28
|
-
* WindowStart: "<ISO 8601>", // e.g. "2026-02-12T04:20:00.000Z"
|
|
29
|
-
* WindowEnd: "<ISO 8601>" // e.g. "2026-02-12T04:29:59.999Z"
|
|
30
|
-
* }
|
|
31
|
-
*/
|
|
32
|
-
execute(pTaskDefinition, pContext, pManifestEntry, fCallback)
|
|
33
|
-
{
|
|
34
|
-
let tmpInterval = (typeof(pTaskDefinition.IntervalMinutes) === 'number' && pTaskDefinition.IntervalMinutes > 0)
|
|
35
|
-
? pTaskDefinition.IntervalMinutes
|
|
36
|
-
: 10;
|
|
37
|
-
|
|
38
|
-
let tmpNow = new Date();
|
|
39
|
-
|
|
40
|
-
// Floor to the nearest interval-aligned minute mark
|
|
41
|
-
let tmpEndMinutes = Math.floor(tmpNow.getMinutes() / tmpInterval) * tmpInterval;
|
|
42
|
-
|
|
43
|
-
let tmpEnd = new Date(tmpNow);
|
|
44
|
-
tmpEnd.setMinutes(tmpEndMinutes, 0, 0);
|
|
45
|
-
|
|
46
|
-
// The window start is one interval before the end
|
|
47
|
-
let tmpStart = new Date(tmpEnd.getTime() - (tmpInterval * 60 * 1000));
|
|
48
|
-
|
|
49
|
-
// The window end is 1ms before the aligned mark (exclusive upper bound)
|
|
50
|
-
let tmpEndExclusive = new Date(tmpEnd.getTime() - 1);
|
|
51
|
-
|
|
52
|
-
let tmpResult = {
|
|
53
|
-
WindowStart: tmpStart.toISOString(),
|
|
54
|
-
WindowEnd: tmpEndExclusive.toISOString()
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
58
|
-
pManifestEntry.Status = 'Complete';
|
|
59
|
-
pManifestEntry.Success = true;
|
|
60
|
-
pManifestEntry.Output = JSON.stringify(tmpResult);
|
|
61
|
-
|
|
62
|
-
pManifestEntry.Log.push(`DateWindow: interval=${tmpInterval}min, now=${tmpNow.toISOString()}`);
|
|
63
|
-
pManifestEntry.Log.push(`DateWindow: WindowStart=${tmpResult.WindowStart}`);
|
|
64
|
-
pManifestEntry.Log.push(`DateWindow: WindowEnd=${tmpResult.WindowEnd}`);
|
|
65
|
-
|
|
66
|
-
this.storeDestination(pTaskDefinition, pContext, pManifestEntry, tmpResult);
|
|
67
|
-
|
|
68
|
-
return fCallback(null, pManifestEntry);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
module.exports = UltravisorTaskDateWindow;
|
|
@@ -1,336 +0,0 @@
|
|
|
1
|
-
const libUltravisorTaskBase = require('./Ultravisor-Task-Base.cjs');
|
|
2
|
-
|
|
3
|
-
const libFS = require('fs');
|
|
4
|
-
const libPath = require('path');
|
|
5
|
-
|
|
6
|
-
class UltravisorTaskGeneratePagedOperation extends libUltravisorTaskBase
|
|
7
|
-
{
|
|
8
|
-
constructor(pFable)
|
|
9
|
-
{
|
|
10
|
-
super(pFable);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Generate a paged operation from a template and optionally execute it.
|
|
15
|
-
*
|
|
16
|
-
* Task definition fields:
|
|
17
|
-
* - RecordCount: GlobalState address (string) or literal number for
|
|
18
|
-
* the total record count.
|
|
19
|
-
* - PageSize (optional, default 25): records per page.
|
|
20
|
-
* - MaximumRecordCount (optional): cap the resolved RecordCount to
|
|
21
|
-
* this value. Useful for fetching only the first N records.
|
|
22
|
-
* - TaskTemplate: a task definition object used as the template for
|
|
23
|
-
* each page-fetch task. String values in the template support
|
|
24
|
-
* interpolation variables: {PageStart}, {PageSize}, {PageIndex},
|
|
25
|
-
* {PageCount}.
|
|
26
|
-
* - OperationName (optional): human-readable name for the generated
|
|
27
|
-
* operation.
|
|
28
|
-
* - AutoExecute (optional, default true): whether to execute the
|
|
29
|
-
* generated operation immediately.
|
|
30
|
-
* - Retries (optional, default 0): number of retries per page task.
|
|
31
|
-
* - Destination (optional): manyfest address in GlobalState to store
|
|
32
|
-
* the generated operation GUID.
|
|
33
|
-
*/
|
|
34
|
-
execute(pTaskDefinition, pContext, pManifestEntry, fCallback)
|
|
35
|
-
{
|
|
36
|
-
// --- Resolve record count ---
|
|
37
|
-
let tmpRecordCount;
|
|
38
|
-
|
|
39
|
-
if (typeof(pTaskDefinition.RecordCount) === 'number')
|
|
40
|
-
{
|
|
41
|
-
tmpRecordCount = pTaskDefinition.RecordCount;
|
|
42
|
-
}
|
|
43
|
-
else if (typeof(pTaskDefinition.RecordCount) === 'string')
|
|
44
|
-
{
|
|
45
|
-
let tmpResolved = this.resolveAddress(pTaskDefinition.RecordCount, pContext);
|
|
46
|
-
|
|
47
|
-
if (typeof(tmpResolved) === 'number')
|
|
48
|
-
{
|
|
49
|
-
tmpRecordCount = tmpResolved;
|
|
50
|
-
}
|
|
51
|
-
else if (typeof(tmpResolved) === 'string')
|
|
52
|
-
{
|
|
53
|
-
tmpRecordCount = parseInt(tmpResolved, 10);
|
|
54
|
-
}
|
|
55
|
-
else
|
|
56
|
-
{
|
|
57
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
58
|
-
pManifestEntry.Status = 'Error';
|
|
59
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: could not resolve RecordCount from "${pTaskDefinition.RecordCount}".`);
|
|
60
|
-
return fCallback(null, pManifestEntry);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
else
|
|
64
|
-
{
|
|
65
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
66
|
-
pManifestEntry.Status = 'Error';
|
|
67
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: RecordCount is required (number or GlobalState address).`);
|
|
68
|
-
return fCallback(null, pManifestEntry);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (isNaN(tmpRecordCount) || tmpRecordCount < 0)
|
|
72
|
-
{
|
|
73
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
74
|
-
pManifestEntry.Status = 'Error';
|
|
75
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: RecordCount resolved to invalid value: ${tmpRecordCount}.`);
|
|
76
|
-
return fCallback(null, pManifestEntry);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// --- Apply MaximumRecordCount cap ---
|
|
80
|
-
if (typeof(pTaskDefinition.MaximumRecordCount) === 'number' && pTaskDefinition.MaximumRecordCount > 0)
|
|
81
|
-
{
|
|
82
|
-
if (tmpRecordCount > pTaskDefinition.MaximumRecordCount)
|
|
83
|
-
{
|
|
84
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: capping RecordCount from ${tmpRecordCount} to MaximumRecordCount ${pTaskDefinition.MaximumRecordCount}.`);
|
|
85
|
-
tmpRecordCount = pTaskDefinition.MaximumRecordCount;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// --- Validate TaskTemplate ---
|
|
90
|
-
if (!pTaskDefinition.TaskTemplate || typeof(pTaskDefinition.TaskTemplate) !== 'object')
|
|
91
|
-
{
|
|
92
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
93
|
-
pManifestEntry.Status = 'Error';
|
|
94
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: TaskTemplate is required.`);
|
|
95
|
-
return fCallback(null, pManifestEntry);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// --- Calculate paging ---
|
|
99
|
-
let tmpPageSize = (typeof(pTaskDefinition.PageSize) === 'number' && pTaskDefinition.PageSize > 0) ? pTaskDefinition.PageSize : 25;
|
|
100
|
-
let tmpPageCount = Math.ceil(tmpRecordCount / tmpPageSize);
|
|
101
|
-
|
|
102
|
-
if (tmpPageCount === 0)
|
|
103
|
-
{
|
|
104
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
105
|
-
pManifestEntry.Status = 'Complete';
|
|
106
|
-
pManifestEntry.Success = true;
|
|
107
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: RecordCount is 0, no pages to generate.`);
|
|
108
|
-
return fCallback(null, pManifestEntry);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
let tmpRetries = (typeof(pTaskDefinition.Retries) === 'number' && pTaskDefinition.Retries > 0) ? pTaskDefinition.Retries : 0;
|
|
112
|
-
let tmpOperationName = pTaskDefinition.OperationName || 'Paged Operation';
|
|
113
|
-
let tmpAutoExecute = (pTaskDefinition.AutoExecute !== false);
|
|
114
|
-
|
|
115
|
-
// --- Generate a GUID for the paged operation ---
|
|
116
|
-
let tmpBaseGUID = pTaskDefinition.GUIDTask || 'paged';
|
|
117
|
-
let tmpOperationGUID = `${tmpBaseGUID}-paged-${Date.now()}`;
|
|
118
|
-
|
|
119
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: ${tmpRecordCount} records, ${tmpPageSize} per page, ${tmpPageCount} page(s).`);
|
|
120
|
-
|
|
121
|
-
// --- Resolve URLAddress in TaskTemplate if present ---
|
|
122
|
-
// When the TaskTemplate has a URLAddress field, resolve it from
|
|
123
|
-
// GlobalState and set it as the URL before pagination interpolation.
|
|
124
|
-
if (pTaskDefinition.TaskTemplate.URLAddress && typeof(pTaskDefinition.TaskTemplate.URLAddress) === 'string')
|
|
125
|
-
{
|
|
126
|
-
let tmpResolvedURL = this.resolveAddress(pTaskDefinition.TaskTemplate.URLAddress, pContext);
|
|
127
|
-
if (tmpResolvedURL && typeof(tmpResolvedURL) === 'string')
|
|
128
|
-
{
|
|
129
|
-
pTaskDefinition.TaskTemplate.URL = tmpResolvedURL;
|
|
130
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: resolved TaskTemplate URL from GlobalState address "${pTaskDefinition.TaskTemplate.URLAddress}": ${tmpResolvedURL.substring(0, 200)}`);
|
|
131
|
-
}
|
|
132
|
-
else
|
|
133
|
-
{
|
|
134
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: WARNING URLAddress "${pTaskDefinition.TaskTemplate.URLAddress}" could not be resolved.`);
|
|
135
|
-
}
|
|
136
|
-
// Remove URLAddress from the template so generated page tasks
|
|
137
|
-
// use the interpolated URL directly instead of re-resolving
|
|
138
|
-
// from GlobalState (which would give the un-interpolated pattern).
|
|
139
|
-
delete pTaskDefinition.TaskTemplate.URLAddress;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// --- Generate task definitions ---
|
|
143
|
-
let tmpTasks = {};
|
|
144
|
-
let tmpTaskGUIDs = [];
|
|
145
|
-
|
|
146
|
-
for (let i = 0; i < tmpPageCount; i++)
|
|
147
|
-
{
|
|
148
|
-
let tmpPageStart = i * tmpPageSize;
|
|
149
|
-
let tmpTaskGUID = `${tmpOperationGUID}-page-${i}`;
|
|
150
|
-
|
|
151
|
-
let tmpVars = {
|
|
152
|
-
PageStart: String(tmpPageStart),
|
|
153
|
-
PageSize: String(tmpPageSize),
|
|
154
|
-
PageIndex: String(i),
|
|
155
|
-
PageCount: String(tmpPageCount)
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
let tmpTaskDef = this._interpolateTemplate(JSON.parse(JSON.stringify(pTaskDefinition.TaskTemplate)), tmpVars);
|
|
159
|
-
tmpTaskDef.GUIDTask = tmpTaskGUID;
|
|
160
|
-
tmpTaskDef.Name = `Page ${i + 1} of ${tmpPageCount}`;
|
|
161
|
-
tmpTaskDef.Destination = `Pages[${i}]`;
|
|
162
|
-
|
|
163
|
-
if (tmpRetries > 0)
|
|
164
|
-
{
|
|
165
|
-
tmpTaskDef.Retries = tmpRetries;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
tmpTasks[tmpTaskGUID] = tmpTaskDef;
|
|
169
|
-
tmpTaskGUIDs.push(tmpTaskGUID);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// --- Generate operation definition ---
|
|
173
|
-
let tmpOperationDef = {
|
|
174
|
-
GUIDOperation: tmpOperationGUID,
|
|
175
|
-
Name: `${tmpOperationName} (${tmpPageCount} pages)`,
|
|
176
|
-
Tasks: tmpTaskGUIDs
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
// --- Write standalone config to staging ---
|
|
180
|
-
let tmpStagingPath = this.resolveStagingPath(pContext);
|
|
181
|
-
let tmpConfigContent = {
|
|
182
|
-
Tasks: tmpTasks,
|
|
183
|
-
Operations: {}
|
|
184
|
-
};
|
|
185
|
-
tmpConfigContent.Operations[tmpOperationGUID] = tmpOperationDef;
|
|
186
|
-
|
|
187
|
-
let tmpConfigPath = libPath.join(tmpStagingPath, `PagedOperation_${tmpOperationGUID}.json`);
|
|
188
|
-
|
|
189
|
-
try
|
|
190
|
-
{
|
|
191
|
-
if (!libFS.existsSync(tmpStagingPath))
|
|
192
|
-
{
|
|
193
|
-
libFS.mkdirSync(tmpStagingPath, { recursive: true });
|
|
194
|
-
}
|
|
195
|
-
libFS.writeFileSync(tmpConfigPath, JSON.stringify(tmpConfigContent, null, 4), 'utf8');
|
|
196
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: wrote config to ${tmpConfigPath}.`);
|
|
197
|
-
}
|
|
198
|
-
catch (pWriteError)
|
|
199
|
-
{
|
|
200
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: warning: could not write config file: ${pWriteError.message}`);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// --- Register tasks and operation in memory (no persist) ---
|
|
204
|
-
let tmpStateService = this.fable['Ultravisor-Hypervisor-State'];
|
|
205
|
-
|
|
206
|
-
for (let i = 0; i < tmpTaskGUIDs.length; i++)
|
|
207
|
-
{
|
|
208
|
-
tmpStateService._Tasks[tmpTaskGUIDs[i]] = tmpTasks[tmpTaskGUIDs[i]];
|
|
209
|
-
}
|
|
210
|
-
tmpStateService._Operations[tmpOperationGUID] = tmpOperationDef;
|
|
211
|
-
|
|
212
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: registered ${tmpPageCount} task(s) and 1 operation in memory.`);
|
|
213
|
-
|
|
214
|
-
// --- Store the operation GUID at Destination ---
|
|
215
|
-
this.storeDestination(pTaskDefinition, pContext, pManifestEntry, tmpOperationGUID);
|
|
216
|
-
|
|
217
|
-
if (!tmpAutoExecute)
|
|
218
|
-
{
|
|
219
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
220
|
-
pManifestEntry.Status = 'Complete';
|
|
221
|
-
pManifestEntry.Success = true;
|
|
222
|
-
pManifestEntry.Output = tmpOperationGUID;
|
|
223
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: AutoExecute is false, operation ${tmpOperationGUID} ready for manual execution.`);
|
|
224
|
-
return fCallback(null, pManifestEntry);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// --- Auto-execute the generated operation ---
|
|
228
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: auto-executing operation ${tmpOperationGUID}.`);
|
|
229
|
-
|
|
230
|
-
// Clone the current GlobalState so cookies/auth carry through
|
|
231
|
-
let tmpChildOperationDef = Object.assign({}, tmpOperationDef);
|
|
232
|
-
tmpChildOperationDef.GlobalState = pContext.GlobalState;
|
|
233
|
-
tmpChildOperationDef.StagingPath = tmpStagingPath;
|
|
234
|
-
|
|
235
|
-
let tmpOperationService = this.fable['Ultravisor-Operation'];
|
|
236
|
-
|
|
237
|
-
tmpOperationService.executeOperation(tmpChildOperationDef,
|
|
238
|
-
(pError, pChildManifest) =>
|
|
239
|
-
{
|
|
240
|
-
pManifestEntry.StopTime = new Date().toISOString();
|
|
241
|
-
|
|
242
|
-
if (pError)
|
|
243
|
-
{
|
|
244
|
-
pManifestEntry.Status = 'Error';
|
|
245
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: execution error: ${pError.message}`);
|
|
246
|
-
return fCallback(null, pManifestEntry);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
pManifestEntry.Status = 'Complete';
|
|
250
|
-
pManifestEntry.Success = pChildManifest.Success;
|
|
251
|
-
pManifestEntry.Output = JSON.stringify({
|
|
252
|
-
OperationGUID: tmpOperationGUID,
|
|
253
|
-
PageCount: tmpPageCount,
|
|
254
|
-
ChildManifestSummary: pChildManifest.Summary,
|
|
255
|
-
ChildManifestStatus: pChildManifest.Status,
|
|
256
|
-
ChildManifestSuccess: pChildManifest.Success
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
let tmpSuccessCount = 0;
|
|
260
|
-
let tmpFailCount = 0;
|
|
261
|
-
if (pChildManifest.TaskResults && Array.isArray(pChildManifest.TaskResults))
|
|
262
|
-
{
|
|
263
|
-
for (let i = 0; i < pChildManifest.TaskResults.length; i++)
|
|
264
|
-
{
|
|
265
|
-
if (pChildManifest.TaskResults[i].Success)
|
|
266
|
-
{
|
|
267
|
-
tmpSuccessCount++;
|
|
268
|
-
}
|
|
269
|
-
else
|
|
270
|
-
{
|
|
271
|
-
tmpFailCount++;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
pManifestEntry.Log.push(`GeneratePagedOperation: completed ${tmpSuccessCount} of ${tmpPageCount} page(s) successfully${tmpFailCount > 0 ? `, ${tmpFailCount} failed` : ''}.`);
|
|
277
|
-
|
|
278
|
-
// Clean up ephemeral tasks and operation from state
|
|
279
|
-
for (let i = 0; i < tmpTaskGUIDs.length; i++)
|
|
280
|
-
{
|
|
281
|
-
delete tmpStateService._Tasks[tmpTaskGUIDs[i]];
|
|
282
|
-
}
|
|
283
|
-
delete tmpStateService._Operations[tmpOperationGUID];
|
|
284
|
-
|
|
285
|
-
return fCallback(null, pManifestEntry);
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Recursively replace interpolation variables in all string values
|
|
291
|
-
* of an object. Variables use {VarName} syntax.
|
|
292
|
-
*
|
|
293
|
-
* @param {*} pValue - The value to interpolate.
|
|
294
|
-
* @param {object} pVars - Map of variable names to replacement values.
|
|
295
|
-
* @returns {*} The interpolated value.
|
|
296
|
-
*/
|
|
297
|
-
_interpolateTemplate(pValue, pVars)
|
|
298
|
-
{
|
|
299
|
-
if (typeof(pValue) === 'string')
|
|
300
|
-
{
|
|
301
|
-
let tmpResult = pValue;
|
|
302
|
-
let tmpVarKeys = Object.keys(pVars);
|
|
303
|
-
for (let i = 0; i < tmpVarKeys.length; i++)
|
|
304
|
-
{
|
|
305
|
-
// Replace all occurrences of {VarName}
|
|
306
|
-
let tmpPattern = `{${tmpVarKeys[i]}}`;
|
|
307
|
-
while (tmpResult.indexOf(tmpPattern) !== -1)
|
|
308
|
-
{
|
|
309
|
-
tmpResult = tmpResult.replace(tmpPattern, pVars[tmpVarKeys[i]]);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
return tmpResult;
|
|
313
|
-
}
|
|
314
|
-
else if (Array.isArray(pValue))
|
|
315
|
-
{
|
|
316
|
-
for (let i = 0; i < pValue.length; i++)
|
|
317
|
-
{
|
|
318
|
-
pValue[i] = this._interpolateTemplate(pValue[i], pVars);
|
|
319
|
-
}
|
|
320
|
-
return pValue;
|
|
321
|
-
}
|
|
322
|
-
else if (typeof(pValue) === 'object' && pValue !== null)
|
|
323
|
-
{
|
|
324
|
-
let tmpKeys = Object.keys(pValue);
|
|
325
|
-
for (let i = 0; i < tmpKeys.length; i++)
|
|
326
|
-
{
|
|
327
|
-
pValue[tmpKeys[i]] = this._interpolateTemplate(pValue[tmpKeys[i]], pVars);
|
|
328
|
-
}
|
|
329
|
-
return pValue;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
return pValue;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
module.exports = UltravisorTaskGeneratePagedOperation;
|