@positronic/cli 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/commands/helpers.js +57 -27
- package/dist/types/commands/helpers.d.ts.map +1 -1
- package/package.json +5 -1
- package/dist/src/commands/brain.test.js +0 -2936
- package/dist/src/commands/helpers.test.js +0 -832
- package/dist/src/commands/project.test.js +0 -1201
- package/dist/src/commands/resources.test.js +0 -2511
- package/dist/src/commands/schedule.test.js +0 -1235
- package/dist/src/commands/secret.test.d.js +0 -1
- package/dist/src/commands/secret.test.js +0 -761
- package/dist/src/commands/server.test.js +0 -1237
- package/dist/src/commands/test-utils.js +0 -737
- package/dist/src/components/secret-sync.js +0 -303
- package/dist/src/test/mock-api-client.js +0 -371
- package/dist/src/test/test-dev-server.js +0 -1376
- package/dist/types/commands/test-utils.d.ts +0 -45
- package/dist/types/commands/test-utils.d.ts.map +0 -1
- package/dist/types/components/secret-sync.d.ts +0 -9
- package/dist/types/components/secret-sync.d.ts.map +0 -1
- package/dist/types/test/mock-api-client.d.ts +0 -25
- package/dist/types/test/mock-api-client.d.ts.map +0 -1
- package/dist/types/test/test-dev-server.d.ts +0 -129
- package/dist/types/test/test-dev-server.d.ts.map +0 -1
- package/src/cli.ts +0 -997
- package/src/commands/backend.ts +0 -63
- package/src/commands/brain.test.ts +0 -1004
- package/src/commands/brain.ts +0 -215
- package/src/commands/helpers.test.ts +0 -487
- package/src/commands/helpers.ts +0 -870
- package/src/commands/project-config-manager.ts +0 -152
- package/src/commands/project.test.ts +0 -502
- package/src/commands/project.ts +0 -109
- package/src/commands/resources.test.ts +0 -1052
- package/src/commands/resources.ts +0 -97
- package/src/commands/schedule.test.ts +0 -481
- package/src/commands/schedule.ts +0 -65
- package/src/commands/secret.test.ts +0 -210
- package/src/commands/secret.ts +0 -50
- package/src/commands/server.test.ts +0 -493
- package/src/commands/server.ts +0 -353
- package/src/commands/test-utils.ts +0 -324
- package/src/components/brain-history.tsx +0 -198
- package/src/components/brain-list.tsx +0 -105
- package/src/components/brain-rerun.tsx +0 -111
- package/src/components/brain-show.tsx +0 -92
- package/src/components/error.tsx +0 -24
- package/src/components/project-add.tsx +0 -59
- package/src/components/project-create.tsx +0 -83
- package/src/components/project-list.tsx +0 -83
- package/src/components/project-remove.tsx +0 -55
- package/src/components/project-select.tsx +0 -200
- package/src/components/project-show.tsx +0 -58
- package/src/components/resource-clear.tsx +0 -127
- package/src/components/resource-delete.tsx +0 -160
- package/src/components/resource-list.tsx +0 -177
- package/src/components/resource-sync.tsx +0 -170
- package/src/components/resource-types.tsx +0 -55
- package/src/components/resource-upload.tsx +0 -182
- package/src/components/schedule-create.tsx +0 -90
- package/src/components/schedule-delete.tsx +0 -116
- package/src/components/schedule-list.tsx +0 -186
- package/src/components/schedule-runs.tsx +0 -151
- package/src/components/secret-bulk.tsx +0 -79
- package/src/components/secret-create.tsx +0 -49
- package/src/components/secret-delete.tsx +0 -41
- package/src/components/secret-list.tsx +0 -41
- package/src/components/watch.tsx +0 -155
- package/src/hooks/useApi.ts +0 -183
- package/src/positronic.ts +0 -40
- package/src/test/data/resources/config.json +0 -1
- package/src/test/data/resources/data/config.json +0 -1
- package/src/test/data/resources/data/logo.png +0 -2
- package/src/test/data/resources/docs/api.md +0 -3
- package/src/test/data/resources/docs/readme.md +0 -3
- package/src/test/data/resources/example.md +0 -3
- package/src/test/data/resources/file with spaces.txt +0 -1
- package/src/test/data/resources/readme.md +0 -3
- package/src/test/data/resources/test.txt +0 -1
- package/src/test/mock-api-client.ts +0 -145
- package/src/test/test-dev-server.ts +0 -1003
- package/tsconfig.json +0 -11
|
@@ -1,1376 +0,0 @@
|
|
|
1
|
-
function _array_like_to_array(arr, len) {
|
|
2
|
-
if (len == null || len > arr.length) len = arr.length;
|
|
3
|
-
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
4
|
-
return arr2;
|
|
5
|
-
}
|
|
6
|
-
function _array_with_holes(arr) {
|
|
7
|
-
if (Array.isArray(arr)) return arr;
|
|
8
|
-
}
|
|
9
|
-
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
10
|
-
try {
|
|
11
|
-
var info = gen[key](arg);
|
|
12
|
-
var value = info.value;
|
|
13
|
-
} catch (error) {
|
|
14
|
-
reject(error);
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
if (info.done) {
|
|
18
|
-
resolve(value);
|
|
19
|
-
} else {
|
|
20
|
-
Promise.resolve(value).then(_next, _throw);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
function _async_to_generator(fn) {
|
|
24
|
-
return function() {
|
|
25
|
-
var self = this, args = arguments;
|
|
26
|
-
return new Promise(function(resolve, reject) {
|
|
27
|
-
var gen = fn.apply(self, args);
|
|
28
|
-
function _next(value) {
|
|
29
|
-
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
30
|
-
}
|
|
31
|
-
function _throw(err) {
|
|
32
|
-
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
33
|
-
}
|
|
34
|
-
_next(undefined);
|
|
35
|
-
});
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function _class_call_check(instance, Constructor) {
|
|
39
|
-
if (!(instance instanceof Constructor)) {
|
|
40
|
-
throw new TypeError("Cannot call a class as a function");
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
function _defineProperties(target, props) {
|
|
44
|
-
for(var i = 0; i < props.length; i++){
|
|
45
|
-
var descriptor = props[i];
|
|
46
|
-
descriptor.enumerable = descriptor.enumerable || false;
|
|
47
|
-
descriptor.configurable = true;
|
|
48
|
-
if ("value" in descriptor) descriptor.writable = true;
|
|
49
|
-
Object.defineProperty(target, descriptor.key, descriptor);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function _create_class(Constructor, protoProps, staticProps) {
|
|
53
|
-
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
54
|
-
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
55
|
-
return Constructor;
|
|
56
|
-
}
|
|
57
|
-
function _define_property(obj, key, value) {
|
|
58
|
-
if (key in obj) {
|
|
59
|
-
Object.defineProperty(obj, key, {
|
|
60
|
-
value: value,
|
|
61
|
-
enumerable: true,
|
|
62
|
-
configurable: true,
|
|
63
|
-
writable: true
|
|
64
|
-
});
|
|
65
|
-
} else {
|
|
66
|
-
obj[key] = value;
|
|
67
|
-
}
|
|
68
|
-
return obj;
|
|
69
|
-
}
|
|
70
|
-
function _iterable_to_array_limit(arr, i) {
|
|
71
|
-
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
72
|
-
if (_i == null) return;
|
|
73
|
-
var _arr = [];
|
|
74
|
-
var _n = true;
|
|
75
|
-
var _d = false;
|
|
76
|
-
var _s, _e;
|
|
77
|
-
try {
|
|
78
|
-
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
79
|
-
_arr.push(_s.value);
|
|
80
|
-
if (i && _arr.length === i) break;
|
|
81
|
-
}
|
|
82
|
-
} catch (err) {
|
|
83
|
-
_d = true;
|
|
84
|
-
_e = err;
|
|
85
|
-
} finally{
|
|
86
|
-
try {
|
|
87
|
-
if (!_n && _i["return"] != null) _i["return"]();
|
|
88
|
-
} finally{
|
|
89
|
-
if (_d) throw _e;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return _arr;
|
|
93
|
-
}
|
|
94
|
-
function _non_iterable_rest() {
|
|
95
|
-
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
96
|
-
}
|
|
97
|
-
function _sliced_to_array(arr, i) {
|
|
98
|
-
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
99
|
-
}
|
|
100
|
-
function _unsupported_iterable_to_array(o, minLen) {
|
|
101
|
-
if (!o) return;
|
|
102
|
-
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
103
|
-
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
104
|
-
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
105
|
-
if (n === "Map" || n === "Set") return Array.from(n);
|
|
106
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
107
|
-
}
|
|
108
|
-
function _ts_generator(thisArg, body) {
|
|
109
|
-
var f, y, t, _ = {
|
|
110
|
-
label: 0,
|
|
111
|
-
sent: function() {
|
|
112
|
-
if (t[0] & 1) throw t[1];
|
|
113
|
-
return t[1];
|
|
114
|
-
},
|
|
115
|
-
trys: [],
|
|
116
|
-
ops: []
|
|
117
|
-
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
118
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
119
|
-
return this;
|
|
120
|
-
}), g;
|
|
121
|
-
function verb(n) {
|
|
122
|
-
return function(v) {
|
|
123
|
-
return step([
|
|
124
|
-
n,
|
|
125
|
-
v
|
|
126
|
-
]);
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
function step(op) {
|
|
130
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
131
|
-
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
132
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
133
|
-
if (y = 0, t) op = [
|
|
134
|
-
op[0] & 2,
|
|
135
|
-
t.value
|
|
136
|
-
];
|
|
137
|
-
switch(op[0]){
|
|
138
|
-
case 0:
|
|
139
|
-
case 1:
|
|
140
|
-
t = op;
|
|
141
|
-
break;
|
|
142
|
-
case 4:
|
|
143
|
-
_.label++;
|
|
144
|
-
return {
|
|
145
|
-
value: op[1],
|
|
146
|
-
done: false
|
|
147
|
-
};
|
|
148
|
-
case 5:
|
|
149
|
-
_.label++;
|
|
150
|
-
y = op[1];
|
|
151
|
-
op = [
|
|
152
|
-
0
|
|
153
|
-
];
|
|
154
|
-
continue;
|
|
155
|
-
case 7:
|
|
156
|
-
op = _.ops.pop();
|
|
157
|
-
_.trys.pop();
|
|
158
|
-
continue;
|
|
159
|
-
default:
|
|
160
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
161
|
-
_ = 0;
|
|
162
|
-
continue;
|
|
163
|
-
}
|
|
164
|
-
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
165
|
-
_.label = op[1];
|
|
166
|
-
break;
|
|
167
|
-
}
|
|
168
|
-
if (op[0] === 6 && _.label < t[1]) {
|
|
169
|
-
_.label = t[1];
|
|
170
|
-
t = op;
|
|
171
|
-
break;
|
|
172
|
-
}
|
|
173
|
-
if (t && _.label < t[2]) {
|
|
174
|
-
_.label = t[2];
|
|
175
|
-
_.ops.push(op);
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
if (t[2]) _.ops.pop();
|
|
179
|
-
_.trys.pop();
|
|
180
|
-
continue;
|
|
181
|
-
}
|
|
182
|
-
op = body.call(thisArg, _);
|
|
183
|
-
} catch (e) {
|
|
184
|
-
op = [
|
|
185
|
-
6,
|
|
186
|
-
e
|
|
187
|
-
];
|
|
188
|
-
y = 0;
|
|
189
|
-
} finally{
|
|
190
|
-
f = t = 0;
|
|
191
|
-
}
|
|
192
|
-
if (op[0] & 5) throw op[1];
|
|
193
|
-
return {
|
|
194
|
-
value: op[0] ? op[1] : void 0,
|
|
195
|
-
done: true
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
import nock from 'nock';
|
|
200
|
-
import { parse } from 'dotenv';
|
|
201
|
-
import fs from 'fs';
|
|
202
|
-
/**
|
|
203
|
-
* Mock implementation of TestServerHandle for testing
|
|
204
|
-
* Since we're using nock, there's no real process to manage
|
|
205
|
-
*/ var MockServerHandle = /*#__PURE__*/ function() {
|
|
206
|
-
"use strict";
|
|
207
|
-
function MockServerHandle(stopFn, getLogsFn, clearLogsFn, port) {
|
|
208
|
-
_class_call_check(this, MockServerHandle);
|
|
209
|
-
_define_property(this, "stopFn", void 0);
|
|
210
|
-
_define_property(this, "getLogsFn", void 0);
|
|
211
|
-
_define_property(this, "clearLogsFn", void 0);
|
|
212
|
-
_define_property(this, "port", void 0);
|
|
213
|
-
_define_property(this, "_killed", void 0);
|
|
214
|
-
_define_property(this, "_errorCallback", void 0);
|
|
215
|
-
_define_property(this, "_closeCallback", void 0);
|
|
216
|
-
this.stopFn = stopFn;
|
|
217
|
-
this.getLogsFn = getLogsFn;
|
|
218
|
-
this.clearLogsFn = clearLogsFn;
|
|
219
|
-
this.port = port;
|
|
220
|
-
this._killed = false;
|
|
221
|
-
}
|
|
222
|
-
_create_class(MockServerHandle, [
|
|
223
|
-
{
|
|
224
|
-
key: "onClose",
|
|
225
|
-
value: function onClose(callback) {
|
|
226
|
-
this._closeCallback = callback;
|
|
227
|
-
}
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
key: "onError",
|
|
231
|
-
value: function onError(callback) {
|
|
232
|
-
this._errorCallback = callback;
|
|
233
|
-
}
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
key: "kill",
|
|
237
|
-
value: function kill(signal) {
|
|
238
|
-
if (!this._killed) {
|
|
239
|
-
this.stopFn();
|
|
240
|
-
this._killed = true;
|
|
241
|
-
return true;
|
|
242
|
-
}
|
|
243
|
-
return false;
|
|
244
|
-
}
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
key: "killed",
|
|
248
|
-
get: function get() {
|
|
249
|
-
return this._killed;
|
|
250
|
-
}
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
key: "waitUntilReady",
|
|
254
|
-
value: function waitUntilReady(maxWaitMs) {
|
|
255
|
-
return _async_to_generator(function() {
|
|
256
|
-
return _ts_generator(this, function(_state) {
|
|
257
|
-
// Test server with nock is always ready immediately
|
|
258
|
-
return [
|
|
259
|
-
2,
|
|
260
|
-
true
|
|
261
|
-
];
|
|
262
|
-
});
|
|
263
|
-
})();
|
|
264
|
-
}
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
key: "getLogs",
|
|
268
|
-
value: function getLogs() {
|
|
269
|
-
return this.getLogsFn();
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
key: "clearLogs",
|
|
274
|
-
value: function clearLogs() {
|
|
275
|
-
this.clearLogsFn();
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
]);
|
|
279
|
-
return MockServerHandle;
|
|
280
|
-
}();
|
|
281
|
-
export var TestDevServer = /*#__PURE__*/ function() {
|
|
282
|
-
"use strict";
|
|
283
|
-
function TestDevServer() {
|
|
284
|
-
var projectRootDir = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : '';
|
|
285
|
-
_class_call_check(this, TestDevServer);
|
|
286
|
-
_define_property(this, "projectRootDir", void 0);
|
|
287
|
-
_define_property(this, "resources", void 0);
|
|
288
|
-
_define_property(this, "schedules", void 0);
|
|
289
|
-
_define_property(this, "scheduleRuns", void 0);
|
|
290
|
-
_define_property(this, "brains", void 0);
|
|
291
|
-
_define_property(this, "brainRuns", void 0);
|
|
292
|
-
_define_property(this, "secrets", void 0);
|
|
293
|
-
_define_property(this, "port", void 0);
|
|
294
|
-
_define_property(this, "callLog", void 0);
|
|
295
|
-
_define_property(this, "nockScope", void 0);
|
|
296
|
-
_define_property(this, "logCallbacks", void 0);
|
|
297
|
-
_define_property(this, "errorCallbacks", void 0);
|
|
298
|
-
_define_property(this, "warningCallbacks", void 0);
|
|
299
|
-
this.projectRootDir = projectRootDir;
|
|
300
|
-
this.resources = new Map();
|
|
301
|
-
this.schedules = new Map();
|
|
302
|
-
this.scheduleRuns = [];
|
|
303
|
-
this.brains = new Map();
|
|
304
|
-
this.brainRuns = [];
|
|
305
|
-
this.secrets = new Map();
|
|
306
|
-
this.port = 0;
|
|
307
|
-
this.callLog = [];
|
|
308
|
-
this.nockScope = null;
|
|
309
|
-
this.logCallbacks = [];
|
|
310
|
-
this.errorCallbacks = [];
|
|
311
|
-
this.warningCallbacks = [];
|
|
312
|
-
}
|
|
313
|
-
_create_class(TestDevServer, [
|
|
314
|
-
{
|
|
315
|
-
key: "logCall",
|
|
316
|
-
value: function logCall(method, args) {
|
|
317
|
-
var call = {
|
|
318
|
-
method: method,
|
|
319
|
-
args: args,
|
|
320
|
-
timestamp: Date.now()
|
|
321
|
-
};
|
|
322
|
-
this.callLog.push(call);
|
|
323
|
-
}
|
|
324
|
-
},
|
|
325
|
-
{
|
|
326
|
-
key: "deploy",
|
|
327
|
-
value: function deploy(config) {
|
|
328
|
-
return _async_to_generator(function() {
|
|
329
|
-
return _ts_generator(this, function(_state) {
|
|
330
|
-
this.logCall('deploy', [
|
|
331
|
-
this.projectRootDir,
|
|
332
|
-
config
|
|
333
|
-
]);
|
|
334
|
-
return [
|
|
335
|
-
2
|
|
336
|
-
];
|
|
337
|
-
});
|
|
338
|
-
}).call(this);
|
|
339
|
-
}
|
|
340
|
-
},
|
|
341
|
-
{
|
|
342
|
-
key: "setup",
|
|
343
|
-
value: function setup(force) {
|
|
344
|
-
return _async_to_generator(function() {
|
|
345
|
-
return _ts_generator(this, function(_state) {
|
|
346
|
-
this.logCall('setup', [
|
|
347
|
-
force
|
|
348
|
-
]);
|
|
349
|
-
return [
|
|
350
|
-
2
|
|
351
|
-
];
|
|
352
|
-
});
|
|
353
|
-
// For tests, we don't need to set up .positronic directory
|
|
354
|
-
// Just ensure we're ready to serve
|
|
355
|
-
}).call(this);
|
|
356
|
-
}
|
|
357
|
-
},
|
|
358
|
-
{
|
|
359
|
-
key: "getLogs",
|
|
360
|
-
value: function getLogs() {
|
|
361
|
-
return this.callLog;
|
|
362
|
-
}
|
|
363
|
-
},
|
|
364
|
-
{
|
|
365
|
-
key: "start",
|
|
366
|
-
value: function start(port) {
|
|
367
|
-
return _async_to_generator(function() {
|
|
368
|
-
var _this, nockInstance;
|
|
369
|
-
return _ts_generator(this, function(_state) {
|
|
370
|
-
_this = this;
|
|
371
|
-
this.logCall('start', [
|
|
372
|
-
port
|
|
373
|
-
]);
|
|
374
|
-
this.port = port || 9000 + Math.floor(Math.random() * 1000);
|
|
375
|
-
process.env.POSITRONIC_PORT = this.port.toString();
|
|
376
|
-
// Set up nock interceptors for all endpoints
|
|
377
|
-
nockInstance = nock("http://localhost:".concat(this.port)).persist();
|
|
378
|
-
// GET /resources
|
|
379
|
-
nockInstance.get('/resources').reply(200, function() {
|
|
380
|
-
// Return the current in-memory resource list (populated by uploads)
|
|
381
|
-
var resources = Array.from(_this.resources.values());
|
|
382
|
-
return {
|
|
383
|
-
resources: resources,
|
|
384
|
-
truncated: false,
|
|
385
|
-
count: resources.length
|
|
386
|
-
};
|
|
387
|
-
});
|
|
388
|
-
// POST /resources
|
|
389
|
-
nockInstance.post('/resources').reply(201, function(uri, requestBody) {
|
|
390
|
-
// Convert request body to string using latin1 encoding to preserve binary data
|
|
391
|
-
var bodyString = Buffer.isBuffer(requestBody) ? requestBody.toString('latin1') : typeof requestBody === 'string' ? requestBody : JSON.stringify(requestBody);
|
|
392
|
-
// Check if the body string appears to be hex-encoded (all characters are hex)
|
|
393
|
-
var isHexEncoded = /^[0-9a-fA-F]+$/.test(bodyString);
|
|
394
|
-
if (isHexEncoded) {
|
|
395
|
-
// Convert hex string back to buffer and then to latin1 string
|
|
396
|
-
var hexBuffer = Buffer.from(bodyString, 'hex');
|
|
397
|
-
bodyString = hexBuffer.toString('latin1');
|
|
398
|
-
}
|
|
399
|
-
// Attempt to extract the "key" (resource path) and "type" fields from the multipart data
|
|
400
|
-
var keyMatch = bodyString.match(/name="key"\s*\r?\n\r?\n([^\r\n]+)/);
|
|
401
|
-
var typeMatch = bodyString.match(/name="type"\s*\r?\n\r?\n([^\r\n]+)/);
|
|
402
|
-
var key = keyMatch ? keyMatch[1] : undefined;
|
|
403
|
-
var type = typeMatch ? typeMatch[1] : 'text';
|
|
404
|
-
if (key) {
|
|
405
|
-
_this.resources.set(key, {
|
|
406
|
-
key: key,
|
|
407
|
-
type: type,
|
|
408
|
-
size: 0,
|
|
409
|
-
lastModified: new Date().toISOString()
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
// Log the upload so tests can verify resource sync behavior
|
|
413
|
-
_this.logCall('upload', [
|
|
414
|
-
bodyString
|
|
415
|
-
]);
|
|
416
|
-
// Success response
|
|
417
|
-
return '';
|
|
418
|
-
});
|
|
419
|
-
// DELETE /resources (bulk delete all)
|
|
420
|
-
nockInstance.delete('/resources').reply(204, function() {
|
|
421
|
-
_this.resources.clear();
|
|
422
|
-
_this.logCall('deleteAllResources', []);
|
|
423
|
-
return '';
|
|
424
|
-
});
|
|
425
|
-
// DELETE /resources/:key
|
|
426
|
-
nockInstance.delete(/^\/resources\/(.+)$/).reply(function(uri) {
|
|
427
|
-
var match = uri.match(/^\/resources\/(.+)$/);
|
|
428
|
-
if (match) {
|
|
429
|
-
var key = decodeURIComponent(match[1]);
|
|
430
|
-
if (_this.resources.has(key)) {
|
|
431
|
-
_this.resources.delete(key);
|
|
432
|
-
_this.logCall('deleteResource', [
|
|
433
|
-
key
|
|
434
|
-
]);
|
|
435
|
-
return [
|
|
436
|
-
204,
|
|
437
|
-
''
|
|
438
|
-
];
|
|
439
|
-
} else {
|
|
440
|
-
// Check if it was already deleted (idempotent delete)
|
|
441
|
-
var wasDeleted = _this.callLog.some(function(call) {
|
|
442
|
-
return call.method === 'deleteResource' && call.args[0] === key;
|
|
443
|
-
});
|
|
444
|
-
if (wasDeleted) {
|
|
445
|
-
// Return success for idempotent delete
|
|
446
|
-
return [
|
|
447
|
-
204,
|
|
448
|
-
''
|
|
449
|
-
];
|
|
450
|
-
}
|
|
451
|
-
return [
|
|
452
|
-
404,
|
|
453
|
-
JSON.stringify({
|
|
454
|
-
error: 'Resource "'.concat(key, '" not found')
|
|
455
|
-
})
|
|
456
|
-
];
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
return [
|
|
460
|
-
404,
|
|
461
|
-
'Not Found'
|
|
462
|
-
];
|
|
463
|
-
});
|
|
464
|
-
// POST /brains/runs
|
|
465
|
-
nockInstance.post('/brains/runs').reply(function(uri, requestBody) {
|
|
466
|
-
var body = typeof requestBody === 'string' ? JSON.parse(requestBody) : requestBody;
|
|
467
|
-
// Check if brain exists (for testing brain not found scenario)
|
|
468
|
-
if (body.brainName === 'non-existent-brain') {
|
|
469
|
-
_this.logCall('createBrainRun', [
|
|
470
|
-
body.brainName
|
|
471
|
-
]);
|
|
472
|
-
return [
|
|
473
|
-
404,
|
|
474
|
-
{
|
|
475
|
-
error: "Brain '".concat(body.brainName, "' not found")
|
|
476
|
-
}
|
|
477
|
-
];
|
|
478
|
-
}
|
|
479
|
-
var brainRunId = "run-".concat(Date.now());
|
|
480
|
-
// Return specific runIds for specific test scenarios
|
|
481
|
-
if (body.brainName === 'error-brain') {
|
|
482
|
-
brainRunId = 'test-error-brain';
|
|
483
|
-
} else if (body.brainName === 'restart-brain') {
|
|
484
|
-
brainRunId = 'test-restart-brain';
|
|
485
|
-
} else if (body.brainName === 'multi-status-brain') {
|
|
486
|
-
brainRunId = 'test-multi-status';
|
|
487
|
-
}
|
|
488
|
-
_this.logCall('createBrainRun', [
|
|
489
|
-
brainRunId
|
|
490
|
-
]);
|
|
491
|
-
return [
|
|
492
|
-
201,
|
|
493
|
-
{
|
|
494
|
-
brainRunId: brainRunId
|
|
495
|
-
}
|
|
496
|
-
];
|
|
497
|
-
});
|
|
498
|
-
// POST /brains/runs/rerun
|
|
499
|
-
nockInstance.post('/brains/runs/rerun').reply(function(uri, requestBody) {
|
|
500
|
-
var body = typeof requestBody === 'string' ? JSON.parse(requestBody) : requestBody;
|
|
501
|
-
// Check if brain exists
|
|
502
|
-
if (body.brainName === 'non-existent-brain') {
|
|
503
|
-
_this.logCall('rerunBrain', [
|
|
504
|
-
body.brainName,
|
|
505
|
-
body.runId,
|
|
506
|
-
body.startsAt,
|
|
507
|
-
body.stopsAfter
|
|
508
|
-
]);
|
|
509
|
-
return [
|
|
510
|
-
404,
|
|
511
|
-
{
|
|
512
|
-
error: "Brain '".concat(body.brainName, "' not found")
|
|
513
|
-
}
|
|
514
|
-
];
|
|
515
|
-
}
|
|
516
|
-
// Check if run ID exists (if provided)
|
|
517
|
-
if (body.runId === 'non-existent-run') {
|
|
518
|
-
_this.logCall('rerunBrain', [
|
|
519
|
-
body.brainName,
|
|
520
|
-
body.runId,
|
|
521
|
-
body.startsAt,
|
|
522
|
-
body.stopsAfter
|
|
523
|
-
]);
|
|
524
|
-
return [
|
|
525
|
-
404,
|
|
526
|
-
{
|
|
527
|
-
error: "Brain run '".concat(body.runId, "' not found")
|
|
528
|
-
}
|
|
529
|
-
];
|
|
530
|
-
}
|
|
531
|
-
var newBrainRunId = "rerun-".concat(Date.now());
|
|
532
|
-
_this.logCall('rerunBrain', [
|
|
533
|
-
body.brainName,
|
|
534
|
-
body.runId,
|
|
535
|
-
body.startsAt,
|
|
536
|
-
body.stopsAfter
|
|
537
|
-
]);
|
|
538
|
-
return [
|
|
539
|
-
201,
|
|
540
|
-
{
|
|
541
|
-
brainRunId: newBrainRunId
|
|
542
|
-
}
|
|
543
|
-
];
|
|
544
|
-
});
|
|
545
|
-
// GET /brains/runs/:runId/watch (SSE endpoint)
|
|
546
|
-
nockInstance.get(/^\/brains\/runs\/(.+)\/watch$/).reply(200, function(uri) {
|
|
547
|
-
var match = uri.match(/^\/brains\/runs\/(.+)\/watch$/);
|
|
548
|
-
if (match) {
|
|
549
|
-
var runId = match[1];
|
|
550
|
-
// Different scenarios based on runId
|
|
551
|
-
if (runId === 'test-error-brain') {
|
|
552
|
-
// Error scenario
|
|
553
|
-
return [
|
|
554
|
-
"data: ".concat(JSON.stringify({
|
|
555
|
-
type: 'brain:start',
|
|
556
|
-
brainTitle: 'Error Brain',
|
|
557
|
-
brainRunId: runId,
|
|
558
|
-
options: {},
|
|
559
|
-
status: 'running',
|
|
560
|
-
initialState: {}
|
|
561
|
-
}), "\n\n"),
|
|
562
|
-
"data: ".concat(JSON.stringify({
|
|
563
|
-
type: 'brain:error',
|
|
564
|
-
brainRunId: runId,
|
|
565
|
-
brainTitle: 'Error Brain',
|
|
566
|
-
options: {},
|
|
567
|
-
status: 'error',
|
|
568
|
-
error: {
|
|
569
|
-
name: 'TestError',
|
|
570
|
-
message: 'Something went wrong in the brain',
|
|
571
|
-
stack: 'Error: Something went wrong\n at test.js:1:1'
|
|
572
|
-
}
|
|
573
|
-
}), "\n\n")
|
|
574
|
-
].join('');
|
|
575
|
-
} else if (runId === 'test-restart-brain') {
|
|
576
|
-
// Restart scenario
|
|
577
|
-
return [
|
|
578
|
-
"data: ".concat(JSON.stringify({
|
|
579
|
-
type: 'brain:restart',
|
|
580
|
-
brainTitle: 'Restarted Brain',
|
|
581
|
-
brainRunId: runId,
|
|
582
|
-
options: {},
|
|
583
|
-
status: 'running',
|
|
584
|
-
initialState: {}
|
|
585
|
-
}), "\n\n"),
|
|
586
|
-
"data: ".concat(JSON.stringify({
|
|
587
|
-
type: 'step:status',
|
|
588
|
-
brainRunId: runId,
|
|
589
|
-
options: {},
|
|
590
|
-
steps: [
|
|
591
|
-
{
|
|
592
|
-
id: 'restart-step-1',
|
|
593
|
-
title: 'Restart Step',
|
|
594
|
-
status: 'pending'
|
|
595
|
-
}
|
|
596
|
-
]
|
|
597
|
-
}), "\n\n")
|
|
598
|
-
].join('');
|
|
599
|
-
} else if (runId === 'test-multi-status') {
|
|
600
|
-
// Multiple step statuses
|
|
601
|
-
return [
|
|
602
|
-
"data: ".concat(JSON.stringify({
|
|
603
|
-
type: 'brain:start',
|
|
604
|
-
brainTitle: 'Multi Status Brain',
|
|
605
|
-
brainRunId: runId,
|
|
606
|
-
options: {},
|
|
607
|
-
status: 'running',
|
|
608
|
-
initialState: {}
|
|
609
|
-
}), "\n\n"),
|
|
610
|
-
"data: ".concat(JSON.stringify({
|
|
611
|
-
type: 'step:status',
|
|
612
|
-
brainRunId: runId,
|
|
613
|
-
options: {},
|
|
614
|
-
steps: [
|
|
615
|
-
{
|
|
616
|
-
id: 'step-1',
|
|
617
|
-
title: 'Complete Step',
|
|
618
|
-
status: 'complete'
|
|
619
|
-
},
|
|
620
|
-
{
|
|
621
|
-
id: 'step-2',
|
|
622
|
-
title: 'Error Step',
|
|
623
|
-
status: 'error'
|
|
624
|
-
},
|
|
625
|
-
{
|
|
626
|
-
id: 'step-3',
|
|
627
|
-
title: 'Running Step',
|
|
628
|
-
status: 'running'
|
|
629
|
-
},
|
|
630
|
-
{
|
|
631
|
-
id: 'step-4',
|
|
632
|
-
title: 'Pending Step',
|
|
633
|
-
status: 'pending'
|
|
634
|
-
}
|
|
635
|
-
]
|
|
636
|
-
}), "\n\n")
|
|
637
|
-
].join('');
|
|
638
|
-
} else if (runId === 'test-complete-flow') {
|
|
639
|
-
// Full flow from start to complete
|
|
640
|
-
return [
|
|
641
|
-
"data: ".concat(JSON.stringify({
|
|
642
|
-
type: 'brain:start',
|
|
643
|
-
brainTitle: 'Complete Flow Brain',
|
|
644
|
-
brainRunId: runId,
|
|
645
|
-
options: {},
|
|
646
|
-
status: 'running',
|
|
647
|
-
initialState: {}
|
|
648
|
-
}), "\n\n"),
|
|
649
|
-
"data: ".concat(JSON.stringify({
|
|
650
|
-
type: 'step:status',
|
|
651
|
-
brainRunId: runId,
|
|
652
|
-
options: {},
|
|
653
|
-
steps: [
|
|
654
|
-
{
|
|
655
|
-
id: 'step-1',
|
|
656
|
-
title: 'First Step',
|
|
657
|
-
status: 'complete'
|
|
658
|
-
},
|
|
659
|
-
{
|
|
660
|
-
id: 'step-2',
|
|
661
|
-
title: 'Second Step',
|
|
662
|
-
status: 'complete'
|
|
663
|
-
}
|
|
664
|
-
]
|
|
665
|
-
}), "\n\n"),
|
|
666
|
-
"data: ".concat(JSON.stringify({
|
|
667
|
-
type: 'brain:complete',
|
|
668
|
-
brainRunId: runId,
|
|
669
|
-
brainTitle: 'Complete Flow Brain',
|
|
670
|
-
options: {},
|
|
671
|
-
status: 'complete'
|
|
672
|
-
}), "\n\n")
|
|
673
|
-
].join('');
|
|
674
|
-
} else if (runId === 'test-brain-error') {
|
|
675
|
-
// Brain error scenario
|
|
676
|
-
return [
|
|
677
|
-
"data: ".concat(JSON.stringify({
|
|
678
|
-
type: 'brain:start',
|
|
679
|
-
brainTitle: 'Error Brain',
|
|
680
|
-
brainRunId: runId,
|
|
681
|
-
options: {},
|
|
682
|
-
status: 'running',
|
|
683
|
-
initialState: {}
|
|
684
|
-
}), "\n\n"),
|
|
685
|
-
"data: ".concat(JSON.stringify({
|
|
686
|
-
type: 'brain:error',
|
|
687
|
-
brainRunId: runId,
|
|
688
|
-
brainTitle: 'Error Brain',
|
|
689
|
-
error: {
|
|
690
|
-
name: 'BrainExecutionError',
|
|
691
|
-
message: 'Something went wrong during brain execution',
|
|
692
|
-
stack: 'Error: Something went wrong during brain execution\n at BrainRunner.run'
|
|
693
|
-
}
|
|
694
|
-
}), "\n\n")
|
|
695
|
-
].join('');
|
|
696
|
-
} else if (runId === 'test-malformed-event') {
|
|
697
|
-
// Send malformed JSON
|
|
698
|
-
return 'data: {invalid json here}\n\n';
|
|
699
|
-
} else if (runId === 'test-no-steps') {
|
|
700
|
-
// Brain with no steps initially
|
|
701
|
-
return [
|
|
702
|
-
"data: ".concat(JSON.stringify({
|
|
703
|
-
type: 'brain:start',
|
|
704
|
-
brainTitle: 'No Steps Brain',
|
|
705
|
-
brainRunId: runId,
|
|
706
|
-
options: {},
|
|
707
|
-
status: 'running',
|
|
708
|
-
initialState: {}
|
|
709
|
-
}), "\n\n"),
|
|
710
|
-
"data: ".concat(JSON.stringify({
|
|
711
|
-
type: 'step:status',
|
|
712
|
-
brainRunId: runId,
|
|
713
|
-
options: {},
|
|
714
|
-
steps: []
|
|
715
|
-
}), "\n\n")
|
|
716
|
-
].join('');
|
|
717
|
-
} else if (runId === 'test-connection-error') {
|
|
718
|
-
// Simulate connection error by returning error
|
|
719
|
-
throw new Error('ECONNREFUSED');
|
|
720
|
-
} else {
|
|
721
|
-
// Default scenario
|
|
722
|
-
var mockEvents = [
|
|
723
|
-
"data: ".concat(JSON.stringify({
|
|
724
|
-
type: 'brain:start',
|
|
725
|
-
brainTitle: 'test-brain',
|
|
726
|
-
brainRunId: runId,
|
|
727
|
-
options: {},
|
|
728
|
-
status: 'running',
|
|
729
|
-
initialState: {}
|
|
730
|
-
}), "\n\n"),
|
|
731
|
-
"data: ".concat(JSON.stringify({
|
|
732
|
-
type: 'step:status',
|
|
733
|
-
brainRunId: runId,
|
|
734
|
-
options: {},
|
|
735
|
-
steps: [
|
|
736
|
-
{
|
|
737
|
-
id: 'step-1',
|
|
738
|
-
title: 'Test Step 1',
|
|
739
|
-
status: 'running'
|
|
740
|
-
}
|
|
741
|
-
]
|
|
742
|
-
}), "\n\n"),
|
|
743
|
-
"data: ".concat(JSON.stringify({
|
|
744
|
-
type: 'brain:complete',
|
|
745
|
-
brainRunId: runId,
|
|
746
|
-
brainTitle: 'test-brain',
|
|
747
|
-
options: {},
|
|
748
|
-
status: 'complete'
|
|
749
|
-
}), "\n\n")
|
|
750
|
-
];
|
|
751
|
-
return mockEvents.join('');
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
return 'data: {"type":"ERROR","error":{"message":"Invalid run ID"}}\n\n';
|
|
755
|
-
}, {
|
|
756
|
-
'Content-Type': 'text/event-stream',
|
|
757
|
-
'Cache-Control': 'no-cache',
|
|
758
|
-
Connection: 'keep-alive'
|
|
759
|
-
});
|
|
760
|
-
// GET /brains
|
|
761
|
-
nockInstance.get('/brains').reply(200, function() {
|
|
762
|
-
var brains = Array.from(_this.brains.values());
|
|
763
|
-
_this.logCall('getBrains', []);
|
|
764
|
-
return {
|
|
765
|
-
brains: brains,
|
|
766
|
-
count: brains.length
|
|
767
|
-
};
|
|
768
|
-
});
|
|
769
|
-
// GET /brains/schedules
|
|
770
|
-
nockInstance.get('/brains/schedules').reply(200, function() {
|
|
771
|
-
var schedules = Array.from(_this.schedules.values());
|
|
772
|
-
_this.logCall('getSchedules', []);
|
|
773
|
-
return {
|
|
774
|
-
schedules: schedules,
|
|
775
|
-
count: schedules.length
|
|
776
|
-
};
|
|
777
|
-
});
|
|
778
|
-
// POST /brains/schedules
|
|
779
|
-
nockInstance.post('/brains/schedules').reply(201, function(uri, requestBody) {
|
|
780
|
-
var body = typeof requestBody === 'string' ? JSON.parse(requestBody) : requestBody;
|
|
781
|
-
var scheduleId = "schedule-".concat(Date.now());
|
|
782
|
-
var schedule = {
|
|
783
|
-
id: scheduleId,
|
|
784
|
-
brainName: body.brainName,
|
|
785
|
-
cronExpression: body.cronExpression,
|
|
786
|
-
enabled: true,
|
|
787
|
-
createdAt: Date.now(),
|
|
788
|
-
nextRunAt: Date.now() + 3600000
|
|
789
|
-
};
|
|
790
|
-
_this.schedules.set(scheduleId, schedule);
|
|
791
|
-
_this.logCall('createSchedule', [
|
|
792
|
-
body
|
|
793
|
-
]);
|
|
794
|
-
return schedule;
|
|
795
|
-
});
|
|
796
|
-
// GET /brains/schedules/runs
|
|
797
|
-
nockInstance.get('/brains/schedules/runs').query(true).reply(function(uri) {
|
|
798
|
-
var url = new URL(uri, 'http://example.com');
|
|
799
|
-
var scheduleId = url.searchParams.get('scheduleId');
|
|
800
|
-
var limit = parseInt(url.searchParams.get('limit') || '100', 10);
|
|
801
|
-
_this.logCall('getScheduleRuns', [
|
|
802
|
-
uri
|
|
803
|
-
]);
|
|
804
|
-
var runs = _this.scheduleRuns;
|
|
805
|
-
// Filter by scheduleId if provided
|
|
806
|
-
if (scheduleId) {
|
|
807
|
-
runs = runs.filter(function(run) {
|
|
808
|
-
return run.scheduleId === scheduleId;
|
|
809
|
-
});
|
|
810
|
-
}
|
|
811
|
-
// Sort by ranAt descending (newest first)
|
|
812
|
-
runs = runs.sort(function(a, b) {
|
|
813
|
-
return b.ranAt - a.ranAt;
|
|
814
|
-
});
|
|
815
|
-
// Apply limit
|
|
816
|
-
runs = runs.slice(0, limit);
|
|
817
|
-
return [
|
|
818
|
-
200,
|
|
819
|
-
{
|
|
820
|
-
runs: runs,
|
|
821
|
-
count: runs.length
|
|
822
|
-
}
|
|
823
|
-
];
|
|
824
|
-
});
|
|
825
|
-
// DELETE /brains/schedules/:id
|
|
826
|
-
nockInstance.delete(/^\/brains\/schedules\/(.+)$/).reply(function(uri) {
|
|
827
|
-
var match = uri.match(/^\/brains\/schedules\/(.+)$/);
|
|
828
|
-
if (match) {
|
|
829
|
-
var scheduleId = decodeURIComponent(match[1]);
|
|
830
|
-
if (_this.schedules.has(scheduleId)) {
|
|
831
|
-
_this.schedules.delete(scheduleId);
|
|
832
|
-
_this.logCall('deleteSchedule', [
|
|
833
|
-
scheduleId
|
|
834
|
-
]);
|
|
835
|
-
return [
|
|
836
|
-
204,
|
|
837
|
-
''
|
|
838
|
-
];
|
|
839
|
-
} else {
|
|
840
|
-
return [
|
|
841
|
-
404,
|
|
842
|
-
JSON.stringify({
|
|
843
|
-
error: 'Schedule "'.concat(scheduleId, '" not found')
|
|
844
|
-
})
|
|
845
|
-
];
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
return [
|
|
849
|
-
404,
|
|
850
|
-
'Not Found'
|
|
851
|
-
];
|
|
852
|
-
});
|
|
853
|
-
// GET /brains/:brainName/history
|
|
854
|
-
nockInstance.get(/^\/brains\/(.+)\/history$/).query(true).reply(function(uri) {
|
|
855
|
-
var parts = uri.split('/');
|
|
856
|
-
var brainName = decodeURIComponent(parts[2]);
|
|
857
|
-
var url = new URL(uri, 'http://example.com');
|
|
858
|
-
var limit = parseInt(url.searchParams.get('limit') || '10', 10);
|
|
859
|
-
_this.logCall('getBrainHistory', [
|
|
860
|
-
brainName,
|
|
861
|
-
limit
|
|
862
|
-
]);
|
|
863
|
-
// Filter runs by brain title
|
|
864
|
-
var runs = _this.brainRuns.filter(function(run) {
|
|
865
|
-
return run.brainTitle.toLowerCase() === brainName.toLowerCase().replace(/-/g, ' ');
|
|
866
|
-
}).sort(function(a, b) {
|
|
867
|
-
return b.createdAt - a.createdAt;
|
|
868
|
-
}).slice(0, limit);
|
|
869
|
-
return [
|
|
870
|
-
200,
|
|
871
|
-
{
|
|
872
|
-
runs: runs
|
|
873
|
-
}
|
|
874
|
-
];
|
|
875
|
-
});
|
|
876
|
-
// GET /brains/:brainName/active-runs
|
|
877
|
-
nockInstance.get(/^\/brains\/(.+)\/active-runs$/).reply(function(uri) {
|
|
878
|
-
var parts = uri.split('/');
|
|
879
|
-
var brainName = decodeURIComponent(parts[2]);
|
|
880
|
-
_this.logCall('getBrainActiveRuns', [
|
|
881
|
-
brainName
|
|
882
|
-
]);
|
|
883
|
-
// Filter brain runs by brain title and status RUNNING
|
|
884
|
-
var activeRuns = _this.brainRuns.filter(function(run) {
|
|
885
|
-
return run.brainTitle.toLowerCase() === brainName.toLowerCase().replace(/-/g, ' ') && run.status === 'RUNNING';
|
|
886
|
-
}).sort(function(a, b) {
|
|
887
|
-
return b.createdAt - a.createdAt;
|
|
888
|
-
});
|
|
889
|
-
return [
|
|
890
|
-
200,
|
|
891
|
-
{
|
|
892
|
-
runs: activeRuns
|
|
893
|
-
}
|
|
894
|
-
];
|
|
895
|
-
});
|
|
896
|
-
// GET /brains/:brainName
|
|
897
|
-
nockInstance.get(/^\/brains\/(.+)$/).reply(function(uri) {
|
|
898
|
-
var brainName = decodeURIComponent(uri.split('/')[2]);
|
|
899
|
-
var brain = _this.brains.get(brainName);
|
|
900
|
-
_this.logCall('getBrain', [
|
|
901
|
-
brainName
|
|
902
|
-
]);
|
|
903
|
-
if (!brain) {
|
|
904
|
-
return [
|
|
905
|
-
404,
|
|
906
|
-
{
|
|
907
|
-
error: "Brain '".concat(brainName, "' not found")
|
|
908
|
-
}
|
|
909
|
-
];
|
|
910
|
-
}
|
|
911
|
-
return [
|
|
912
|
-
200,
|
|
913
|
-
{
|
|
914
|
-
name: brain.name,
|
|
915
|
-
title: brain.title,
|
|
916
|
-
description: brain.description || "".concat(brain.title, " brain"),
|
|
917
|
-
steps: brain.steps || []
|
|
918
|
-
}
|
|
919
|
-
];
|
|
920
|
-
});
|
|
921
|
-
// Secret Management Endpoints
|
|
922
|
-
// POST /secrets
|
|
923
|
-
nockInstance.post('/secrets').reply(201, function(uri, requestBody) {
|
|
924
|
-
var body = typeof requestBody === 'string' ? JSON.parse(requestBody) : requestBody;
|
|
925
|
-
var now = new Date().toISOString();
|
|
926
|
-
var secret = {
|
|
927
|
-
name: body.name,
|
|
928
|
-
value: body.value,
|
|
929
|
-
createdAt: now,
|
|
930
|
-
updatedAt: now
|
|
931
|
-
};
|
|
932
|
-
_this.secrets.set(body.name, secret);
|
|
933
|
-
_this.logCall('createSecret', [
|
|
934
|
-
body.name
|
|
935
|
-
]);
|
|
936
|
-
// Return without the value for security
|
|
937
|
-
return {
|
|
938
|
-
name: secret.name,
|
|
939
|
-
createdAt: secret.createdAt,
|
|
940
|
-
updatedAt: secret.updatedAt
|
|
941
|
-
};
|
|
942
|
-
});
|
|
943
|
-
// GET /secrets
|
|
944
|
-
nockInstance.get('/secrets').reply(200, function() {
|
|
945
|
-
_this.logCall('listSecrets', []);
|
|
946
|
-
// Return secrets without values
|
|
947
|
-
var secrets = Array.from(_this.secrets.values()).map(function(secret) {
|
|
948
|
-
return {
|
|
949
|
-
name: secret.name,
|
|
950
|
-
createdAt: secret.createdAt,
|
|
951
|
-
updatedAt: secret.updatedAt
|
|
952
|
-
};
|
|
953
|
-
});
|
|
954
|
-
return {
|
|
955
|
-
secrets: secrets,
|
|
956
|
-
count: secrets.length
|
|
957
|
-
};
|
|
958
|
-
});
|
|
959
|
-
// DELETE /secrets/:name
|
|
960
|
-
nockInstance.delete(/^\/secrets\/(.+)$/).reply(function(uri) {
|
|
961
|
-
var match = uri.match(/^\/secrets\/(.+)$/);
|
|
962
|
-
if (match) {
|
|
963
|
-
var secretName = decodeURIComponent(match[1]);
|
|
964
|
-
if (_this.secrets.has(secretName)) {
|
|
965
|
-
_this.secrets.delete(secretName);
|
|
966
|
-
_this.logCall('deleteSecret', [
|
|
967
|
-
secretName
|
|
968
|
-
]);
|
|
969
|
-
return [
|
|
970
|
-
204,
|
|
971
|
-
''
|
|
972
|
-
];
|
|
973
|
-
} else {
|
|
974
|
-
return [
|
|
975
|
-
404,
|
|
976
|
-
{
|
|
977
|
-
error: 'Secret "'.concat(secretName, '" not found')
|
|
978
|
-
}
|
|
979
|
-
];
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
return [
|
|
983
|
-
404,
|
|
984
|
-
'Not Found'
|
|
985
|
-
];
|
|
986
|
-
});
|
|
987
|
-
// GET /secrets/:name/exists
|
|
988
|
-
nockInstance.get(/^\/secrets\/(.+)\/exists$/).reply(function(uri) {
|
|
989
|
-
var match = uri.match(/^\/secrets\/(.+)\/exists$/);
|
|
990
|
-
if (match) {
|
|
991
|
-
var secretName = decodeURIComponent(match[1]);
|
|
992
|
-
var exists = _this.secrets.has(secretName);
|
|
993
|
-
_this.logCall('secretExists', [
|
|
994
|
-
secretName
|
|
995
|
-
]);
|
|
996
|
-
return [
|
|
997
|
-
200,
|
|
998
|
-
{
|
|
999
|
-
exists: exists
|
|
1000
|
-
}
|
|
1001
|
-
];
|
|
1002
|
-
}
|
|
1003
|
-
return [
|
|
1004
|
-
404,
|
|
1005
|
-
'Not Found'
|
|
1006
|
-
];
|
|
1007
|
-
});
|
|
1008
|
-
// POST /secrets/bulk
|
|
1009
|
-
nockInstance.post('/secrets/bulk').reply(201, function(uri, requestBody) {
|
|
1010
|
-
var body = typeof requestBody === 'string' ? JSON.parse(requestBody) : requestBody;
|
|
1011
|
-
var created = 0;
|
|
1012
|
-
var updated = 0;
|
|
1013
|
-
var now = new Date().toISOString();
|
|
1014
|
-
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1015
|
-
try {
|
|
1016
|
-
for(var _iterator = body.secrets[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1017
|
-
var secretData = _step.value;
|
|
1018
|
-
var existing = _this.secrets.has(secretData.name);
|
|
1019
|
-
var secret = {
|
|
1020
|
-
name: secretData.name,
|
|
1021
|
-
value: secretData.value,
|
|
1022
|
-
createdAt: existing ? _this.secrets.get(secretData.name).createdAt : now,
|
|
1023
|
-
updatedAt: now
|
|
1024
|
-
};
|
|
1025
|
-
_this.secrets.set(secretData.name, secret);
|
|
1026
|
-
if (existing) {
|
|
1027
|
-
updated++;
|
|
1028
|
-
} else {
|
|
1029
|
-
created++;
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
} catch (err) {
|
|
1033
|
-
_didIteratorError = true;
|
|
1034
|
-
_iteratorError = err;
|
|
1035
|
-
} finally{
|
|
1036
|
-
try {
|
|
1037
|
-
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
1038
|
-
_iterator.return();
|
|
1039
|
-
}
|
|
1040
|
-
} finally{
|
|
1041
|
-
if (_didIteratorError) {
|
|
1042
|
-
throw _iteratorError;
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
_this.logCall('bulkCreateSecrets', [
|
|
1047
|
-
body.secrets.length
|
|
1048
|
-
]);
|
|
1049
|
-
return {
|
|
1050
|
-
created: created,
|
|
1051
|
-
updated: updated
|
|
1052
|
-
};
|
|
1053
|
-
});
|
|
1054
|
-
this.nockScope = nockInstance;
|
|
1055
|
-
// Simulate some initial log output after server starts
|
|
1056
|
-
setTimeout(function() {
|
|
1057
|
-
_this.logCallbacks.forEach(function(cb) {
|
|
1058
|
-
return cb('✅ Synced 3 resources (0 up to date, 0 deleted)\n');
|
|
1059
|
-
});
|
|
1060
|
-
_this.logCallbacks.forEach(function(cb) {
|
|
1061
|
-
return cb('🚀 Server started on port ' + _this.port + '\n');
|
|
1062
|
-
});
|
|
1063
|
-
}, 100);
|
|
1064
|
-
return [
|
|
1065
|
-
2,
|
|
1066
|
-
new MockServerHandle(function() {
|
|
1067
|
-
_this.stop();
|
|
1068
|
-
}, function() {
|
|
1069
|
-
return _this.callLog;
|
|
1070
|
-
}, function() {
|
|
1071
|
-
_this.callLog = [];
|
|
1072
|
-
}, this.port)
|
|
1073
|
-
];
|
|
1074
|
-
});
|
|
1075
|
-
}).call(this);
|
|
1076
|
-
}
|
|
1077
|
-
},
|
|
1078
|
-
{
|
|
1079
|
-
key: "watch",
|
|
1080
|
-
value: // Add watch method to track calls
|
|
1081
|
-
function watch(event) {
|
|
1082
|
-
return _async_to_generator(function() {
|
|
1083
|
-
return _ts_generator(this, function(_state) {
|
|
1084
|
-
this.logCall('watch', [
|
|
1085
|
-
this.projectRootDir,
|
|
1086
|
-
event
|
|
1087
|
-
]);
|
|
1088
|
-
return [
|
|
1089
|
-
2
|
|
1090
|
-
];
|
|
1091
|
-
});
|
|
1092
|
-
}).call(this);
|
|
1093
|
-
}
|
|
1094
|
-
},
|
|
1095
|
-
{
|
|
1096
|
-
// Helper methods for tests to manipulate the server state
|
|
1097
|
-
key: "addResource",
|
|
1098
|
-
value: function addResource(resource) {
|
|
1099
|
-
this.resources.set(resource.key, resource);
|
|
1100
|
-
}
|
|
1101
|
-
},
|
|
1102
|
-
{
|
|
1103
|
-
key: "clearResources",
|
|
1104
|
-
value: function clearResources() {
|
|
1105
|
-
this.resources.clear();
|
|
1106
|
-
}
|
|
1107
|
-
},
|
|
1108
|
-
{
|
|
1109
|
-
key: "getResources",
|
|
1110
|
-
value: function getResources() {
|
|
1111
|
-
return Array.from(this.resources.values());
|
|
1112
|
-
}
|
|
1113
|
-
},
|
|
1114
|
-
{
|
|
1115
|
-
// Schedule helper methods
|
|
1116
|
-
key: "addSchedule",
|
|
1117
|
-
value: function addSchedule(schedule) {
|
|
1118
|
-
this.schedules.set(schedule.id, schedule);
|
|
1119
|
-
}
|
|
1120
|
-
},
|
|
1121
|
-
{
|
|
1122
|
-
key: "clearSchedules",
|
|
1123
|
-
value: function clearSchedules() {
|
|
1124
|
-
this.schedules.clear();
|
|
1125
|
-
}
|
|
1126
|
-
},
|
|
1127
|
-
{
|
|
1128
|
-
key: "addScheduleRun",
|
|
1129
|
-
value: function addScheduleRun(run) {
|
|
1130
|
-
this.scheduleRuns.push(run);
|
|
1131
|
-
}
|
|
1132
|
-
},
|
|
1133
|
-
{
|
|
1134
|
-
key: "clearScheduleRuns",
|
|
1135
|
-
value: function clearScheduleRuns() {
|
|
1136
|
-
this.scheduleRuns = [];
|
|
1137
|
-
}
|
|
1138
|
-
},
|
|
1139
|
-
{
|
|
1140
|
-
key: "getSchedules",
|
|
1141
|
-
value: function getSchedules() {
|
|
1142
|
-
return Array.from(this.schedules.values());
|
|
1143
|
-
}
|
|
1144
|
-
},
|
|
1145
|
-
{
|
|
1146
|
-
// Secret helper methods
|
|
1147
|
-
key: "addSecret",
|
|
1148
|
-
value: function addSecret(name, value) {
|
|
1149
|
-
var now = new Date().toISOString();
|
|
1150
|
-
this.secrets.set(name, {
|
|
1151
|
-
name: name,
|
|
1152
|
-
value: value,
|
|
1153
|
-
createdAt: now,
|
|
1154
|
-
updatedAt: now
|
|
1155
|
-
});
|
|
1156
|
-
}
|
|
1157
|
-
},
|
|
1158
|
-
{
|
|
1159
|
-
key: "clearSecrets",
|
|
1160
|
-
value: function clearSecrets() {
|
|
1161
|
-
this.secrets.clear();
|
|
1162
|
-
}
|
|
1163
|
-
},
|
|
1164
|
-
{
|
|
1165
|
-
key: "getSecrets",
|
|
1166
|
-
value: function getSecrets() {
|
|
1167
|
-
return Array.from(this.secrets.values());
|
|
1168
|
-
}
|
|
1169
|
-
},
|
|
1170
|
-
{
|
|
1171
|
-
key: "getSecret",
|
|
1172
|
-
value: function getSecret(name) {
|
|
1173
|
-
return this.secrets.get(name);
|
|
1174
|
-
}
|
|
1175
|
-
},
|
|
1176
|
-
{
|
|
1177
|
-
// Brain helper methods
|
|
1178
|
-
key: "addBrain",
|
|
1179
|
-
value: function addBrain(brain) {
|
|
1180
|
-
this.brains.set(brain.name, brain);
|
|
1181
|
-
}
|
|
1182
|
-
},
|
|
1183
|
-
{
|
|
1184
|
-
key: "addBrainRun",
|
|
1185
|
-
value: function addBrainRun(run) {
|
|
1186
|
-
this.brainRuns.push(run);
|
|
1187
|
-
}
|
|
1188
|
-
},
|
|
1189
|
-
{
|
|
1190
|
-
key: "clearBrainRuns",
|
|
1191
|
-
value: function clearBrainRuns() {
|
|
1192
|
-
this.brainRuns = [];
|
|
1193
|
-
}
|
|
1194
|
-
},
|
|
1195
|
-
{
|
|
1196
|
-
key: "clearBrains",
|
|
1197
|
-
value: function clearBrains() {
|
|
1198
|
-
this.brains.clear();
|
|
1199
|
-
}
|
|
1200
|
-
},
|
|
1201
|
-
{
|
|
1202
|
-
key: "getBrains",
|
|
1203
|
-
value: function getBrains() {
|
|
1204
|
-
return Array.from(this.brains.values());
|
|
1205
|
-
}
|
|
1206
|
-
},
|
|
1207
|
-
{
|
|
1208
|
-
key: "stop",
|
|
1209
|
-
value: function stop() {
|
|
1210
|
-
if (this.nockScope) {
|
|
1211
|
-
// Clean up all nock interceptors
|
|
1212
|
-
nock.cleanAll();
|
|
1213
|
-
this.nockScope = null;
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
},
|
|
1217
|
-
{
|
|
1218
|
-
key: "onLog",
|
|
1219
|
-
value: function onLog(callback) {
|
|
1220
|
-
this.logCall('onLog', [
|
|
1221
|
-
'callback registered'
|
|
1222
|
-
]);
|
|
1223
|
-
this.logCallbacks.push(callback);
|
|
1224
|
-
}
|
|
1225
|
-
},
|
|
1226
|
-
{
|
|
1227
|
-
key: "onError",
|
|
1228
|
-
value: function onError(callback) {
|
|
1229
|
-
this.logCall('onError', [
|
|
1230
|
-
'callback registered'
|
|
1231
|
-
]);
|
|
1232
|
-
this.errorCallbacks.push(callback);
|
|
1233
|
-
}
|
|
1234
|
-
},
|
|
1235
|
-
{
|
|
1236
|
-
key: "onWarning",
|
|
1237
|
-
value: function onWarning(callback) {
|
|
1238
|
-
this.logCall('onWarning', [
|
|
1239
|
-
'callback registered'
|
|
1240
|
-
]);
|
|
1241
|
-
this.warningCallbacks.push(callback);
|
|
1242
|
-
}
|
|
1243
|
-
},
|
|
1244
|
-
{
|
|
1245
|
-
key: "listSecrets",
|
|
1246
|
-
value: function listSecrets() {
|
|
1247
|
-
return _async_to_generator(function() {
|
|
1248
|
-
return _ts_generator(this, function(_state) {
|
|
1249
|
-
this.logCall('listSecrets', []);
|
|
1250
|
-
return [
|
|
1251
|
-
2,
|
|
1252
|
-
Array.from(this.secrets.values()).map(function(secret) {
|
|
1253
|
-
return {
|
|
1254
|
-
name: secret.name,
|
|
1255
|
-
createdAt: new Date(secret.createdAt),
|
|
1256
|
-
updatedAt: new Date(secret.updatedAt)
|
|
1257
|
-
};
|
|
1258
|
-
})
|
|
1259
|
-
];
|
|
1260
|
-
});
|
|
1261
|
-
}).call(this);
|
|
1262
|
-
}
|
|
1263
|
-
},
|
|
1264
|
-
{
|
|
1265
|
-
key: "setSecret",
|
|
1266
|
-
value: function setSecret(name, value) {
|
|
1267
|
-
return _async_to_generator(function() {
|
|
1268
|
-
var now, existing;
|
|
1269
|
-
return _ts_generator(this, function(_state) {
|
|
1270
|
-
this.logCall('setSecret', [
|
|
1271
|
-
name,
|
|
1272
|
-
value
|
|
1273
|
-
]);
|
|
1274
|
-
now = new Date().toISOString();
|
|
1275
|
-
existing = this.secrets.get(name);
|
|
1276
|
-
this.secrets.set(name, {
|
|
1277
|
-
name: name,
|
|
1278
|
-
value: value,
|
|
1279
|
-
createdAt: (existing === null || existing === void 0 ? void 0 : existing.createdAt) || now,
|
|
1280
|
-
updatedAt: now
|
|
1281
|
-
});
|
|
1282
|
-
return [
|
|
1283
|
-
2
|
|
1284
|
-
];
|
|
1285
|
-
});
|
|
1286
|
-
}).call(this);
|
|
1287
|
-
}
|
|
1288
|
-
},
|
|
1289
|
-
{
|
|
1290
|
-
key: "deleteSecret",
|
|
1291
|
-
value: function deleteSecret(name) {
|
|
1292
|
-
return _async_to_generator(function() {
|
|
1293
|
-
return _ts_generator(this, function(_state) {
|
|
1294
|
-
this.logCall('deleteSecret', [
|
|
1295
|
-
name
|
|
1296
|
-
]);
|
|
1297
|
-
if (this.secrets.has(name)) {
|
|
1298
|
-
this.secrets.delete(name);
|
|
1299
|
-
return [
|
|
1300
|
-
2,
|
|
1301
|
-
true
|
|
1302
|
-
];
|
|
1303
|
-
}
|
|
1304
|
-
return [
|
|
1305
|
-
2,
|
|
1306
|
-
false
|
|
1307
|
-
];
|
|
1308
|
-
});
|
|
1309
|
-
}).call(this);
|
|
1310
|
-
}
|
|
1311
|
-
},
|
|
1312
|
-
{
|
|
1313
|
-
key: "bulkSecrets",
|
|
1314
|
-
value: function bulkSecrets(filePath) {
|
|
1315
|
-
return _async_to_generator(function() {
|
|
1316
|
-
var envContent, secrets, secretsArray, now, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step_value, name, value, existing;
|
|
1317
|
-
return _ts_generator(this, function(_state) {
|
|
1318
|
-
this.logCall('bulkSecrets', [
|
|
1319
|
-
filePath
|
|
1320
|
-
]);
|
|
1321
|
-
try {
|
|
1322
|
-
// Read and parse the .env file
|
|
1323
|
-
if (!fs.existsSync(filePath)) {
|
|
1324
|
-
throw new Error("File not found: ".concat(filePath));
|
|
1325
|
-
}
|
|
1326
|
-
envContent = fs.readFileSync(filePath, 'utf8');
|
|
1327
|
-
secrets = parse(envContent);
|
|
1328
|
-
secretsArray = Object.entries(secrets);
|
|
1329
|
-
if (secretsArray.length === 0) {
|
|
1330
|
-
throw new Error('No secrets found in the .env file');
|
|
1331
|
-
}
|
|
1332
|
-
// Simulate the bulk upload - just store them
|
|
1333
|
-
now = new Date().toISOString();
|
|
1334
|
-
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1335
|
-
try {
|
|
1336
|
-
for(_iterator = secretsArray[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1337
|
-
_step_value = _sliced_to_array(_step.value, 2), name = _step_value[0], value = _step_value[1];
|
|
1338
|
-
existing = this.secrets.has(name);
|
|
1339
|
-
this.secrets.set(name, {
|
|
1340
|
-
name: name,
|
|
1341
|
-
value: value,
|
|
1342
|
-
createdAt: existing ? this.secrets.get(name).createdAt : now,
|
|
1343
|
-
updatedAt: now
|
|
1344
|
-
});
|
|
1345
|
-
}
|
|
1346
|
-
} catch (err) {
|
|
1347
|
-
_didIteratorError = true;
|
|
1348
|
-
_iteratorError = err;
|
|
1349
|
-
} finally{
|
|
1350
|
-
try {
|
|
1351
|
-
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
1352
|
-
_iterator.return();
|
|
1353
|
-
}
|
|
1354
|
-
} finally{
|
|
1355
|
-
if (_didIteratorError) {
|
|
1356
|
-
throw _iteratorError;
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
// Simulate console output
|
|
1361
|
-
this.logCallbacks.forEach(function(cb) {
|
|
1362
|
-
return cb("✨ Successfully uploaded ".concat(secretsArray.length, " secrets\n"));
|
|
1363
|
-
});
|
|
1364
|
-
} catch (error) {
|
|
1365
|
-
throw error;
|
|
1366
|
-
}
|
|
1367
|
-
return [
|
|
1368
|
-
2
|
|
1369
|
-
];
|
|
1370
|
-
});
|
|
1371
|
-
}).call(this);
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
]);
|
|
1375
|
-
return TestDevServer;
|
|
1376
|
-
}();
|