@@ -545,17 +545,24 @@ describe('createHonoApp', () => {
545545 } ) ;
546546 } ) ;
547547
548- describe ( 'Vercel Delegation Pattern (inner.fetch)' , ( ) => {
549- it ( 'works when an outer Hono app delegates via inner.fetch(c.req.raw)' , async ( ) => {
548+ describe ( 'Vercel Delegation Pattern (api/index.ts → inner.fetch)' , ( ) => {
549+ /**
550+ * Helper: creates the same outer→inner delegation pattern used by
551+ * `apps/studio/api/index.ts`. The outer Hono app delegates all
552+ * requests to the inner ObjectStack Hono app via `inner.fetch()`.
553+ */
554+ function createVercelApp ( ) {
550555 const innerApp = createHonoApp ( { kernel : mockKernel , prefix : '/api/v1' } ) ;
551-
552- // Simulate the Vercel catch-all pattern: outer app wraps inner app
553556 const outerApp = new Hono ( ) ;
554- outerApp . all ( '/ *' , async ( c ) => {
557+ outerApp . all ( '*' , async ( c ) => {
555558 return innerApp . fetch ( c . req . raw ) ;
556559 } ) ;
560+ return outerApp ;
561+ }
562+
563+ it ( 'works when an outer Hono app delegates via inner.fetch(c.req.raw)' , async ( ) => {
564+ const outerApp = createVercelApp ( ) ;
557565
558- // Request with the full /api/v1 prefix — should route correctly
559566 const res = await outerApp . request ( '/api/v1/meta' ) ;
560567 expect ( res . status ) . toBe ( 200 ) ;
561568 expect ( mockDispatcher . dispatch ) . toHaveBeenCalledWith (
@@ -568,12 +575,7 @@ describe('createHonoApp', () => {
568575 } ) ;
569576
570577 it ( 'routes /api/v1/packages through outer→inner delegation' , async ( ) => {
571- const innerApp = createHonoApp ( { kernel : mockKernel , prefix : '/api/v1' } ) ;
572-
573- const outerApp = new Hono ( ) ;
574- outerApp . all ( '/*' , async ( c ) => {
575- return innerApp . fetch ( c . req . raw ) ;
576- } ) ;
578+ const outerApp = createVercelApp ( ) ;
577579
578580 const res = await outerApp . request ( '/api/v1/packages' ) ;
579581 expect ( res . status ) . toBe ( 200 ) ;
@@ -587,12 +589,7 @@ describe('createHonoApp', () => {
587589 } ) ;
588590
589591 it ( 'routes /api/v1 discovery through outer→inner delegation' , async ( ) => {
590- const innerApp = createHonoApp ( { kernel : mockKernel , prefix : '/api/v1' } ) ;
591-
592- const outerApp = new Hono ( ) ;
593- outerApp . all ( '/*' , async ( c ) => {
594- return innerApp . fetch ( c . req . raw ) ;
595- } ) ;
592+ const outerApp = createVercelApp ( ) ;
596593
597594 const res = await outerApp . request ( '/api/v1' ) ;
598595 expect ( res . status ) . toBe ( 200 ) ;
@@ -601,24 +598,11 @@ describe('createHonoApp', () => {
601598 expect ( mockDispatcher . getDiscoveryInfo ) . toHaveBeenCalledWith ( '/api/v1' ) ;
602599 } ) ;
603600
604- it ( 'handles path normalisation (strips prefix correctly) through delegation' , async ( ) => {
605- const innerApp = createHonoApp ( { kernel : mockKernel , prefix : '/api/v1' } ) ;
601+ it ( 'routes /api/v1/data/account through outer→inner delegation' , async ( ) => {
602+ const outerApp = createVercelApp ( ) ;
606603
607- const outerApp = new Hono ( ) ;
608- outerApp . all ( '/*' , async ( c ) => {
609- // Simulate the normalisation logic from [...path].ts
610- const url = new URL ( c . req . url ) ;
611- if ( ! url . pathname . startsWith ( '/api' ) ) {
612- url . pathname = '/api' + url . pathname ;
613- const request = new Request ( url . toString ( ) , c . req . raw ) ;
614- return innerApp . fetch ( request ) ;
615- }
616- return innerApp . fetch ( c . req . raw ) ;
617- } ) ;
618-
619- // Request with the full path — should work directly
620- const res1 = await outerApp . request ( '/api/v1/data/account' ) ;
621- expect ( res1 . status ) . toBe ( 200 ) ;
604+ const res = await outerApp . request ( '/api/v1/data/account' ) ;
605+ expect ( res . status ) . toBe ( 200 ) ;
622606 expect ( mockDispatcher . dispatch ) . toHaveBeenCalledWith (
623607 'GET' ,
624608 '/data/account' ,
@@ -631,7 +615,7 @@ describe('createHonoApp', () => {
631615 it ( 'returns 500 with error details when inner app throws' , async ( ) => {
632616 const outerApp = new Hono ( ) ;
633617
634- outerApp . all ( '/ *' , async ( c ) => {
618+ outerApp . all ( '*' , async ( c ) => {
635619 try {
636620 // Simulate a kernel boot failure
637621 throw new Error ( 'Kernel boot failed' ) ;
@@ -650,4 +634,48 @@ describe('createHonoApp', () => {
650634 expect ( json . error . message ) . toBe ( 'Kernel boot failed' ) ;
651635 } ) ;
652636 } ) ;
637+
638+ describe ( 'Vercel deployment endpoint smoke tests' , ( ) => {
639+ /**
640+ * These tests validate that the two key deployment-health endpoints
641+ * `/api/v1/meta` and `/api/v1/packages` return 200 OK when routed
642+ * through the Vercel adapter pattern (outer Hono → inner ObjectStack Hono).
643+ */
644+ let outerApp : Hono ;
645+
646+ beforeEach ( ( ) => {
647+ vi . clearAllMocks ( ) ;
648+ const innerApp = createHonoApp ( { kernel : mockKernel , prefix : '/api/v1' } ) ;
649+ outerApp = new Hono ( ) ;
650+ outerApp . all ( '*' , async ( c ) => innerApp . fetch ( c . req . raw ) ) ;
651+ } ) ;
652+
653+ it ( 'GET /api/v1/meta returns 200 OK' , async ( ) => {
654+ const res = await outerApp . request ( '/api/v1/meta' ) ;
655+ expect ( res . status ) . toBe ( 200 ) ;
656+ const json = await res . json ( ) ;
657+ expect ( json . success ) . toBe ( true ) ;
658+ } ) ;
659+
660+ it ( 'GET /api/v1/meta/object returns 200 OK' , async ( ) => {
661+ const res = await outerApp . request ( '/api/v1/meta/object' ) ;
662+ expect ( res . status ) . toBe ( 200 ) ;
663+ const json = await res . json ( ) ;
664+ expect ( json . success ) . toBe ( true ) ;
665+ } ) ;
666+
667+ it ( 'GET /api/v1/packages returns 200 OK' , async ( ) => {
668+ const res = await outerApp . request ( '/api/v1/packages' ) ;
669+ expect ( res . status ) . toBe ( 200 ) ;
670+ const json = await res . json ( ) ;
671+ expect ( json . success ) . toBe ( true ) ;
672+ } ) ;
673+
674+ it ( 'GET /api/v1/packages/:id returns 200 OK' , async ( ) => {
675+ const res = await outerApp . request ( '/api/v1/packages/com.acme.crm' ) ;
676+ expect ( res . status ) . toBe ( 200 ) ;
677+ const json = await res . json ( ) ;
678+ expect ( json . success ) . toBe ( true ) ;
679+ } ) ;
680+ } ) ;
653681} ) ;
0 commit comments