@positronic/cloudflare 0.0.76 → 0.0.78
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/brains.js +90 -195
- package/dist/src/api/files.js +178 -0
- package/dist/src/api/index.js +9 -0
- package/dist/src/api/webhooks/coordination.js +0 -2
- package/dist/src/api/webhooks/index.js +43 -36
- package/dist/src/api/webhooks/system.js +23 -21
- package/dist/src/brain-runner-do.js +113 -173
- package/dist/src/content-type.js +6 -0
- package/dist/src/dev-server.js +128 -18
- package/dist/src/file-utils.js +7 -0
- package/dist/src/files-service.js +465 -0
- package/dist/src/manifest.js +13 -8
- package/dist/src/monitor-do.js +17 -0
- package/dist/src/schedule-do.js +5 -19
- package/dist/src/zip-builder.js +507 -0
- package/dist/types/api/brains.d.ts.map +1 -1
- package/dist/types/api/files.d.ts +7 -0
- package/dist/types/api/files.d.ts.map +1 -0
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/webhooks/coordination.d.ts +0 -1
- package/dist/types/api/webhooks/coordination.d.ts.map +1 -1
- package/dist/types/api/webhooks/index.d.ts.map +1 -1
- package/dist/types/api/webhooks/system.d.ts.map +1 -1
- package/dist/types/brain-runner-do.d.ts +13 -7
- package/dist/types/brain-runner-do.d.ts.map +1 -1
- package/dist/types/content-type.d.ts +2 -0
- package/dist/types/content-type.d.ts.map +1 -0
- package/dist/types/dev-server.d.ts +1 -0
- package/dist/types/dev-server.d.ts.map +1 -1
- package/dist/types/file-utils.d.ts +3 -0
- package/dist/types/file-utils.d.ts.map +1 -0
- package/dist/types/files-service.d.ts +4 -0
- package/dist/types/files-service.d.ts.map +1 -0
- package/dist/types/manifest.d.ts.map +1 -1
- package/dist/types/monitor-do.d.ts +6 -0
- package/dist/types/monitor-do.d.ts.map +1 -1
- package/dist/types/schedule-do.d.ts +0 -1
- package/dist/types/schedule-do.d.ts.map +1 -1
- package/dist/types/zip-builder.d.ts +4 -0
- package/dist/types/zip-builder.d.ts.map +1 -0
- package/package.json +5 -4
package/dist/src/api/brains.js
CHANGED
|
@@ -154,13 +154,43 @@ function _ts_generator(thisArg, body) {
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
import { Hono } from 'hono';
|
|
157
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
158
157
|
import { Cron } from 'croner';
|
|
159
158
|
import Fuse from 'fuse.js';
|
|
160
159
|
import { isSignalValid, brainMachineDefinition } from '@positronic/core';
|
|
161
160
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
162
|
-
import { getManifest } from '../brain-runner-do.js';
|
|
161
|
+
import { getManifest, startBrainRun } from '../brain-runner-do.js';
|
|
163
162
|
var brains = new Hono();
|
|
163
|
+
/**
|
|
164
|
+
* Resolve a brain identifier from the manifest. Returns the brain and title
|
|
165
|
+
* on success, or an HTTP error Response on failure.
|
|
166
|
+
*/ function resolveBrain(context, identifier) {
|
|
167
|
+
var multipleMatchStatus = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 300;
|
|
168
|
+
var manifest = getManifest();
|
|
169
|
+
if (!manifest) {
|
|
170
|
+
return context.json({
|
|
171
|
+
error: 'Manifest not initialized'
|
|
172
|
+
}, 500);
|
|
173
|
+
}
|
|
174
|
+
var resolution = manifest.resolve(identifier);
|
|
175
|
+
if (resolution.matchType === 'none') {
|
|
176
|
+
return context.json({
|
|
177
|
+
error: "Brain '".concat(identifier, "' not found")
|
|
178
|
+
}, 404);
|
|
179
|
+
}
|
|
180
|
+
if (resolution.matchType === 'multiple') {
|
|
181
|
+
return context.json({
|
|
182
|
+
error: 'Multiple brains match the identifier',
|
|
183
|
+
matchType: 'multiple',
|
|
184
|
+
candidates: resolution.candidates
|
|
185
|
+
}, multipleMatchStatus);
|
|
186
|
+
}
|
|
187
|
+
var brain = resolution.brain;
|
|
188
|
+
var brainTitle = brain.title || identifier;
|
|
189
|
+
return {
|
|
190
|
+
brain: brain,
|
|
191
|
+
brainTitle: brainTitle
|
|
192
|
+
};
|
|
193
|
+
}
|
|
164
194
|
/**
|
|
165
195
|
* Get the userName for ownership filtering from the auth context.
|
|
166
196
|
* Root users get null (no filter — sees everything).
|
|
@@ -172,7 +202,7 @@ var brains = new Hono();
|
|
|
172
202
|
}
|
|
173
203
|
brains.post('/runs', function(context) {
|
|
174
204
|
return _async_to_generator(function() {
|
|
175
|
-
var requestBody, options, initialState, identifier,
|
|
205
|
+
var requestBody, options, initialState, identifier, result, brain, auth, currentUser, initialData, brainRunId, response;
|
|
176
206
|
return _ts_generator(this, function(_state) {
|
|
177
207
|
switch(_state.label){
|
|
178
208
|
case 0:
|
|
@@ -194,40 +224,12 @@ brains.post('/runs', function(context) {
|
|
|
194
224
|
];
|
|
195
225
|
}
|
|
196
226
|
// Validate that the brain exists before starting it
|
|
197
|
-
|
|
198
|
-
if (!
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}, 500)
|
|
204
|
-
];
|
|
205
|
-
}
|
|
206
|
-
// Resolve the identifier to find the brain
|
|
207
|
-
resolution = manifest.resolve(identifier);
|
|
208
|
-
if (resolution.matchType === 'none') {
|
|
209
|
-
return [
|
|
210
|
-
2,
|
|
211
|
-
context.json({
|
|
212
|
-
error: "Brain '".concat(identifier, "' not found")
|
|
213
|
-
}, 404)
|
|
214
|
-
];
|
|
215
|
-
}
|
|
216
|
-
if (resolution.matchType === 'multiple') {
|
|
217
|
-
return [
|
|
218
|
-
2,
|
|
219
|
-
context.json({
|
|
220
|
-
error: 'Multiple brains match the identifier',
|
|
221
|
-
matchType: 'multiple',
|
|
222
|
-
candidates: resolution.candidates
|
|
223
|
-
}, 409)
|
|
224
|
-
];
|
|
225
|
-
}
|
|
226
|
-
brain = resolution.brain;
|
|
227
|
-
brainRunId = uuidv4();
|
|
228
|
-
namespace = context.env.BRAIN_RUNNER_DO;
|
|
229
|
-
doId = namespace.idFromName(brainRunId);
|
|
230
|
-
stub = namespace.get(doId);
|
|
227
|
+
result = resolveBrain(context, identifier, 409);
|
|
228
|
+
if (!('brain' in result)) return [
|
|
229
|
+
2,
|
|
230
|
+
result
|
|
231
|
+
];
|
|
232
|
+
brain = result.brain;
|
|
231
233
|
// Read auth context for currentUser (every brain run must have an owner)
|
|
232
234
|
auth = context.get('auth');
|
|
233
235
|
if (!(auth === null || auth === void 0 ? void 0 : auth.userName) && !(auth === null || auth === void 0 ? void 0 : auth.isRoot)) {
|
|
@@ -247,14 +249,12 @@ brains.post('/runs', function(context) {
|
|
|
247
249
|
}, initialState && {
|
|
248
250
|
initialState: initialState
|
|
249
251
|
}) : undefined;
|
|
250
|
-
// Get the actual brain title from the resolved brain
|
|
251
|
-
brainTitle = brain.title || identifier;
|
|
252
252
|
return [
|
|
253
253
|
4,
|
|
254
|
-
|
|
254
|
+
startBrainRun(context.env.BRAIN_RUNNER_DO, result.brainTitle, currentUser, initialData)
|
|
255
255
|
];
|
|
256
256
|
case 2:
|
|
257
|
-
_state.sent();
|
|
257
|
+
brainRunId = _state.sent();
|
|
258
258
|
response = {
|
|
259
259
|
brainRunId: brainRunId
|
|
260
260
|
};
|
|
@@ -321,21 +321,27 @@ brains.post('/runs/rerun', function(context) {
|
|
|
321
321
|
case 3:
|
|
322
322
|
_state.trys.push([
|
|
323
323
|
3,
|
|
324
|
-
|
|
324
|
+
6,
|
|
325
325
|
,
|
|
326
|
-
|
|
326
|
+
7
|
|
327
327
|
]);
|
|
328
328
|
return [
|
|
329
329
|
4,
|
|
330
|
-
|
|
330
|
+
monitorStub.prepareForRerun(runId)
|
|
331
331
|
];
|
|
332
332
|
case 4:
|
|
333
333
|
_state.sent();
|
|
334
334
|
return [
|
|
335
|
-
|
|
336
|
-
|
|
335
|
+
4,
|
|
336
|
+
stub.rerun(startsAt)
|
|
337
337
|
];
|
|
338
338
|
case 5:
|
|
339
|
+
_state.sent();
|
|
340
|
+
return [
|
|
341
|
+
3,
|
|
342
|
+
7
|
|
343
|
+
];
|
|
344
|
+
case 6:
|
|
339
345
|
error = _state.sent();
|
|
340
346
|
return [
|
|
341
347
|
2,
|
|
@@ -343,7 +349,7 @@ brains.post('/runs/rerun', function(context) {
|
|
|
343
349
|
error: error.message || 'Rerun failed'
|
|
344
350
|
}, 500)
|
|
345
351
|
];
|
|
346
|
-
case
|
|
352
|
+
case 7:
|
|
347
353
|
return [
|
|
348
354
|
2,
|
|
349
355
|
context.json({
|
|
@@ -486,7 +492,7 @@ brains.delete('/runs/:runId', function(context) {
|
|
|
486
492
|
});
|
|
487
493
|
})();
|
|
488
494
|
});
|
|
489
|
-
// Signal endpoint - queue KILL, PAUSE,
|
|
495
|
+
// Signal endpoint - queue KILL, PAUSE, RESUME, or WEBHOOK_RESPONSE signals
|
|
490
496
|
brains.post('/runs/:runId/signals', function(context) {
|
|
491
497
|
return _async_to_generator(function() {
|
|
492
498
|
var runId, body, monitorId, monitorStub, run, validation, namespace, doId, stub, signal;
|
|
@@ -504,7 +510,6 @@ brains.post('/runs/:runId/signals', function(context) {
|
|
|
504
510
|
if (![
|
|
505
511
|
'KILL',
|
|
506
512
|
'PAUSE',
|
|
507
|
-
'USER_MESSAGE',
|
|
508
513
|
'RESUME',
|
|
509
514
|
'WEBHOOK_RESPONSE'
|
|
510
515
|
].includes(body.type)) {
|
|
@@ -533,18 +538,14 @@ brains.post('/runs/:runId/signals', function(context) {
|
|
|
533
538
|
];
|
|
534
539
|
}
|
|
535
540
|
// Validate control signals against current brain state using state machine definition
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
error: validation.reason
|
|
545
|
-
}, 409)
|
|
546
|
-
];
|
|
547
|
-
}
|
|
541
|
+
validation = isSignalValid(brainMachineDefinition, run.status, body.type);
|
|
542
|
+
if (!validation.valid) {
|
|
543
|
+
return [
|
|
544
|
+
2,
|
|
545
|
+
context.json({
|
|
546
|
+
error: validation.reason
|
|
547
|
+
}, 409)
|
|
548
|
+
];
|
|
548
549
|
}
|
|
549
550
|
// Get BrainRunnerDO stub and queue the signal
|
|
550
551
|
namespace = context.env.BRAIN_RUNNER_DO;
|
|
@@ -647,51 +648,23 @@ brains.post('/runs/:runId/resume', function(context) {
|
|
|
647
648
|
});
|
|
648
649
|
brains.get('/:identifier/history', function(context) {
|
|
649
650
|
return _async_to_generator(function() {
|
|
650
|
-
var identifier, limit,
|
|
651
|
+
var identifier, limit, result, monitorId, monitorStub, userName, runs;
|
|
651
652
|
return _ts_generator(this, function(_state) {
|
|
652
653
|
switch(_state.label){
|
|
653
654
|
case 0:
|
|
654
655
|
identifier = context.req.param('identifier');
|
|
655
656
|
limit = Number(context.req.query('limit') || '10');
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
context.json({
|
|
662
|
-
error: 'Manifest not initialized'
|
|
663
|
-
}, 500)
|
|
664
|
-
];
|
|
665
|
-
}
|
|
666
|
-
resolution = manifest.resolve(identifier);
|
|
667
|
-
if (resolution.matchType === 'none') {
|
|
668
|
-
return [
|
|
669
|
-
2,
|
|
670
|
-
context.json({
|
|
671
|
-
error: "Brain '".concat(identifier, "' not found")
|
|
672
|
-
}, 404)
|
|
673
|
-
];
|
|
674
|
-
}
|
|
675
|
-
if (resolution.matchType === 'multiple') {
|
|
676
|
-
return [
|
|
677
|
-
2,
|
|
678
|
-
context.json({
|
|
679
|
-
error: 'Multiple brains match the identifier',
|
|
680
|
-
matchType: 'multiple',
|
|
681
|
-
candidates: resolution.candidates
|
|
682
|
-
}, 300)
|
|
683
|
-
];
|
|
684
|
-
}
|
|
685
|
-
// Get the actual brain title
|
|
686
|
-
brain = resolution.brain;
|
|
687
|
-
brainTitle = brain.title || identifier;
|
|
688
|
-
// Get the monitor singleton instance
|
|
657
|
+
result = resolveBrain(context, identifier);
|
|
658
|
+
if (!('brain' in result)) return [
|
|
659
|
+
2,
|
|
660
|
+
result
|
|
661
|
+
];
|
|
689
662
|
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
690
663
|
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
691
664
|
userName = scopeUserName(context);
|
|
692
665
|
return [
|
|
693
666
|
4,
|
|
694
|
-
monitorStub.history(brainTitle, limit, userName)
|
|
667
|
+
monitorStub.history(result.brainTitle, limit, userName)
|
|
695
668
|
];
|
|
696
669
|
case 1:
|
|
697
670
|
runs = _state.sent();
|
|
@@ -707,50 +680,22 @@ brains.get('/:identifier/history', function(context) {
|
|
|
707
680
|
});
|
|
708
681
|
brains.get('/:identifier/active-runs', function(context) {
|
|
709
682
|
return _async_to_generator(function() {
|
|
710
|
-
var identifier,
|
|
683
|
+
var identifier, result, monitorId, monitorStub, userName, runs;
|
|
711
684
|
return _ts_generator(this, function(_state) {
|
|
712
685
|
switch(_state.label){
|
|
713
686
|
case 0:
|
|
714
687
|
identifier = context.req.param('identifier');
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
context.json({
|
|
721
|
-
error: 'Manifest not initialized'
|
|
722
|
-
}, 500)
|
|
723
|
-
];
|
|
724
|
-
}
|
|
725
|
-
resolution = manifest.resolve(identifier);
|
|
726
|
-
if (resolution.matchType === 'none') {
|
|
727
|
-
return [
|
|
728
|
-
2,
|
|
729
|
-
context.json({
|
|
730
|
-
error: "Brain '".concat(identifier, "' not found")
|
|
731
|
-
}, 404)
|
|
732
|
-
];
|
|
733
|
-
}
|
|
734
|
-
if (resolution.matchType === 'multiple') {
|
|
735
|
-
return [
|
|
736
|
-
2,
|
|
737
|
-
context.json({
|
|
738
|
-
error: 'Multiple brains match the identifier',
|
|
739
|
-
matchType: 'multiple',
|
|
740
|
-
candidates: resolution.candidates
|
|
741
|
-
}, 300)
|
|
742
|
-
];
|
|
743
|
-
}
|
|
744
|
-
// Get the actual brain title
|
|
745
|
-
brain = resolution.brain;
|
|
746
|
-
brainTitle = brain.title || identifier;
|
|
747
|
-
// Get the monitor singleton instance
|
|
688
|
+
result = resolveBrain(context, identifier);
|
|
689
|
+
if (!('brain' in result)) return [
|
|
690
|
+
2,
|
|
691
|
+
result
|
|
692
|
+
];
|
|
748
693
|
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
749
694
|
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
750
695
|
userName = scopeUserName(context);
|
|
751
696
|
return [
|
|
752
697
|
4,
|
|
753
|
-
monitorStub.activeRuns(brainTitle, userName)
|
|
698
|
+
monitorStub.activeRuns(result.brainTitle, userName)
|
|
754
699
|
];
|
|
755
700
|
case 1:
|
|
756
701
|
runs = _state.sent();
|
|
@@ -931,7 +876,7 @@ brains.get('/', function(context) {
|
|
|
931
876
|
// Create a new schedule
|
|
932
877
|
brains.post('/schedules', function(context) {
|
|
933
878
|
return _async_to_generator(function() {
|
|
934
|
-
var body, cronExpression, identifier,
|
|
879
|
+
var body, cronExpression, identifier, result, brainTitle, scheduleDoId, scheduleStub, auth, runAsUserName, timezone, schedule, error, errorMessage;
|
|
935
880
|
return _ts_generator(this, function(_state) {
|
|
936
881
|
switch(_state.label){
|
|
937
882
|
case 0:
|
|
@@ -978,37 +923,12 @@ brains.post('/schedules', function(context) {
|
|
|
978
923
|
];
|
|
979
924
|
}
|
|
980
925
|
// Resolve the identifier to get the actual brain title
|
|
981
|
-
|
|
982
|
-
if (!
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
}, 500)
|
|
988
|
-
];
|
|
989
|
-
}
|
|
990
|
-
resolution = manifest.resolve(identifier);
|
|
991
|
-
if (resolution.matchType === 'none') {
|
|
992
|
-
return [
|
|
993
|
-
2,
|
|
994
|
-
context.json({
|
|
995
|
-
error: "Brain '".concat(identifier, "' not found")
|
|
996
|
-
}, 404)
|
|
997
|
-
];
|
|
998
|
-
}
|
|
999
|
-
if (resolution.matchType === 'multiple') {
|
|
1000
|
-
return [
|
|
1001
|
-
2,
|
|
1002
|
-
context.json({
|
|
1003
|
-
error: 'Multiple brains match the identifier',
|
|
1004
|
-
matchType: 'multiple',
|
|
1005
|
-
candidates: resolution.candidates
|
|
1006
|
-
}, 409)
|
|
1007
|
-
];
|
|
1008
|
-
}
|
|
1009
|
-
// Get the actual brain title
|
|
1010
|
-
brain = resolution.brain;
|
|
1011
|
-
brainTitle = brain.title || identifier;
|
|
926
|
+
result = resolveBrain(context, identifier, 409);
|
|
927
|
+
if (!('brain' in result)) return [
|
|
928
|
+
2,
|
|
929
|
+
result
|
|
930
|
+
];
|
|
931
|
+
brainTitle = result.brainTitle;
|
|
1012
932
|
// Get the schedule singleton instance
|
|
1013
933
|
scheduleDoId = context.env.SCHEDULE_DO.idFromName('singleton');
|
|
1014
934
|
scheduleStub = context.env.SCHEDULE_DO.get(scheduleDoId);
|
|
@@ -1241,40 +1161,15 @@ brains.delete('/schedules/:scheduleId', function(context) {
|
|
|
1241
1161
|
});
|
|
1242
1162
|
brains.get('/:identifier', function(context) {
|
|
1243
1163
|
return _async_to_generator(function() {
|
|
1244
|
-
var identifier,
|
|
1164
|
+
var identifier, result, brain, structure;
|
|
1245
1165
|
return _ts_generator(this, function(_state) {
|
|
1246
1166
|
identifier = context.req.param('identifier');
|
|
1247
|
-
|
|
1248
|
-
if (!
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
}, 500)
|
|
1254
|
-
];
|
|
1255
|
-
}
|
|
1256
|
-
// Resolve the identifier to find the brain
|
|
1257
|
-
resolution = manifest.resolve(identifier);
|
|
1258
|
-
if (resolution.matchType === 'none') {
|
|
1259
|
-
return [
|
|
1260
|
-
2,
|
|
1261
|
-
context.json({
|
|
1262
|
-
error: "Brain '".concat(identifier, "' not found")
|
|
1263
|
-
}, 404)
|
|
1264
|
-
];
|
|
1265
|
-
}
|
|
1266
|
-
if (resolution.matchType === 'multiple') {
|
|
1267
|
-
return [
|
|
1268
|
-
2,
|
|
1269
|
-
context.json({
|
|
1270
|
-
error: 'Multiple brains match the identifier',
|
|
1271
|
-
matchType: 'multiple',
|
|
1272
|
-
candidates: resolution.candidates
|
|
1273
|
-
}, 300)
|
|
1274
|
-
];
|
|
1275
|
-
}
|
|
1276
|
-
brain = resolution.brain;
|
|
1277
|
-
// Get the brain structure
|
|
1167
|
+
result = resolveBrain(context, identifier);
|
|
1168
|
+
if (!('brain' in result)) return [
|
|
1169
|
+
2,
|
|
1170
|
+
result
|
|
1171
|
+
];
|
|
1172
|
+
brain = result.brain;
|
|
1278
1173
|
structure = brain.structure;
|
|
1279
1174
|
return [
|
|
1280
1175
|
2,
|
|
@@ -0,0 +1,178 @@
|
|
|
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 _ts_generator(thisArg, body) {
|
|
31
|
+
var f, y, t, _ = {
|
|
32
|
+
label: 0,
|
|
33
|
+
sent: function() {
|
|
34
|
+
if (t[0] & 1) throw t[1];
|
|
35
|
+
return t[1];
|
|
36
|
+
},
|
|
37
|
+
trys: [],
|
|
38
|
+
ops: []
|
|
39
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
40
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
41
|
+
return this;
|
|
42
|
+
}), g;
|
|
43
|
+
function verb(n) {
|
|
44
|
+
return function(v) {
|
|
45
|
+
return step([
|
|
46
|
+
n,
|
|
47
|
+
v
|
|
48
|
+
]);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function step(op) {
|
|
52
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
53
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
54
|
+
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;
|
|
55
|
+
if (y = 0, t) op = [
|
|
56
|
+
op[0] & 2,
|
|
57
|
+
t.value
|
|
58
|
+
];
|
|
59
|
+
switch(op[0]){
|
|
60
|
+
case 0:
|
|
61
|
+
case 1:
|
|
62
|
+
t = op;
|
|
63
|
+
break;
|
|
64
|
+
case 4:
|
|
65
|
+
_.label++;
|
|
66
|
+
return {
|
|
67
|
+
value: op[1],
|
|
68
|
+
done: false
|
|
69
|
+
};
|
|
70
|
+
case 5:
|
|
71
|
+
_.label++;
|
|
72
|
+
y = op[1];
|
|
73
|
+
op = [
|
|
74
|
+
0
|
|
75
|
+
];
|
|
76
|
+
continue;
|
|
77
|
+
case 7:
|
|
78
|
+
op = _.ops.pop();
|
|
79
|
+
_.trys.pop();
|
|
80
|
+
continue;
|
|
81
|
+
default:
|
|
82
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
83
|
+
_ = 0;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
87
|
+
_.label = op[1];
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
91
|
+
_.label = t[1];
|
|
92
|
+
t = op;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
if (t && _.label < t[2]) {
|
|
96
|
+
_.label = t[2];
|
|
97
|
+
_.ops.push(op);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
if (t[2]) _.ops.pop();
|
|
101
|
+
_.trys.pop();
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
op = body.call(thisArg, _);
|
|
105
|
+
} catch (e) {
|
|
106
|
+
op = [
|
|
107
|
+
6,
|
|
108
|
+
e
|
|
109
|
+
];
|
|
110
|
+
y = 0;
|
|
111
|
+
} finally{
|
|
112
|
+
f = t = 0;
|
|
113
|
+
}
|
|
114
|
+
if (op[0] & 5) throw op[1];
|
|
115
|
+
return {
|
|
116
|
+
value: op[0] ? op[1] : void 0,
|
|
117
|
+
done: true
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
import { Hono } from 'hono';
|
|
122
|
+
import { guessContentType } from '../content-type.js';
|
|
123
|
+
var files = new Hono();
|
|
124
|
+
/**
|
|
125
|
+
* GET /files/* — serves file content from R2.
|
|
126
|
+
* URL path is /files/user/{userName}/{brainTitle}/{name}
|
|
127
|
+
* R2 key is files/user/{userName}/{brainTitle}/{name} (prepend "files/" prefix)
|
|
128
|
+
* Public endpoint (no auth) so download URLs work in browsers.
|
|
129
|
+
*/ files.get('/*', function(context) {
|
|
130
|
+
return _async_to_generator(function() {
|
|
131
|
+
var path, key, bucket, object, headers;
|
|
132
|
+
return _ts_generator(this, function(_state) {
|
|
133
|
+
switch(_state.label){
|
|
134
|
+
case 0:
|
|
135
|
+
path = context.req.path.replace(/^\/files\//, '');
|
|
136
|
+
if (!path) {
|
|
137
|
+
return [
|
|
138
|
+
2,
|
|
139
|
+
context.json({
|
|
140
|
+
error: 'File path is required'
|
|
141
|
+
}, 400)
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
// Reconstruct the R2 key by adding the "files/" namespace prefix
|
|
145
|
+
key = "files/".concat(path);
|
|
146
|
+
bucket = context.env.RESOURCES_BUCKET;
|
|
147
|
+
return [
|
|
148
|
+
4,
|
|
149
|
+
bucket.get(key)
|
|
150
|
+
];
|
|
151
|
+
case 1:
|
|
152
|
+
object = _state.sent();
|
|
153
|
+
if (!object) {
|
|
154
|
+
return [
|
|
155
|
+
2,
|
|
156
|
+
context.json({
|
|
157
|
+
error: 'File not found'
|
|
158
|
+
}, 404)
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
headers = new Headers();
|
|
162
|
+
object.writeHttpMetadata(headers);
|
|
163
|
+
// If no content-type was stored, infer from the key
|
|
164
|
+
if (!headers.get('content-type')) {
|
|
165
|
+
headers.set('content-type', guessContentType(key));
|
|
166
|
+
}
|
|
167
|
+
headers.set('etag', object.httpEtag);
|
|
168
|
+
return [
|
|
169
|
+
2,
|
|
170
|
+
new Response(object.body, {
|
|
171
|
+
headers: headers
|
|
172
|
+
})
|
|
173
|
+
];
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
})();
|
|
177
|
+
});
|
|
178
|
+
export default files;
|
package/dist/src/api/index.js
CHANGED
|
@@ -127,6 +127,7 @@ import secrets from './secrets.js';
|
|
|
127
127
|
import bundle from './bundle.js';
|
|
128
128
|
import users from './users.js';
|
|
129
129
|
import store from './store.js';
|
|
130
|
+
import files from './files.js';
|
|
130
131
|
import { authMiddleware } from './auth-middleware.js';
|
|
131
132
|
var app = new Hono();
|
|
132
133
|
// Health check endpoint (no auth required)
|
|
@@ -191,6 +192,13 @@ app.use('*', function(c, next) {
|
|
|
191
192
|
next()
|
|
192
193
|
];
|
|
193
194
|
}
|
|
195
|
+
// Skip auth for files (download URLs are public)
|
|
196
|
+
if (c.req.method === 'GET' && c.req.path.startsWith('/files/')) {
|
|
197
|
+
return [
|
|
198
|
+
2,
|
|
199
|
+
next()
|
|
200
|
+
];
|
|
201
|
+
}
|
|
194
202
|
// Skip auth for all webhook POST requests (external services and browser forms can't send JWT)
|
|
195
203
|
if (c.req.method === 'POST' && c.req.path.startsWith('/webhooks/')) {
|
|
196
204
|
return [
|
|
@@ -239,4 +247,5 @@ app.route('/secrets', secrets);
|
|
|
239
247
|
app.route('/bundle', bundle);
|
|
240
248
|
app.route('/users', users);
|
|
241
249
|
app.route('/store', store);
|
|
250
|
+
app.route('/files', files);
|
|
242
251
|
export default app;
|