Search code examples
javascriptangulartypescriptdependency-injectionsuperagent

What is the proper type for Angular DI injected superagent?


I'm trying to inject Superagent in a node.js app which users Angular DI (ngx).

import * as request from 'superagent';
 ... 
 {
    provide: request,
    useFactory: () =>
      request.agent()
        .timeout({deadline: 10000, timeout: 60000}),
  },

But I get propertytimeoutdoes not exist on SuperAgent<SuperAgentRequest>. I tried following these docs but the SuperAgent doesn't seem to be the correct type. The type of request.agent() should be request.Request.

What Am I missing? How do I properly provide request.Request so that I can configure it globally in order to use the same (injected) instance?


Solution

  • As it can be seen in Superagent typings, request.agent() returns SuperAgent<SuperAgentRequest> that doesn't have timeout method, this is what error message says.

    While timeout method exists in Request type that is a promise of a response. This is the reason why this error was thrown. There's no request and no response. Superagent documentation provides an example for timeout:

    request
      .get('/big-file?network=slow')
      .timeout({
        response: 5000,  // Wait 5 seconds for the server to start sending,
        deadline: 60000, // but allow 1 minute for the file to finish loading.
      })
    

    The documentation states that agent instance has methods that set defaults, so typings are lacking. There is no deadline method, and it doesn't make sense with timeout, because this is deadline timeout .

    superagent typings should be augmented locally, or be improved and PRed to DefinitelyTyped repository, or fixed in-place:

     {
        provide: request,
        useFactory: () =>
          <SuperAgent<SuperAgentRequest>>request.agent()
            ['timeout'](30)
      }
    

    I would expect augmented typings to be something like (processed original Request interface with regular expression):

    custom.d.ts

    import * as request from 'superagent';
    
    type CallbackHandler = (err: any, res: request.Response) => void;
    type Serializer = (obj: any) => string;
    type BrowserParser = (str: string) => any;
    type NodeParser = (res: request.Response, callback: (err: Error | null, body: any) => void) => void;
    type Parser = BrowserParser | NodeParser;
    
    declare module "superagent" {
        interface ConfigurableSuperAgent<Req extends request.SuperAgentRequest> extends request.SuperAgent<Req> {
            accept(type: string): this;
            auth(user: string, name: string): this;
            buffer(val?: boolean): this;
            ca(cert: Buffer): this;
            cert(cert: Buffer | string): this;
            key(cert: Buffer | string): this;
            ok(callback: (res: Response) => boolean): this;
            on(name: 'error', handler: (err: any) => void): this;
            on(name: 'progress', handler: (event: ProgressEvent) => void): this;
            on(name: string, handler: (event: any) => void): this;
            parse(parser: Parser): this;
            pfx(cert: Buffer | string): this;
            query(val: object | string): this;
            redirects(n: number): this;
            retry(count?: number, callback?: CallbackHandler): this;
            serialize(serializer: Serializer): this;
            set(field: object): this;
            set(field: string, val: string): this;
            timeout(ms: number | { deadline?: number, response?: number }): this;
            type(val: string): this;
            use(fn: Plugin): this;
        }
    
        interface SuperAgentStatic extends request.SuperAgent<request.SuperAgentRequest> {
            agent(): ConfigurableSuperAgent<request.SuperAgentRequest>;
        }
    }