@positronic/cloudflare 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/api.js +1270 -0
- package/dist/src/brain-runner-do.js +654 -0
- package/dist/src/dev-server.js +1357 -0
- package/{src/index.ts → dist/src/index.js} +1 -6
- package/dist/src/manifest.js +278 -0
- package/dist/src/monitor-do.js +408 -0
- package/{src/node-index.ts → dist/src/node-index.js} +3 -7
- package/dist/src/r2-loader.js +207 -0
- package/dist/src/schedule-do.js +705 -0
- package/dist/src/sqlite-adapter.js +69 -0
- package/dist/types/api.d.ts +21 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/brain-runner-do.d.ts +25 -0
- package/dist/types/brain-runner-do.d.ts.map +1 -0
- package/dist/types/dev-server.d.ts +45 -0
- package/dist/types/dev-server.d.ts.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/manifest.d.ts +11 -0
- package/dist/types/manifest.d.ts.map +1 -0
- package/dist/types/monitor-do.d.ts +16 -0
- package/dist/types/monitor-do.d.ts.map +1 -0
- package/dist/types/node-index.d.ts +10 -0
- package/dist/types/node-index.d.ts.map +1 -0
- package/dist/types/r2-loader.d.ts +10 -0
- package/dist/types/r2-loader.d.ts.map +1 -0
- package/dist/types/schedule-do.d.ts +47 -0
- package/dist/types/schedule-do.d.ts.map +1 -0
- package/dist/types/sqlite-adapter.d.ts +10 -0
- package/dist/types/sqlite-adapter.d.ts.map +1 -0
- package/package.json +5 -1
- package/src/api.ts +0 -579
- package/src/brain-runner-do.ts +0 -309
- package/src/dev-server.ts +0 -776
- package/src/manifest.ts +0 -69
- package/src/monitor-do.ts +0 -268
- package/src/r2-loader.ts +0 -27
- package/src/schedule-do.ts +0 -377
- package/src/sqlite-adapter.ts +0 -50
- package/test-project/package-lock.json +0 -3010
- package/test-project/package.json +0 -21
- package/test-project/src/index.ts +0 -70
- package/test-project/src/runner.ts +0 -24
- package/test-project/tests/api.test.ts +0 -1005
- package/test-project/tests/r2loader.test.ts +0 -73
- package/test-project/tests/resources-api.test.ts +0 -671
- package/test-project/tests/spec.test.ts +0 -135
- package/test-project/tests/tsconfig.json +0 -7
- package/test-project/tsconfig.json +0 -20
- package/test-project/vitest.config.ts +0 -12
- package/test-project/wrangler.jsonc +0 -53
- package/tsconfig.json +0 -11
package/dist/src/api.js
ADDED
|
@@ -0,0 +1,1270 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
+
try {
|
|
3
|
+
var info = gen[key](arg);
|
|
4
|
+
var value = info.value;
|
|
5
|
+
} catch (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (info.done) {
|
|
10
|
+
resolve(value);
|
|
11
|
+
} else {
|
|
12
|
+
Promise.resolve(value).then(_next, _throw);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function _async_to_generator(fn) {
|
|
16
|
+
return function() {
|
|
17
|
+
var self = this, args = arguments;
|
|
18
|
+
return new Promise(function(resolve, reject) {
|
|
19
|
+
var gen = fn.apply(self, args);
|
|
20
|
+
function _next(value) {
|
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
22
|
+
}
|
|
23
|
+
function _throw(err) {
|
|
24
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
25
|
+
}
|
|
26
|
+
_next(undefined);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function _define_property(obj, key, value) {
|
|
31
|
+
if (key in obj) {
|
|
32
|
+
Object.defineProperty(obj, key, {
|
|
33
|
+
value: value,
|
|
34
|
+
enumerable: true,
|
|
35
|
+
configurable: true,
|
|
36
|
+
writable: true
|
|
37
|
+
});
|
|
38
|
+
} else {
|
|
39
|
+
obj[key] = value;
|
|
40
|
+
}
|
|
41
|
+
return obj;
|
|
42
|
+
}
|
|
43
|
+
function _instanceof(left, right) {
|
|
44
|
+
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
45
|
+
return !!right[Symbol.hasInstance](left);
|
|
46
|
+
} else {
|
|
47
|
+
return left instanceof right;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function _object_spread(target) {
|
|
51
|
+
for(var i = 1; i < arguments.length; i++){
|
|
52
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
53
|
+
var ownKeys = Object.keys(source);
|
|
54
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
55
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
56
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
ownKeys.forEach(function(key) {
|
|
60
|
+
_define_property(target, key, source[key]);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return target;
|
|
64
|
+
}
|
|
65
|
+
function ownKeys(object, enumerableOnly) {
|
|
66
|
+
var keys = Object.keys(object);
|
|
67
|
+
if (Object.getOwnPropertySymbols) {
|
|
68
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
69
|
+
if (enumerableOnly) {
|
|
70
|
+
symbols = symbols.filter(function(sym) {
|
|
71
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
keys.push.apply(keys, symbols);
|
|
75
|
+
}
|
|
76
|
+
return keys;
|
|
77
|
+
}
|
|
78
|
+
function _object_spread_props(target, source) {
|
|
79
|
+
source = source != null ? source : {};
|
|
80
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
81
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
82
|
+
} else {
|
|
83
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
84
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return target;
|
|
88
|
+
}
|
|
89
|
+
function _ts_generator(thisArg, body) {
|
|
90
|
+
var f, y, t, _ = {
|
|
91
|
+
label: 0,
|
|
92
|
+
sent: function() {
|
|
93
|
+
if (t[0] & 1) throw t[1];
|
|
94
|
+
return t[1];
|
|
95
|
+
},
|
|
96
|
+
trys: [],
|
|
97
|
+
ops: []
|
|
98
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
99
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
100
|
+
return this;
|
|
101
|
+
}), g;
|
|
102
|
+
function verb(n) {
|
|
103
|
+
return function(v) {
|
|
104
|
+
return step([
|
|
105
|
+
n,
|
|
106
|
+
v
|
|
107
|
+
]);
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function step(op) {
|
|
111
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
112
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
113
|
+
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;
|
|
114
|
+
if (y = 0, t) op = [
|
|
115
|
+
op[0] & 2,
|
|
116
|
+
t.value
|
|
117
|
+
];
|
|
118
|
+
switch(op[0]){
|
|
119
|
+
case 0:
|
|
120
|
+
case 1:
|
|
121
|
+
t = op;
|
|
122
|
+
break;
|
|
123
|
+
case 4:
|
|
124
|
+
_.label++;
|
|
125
|
+
return {
|
|
126
|
+
value: op[1],
|
|
127
|
+
done: false
|
|
128
|
+
};
|
|
129
|
+
case 5:
|
|
130
|
+
_.label++;
|
|
131
|
+
y = op[1];
|
|
132
|
+
op = [
|
|
133
|
+
0
|
|
134
|
+
];
|
|
135
|
+
continue;
|
|
136
|
+
case 7:
|
|
137
|
+
op = _.ops.pop();
|
|
138
|
+
_.trys.pop();
|
|
139
|
+
continue;
|
|
140
|
+
default:
|
|
141
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
142
|
+
_ = 0;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
146
|
+
_.label = op[1];
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
150
|
+
_.label = t[1];
|
|
151
|
+
t = op;
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
if (t && _.label < t[2]) {
|
|
155
|
+
_.label = t[2];
|
|
156
|
+
_.ops.push(op);
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
if (t[2]) _.ops.pop();
|
|
160
|
+
_.trys.pop();
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
op = body.call(thisArg, _);
|
|
164
|
+
} catch (e) {
|
|
165
|
+
op = [
|
|
166
|
+
6,
|
|
167
|
+
e
|
|
168
|
+
];
|
|
169
|
+
y = 0;
|
|
170
|
+
} finally{
|
|
171
|
+
f = t = 0;
|
|
172
|
+
}
|
|
173
|
+
if (op[0] & 5) throw op[1];
|
|
174
|
+
return {
|
|
175
|
+
value: op[0] ? op[1] : void 0,
|
|
176
|
+
done: true
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
import { Hono } from 'hono';
|
|
181
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
182
|
+
import { AwsClient } from 'aws4fetch';
|
|
183
|
+
import { parseCronExpression } from 'cron-schedule';
|
|
184
|
+
import { getManifest } from './brain-runner-do.js';
|
|
185
|
+
import { RESOURCE_TYPES } from '@positronic/core';
|
|
186
|
+
var app = new Hono();
|
|
187
|
+
app.post('/brains/runs', function(context) {
|
|
188
|
+
return _async_to_generator(function() {
|
|
189
|
+
var brainName, manifest, brain, brainRunId, namespace, doId, stub, response;
|
|
190
|
+
return _ts_generator(this, function(_state) {
|
|
191
|
+
switch(_state.label){
|
|
192
|
+
case 0:
|
|
193
|
+
return [
|
|
194
|
+
4,
|
|
195
|
+
context.req.json()
|
|
196
|
+
];
|
|
197
|
+
case 1:
|
|
198
|
+
brainName = _state.sent().brainName;
|
|
199
|
+
if (!brainName) {
|
|
200
|
+
return [
|
|
201
|
+
2,
|
|
202
|
+
context.json({
|
|
203
|
+
error: 'Missing brainName in request body'
|
|
204
|
+
}, 400)
|
|
205
|
+
];
|
|
206
|
+
}
|
|
207
|
+
// Validate that the brain exists before starting it
|
|
208
|
+
manifest = getManifest();
|
|
209
|
+
if (!manifest) {
|
|
210
|
+
return [
|
|
211
|
+
2,
|
|
212
|
+
context.json({
|
|
213
|
+
error: 'Manifest not initialized'
|
|
214
|
+
}, 500)
|
|
215
|
+
];
|
|
216
|
+
}
|
|
217
|
+
return [
|
|
218
|
+
4,
|
|
219
|
+
manifest.import(brainName)
|
|
220
|
+
];
|
|
221
|
+
case 2:
|
|
222
|
+
brain = _state.sent();
|
|
223
|
+
if (!brain) {
|
|
224
|
+
return [
|
|
225
|
+
2,
|
|
226
|
+
context.json({
|
|
227
|
+
error: "Brain '".concat(brainName, "' not found")
|
|
228
|
+
}, 404)
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
brainRunId = uuidv4();
|
|
232
|
+
namespace = context.env.BRAIN_RUNNER_DO;
|
|
233
|
+
doId = namespace.idFromName(brainRunId);
|
|
234
|
+
stub = namespace.get(doId);
|
|
235
|
+
return [
|
|
236
|
+
4,
|
|
237
|
+
stub.start(brainName, brainRunId)
|
|
238
|
+
];
|
|
239
|
+
case 3:
|
|
240
|
+
_state.sent();
|
|
241
|
+
response = {
|
|
242
|
+
brainRunId: brainRunId
|
|
243
|
+
};
|
|
244
|
+
return [
|
|
245
|
+
2,
|
|
246
|
+
context.json(response, 201)
|
|
247
|
+
];
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
})();
|
|
251
|
+
});
|
|
252
|
+
app.post('/brains/runs/rerun', function(context) {
|
|
253
|
+
return _async_to_generator(function() {
|
|
254
|
+
var _ref, brainName, runId, startsAt, stopsAfter, manifest, brain, monitorId, monitorStub, existingRun, newBrainRunId, namespace, doId, stub, rerunOptions, response;
|
|
255
|
+
return _ts_generator(this, function(_state) {
|
|
256
|
+
switch(_state.label){
|
|
257
|
+
case 0:
|
|
258
|
+
return [
|
|
259
|
+
4,
|
|
260
|
+
context.req.json()
|
|
261
|
+
];
|
|
262
|
+
case 1:
|
|
263
|
+
_ref = _state.sent(), brainName = _ref.brainName, runId = _ref.runId, startsAt = _ref.startsAt, stopsAfter = _ref.stopsAfter;
|
|
264
|
+
if (!brainName) {
|
|
265
|
+
return [
|
|
266
|
+
2,
|
|
267
|
+
context.json({
|
|
268
|
+
error: 'Missing brainName in request body'
|
|
269
|
+
}, 400)
|
|
270
|
+
];
|
|
271
|
+
}
|
|
272
|
+
// Validate that the brain exists
|
|
273
|
+
manifest = getManifest();
|
|
274
|
+
if (!manifest) {
|
|
275
|
+
return [
|
|
276
|
+
2,
|
|
277
|
+
context.json({
|
|
278
|
+
error: 'Manifest not initialized'
|
|
279
|
+
}, 500)
|
|
280
|
+
];
|
|
281
|
+
}
|
|
282
|
+
return [
|
|
283
|
+
4,
|
|
284
|
+
manifest.import(brainName)
|
|
285
|
+
];
|
|
286
|
+
case 2:
|
|
287
|
+
brain = _state.sent();
|
|
288
|
+
if (!brain) {
|
|
289
|
+
return [
|
|
290
|
+
2,
|
|
291
|
+
context.json({
|
|
292
|
+
error: "Brain '".concat(brainName, "' not found")
|
|
293
|
+
}, 404)
|
|
294
|
+
];
|
|
295
|
+
}
|
|
296
|
+
if (!runId) return [
|
|
297
|
+
3,
|
|
298
|
+
4
|
|
299
|
+
];
|
|
300
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
301
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
302
|
+
return [
|
|
303
|
+
4,
|
|
304
|
+
monitorStub.getLastEvent(runId)
|
|
305
|
+
];
|
|
306
|
+
case 3:
|
|
307
|
+
existingRun = _state.sent();
|
|
308
|
+
if (!existingRun) {
|
|
309
|
+
return [
|
|
310
|
+
2,
|
|
311
|
+
context.json({
|
|
312
|
+
error: "Brain run '".concat(runId, "' not found")
|
|
313
|
+
}, 404)
|
|
314
|
+
];
|
|
315
|
+
}
|
|
316
|
+
_state.label = 4;
|
|
317
|
+
case 4:
|
|
318
|
+
// Create a new brain run with rerun parameters
|
|
319
|
+
newBrainRunId = uuidv4();
|
|
320
|
+
namespace = context.env.BRAIN_RUNNER_DO;
|
|
321
|
+
doId = namespace.idFromName(newBrainRunId);
|
|
322
|
+
stub = namespace.get(doId);
|
|
323
|
+
// Start the brain with rerun options
|
|
324
|
+
rerunOptions = _object_spread({}, runId && {
|
|
325
|
+
originalRunId: runId
|
|
326
|
+
}, startsAt !== undefined && {
|
|
327
|
+
startsAt: startsAt
|
|
328
|
+
}, stopsAfter !== undefined && {
|
|
329
|
+
stopsAfter: stopsAfter
|
|
330
|
+
});
|
|
331
|
+
return [
|
|
332
|
+
4,
|
|
333
|
+
stub.start(brainName, newBrainRunId, rerunOptions)
|
|
334
|
+
];
|
|
335
|
+
case 5:
|
|
336
|
+
_state.sent();
|
|
337
|
+
response = {
|
|
338
|
+
brainRunId: newBrainRunId
|
|
339
|
+
};
|
|
340
|
+
return [
|
|
341
|
+
2,
|
|
342
|
+
context.json(response, 201)
|
|
343
|
+
];
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
})();
|
|
347
|
+
});
|
|
348
|
+
app.get('/brains/runs/:runId/watch', function(context) {
|
|
349
|
+
return _async_to_generator(function() {
|
|
350
|
+
var runId, namespace, doId, stub, response;
|
|
351
|
+
return _ts_generator(this, function(_state) {
|
|
352
|
+
switch(_state.label){
|
|
353
|
+
case 0:
|
|
354
|
+
runId = context.req.param('runId');
|
|
355
|
+
namespace = context.env.BRAIN_RUNNER_DO;
|
|
356
|
+
doId = namespace.idFromName(runId);
|
|
357
|
+
stub = namespace.get(doId);
|
|
358
|
+
return [
|
|
359
|
+
4,
|
|
360
|
+
stub.fetch(new Request("http://do/watch"))
|
|
361
|
+
];
|
|
362
|
+
case 1:
|
|
363
|
+
response = _state.sent();
|
|
364
|
+
return [
|
|
365
|
+
2,
|
|
366
|
+
response
|
|
367
|
+
];
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
})();
|
|
371
|
+
});
|
|
372
|
+
app.get('/brains/:brainName/history', function(context) {
|
|
373
|
+
return _async_to_generator(function() {
|
|
374
|
+
var brainName, limit, monitorId, monitorStub, runs;
|
|
375
|
+
return _ts_generator(this, function(_state) {
|
|
376
|
+
switch(_state.label){
|
|
377
|
+
case 0:
|
|
378
|
+
brainName = context.req.param('brainName');
|
|
379
|
+
limit = Number(context.req.query('limit') || '10');
|
|
380
|
+
// Get the monitor singleton instance
|
|
381
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
382
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
383
|
+
return [
|
|
384
|
+
4,
|
|
385
|
+
monitorStub.history(brainName, limit)
|
|
386
|
+
];
|
|
387
|
+
case 1:
|
|
388
|
+
runs = _state.sent();
|
|
389
|
+
return [
|
|
390
|
+
2,
|
|
391
|
+
context.json({
|
|
392
|
+
runs: runs
|
|
393
|
+
})
|
|
394
|
+
];
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
})();
|
|
398
|
+
});
|
|
399
|
+
app.get('/brains/:brainName/active-runs', function(context) {
|
|
400
|
+
return _async_to_generator(function() {
|
|
401
|
+
var brainName, monitorId, monitorStub, runs;
|
|
402
|
+
return _ts_generator(this, function(_state) {
|
|
403
|
+
switch(_state.label){
|
|
404
|
+
case 0:
|
|
405
|
+
brainName = context.req.param('brainName');
|
|
406
|
+
// Get the monitor singleton instance
|
|
407
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
408
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
409
|
+
return [
|
|
410
|
+
4,
|
|
411
|
+
monitorStub.activeRuns(brainName)
|
|
412
|
+
];
|
|
413
|
+
case 1:
|
|
414
|
+
runs = _state.sent();
|
|
415
|
+
return [
|
|
416
|
+
2,
|
|
417
|
+
context.json({
|
|
418
|
+
runs: runs
|
|
419
|
+
})
|
|
420
|
+
];
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
})();
|
|
424
|
+
});
|
|
425
|
+
app.get('/brains/watch', function(context) {
|
|
426
|
+
return _async_to_generator(function() {
|
|
427
|
+
var monitorId, monitorStub, response;
|
|
428
|
+
return _ts_generator(this, function(_state) {
|
|
429
|
+
switch(_state.label){
|
|
430
|
+
case 0:
|
|
431
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
432
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
433
|
+
return [
|
|
434
|
+
4,
|
|
435
|
+
monitorStub.fetch(new Request("http://do/watch"))
|
|
436
|
+
];
|
|
437
|
+
case 1:
|
|
438
|
+
response = _state.sent();
|
|
439
|
+
return [
|
|
440
|
+
2,
|
|
441
|
+
response
|
|
442
|
+
];
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
})();
|
|
446
|
+
});
|
|
447
|
+
app.get('/brains', function(context) {
|
|
448
|
+
return _async_to_generator(function() {
|
|
449
|
+
var manifest, brainNames, brains, validBrains;
|
|
450
|
+
return _ts_generator(this, function(_state) {
|
|
451
|
+
switch(_state.label){
|
|
452
|
+
case 0:
|
|
453
|
+
manifest = getManifest();
|
|
454
|
+
if (!manifest) {
|
|
455
|
+
return [
|
|
456
|
+
2,
|
|
457
|
+
context.json({
|
|
458
|
+
error: 'Manifest not initialized'
|
|
459
|
+
}, 500)
|
|
460
|
+
];
|
|
461
|
+
}
|
|
462
|
+
brainNames = manifest.list();
|
|
463
|
+
return [
|
|
464
|
+
4,
|
|
465
|
+
Promise.all(brainNames.map(function(name) {
|
|
466
|
+
return _async_to_generator(function() {
|
|
467
|
+
var brain;
|
|
468
|
+
return _ts_generator(this, function(_state) {
|
|
469
|
+
switch(_state.label){
|
|
470
|
+
case 0:
|
|
471
|
+
return [
|
|
472
|
+
4,
|
|
473
|
+
manifest.import(name)
|
|
474
|
+
];
|
|
475
|
+
case 1:
|
|
476
|
+
brain = _state.sent();
|
|
477
|
+
if (!brain) {
|
|
478
|
+
return [
|
|
479
|
+
2,
|
|
480
|
+
null
|
|
481
|
+
];
|
|
482
|
+
}
|
|
483
|
+
return [
|
|
484
|
+
2,
|
|
485
|
+
{
|
|
486
|
+
name: name,
|
|
487
|
+
title: brain.title,
|
|
488
|
+
description: "".concat(brain.title, " brain")
|
|
489
|
+
}
|
|
490
|
+
];
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
})();
|
|
494
|
+
}))
|
|
495
|
+
];
|
|
496
|
+
case 1:
|
|
497
|
+
brains = _state.sent();
|
|
498
|
+
// Filter out any null entries
|
|
499
|
+
validBrains = brains.filter(function(brain) {
|
|
500
|
+
return brain !== null;
|
|
501
|
+
});
|
|
502
|
+
return [
|
|
503
|
+
2,
|
|
504
|
+
context.json({
|
|
505
|
+
brains: validBrains,
|
|
506
|
+
count: validBrains.length
|
|
507
|
+
})
|
|
508
|
+
];
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
})();
|
|
512
|
+
});
|
|
513
|
+
// Schedule endpoints
|
|
514
|
+
// Create a new schedule
|
|
515
|
+
app.post('/brains/schedules', function(context) {
|
|
516
|
+
return _async_to_generator(function() {
|
|
517
|
+
var body, brainName, cronExpression, scheduleId, scheduleStub, schedule, error, errorMessage;
|
|
518
|
+
return _ts_generator(this, function(_state) {
|
|
519
|
+
switch(_state.label){
|
|
520
|
+
case 0:
|
|
521
|
+
_state.trys.push([
|
|
522
|
+
0,
|
|
523
|
+
3,
|
|
524
|
+
,
|
|
525
|
+
4
|
|
526
|
+
]);
|
|
527
|
+
return [
|
|
528
|
+
4,
|
|
529
|
+
context.req.json()
|
|
530
|
+
];
|
|
531
|
+
case 1:
|
|
532
|
+
body = _state.sent();
|
|
533
|
+
brainName = body.brainName, cronExpression = body.cronExpression;
|
|
534
|
+
if (!brainName) {
|
|
535
|
+
return [
|
|
536
|
+
2,
|
|
537
|
+
context.json({
|
|
538
|
+
error: 'Missing required field "brainName"'
|
|
539
|
+
}, 400)
|
|
540
|
+
];
|
|
541
|
+
}
|
|
542
|
+
if (!cronExpression) {
|
|
543
|
+
return [
|
|
544
|
+
2,
|
|
545
|
+
context.json({
|
|
546
|
+
error: 'Missing required field "cronExpression"'
|
|
547
|
+
}, 400)
|
|
548
|
+
];
|
|
549
|
+
}
|
|
550
|
+
// Validate cron expression before calling DO
|
|
551
|
+
try {
|
|
552
|
+
parseCronExpression(cronExpression);
|
|
553
|
+
} catch (e) {
|
|
554
|
+
return [
|
|
555
|
+
2,
|
|
556
|
+
context.json({
|
|
557
|
+
error: "Invalid cron expression: ".concat(cronExpression)
|
|
558
|
+
}, 400)
|
|
559
|
+
];
|
|
560
|
+
}
|
|
561
|
+
// Get the schedule singleton instance
|
|
562
|
+
scheduleId = context.env.SCHEDULE_DO.idFromName('singleton');
|
|
563
|
+
scheduleStub = context.env.SCHEDULE_DO.get(scheduleId);
|
|
564
|
+
return [
|
|
565
|
+
4,
|
|
566
|
+
scheduleStub.createSchedule(brainName, cronExpression)
|
|
567
|
+
];
|
|
568
|
+
case 2:
|
|
569
|
+
schedule = _state.sent();
|
|
570
|
+
return [
|
|
571
|
+
2,
|
|
572
|
+
context.json(schedule, 201)
|
|
573
|
+
];
|
|
574
|
+
case 3:
|
|
575
|
+
error = _state.sent();
|
|
576
|
+
errorMessage = _instanceof(error, Error) ? error.message : 'Failed to create schedule';
|
|
577
|
+
return [
|
|
578
|
+
2,
|
|
579
|
+
context.json({
|
|
580
|
+
error: errorMessage
|
|
581
|
+
}, 400)
|
|
582
|
+
];
|
|
583
|
+
case 4:
|
|
584
|
+
return [
|
|
585
|
+
2
|
|
586
|
+
];
|
|
587
|
+
}
|
|
588
|
+
});
|
|
589
|
+
})();
|
|
590
|
+
});
|
|
591
|
+
// List all schedules
|
|
592
|
+
app.get('/brains/schedules', function(context) {
|
|
593
|
+
return _async_to_generator(function() {
|
|
594
|
+
var scheduleId, scheduleStub, result;
|
|
595
|
+
return _ts_generator(this, function(_state) {
|
|
596
|
+
switch(_state.label){
|
|
597
|
+
case 0:
|
|
598
|
+
scheduleId = context.env.SCHEDULE_DO.idFromName('singleton');
|
|
599
|
+
scheduleStub = context.env.SCHEDULE_DO.get(scheduleId);
|
|
600
|
+
return [
|
|
601
|
+
4,
|
|
602
|
+
scheduleStub.listSchedules()
|
|
603
|
+
];
|
|
604
|
+
case 1:
|
|
605
|
+
result = _state.sent();
|
|
606
|
+
return [
|
|
607
|
+
2,
|
|
608
|
+
context.json(result)
|
|
609
|
+
];
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
})();
|
|
613
|
+
});
|
|
614
|
+
// Get scheduled run history - MUST be before :scheduleId route
|
|
615
|
+
app.get('/brains/schedules/runs', function(context) {
|
|
616
|
+
return _async_to_generator(function() {
|
|
617
|
+
var scheduleIdParam, limit, scheduleDoId, scheduleStub, result;
|
|
618
|
+
return _ts_generator(this, function(_state) {
|
|
619
|
+
switch(_state.label){
|
|
620
|
+
case 0:
|
|
621
|
+
scheduleIdParam = context.req.query('scheduleId');
|
|
622
|
+
limit = Number(context.req.query('limit') || '100');
|
|
623
|
+
scheduleDoId = context.env.SCHEDULE_DO.idFromName('singleton');
|
|
624
|
+
scheduleStub = context.env.SCHEDULE_DO.get(scheduleDoId);
|
|
625
|
+
return [
|
|
626
|
+
4,
|
|
627
|
+
scheduleStub.getAllRuns(scheduleIdParam, limit)
|
|
628
|
+
];
|
|
629
|
+
case 1:
|
|
630
|
+
result = _state.sent();
|
|
631
|
+
return [
|
|
632
|
+
2,
|
|
633
|
+
context.json(result)
|
|
634
|
+
];
|
|
635
|
+
}
|
|
636
|
+
});
|
|
637
|
+
})();
|
|
638
|
+
});
|
|
639
|
+
// Delete a schedule
|
|
640
|
+
app.delete('/brains/schedules/:scheduleId', function(context) {
|
|
641
|
+
return _async_to_generator(function() {
|
|
642
|
+
var scheduleIdParam, scheduleDoId, scheduleStub, deleted;
|
|
643
|
+
return _ts_generator(this, function(_state) {
|
|
644
|
+
switch(_state.label){
|
|
645
|
+
case 0:
|
|
646
|
+
scheduleIdParam = context.req.param('scheduleId');
|
|
647
|
+
scheduleDoId = context.env.SCHEDULE_DO.idFromName('singleton');
|
|
648
|
+
scheduleStub = context.env.SCHEDULE_DO.get(scheduleDoId);
|
|
649
|
+
return [
|
|
650
|
+
4,
|
|
651
|
+
scheduleStub.deleteSchedule(scheduleIdParam)
|
|
652
|
+
];
|
|
653
|
+
case 1:
|
|
654
|
+
deleted = _state.sent();
|
|
655
|
+
if (!deleted) {
|
|
656
|
+
return [
|
|
657
|
+
2,
|
|
658
|
+
context.json({
|
|
659
|
+
error: 'Schedule not found'
|
|
660
|
+
}, 404)
|
|
661
|
+
];
|
|
662
|
+
}
|
|
663
|
+
return [
|
|
664
|
+
2,
|
|
665
|
+
new Response(null, {
|
|
666
|
+
status: 204
|
|
667
|
+
})
|
|
668
|
+
];
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
})();
|
|
672
|
+
});
|
|
673
|
+
app.get('/brains/:brainName', function(context) {
|
|
674
|
+
return _async_to_generator(function() {
|
|
675
|
+
var brainName, manifest, brain, structure;
|
|
676
|
+
return _ts_generator(this, function(_state) {
|
|
677
|
+
switch(_state.label){
|
|
678
|
+
case 0:
|
|
679
|
+
brainName = context.req.param('brainName');
|
|
680
|
+
manifest = getManifest();
|
|
681
|
+
if (!manifest) {
|
|
682
|
+
return [
|
|
683
|
+
2,
|
|
684
|
+
context.json({
|
|
685
|
+
error: 'Manifest not initialized'
|
|
686
|
+
}, 500)
|
|
687
|
+
];
|
|
688
|
+
}
|
|
689
|
+
return [
|
|
690
|
+
4,
|
|
691
|
+
manifest.import(brainName)
|
|
692
|
+
];
|
|
693
|
+
case 1:
|
|
694
|
+
brain = _state.sent();
|
|
695
|
+
if (!brain) {
|
|
696
|
+
return [
|
|
697
|
+
2,
|
|
698
|
+
context.json({
|
|
699
|
+
error: "Brain '".concat(brainName, "' not found")
|
|
700
|
+
}, 404)
|
|
701
|
+
];
|
|
702
|
+
}
|
|
703
|
+
// Get the brain structure
|
|
704
|
+
structure = brain.structure;
|
|
705
|
+
return [
|
|
706
|
+
2,
|
|
707
|
+
context.json({
|
|
708
|
+
name: brainName,
|
|
709
|
+
title: structure.title,
|
|
710
|
+
description: structure.description || "".concat(structure.title, " brain"),
|
|
711
|
+
steps: structure.steps
|
|
712
|
+
})
|
|
713
|
+
];
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
})();
|
|
717
|
+
});
|
|
718
|
+
app.get('/resources', function(context) {
|
|
719
|
+
return _async_to_generator(function() {
|
|
720
|
+
var bucket, listed, resources, error, errorMessage;
|
|
721
|
+
return _ts_generator(this, function(_state) {
|
|
722
|
+
switch(_state.label){
|
|
723
|
+
case 0:
|
|
724
|
+
bucket = context.env.RESOURCES_BUCKET;
|
|
725
|
+
_state.label = 1;
|
|
726
|
+
case 1:
|
|
727
|
+
_state.trys.push([
|
|
728
|
+
1,
|
|
729
|
+
4,
|
|
730
|
+
,
|
|
731
|
+
5
|
|
732
|
+
]);
|
|
733
|
+
return [
|
|
734
|
+
4,
|
|
735
|
+
bucket.list()
|
|
736
|
+
];
|
|
737
|
+
case 2:
|
|
738
|
+
listed = _state.sent();
|
|
739
|
+
return [
|
|
740
|
+
4,
|
|
741
|
+
Promise.all(listed.objects.map(function(object) {
|
|
742
|
+
return _async_to_generator(function() {
|
|
743
|
+
var _r2Object_customMetadata, r2Object, resource;
|
|
744
|
+
return _ts_generator(this, function(_state) {
|
|
745
|
+
switch(_state.label){
|
|
746
|
+
case 0:
|
|
747
|
+
return [
|
|
748
|
+
4,
|
|
749
|
+
bucket.head(object.key)
|
|
750
|
+
];
|
|
751
|
+
case 1:
|
|
752
|
+
r2Object = _state.sent();
|
|
753
|
+
if (!r2Object) {
|
|
754
|
+
throw new Error('Resource "'.concat(object.key, '" not found'));
|
|
755
|
+
}
|
|
756
|
+
if (!((_r2Object_customMetadata = r2Object.customMetadata) === null || _r2Object_customMetadata === void 0 ? void 0 : _r2Object_customMetadata.type)) {
|
|
757
|
+
throw new Error('Resource "'.concat(object.key, '" is missing required metadata field "type"'));
|
|
758
|
+
}
|
|
759
|
+
resource = _object_spread_props(_object_spread({
|
|
760
|
+
type: r2Object.customMetadata.type
|
|
761
|
+
}, r2Object.customMetadata.path && {
|
|
762
|
+
path: r2Object.customMetadata.path
|
|
763
|
+
}), {
|
|
764
|
+
key: object.key,
|
|
765
|
+
size: object.size,
|
|
766
|
+
lastModified: object.uploaded.toISOString(),
|
|
767
|
+
local: r2Object.customMetadata.local === 'true'
|
|
768
|
+
});
|
|
769
|
+
return [
|
|
770
|
+
2,
|
|
771
|
+
resource
|
|
772
|
+
];
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
})();
|
|
776
|
+
}))
|
|
777
|
+
];
|
|
778
|
+
case 3:
|
|
779
|
+
resources = _state.sent();
|
|
780
|
+
return [
|
|
781
|
+
2,
|
|
782
|
+
context.json({
|
|
783
|
+
resources: resources,
|
|
784
|
+
truncated: listed.truncated,
|
|
785
|
+
count: resources.length
|
|
786
|
+
})
|
|
787
|
+
];
|
|
788
|
+
case 4:
|
|
789
|
+
error = _state.sent();
|
|
790
|
+
errorMessage = _instanceof(error, Error) ? error.message : 'Unknown error occurred';
|
|
791
|
+
return [
|
|
792
|
+
2,
|
|
793
|
+
context.json({
|
|
794
|
+
error: errorMessage
|
|
795
|
+
}, 500)
|
|
796
|
+
];
|
|
797
|
+
case 5:
|
|
798
|
+
return [
|
|
799
|
+
2
|
|
800
|
+
];
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
})();
|
|
804
|
+
});
|
|
805
|
+
app.get('/status', function(context) {
|
|
806
|
+
return _async_to_generator(function() {
|
|
807
|
+
return _ts_generator(this, function(_state) {
|
|
808
|
+
return [
|
|
809
|
+
2,
|
|
810
|
+
context.json({
|
|
811
|
+
ready: true
|
|
812
|
+
})
|
|
813
|
+
];
|
|
814
|
+
});
|
|
815
|
+
})();
|
|
816
|
+
});
|
|
817
|
+
app.post('/resources', function(context) {
|
|
818
|
+
return _async_to_generator(function() {
|
|
819
|
+
var bucket, formData, file, type, path, key, local, objectKey, arrayBuffer, uploadedObject, resource, error, errorMessage;
|
|
820
|
+
return _ts_generator(this, function(_state) {
|
|
821
|
+
switch(_state.label){
|
|
822
|
+
case 0:
|
|
823
|
+
bucket = context.env.RESOURCES_BUCKET;
|
|
824
|
+
return [
|
|
825
|
+
4,
|
|
826
|
+
context.req.formData()
|
|
827
|
+
];
|
|
828
|
+
case 1:
|
|
829
|
+
formData = _state.sent();
|
|
830
|
+
file = formData.get('file');
|
|
831
|
+
type = formData.get('type');
|
|
832
|
+
path = formData.get('path');
|
|
833
|
+
key = formData.get('key');
|
|
834
|
+
local = formData.get('local');
|
|
835
|
+
if (!file) {
|
|
836
|
+
return [
|
|
837
|
+
2,
|
|
838
|
+
context.json({
|
|
839
|
+
error: 'Missing required field "file"'
|
|
840
|
+
}, 400)
|
|
841
|
+
];
|
|
842
|
+
}
|
|
843
|
+
if (!type) {
|
|
844
|
+
return [
|
|
845
|
+
2,
|
|
846
|
+
context.json({
|
|
847
|
+
error: 'Missing required field "type"'
|
|
848
|
+
}, 400)
|
|
849
|
+
];
|
|
850
|
+
}
|
|
851
|
+
if (!RESOURCE_TYPES.includes(type)) {
|
|
852
|
+
return [
|
|
853
|
+
2,
|
|
854
|
+
context.json({
|
|
855
|
+
error: 'Field "type" must be one of: '.concat(RESOURCE_TYPES.join(', '))
|
|
856
|
+
}, 400)
|
|
857
|
+
];
|
|
858
|
+
}
|
|
859
|
+
// Either key or path must be provided
|
|
860
|
+
if (!key && !path) {
|
|
861
|
+
return [
|
|
862
|
+
2,
|
|
863
|
+
context.json({
|
|
864
|
+
error: 'Either "key" or "path" must be provided'
|
|
865
|
+
}, 400)
|
|
866
|
+
];
|
|
867
|
+
}
|
|
868
|
+
// Use key if provided, otherwise use path
|
|
869
|
+
objectKey = key || path;
|
|
870
|
+
_state.label = 2;
|
|
871
|
+
case 2:
|
|
872
|
+
_state.trys.push([
|
|
873
|
+
2,
|
|
874
|
+
5,
|
|
875
|
+
,
|
|
876
|
+
6
|
|
877
|
+
]);
|
|
878
|
+
return [
|
|
879
|
+
4,
|
|
880
|
+
file.arrayBuffer()
|
|
881
|
+
];
|
|
882
|
+
case 3:
|
|
883
|
+
arrayBuffer = _state.sent();
|
|
884
|
+
return [
|
|
885
|
+
4,
|
|
886
|
+
bucket.put(objectKey, arrayBuffer, {
|
|
887
|
+
customMetadata: _object_spread_props(_object_spread({
|
|
888
|
+
type: type
|
|
889
|
+
}, path && {
|
|
890
|
+
path: path
|
|
891
|
+
}), {
|
|
892
|
+
local: local === 'true' ? 'true' : 'false'
|
|
893
|
+
})
|
|
894
|
+
})
|
|
895
|
+
];
|
|
896
|
+
case 4:
|
|
897
|
+
uploadedObject = _state.sent();
|
|
898
|
+
resource = _object_spread_props(_object_spread({
|
|
899
|
+
type: type
|
|
900
|
+
}, path && {
|
|
901
|
+
path: path
|
|
902
|
+
}), {
|
|
903
|
+
key: objectKey,
|
|
904
|
+
size: uploadedObject.size,
|
|
905
|
+
lastModified: uploadedObject.uploaded.toISOString(),
|
|
906
|
+
local: local === 'true'
|
|
907
|
+
});
|
|
908
|
+
return [
|
|
909
|
+
2,
|
|
910
|
+
context.json(resource, 201)
|
|
911
|
+
];
|
|
912
|
+
case 5:
|
|
913
|
+
error = _state.sent();
|
|
914
|
+
errorMessage = _instanceof(error, Error) ? error.message : 'Failed to upload resource';
|
|
915
|
+
return [
|
|
916
|
+
2,
|
|
917
|
+
context.json({
|
|
918
|
+
error: errorMessage
|
|
919
|
+
}, 500)
|
|
920
|
+
];
|
|
921
|
+
case 6:
|
|
922
|
+
return [
|
|
923
|
+
2
|
|
924
|
+
];
|
|
925
|
+
}
|
|
926
|
+
});
|
|
927
|
+
})();
|
|
928
|
+
});
|
|
929
|
+
// Delete a single resource by key
|
|
930
|
+
app.delete('/resources/:key', function(context) {
|
|
931
|
+
return _async_to_generator(function() {
|
|
932
|
+
var bucket, key, decodedKey, error;
|
|
933
|
+
return _ts_generator(this, function(_state) {
|
|
934
|
+
switch(_state.label){
|
|
935
|
+
case 0:
|
|
936
|
+
bucket = context.env.RESOURCES_BUCKET;
|
|
937
|
+
key = context.req.param('key');
|
|
938
|
+
// URL decode the key since it might contain slashes
|
|
939
|
+
decodedKey = decodeURIComponent(key);
|
|
940
|
+
_state.label = 1;
|
|
941
|
+
case 1:
|
|
942
|
+
_state.trys.push([
|
|
943
|
+
1,
|
|
944
|
+
3,
|
|
945
|
+
,
|
|
946
|
+
4
|
|
947
|
+
]);
|
|
948
|
+
// Delete the resource - R2 delete is idempotent, so it's safe to delete non-existent resources
|
|
949
|
+
return [
|
|
950
|
+
4,
|
|
951
|
+
bucket.delete(decodedKey)
|
|
952
|
+
];
|
|
953
|
+
case 2:
|
|
954
|
+
_state.sent();
|
|
955
|
+
return [
|
|
956
|
+
2,
|
|
957
|
+
new Response(null, {
|
|
958
|
+
status: 204
|
|
959
|
+
})
|
|
960
|
+
];
|
|
961
|
+
case 3:
|
|
962
|
+
error = _state.sent();
|
|
963
|
+
console.error('Failed to delete resource "'.concat(decodedKey, '":'), error);
|
|
964
|
+
return [
|
|
965
|
+
2,
|
|
966
|
+
context.json({
|
|
967
|
+
error: "Failed to delete resource: ".concat(_instanceof(error, Error) ? error.message : 'Unknown error')
|
|
968
|
+
}, 500)
|
|
969
|
+
];
|
|
970
|
+
case 4:
|
|
971
|
+
return [
|
|
972
|
+
2
|
|
973
|
+
];
|
|
974
|
+
}
|
|
975
|
+
});
|
|
976
|
+
})();
|
|
977
|
+
});
|
|
978
|
+
// Delete all resources (bulk delete) - only available in development mode
|
|
979
|
+
app.delete('/resources', function(context) {
|
|
980
|
+
return _async_to_generator(function() {
|
|
981
|
+
var isDevelopment, bucket, listed, deletedCount, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, object, err, cursor, nextBatch, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, object1, err;
|
|
982
|
+
return _ts_generator(this, function(_state) {
|
|
983
|
+
switch(_state.label){
|
|
984
|
+
case 0:
|
|
985
|
+
// Check if we're in development mode
|
|
986
|
+
isDevelopment = context.env.NODE_ENV === 'development';
|
|
987
|
+
if (!isDevelopment) {
|
|
988
|
+
return [
|
|
989
|
+
2,
|
|
990
|
+
context.json({
|
|
991
|
+
error: 'Bulk delete is only available in development mode'
|
|
992
|
+
}, 403)
|
|
993
|
+
];
|
|
994
|
+
}
|
|
995
|
+
bucket = context.env.RESOURCES_BUCKET;
|
|
996
|
+
return [
|
|
997
|
+
4,
|
|
998
|
+
bucket.list()
|
|
999
|
+
];
|
|
1000
|
+
case 1:
|
|
1001
|
+
listed = _state.sent();
|
|
1002
|
+
deletedCount = 0;
|
|
1003
|
+
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1004
|
+
_state.label = 2;
|
|
1005
|
+
case 2:
|
|
1006
|
+
_state.trys.push([
|
|
1007
|
+
2,
|
|
1008
|
+
7,
|
|
1009
|
+
8,
|
|
1010
|
+
9
|
|
1011
|
+
]);
|
|
1012
|
+
_iterator = listed.objects[Symbol.iterator]();
|
|
1013
|
+
_state.label = 3;
|
|
1014
|
+
case 3:
|
|
1015
|
+
if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
|
|
1016
|
+
3,
|
|
1017
|
+
6
|
|
1018
|
+
];
|
|
1019
|
+
object = _step.value;
|
|
1020
|
+
return [
|
|
1021
|
+
4,
|
|
1022
|
+
bucket.delete(object.key)
|
|
1023
|
+
];
|
|
1024
|
+
case 4:
|
|
1025
|
+
_state.sent();
|
|
1026
|
+
deletedCount++;
|
|
1027
|
+
_state.label = 5;
|
|
1028
|
+
case 5:
|
|
1029
|
+
_iteratorNormalCompletion = true;
|
|
1030
|
+
return [
|
|
1031
|
+
3,
|
|
1032
|
+
3
|
|
1033
|
+
];
|
|
1034
|
+
case 6:
|
|
1035
|
+
return [
|
|
1036
|
+
3,
|
|
1037
|
+
9
|
|
1038
|
+
];
|
|
1039
|
+
case 7:
|
|
1040
|
+
err = _state.sent();
|
|
1041
|
+
_didIteratorError = true;
|
|
1042
|
+
_iteratorError = err;
|
|
1043
|
+
return [
|
|
1044
|
+
3,
|
|
1045
|
+
9
|
|
1046
|
+
];
|
|
1047
|
+
case 8:
|
|
1048
|
+
try {
|
|
1049
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
1050
|
+
_iterator.return();
|
|
1051
|
+
}
|
|
1052
|
+
} finally{
|
|
1053
|
+
if (_didIteratorError) {
|
|
1054
|
+
throw _iteratorError;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
return [
|
|
1058
|
+
7
|
|
1059
|
+
];
|
|
1060
|
+
case 9:
|
|
1061
|
+
// Handle pagination if there are more than 1000 objects
|
|
1062
|
+
cursor = listed.cursor;
|
|
1063
|
+
_state.label = 10;
|
|
1064
|
+
case 10:
|
|
1065
|
+
if (!(listed.truncated && cursor)) return [
|
|
1066
|
+
3,
|
|
1067
|
+
20
|
|
1068
|
+
];
|
|
1069
|
+
return [
|
|
1070
|
+
4,
|
|
1071
|
+
bucket.list({
|
|
1072
|
+
cursor: cursor
|
|
1073
|
+
})
|
|
1074
|
+
];
|
|
1075
|
+
case 11:
|
|
1076
|
+
nextBatch = _state.sent();
|
|
1077
|
+
_iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
1078
|
+
_state.label = 12;
|
|
1079
|
+
case 12:
|
|
1080
|
+
_state.trys.push([
|
|
1081
|
+
12,
|
|
1082
|
+
17,
|
|
1083
|
+
18,
|
|
1084
|
+
19
|
|
1085
|
+
]);
|
|
1086
|
+
_iterator1 = nextBatch.objects[Symbol.iterator]();
|
|
1087
|
+
_state.label = 13;
|
|
1088
|
+
case 13:
|
|
1089
|
+
if (!!(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done)) return [
|
|
1090
|
+
3,
|
|
1091
|
+
16
|
|
1092
|
+
];
|
|
1093
|
+
object1 = _step1.value;
|
|
1094
|
+
return [
|
|
1095
|
+
4,
|
|
1096
|
+
bucket.delete(object1.key)
|
|
1097
|
+
];
|
|
1098
|
+
case 14:
|
|
1099
|
+
_state.sent();
|
|
1100
|
+
deletedCount++;
|
|
1101
|
+
_state.label = 15;
|
|
1102
|
+
case 15:
|
|
1103
|
+
_iteratorNormalCompletion1 = true;
|
|
1104
|
+
return [
|
|
1105
|
+
3,
|
|
1106
|
+
13
|
|
1107
|
+
];
|
|
1108
|
+
case 16:
|
|
1109
|
+
return [
|
|
1110
|
+
3,
|
|
1111
|
+
19
|
|
1112
|
+
];
|
|
1113
|
+
case 17:
|
|
1114
|
+
err = _state.sent();
|
|
1115
|
+
_didIteratorError1 = true;
|
|
1116
|
+
_iteratorError1 = err;
|
|
1117
|
+
return [
|
|
1118
|
+
3,
|
|
1119
|
+
19
|
|
1120
|
+
];
|
|
1121
|
+
case 18:
|
|
1122
|
+
try {
|
|
1123
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
1124
|
+
_iterator1.return();
|
|
1125
|
+
}
|
|
1126
|
+
} finally{
|
|
1127
|
+
if (_didIteratorError1) {
|
|
1128
|
+
throw _iteratorError1;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
return [
|
|
1132
|
+
7
|
|
1133
|
+
];
|
|
1134
|
+
case 19:
|
|
1135
|
+
cursor = nextBatch.cursor;
|
|
1136
|
+
return [
|
|
1137
|
+
3,
|
|
1138
|
+
10
|
|
1139
|
+
];
|
|
1140
|
+
case 20:
|
|
1141
|
+
return [
|
|
1142
|
+
2,
|
|
1143
|
+
context.json({
|
|
1144
|
+
deletedCount: deletedCount
|
|
1145
|
+
})
|
|
1146
|
+
];
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1149
|
+
})();
|
|
1150
|
+
});
|
|
1151
|
+
// Generate presigned URL for large file uploads
|
|
1152
|
+
app.post('/resources/presigned-link', function(context) {
|
|
1153
|
+
return _async_to_generator(function() {
|
|
1154
|
+
var body, key, type, size, _context_env, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_ACCOUNT_ID, R2_BUCKET_NAME, client, url, expiresIn, requestToSign, signedRequest, error;
|
|
1155
|
+
return _ts_generator(this, function(_state) {
|
|
1156
|
+
switch(_state.label){
|
|
1157
|
+
case 0:
|
|
1158
|
+
_state.trys.push([
|
|
1159
|
+
0,
|
|
1160
|
+
3,
|
|
1161
|
+
,
|
|
1162
|
+
4
|
|
1163
|
+
]);
|
|
1164
|
+
return [
|
|
1165
|
+
4,
|
|
1166
|
+
context.req.json()
|
|
1167
|
+
];
|
|
1168
|
+
case 1:
|
|
1169
|
+
body = _state.sent();
|
|
1170
|
+
key = body.key, type = body.type, size = body.size;
|
|
1171
|
+
// Validate required fields
|
|
1172
|
+
if (!key) {
|
|
1173
|
+
return [
|
|
1174
|
+
2,
|
|
1175
|
+
context.json({
|
|
1176
|
+
error: 'Missing required field "key"'
|
|
1177
|
+
}, 400)
|
|
1178
|
+
];
|
|
1179
|
+
}
|
|
1180
|
+
if (!type) {
|
|
1181
|
+
return [
|
|
1182
|
+
2,
|
|
1183
|
+
context.json({
|
|
1184
|
+
error: 'Missing required field "type"'
|
|
1185
|
+
}, 400)
|
|
1186
|
+
];
|
|
1187
|
+
}
|
|
1188
|
+
if (size === undefined || size === null) {
|
|
1189
|
+
return [
|
|
1190
|
+
2,
|
|
1191
|
+
context.json({
|
|
1192
|
+
error: 'Missing required field "size"'
|
|
1193
|
+
}, 400)
|
|
1194
|
+
];
|
|
1195
|
+
}
|
|
1196
|
+
// Validate type
|
|
1197
|
+
if (type !== 'text' && type !== 'binary') {
|
|
1198
|
+
return [
|
|
1199
|
+
2,
|
|
1200
|
+
context.json({
|
|
1201
|
+
error: 'type must be either "text" or "binary"'
|
|
1202
|
+
}, 400)
|
|
1203
|
+
];
|
|
1204
|
+
}
|
|
1205
|
+
// Check if R2 credentials are configured
|
|
1206
|
+
_context_env = context.env, R2_ACCESS_KEY_ID = _context_env.R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY = _context_env.R2_SECRET_ACCESS_KEY, R2_ACCOUNT_ID = _context_env.R2_ACCOUNT_ID, R2_BUCKET_NAME = _context_env.R2_BUCKET_NAME;
|
|
1207
|
+
if (!R2_ACCESS_KEY_ID || !R2_SECRET_ACCESS_KEY || !R2_ACCOUNT_ID || !R2_BUCKET_NAME) {
|
|
1208
|
+
return [
|
|
1209
|
+
2,
|
|
1210
|
+
context.json({
|
|
1211
|
+
error: 'R2 credentials not configured. Please set R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_ACCOUNT_ID, and R2_BUCKET_NAME environment variables.'
|
|
1212
|
+
}, 400)
|
|
1213
|
+
];
|
|
1214
|
+
}
|
|
1215
|
+
// Create AWS client with R2 credentials
|
|
1216
|
+
client = new AwsClient({
|
|
1217
|
+
accessKeyId: R2_ACCESS_KEY_ID,
|
|
1218
|
+
secretAccessKey: R2_SECRET_ACCESS_KEY
|
|
1219
|
+
});
|
|
1220
|
+
// Construct the R2 URL
|
|
1221
|
+
url = new URL("https://".concat(R2_BUCKET_NAME, ".").concat(R2_ACCOUNT_ID, ".r2.cloudflarestorage.com/").concat(key));
|
|
1222
|
+
// Set expiration to 1 hour (3600 seconds)
|
|
1223
|
+
expiresIn = 3600;
|
|
1224
|
+
url.searchParams.set('X-Amz-Expires', expiresIn.toString());
|
|
1225
|
+
// Create a request to sign
|
|
1226
|
+
requestToSign = new Request(url, {
|
|
1227
|
+
method: 'PUT',
|
|
1228
|
+
headers: {
|
|
1229
|
+
'x-amz-meta-type': type,
|
|
1230
|
+
'x-amz-meta-local': 'false'
|
|
1231
|
+
}
|
|
1232
|
+
});
|
|
1233
|
+
return [
|
|
1234
|
+
4,
|
|
1235
|
+
client.sign(requestToSign, {
|
|
1236
|
+
aws: {
|
|
1237
|
+
signQuery: true,
|
|
1238
|
+
service: 's3'
|
|
1239
|
+
}
|
|
1240
|
+
})
|
|
1241
|
+
];
|
|
1242
|
+
case 2:
|
|
1243
|
+
signedRequest = _state.sent();
|
|
1244
|
+
// Return the presigned URL
|
|
1245
|
+
return [
|
|
1246
|
+
2,
|
|
1247
|
+
context.json({
|
|
1248
|
+
url: signedRequest.url,
|
|
1249
|
+
method: 'PUT',
|
|
1250
|
+
expiresIn: expiresIn
|
|
1251
|
+
})
|
|
1252
|
+
];
|
|
1253
|
+
case 3:
|
|
1254
|
+
error = _state.sent();
|
|
1255
|
+
console.error('Error generating presigned URL:', error);
|
|
1256
|
+
return [
|
|
1257
|
+
2,
|
|
1258
|
+
context.json({
|
|
1259
|
+
error: "Failed to generate presigned URL: ".concat(_instanceof(error, Error) ? error.message : 'Unknown error')
|
|
1260
|
+
}, 500)
|
|
1261
|
+
];
|
|
1262
|
+
case 4:
|
|
1263
|
+
return [
|
|
1264
|
+
2
|
|
1265
|
+
];
|
|
1266
|
+
}
|
|
1267
|
+
});
|
|
1268
|
+
})();
|
|
1269
|
+
});
|
|
1270
|
+
export default app;
|