@@ -150,12 +150,21 @@ export type CreateLayout = <Path extends string>(
150
150
151
151
type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' ;
152
152
153
- export type CreateApi = < Path extends string > ( params : {
154
- path : Path ;
155
- mode : 'static' | 'dynamic' ;
156
- method : Method ;
157
- handler : ( req : Request ) => Promise < Response > ;
158
- } ) => void ;
153
+ export type CreateApi = < Path extends string > (
154
+ params :
155
+ | {
156
+ path : Path ;
157
+ mode : 'static' ;
158
+ method : 'GET' ;
159
+ handler : ( req : Request ) => Promise < Response > ;
160
+ }
161
+ | {
162
+ path : Path ;
163
+ mode : 'dynamic' ;
164
+ method : Method ;
165
+ handler : ( req : Request ) => Promise < Response > ;
166
+ } ,
167
+ ) => void ;
159
168
160
169
type RootItem = {
161
170
render : 'static' | 'dynamic' ;
@@ -227,27 +236,26 @@ export const createPages = <
227
236
[ PathSpec , FunctionComponent < any > ]
228
237
> ( ) ;
229
238
const apiPathMap = new Map <
230
- string ,
239
+ string , // `${method} ${path}`
231
240
{
232
241
mode : 'static' | 'dynamic' ;
233
242
pathSpec : PathSpec ;
234
- method : Method ;
235
243
handler : Parameters < CreateApi > [ 0 ] [ 'handler' ] ;
236
244
}
237
245
> ( ) ;
246
+ const staticApiPaths = new Set < string > ( ) ;
238
247
const staticComponentMap = new Map < string , FunctionComponent < any > > ( ) ;
239
248
let rootItem : RootItem | undefined = undefined ;
240
249
const noSsrSet = new WeakSet < PathSpec > ( ) ;
241
250
242
251
/** helper to find dynamic path when slugs are used */
243
- const getRoutePath : ( path : string ) => string | undefined = ( path ) => {
252
+ const getPageRoutePath : ( path : string ) => string | undefined = ( path ) => {
244
253
if ( staticComponentMap . has ( joinPath ( path , 'page' ) . slice ( 1 ) ) ) {
245
254
return path ;
246
255
}
247
256
const allPaths = [
248
257
...dynamicPagePathMap . keys ( ) ,
249
258
...wildcardPagePathMap . keys ( ) ,
250
- ...apiPathMap . keys ( ) ,
251
259
] ;
252
260
for ( const p of allPaths ) {
253
261
if ( getPathMapping ( parsePathWithSlug ( p ) , path ) ) {
@@ -256,12 +264,29 @@ export const createPages = <
256
264
}
257
265
} ;
258
266
259
- const pathExists = ( path : string ) => {
267
+ const getApiRoutePath : (
268
+ path : string ,
269
+ method : string ,
270
+ ) => string | undefined = ( path , method ) => {
271
+ for ( const pathKey of apiPathMap . keys ( ) ) {
272
+ const [ m , p ] = pathKey . split ( ' ' ) ;
273
+ if ( m === method && getPathMapping ( parsePathWithSlug ( p ! ) , path ) ) {
274
+ return p ;
275
+ }
276
+ }
277
+ } ;
278
+
279
+ const pagePathExists = ( path : string ) => {
280
+ for ( const pathKey of apiPathMap . keys ( ) ) {
281
+ const [ _m , p ] = pathKey . split ( ' ' ) ;
282
+ if ( p === path ) {
283
+ return true ;
284
+ }
285
+ }
260
286
return (
261
287
staticPathMap . has ( path ) ||
262
288
dynamicPagePathMap . has ( path ) ||
263
- wildcardPagePathMap . has ( path ) ||
264
- apiPathMap . has ( path )
289
+ wildcardPagePathMap . has ( path )
265
290
) ;
266
291
} ;
267
292
@@ -290,7 +315,7 @@ export const createPages = <
290
315
if ( configured ) {
291
316
throw new Error ( 'createPage no longer available' ) ;
292
317
}
293
- if ( pathExists ( page . path ) ) {
318
+ if ( pagePathExists ( page . path ) ) {
294
319
throw new Error ( `Duplicated path: ${ page . path } ` ) ;
295
320
}
296
321
@@ -388,12 +413,16 @@ export const createPages = <
388
413
if ( configured ) {
389
414
throw new Error ( 'createApi no longer available' ) ;
390
415
}
391
- if ( apiPathMap . has ( path ) ) {
392
- throw new Error ( `Duplicated api path: ${ path } ` ) ;
416
+ if ( apiPathMap . has ( `${ method } ${ path } ` ) ) {
417
+ throw new Error ( `Duplicated api path+method: ${ path } ${ method } ` ) ;
418
+ } else if ( mode === 'static' && staticApiPaths . has ( path ) ) {
419
+ throw new Error ( 'Static API Routes cannot share paths: ' + path ) ;
420
+ }
421
+ if ( mode === 'static' ) {
422
+ staticApiPaths . add ( path ) ;
393
423
}
394
-
395
424
const pathSpec = parsePathWithSlug ( path ) ;
396
- apiPathMap . set ( path , { mode, pathSpec, method , handler } ) ;
425
+ apiPathMap . set ( ` ${ method } ${ path } ` , { mode, pathSpec, handler } ) ;
397
426
} ;
398
427
399
428
const createRoot : CreateRoot = ( root ) => {
@@ -530,7 +559,7 @@ export const createPages = <
530
559
await configure ( ) ;
531
560
532
561
// path without slugs
533
- const routePath = getRoutePath ( path ) ;
562
+ const routePath = getPageRoutePath ( path ) ;
534
563
if ( ! routePath ) {
535
564
throw new Error ( 'Route not found: ' + path ) ;
536
565
}
@@ -607,11 +636,11 @@ export const createPages = <
607
636
} ,
608
637
handleApi : async ( path , options ) => {
609
638
await configure ( ) ;
610
- const routePath = getRoutePath ( path ) ;
639
+ const routePath = getApiRoutePath ( path , options . method ) ;
611
640
if ( ! routePath ) {
612
- throw new Error ( 'Route not found: ' + path ) ;
641
+ throw new Error ( 'API Route not found: ' + path ) ;
613
642
}
614
- const { handler } = apiPathMap . get ( routePath ) ! ;
643
+ const { handler } = apiPathMap . get ( ` ${ options . method } ${ routePath } ` ) ! ;
615
644
616
645
const req = new Request (
617
646
new URL (
0 commit comments