@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.
Files changed (52) hide show
  1. package/dist/src/api.js +1270 -0
  2. package/dist/src/brain-runner-do.js +654 -0
  3. package/dist/src/dev-server.js +1357 -0
  4. package/{src/index.ts → dist/src/index.js} +1 -6
  5. package/dist/src/manifest.js +278 -0
  6. package/dist/src/monitor-do.js +408 -0
  7. package/{src/node-index.ts → dist/src/node-index.js} +3 -7
  8. package/dist/src/r2-loader.js +207 -0
  9. package/dist/src/schedule-do.js +705 -0
  10. package/dist/src/sqlite-adapter.js +69 -0
  11. package/dist/types/api.d.ts +21 -0
  12. package/dist/types/api.d.ts.map +1 -0
  13. package/dist/types/brain-runner-do.d.ts +25 -0
  14. package/dist/types/brain-runner-do.d.ts.map +1 -0
  15. package/dist/types/dev-server.d.ts +45 -0
  16. package/dist/types/dev-server.d.ts.map +1 -0
  17. package/dist/types/index.d.ts +7 -0
  18. package/dist/types/index.d.ts.map +1 -0
  19. package/dist/types/manifest.d.ts +11 -0
  20. package/dist/types/manifest.d.ts.map +1 -0
  21. package/dist/types/monitor-do.d.ts +16 -0
  22. package/dist/types/monitor-do.d.ts.map +1 -0
  23. package/dist/types/node-index.d.ts +10 -0
  24. package/dist/types/node-index.d.ts.map +1 -0
  25. package/dist/types/r2-loader.d.ts +10 -0
  26. package/dist/types/r2-loader.d.ts.map +1 -0
  27. package/dist/types/schedule-do.d.ts +47 -0
  28. package/dist/types/schedule-do.d.ts.map +1 -0
  29. package/dist/types/sqlite-adapter.d.ts +10 -0
  30. package/dist/types/sqlite-adapter.d.ts.map +1 -0
  31. package/package.json +5 -1
  32. package/src/api.ts +0 -579
  33. package/src/brain-runner-do.ts +0 -309
  34. package/src/dev-server.ts +0 -776
  35. package/src/manifest.ts +0 -69
  36. package/src/monitor-do.ts +0 -268
  37. package/src/r2-loader.ts +0 -27
  38. package/src/schedule-do.ts +0 -377
  39. package/src/sqlite-adapter.ts +0 -50
  40. package/test-project/package-lock.json +0 -3010
  41. package/test-project/package.json +0 -21
  42. package/test-project/src/index.ts +0 -70
  43. package/test-project/src/runner.ts +0 -24
  44. package/test-project/tests/api.test.ts +0 -1005
  45. package/test-project/tests/r2loader.test.ts +0 -73
  46. package/test-project/tests/resources-api.test.ts +0 -671
  47. package/test-project/tests/spec.test.ts +0 -135
  48. package/test-project/tests/tsconfig.json +0 -7
  49. package/test-project/tsconfig.json +0 -20
  50. package/test-project/vitest.config.ts +0 -12
  51. package/test-project/wrangler.jsonc +0 -53
  52. package/tsconfig.json +0 -11
@@ -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;