bxo 0.0.5-dev.35 → 0.0.5-dev.37
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/index.ts +166 -10
- package/package.json +2 -2
- package/example.ts +0 -33
package/index.ts
CHANGED
|
@@ -319,13 +319,22 @@ export default class BXO {
|
|
|
319
319
|
const params: Record<string, string> = {};
|
|
320
320
|
let isMatch = true;
|
|
321
321
|
|
|
322
|
-
//
|
|
322
|
+
// Check for double wildcard (**) in the route
|
|
323
|
+
const hasDoubleWildcard = routeSegments.some(segment => segment === '**');
|
|
324
|
+
|
|
325
|
+
// Handle double wildcard at the end (catch-all with slashes)
|
|
326
|
+
const hasDoubleWildcardAtEnd = routeSegments.length > 0 && routeSegments[routeSegments.length - 1] === '**';
|
|
327
|
+
|
|
328
|
+
// Handle single wildcard at the end (catch-all)
|
|
323
329
|
const hasWildcardAtEnd = routeSegments.length > 0 && routeSegments[routeSegments.length - 1] === '*';
|
|
324
330
|
|
|
325
|
-
if (
|
|
326
|
-
// For
|
|
331
|
+
if (hasDoubleWildcardAtEnd) {
|
|
332
|
+
// For double wildcard at end, path must have at least as many segments as route (minus the double wildcard)
|
|
327
333
|
if (pathSegments.length < routeSegments.length - 1) continue;
|
|
328
|
-
} else {
|
|
334
|
+
} else if (hasWildcardAtEnd) {
|
|
335
|
+
// For single wildcard at end, path must have at least as many segments as route (minus the wildcard)
|
|
336
|
+
if (pathSegments.length < routeSegments.length - 1) continue;
|
|
337
|
+
} else if (!hasDoubleWildcard) {
|
|
329
338
|
// For exact matching (with possible single-segment wildcards), lengths must match
|
|
330
339
|
if (routeSegments.length !== pathSegments.length) continue;
|
|
331
340
|
}
|
|
@@ -339,7 +348,14 @@ export default class BXO {
|
|
|
339
348
|
break;
|
|
340
349
|
}
|
|
341
350
|
|
|
342
|
-
// Handle
|
|
351
|
+
// Handle double wildcard at the end (matches everything including slashes)
|
|
352
|
+
if (routeSegment === '**' && i === routeSegments.length - 1) {
|
|
353
|
+
const remainingPath = pathSegments.slice(i).join('/');
|
|
354
|
+
params['**'] = remainingPath;
|
|
355
|
+
break;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Handle single wildcard at the end (catch-all)
|
|
343
359
|
if (routeSegment === '*' && i === routeSegments.length - 1) {
|
|
344
360
|
// Wildcard at end matches remaining path segments
|
|
345
361
|
const remainingPath = pathSegments.slice(i).join('/');
|
|
@@ -347,6 +363,68 @@ export default class BXO {
|
|
|
347
363
|
break;
|
|
348
364
|
}
|
|
349
365
|
|
|
366
|
+
// Handle double wildcard in the middle (matches everything including slashes)
|
|
367
|
+
if (routeSegment === '**') {
|
|
368
|
+
// Find the next non-wildcard segment to match against
|
|
369
|
+
let nextNonWildcardIndex = i + 1;
|
|
370
|
+
while (nextNonWildcardIndex < routeSegments.length &&
|
|
371
|
+
(routeSegments[nextNonWildcardIndex] === '*' || routeSegments[nextNonWildcardIndex] === '**')) {
|
|
372
|
+
nextNonWildcardIndex++;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (nextNonWildcardIndex >= routeSegments.length) {
|
|
376
|
+
// Double wildcard is at the end or followed by other wildcards
|
|
377
|
+
const remainingPath = pathSegments.slice(i).join('/');
|
|
378
|
+
params['**'] = remainingPath;
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Find the next matching segment in the path
|
|
383
|
+
const nextRouteSegment = routeSegments[nextNonWildcardIndex];
|
|
384
|
+
if (!nextRouteSegment) {
|
|
385
|
+
isMatch = false;
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
let foundMatch = false;
|
|
390
|
+
let matchedPath = '';
|
|
391
|
+
|
|
392
|
+
for (let j = i; j < pathSegments.length; j++) {
|
|
393
|
+
const currentPathSegment = pathSegments[j];
|
|
394
|
+
|
|
395
|
+
// Check if this path segment matches the next route segment
|
|
396
|
+
if (nextRouteSegment.startsWith(':')) {
|
|
397
|
+
// Param segment - always matches
|
|
398
|
+
matchedPath = pathSegments.slice(i, j).join('/');
|
|
399
|
+
params['**'] = matchedPath;
|
|
400
|
+
i = j - 1; // Adjust index for the next iteration
|
|
401
|
+
foundMatch = true;
|
|
402
|
+
break;
|
|
403
|
+
} else if (nextRouteSegment === '*') {
|
|
404
|
+
// Single wildcard - always matches
|
|
405
|
+
matchedPath = pathSegments.slice(i, j).join('/');
|
|
406
|
+
params['**'] = matchedPath;
|
|
407
|
+
i = j - 1; // Adjust index for the next iteration
|
|
408
|
+
foundMatch = true;
|
|
409
|
+
break;
|
|
410
|
+
} else if (nextRouteSegment === currentPathSegment) {
|
|
411
|
+
// Exact match
|
|
412
|
+
matchedPath = pathSegments.slice(i, j).join('/');
|
|
413
|
+
params['**'] = matchedPath;
|
|
414
|
+
i = j - 1; // Adjust index for the next iteration
|
|
415
|
+
foundMatch = true;
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (!foundMatch) {
|
|
421
|
+
isMatch = false;
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
|
|
350
428
|
if (!pathSegment) {
|
|
351
429
|
isMatch = false;
|
|
352
430
|
break;
|
|
@@ -383,13 +461,22 @@ export default class BXO {
|
|
|
383
461
|
const params: Record<string, string> = {};
|
|
384
462
|
let isMatch = true;
|
|
385
463
|
|
|
386
|
-
//
|
|
464
|
+
// Check for double wildcard (**) in the route
|
|
465
|
+
const hasDoubleWildcard = routeSegments.some(segment => segment === '**');
|
|
466
|
+
|
|
467
|
+
// Handle double wildcard at the end (catch-all with slashes)
|
|
468
|
+
const hasDoubleWildcardAtEnd = routeSegments.length > 0 && routeSegments[routeSegments.length - 1] === '**';
|
|
469
|
+
|
|
470
|
+
// Handle single wildcard at the end (catch-all)
|
|
387
471
|
const hasWildcardAtEnd = routeSegments.length > 0 && routeSegments[routeSegments.length - 1] === '*';
|
|
388
472
|
|
|
389
|
-
if (
|
|
390
|
-
// For
|
|
473
|
+
if (hasDoubleWildcardAtEnd) {
|
|
474
|
+
// For double wildcard at end, path must have at least as many segments as route (minus the double wildcard)
|
|
391
475
|
if (pathSegments.length < routeSegments.length - 1) continue;
|
|
392
|
-
} else {
|
|
476
|
+
} else if (hasWildcardAtEnd) {
|
|
477
|
+
// For single wildcard at end, path must have at least as many segments as route (minus the wildcard)
|
|
478
|
+
if (pathSegments.length < routeSegments.length - 1) continue;
|
|
479
|
+
} else if (!hasDoubleWildcard) {
|
|
393
480
|
// For exact matching (with possible single-segment wildcards), lengths must match
|
|
394
481
|
if (routeSegments.length !== pathSegments.length) continue;
|
|
395
482
|
}
|
|
@@ -403,7 +490,14 @@ export default class BXO {
|
|
|
403
490
|
break;
|
|
404
491
|
}
|
|
405
492
|
|
|
406
|
-
// Handle
|
|
493
|
+
// Handle double wildcard at the end (matches everything including slashes)
|
|
494
|
+
if (routeSegment === '**' && i === routeSegments.length - 1) {
|
|
495
|
+
const remainingPath = pathSegments.slice(i).join('/');
|
|
496
|
+
params['**'] = remainingPath;
|
|
497
|
+
break;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Handle single wildcard at the end (catch-all)
|
|
407
501
|
if (routeSegment === '*' && i === routeSegments.length - 1) {
|
|
408
502
|
// Wildcard at end matches remaining path segments
|
|
409
503
|
const remainingPath = pathSegments.slice(i).join('/');
|
|
@@ -411,6 +505,68 @@ export default class BXO {
|
|
|
411
505
|
break;
|
|
412
506
|
}
|
|
413
507
|
|
|
508
|
+
// Handle double wildcard in the middle (matches everything including slashes)
|
|
509
|
+
if (routeSegment === '**') {
|
|
510
|
+
// Find the next non-wildcard segment to match against
|
|
511
|
+
let nextNonWildcardIndex = i + 1;
|
|
512
|
+
while (nextNonWildcardIndex < routeSegments.length &&
|
|
513
|
+
(routeSegments[nextNonWildcardIndex] === '*' || routeSegments[nextNonWildcardIndex] === '**')) {
|
|
514
|
+
nextNonWildcardIndex++;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
if (nextNonWildcardIndex >= routeSegments.length) {
|
|
518
|
+
// Double wildcard is at the end or followed by other wildcards
|
|
519
|
+
const remainingPath = pathSegments.slice(i).join('/');
|
|
520
|
+
params['**'] = remainingPath;
|
|
521
|
+
break;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Find the next matching segment in the path
|
|
525
|
+
const nextRouteSegment = routeSegments[nextNonWildcardIndex];
|
|
526
|
+
if (!nextRouteSegment) {
|
|
527
|
+
isMatch = false;
|
|
528
|
+
break;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
let foundMatch = false;
|
|
532
|
+
let matchedPath = '';
|
|
533
|
+
|
|
534
|
+
for (let j = i; j < pathSegments.length; j++) {
|
|
535
|
+
const currentPathSegment = pathSegments[j];
|
|
536
|
+
|
|
537
|
+
// Check if this path segment matches the next route segment
|
|
538
|
+
if (nextRouteSegment.startsWith(':')) {
|
|
539
|
+
// Param segment - always matches
|
|
540
|
+
matchedPath = pathSegments.slice(i, j).join('/');
|
|
541
|
+
params['**'] = matchedPath;
|
|
542
|
+
i = j - 1; // Adjust index for the next iteration
|
|
543
|
+
foundMatch = true;
|
|
544
|
+
break;
|
|
545
|
+
} else if (nextRouteSegment === '*') {
|
|
546
|
+
// Single wildcard - always matches
|
|
547
|
+
matchedPath = pathSegments.slice(i, j).join('/');
|
|
548
|
+
params['**'] = matchedPath;
|
|
549
|
+
i = j - 1; // Adjust index for the next iteration
|
|
550
|
+
foundMatch = true;
|
|
551
|
+
break;
|
|
552
|
+
} else if (nextRouteSegment === currentPathSegment) {
|
|
553
|
+
// Exact match
|
|
554
|
+
matchedPath = pathSegments.slice(i, j).join('/');
|
|
555
|
+
params['**'] = matchedPath;
|
|
556
|
+
i = j - 1; // Adjust index for the next iteration
|
|
557
|
+
foundMatch = true;
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
if (!foundMatch) {
|
|
563
|
+
isMatch = false;
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
|
|
414
570
|
if (!pathSegment) {
|
|
415
571
|
isMatch = false;
|
|
416
572
|
break;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bxo",
|
|
3
3
|
"module": "index.ts",
|
|
4
|
-
"version": "0.0.5-dev.
|
|
4
|
+
"version": "0.0.5-dev.37",
|
|
5
5
|
"description": "A simple and lightweight web framework for Bun",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"devDependencies": {
|
|
@@ -15,6 +15,6 @@
|
|
|
15
15
|
"typescript": "^5"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"zod": "^
|
|
18
|
+
"zod": "^3.25.76"
|
|
19
19
|
}
|
|
20
20
|
}
|
package/example.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import BXO, { createCookie, redirect } from 'bxo';
|
|
2
|
-
|
|
3
|
-
const app = new BXO();
|
|
4
|
-
|
|
5
|
-
// 1) Explicit return redirect (302 default)
|
|
6
|
-
app.get('/old', ({ redirect }) => {
|
|
7
|
-
return redirect('/new');
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
// 2) Implicit redirect (no return needed)
|
|
11
|
-
app.get('/implicit', (ctx) => {
|
|
12
|
-
ctx.redirect('/new');
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
// 3) Custom status (303 after POST)
|
|
16
|
-
app.post('/submit', (ctx) => {
|
|
17
|
-
// ...handle form...
|
|
18
|
-
return ctx.redirect('/thanks', 303);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
// 4) Redirect with cookie
|
|
22
|
-
app.get('/login', (ctx) => {
|
|
23
|
-
ctx.set.cookies = [
|
|
24
|
-
createCookie('sid', 'abc123', { httpOnly: true, path: '/' })
|
|
25
|
-
];
|
|
26
|
-
ctx.redirect('/dashboard'); // no return required
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
// 5) Using top-level helper (outside ctx)
|
|
30
|
-
app.get('/go-external', () => redirect('https://example.com', 307));
|
|
31
|
-
|
|
32
|
-
await app.start(3000);
|
|
33
|
-
console.log('Server running at http://localhost:3000');
|