File tree Expand file tree Collapse file tree 4 files changed +97
-17
lines changed Expand file tree Collapse file tree 4 files changed +97
-17
lines changed Original file line number Diff line number Diff line change @@ -2,4 +2,5 @@ node_modules
22browser
33* .js
44* .js.map
5- * .d.ts
5+ * .d.ts
6+ ! index.d.ts
Original file line number Diff line number Diff line change @@ -20,13 +20,25 @@ export const makeApi = <Data extends ApiData>({
2020 Object . keys ( headers ) . forEach ( key => fetchHeaders . set ( key , headers [ key ] ) ) ;
2121 }
2222 }
23- return ( action , payload ) =>
24- fetch ( endpoint , {
25- method : "POST" ,
26- headers : fetchHeaders ,
27- body : JSON . stringify ( {
28- action,
29- payload
30- } )
31- } ) . then ( r => r . json ( ) ) ;
23+ return ( action , payload ) => {
24+ try {
25+ const controller = new AbortController ( ) ;
26+ const signal = controller . signal ;
27+ const promise = fetch ( endpoint , {
28+ signal,
29+ method : "POST" ,
30+ headers : fetchHeaders ,
31+ body : JSON . stringify ( {
32+ action,
33+ payload
34+ } )
35+ } ) . then ( r => r . json ( ) ) ;
36+ Object . defineProperty ( promise , "abort" , {
37+ value : ( ) => controller . abort ( )
38+ } ) ;
39+ return promise ;
40+ } catch ( err ) {
41+ return Promise . reject ( err ) ;
42+ }
43+ } ;
3244} ;
Original file line number Diff line number Diff line change 1+ export type ActionFunction < Payload = any , Output = any , Context = any > = (
2+ payload : Payload ,
3+ context : Context
4+ ) => Promise < Output > ;
5+
6+ export type Unpacked < T > = T extends Promise < infer U > ? U : T ;
7+
8+ export type Payload < T extends ActionFunction > = T extends (
9+ p : infer P ,
10+ c : any
11+ ) => any
12+ ? P
13+ : never ;
14+
15+ export type Output < T extends ActionFunction > = T extends (
16+ p : any ,
17+ c : any
18+ ) => infer R
19+ ? R
20+ : never ;
21+
22+ export type ApiData = { [ key : string ] : ActionFunction } ;
23+
24+ export type PromiseA < T > = Promise < T > & {
25+ abort ?: ( ) => void ;
26+ } ;
27+
28+ export type ApiResolver < D extends ApiData > = < N extends keyof D > (
29+ name : N ,
30+ payload : Payload < D [ N ] >
31+ ) => PromiseA < Unpacked < Output < D [ N ] > > > ;
Original file line number Diff line number Diff line change 1- import { ApiResolver , ApiData } from "@webcarrot/api" ;
1+ import {
2+ ApiResolver ,
3+ ApiData ,
4+ Payload ,
5+ PromiseA ,
6+ Unpacked ,
7+ Output
8+ } from "@webcarrot/api" ;
9+
10+ const makeError = ( ) => {
11+ const error = new Error ( "Action aborted" ) ;
12+ error . name === "AbortError" ;
13+ return error ;
14+ } ;
215
316export const makeApi = < Data extends ApiData , Context > ( {
417 actions,
518 context
619} : {
720 actions : Data ;
821 context : Context ;
9- } ) : ApiResolver < Data > => async ( action , payload ) => {
10- if ( action in actions ) {
11- return await actions [ action ] ( payload , context ) ;
12- } else {
13- throw new Error ( `Unknown action ${ action } ` ) ;
14- }
22+ } ) : ApiResolver < Data > => < N extends keyof Data > (
23+ action : N ,
24+ payload : Payload < Data [ N ] >
25+ ) : PromiseA < Unpacked < Output < Data [ N ] > > > => {
26+ let aborted = false ;
27+ const promise = new Promise < Unpacked < Output < Data [ N ] > > > ( ( resolve , reject ) => {
28+ if ( aborted ) {
29+ reject ( makeError ( ) ) ;
30+ } else if ( action in actions ) {
31+ actions [ action ] ( payload , context ) . then (
32+ data => {
33+ if ( ! aborted ) {
34+ resolve ( data ) ;
35+ } else {
36+ reject ( makeError ( ) ) ;
37+ }
38+ } ,
39+ err => reject ( aborted ? makeError ( ) : err )
40+ ) ;
41+ } else {
42+ reject ( new Error ( `Unknown action ${ action } ` ) ) ;
43+ }
44+ } ) ;
45+ Object . defineProperty ( promise , "abort" , {
46+ value : ( ) => {
47+ aborted = true ;
48+ }
49+ } ) ;
50+ return promise ;
1551} ;
You can’t perform that action at this time.
0 commit comments