xmpp.js icon indicating copy to clipboard operation
xmpp.js copied to clipboard

Importing the library for Typescript

Open lifeanddeath opened this issue 6 years ago • 17 comments

Hello, in order to use external javascript libraries in Typescript, there should be defined types for the library. That being the case, currently I cant use this library as it doesn't have any. What can I do to fix this problem?

lifeanddeath avatar May 21 '18 14:05 lifeanddeath

@lifeanddeath I'd be happy to accept/help with a contribution

sonnyp avatar May 21 '18 22:05 sonnyp

create a declaration.d.ts file.. you can start with below..

declare module '@xmpp/client' {
    type ALLOWED_ACTIONS = 'online' | 'error'
    type Fn = (a: any) => any
    export class Client {
        public start(uri: string): void
        public handle(handle: 'authenticate', fn: Fn): void
        public on(action: ALLOWED_ACTIONS, fn: Fn): void
    }
}

wmira avatar Jun 07 '18 09:06 wmira

Below is my current declaration file. Very bare bones, but gets the job done for now.

declare module '@xmpp/client' {
    export class Client {
        public constructor(options?: any);
        public start(options: any): Promise<any>;
        public stop(): Promise<any>;
        public handle(handle: string, fn: (a: any) => any): void;
        public on(event: string, fn: (a: any) => any): void;
        public send(stanza: any): Promise<any>;
    }

    export function xml(...args: any[]): any;
}

robby-cornelissen avatar Jul 26 '18 02:07 robby-cornelissen

Hi @sonnyp! Would you be willing to accept typescript definitions for most/all of the modules? I'd like to make multiple PRs for this because the size of the lib is quite overwhelming. Same goes for your ltx module.

BendingBender avatar Nov 26 '18 23:11 BendingBender

@BendingBender would love to have them and would really appreciate the contributions. However I don't think xmpp.js is quite ready for that, some changes might be coming up. Going on holidays for a month next week, give me some time to come up with a suggestion on how to move forward.

sonnyp avatar Nov 30 '18 17:11 sonnyp

@sonnyp Do you have new thoughts about this?

BendingBender avatar Feb 02 '19 12:02 BendingBender

@sonnyp Bump, I think the library is stable enough to move with this. We can either type the definitions or document the code from witch the types can be generated

filipef101 avatar Jan 08 '20 09:01 filipef101

This is what I personally use it's not very complete but gets the job done

import { EventEmitter } from "react-native";

declare module "@xmpp/client" {
  export function client (options: {
    service?: string,
    domain?: string,
    resource?: string,
    username?: string,
    password?: string,
    credentials?: (auth: ({ username: string, password: string }) => any, mechanism: string) => any
  }): XmppClient;

  type XmppClient = EventEmitter & {
    start: () => void,
    stop: () => void,
    send: (...args: any) => Promise<any>,
  }
  export function jid (): any;

  export function xml (args: any): any;

  export namespace jid {
    class JID {
      constructor(...args: any[]);

      bare (...args: any[]): void;

      equals (...args: any[]): void;

      getDomain (...args: any[]): void;

      getLocal (...args: any[]): void;

      getResource (...args: any[]): void;

      setDomain (...args: any[]): void;

      setLocal (...args: any[]): void;

      setResource (...args: any[]): void;

      toString (...args: any[]): void;

    }

    function detectEscape (local: any): any;

    function equal (a: any, b: any): any;

    function escapeLocal (local: any): any;

    function jid (args: any): any;

    function parse (s: any): any;

    function unescapeLocal (local: any): any;

  }

  export namespace xml {
    class Element {
      constructor(...args: any[]);

      append (...args: any[]): void;

      prepend (...args: any[]): void;

      setAttrs (...args: any[]): void;

    }

    class Parser {
      constructor(...args: any[]);

      end (...args: any[]): void;

      onEndElement (...args: any[]): void;

      onStartElement (...args: any[]): void;

      onText (...args: any[]): void;

      write (...args: any[]): void;

      static XMLError (...args: any[]): void;

      static defaultMaxListeners: number;

      static init (): void;

      static listenerCount (emitter: any, type: any): any;

      static once (emitter: any, name: any): any;

      static usingDomains: boolean;

    }

    function XMLError (...args: any[]): void;

    function escapeXML (s: any): any;

    function escapeXMLText (s: any): any;

    function unescapeXML (s: any): any;

    function unescapeXMLText (s: any): any;

    function x (name: any, attrs: any, children: any): any;

    namespace Parser {
      class EventEmitter {
        constructor();

        addListener (type: any, listener: any): any;

        emit (type: any, args: any): any;

        eventNames (): any;

        getMaxListeners (): any;

        listenerCount (type: any): any;

        listeners (type: any): any;

        off (type: any, listener: any): any;

        on (type: any, listener: any): any;

        once (type: any, listener: any): any;

        prependListener (type: any, listener: any): any;

        prependOnceListener (type: any, listener: any): any;

        rawListeners (type: any): any;

        removeAllListeners (type: any, ...args: any[]): any;

        removeListener (type: any, listener: any): any;

        setMaxListeners (n: any): any;

        static EventEmitter: any;

        static defaultMaxListeners: number;

        static init (): void;

        static listenerCount (emitter: any, type: any): any;

        static once (emitter: any, name: any): any;

        static usingDomains: boolean;

      }

      namespace XMLError {
        const stackTraceLimit: number;

        function captureStackTrace (p0: any, p1: any): any;

      }

    }

    namespace XMLError {
      const stackTraceLimit: number;

      function captureStackTrace (p0: any, p1: any): any;

    }

  }
}


filipef101 avatar Jan 08 '20 11:01 filipef101

~i'm running into issues setting up custom typings... how should my tsconfig.json and folder structure look for these? do i need a types/@xmpp/client/index.d.ts structure, types/xmpp.js/index.d.ts, or something else entirely? do i need to include the types folder in my tsconfig.json's include section?~

Note that the above types (https://github.com/xmppjs/xmpp.js/issues/542#issuecomment-572000068) may not work unless you put the import inside the declare module block (as per https://stackoverflow.com/a/59696400/3697202).

ghost avatar Jan 09 '20 21:01 ghost

PS, I'm not sure that is the right event emitter to extend from, think should me something else, I ended up using strophe, will try to see if I know what eventemitter to import, should be a node.js/eventemitter like typing of it. as the react native one doesn't have the on and once functions. Also it should be something generic, that right now is only for react-native because of the event emitter EDIT: I have the typings of a event emiter under parser namespace. That should be used instead of the react native event emitter

EDIT: this types worked altough the event emiter shouldn't be that import, but cant fix that since I no longer use xmppjs. hope it helps someone

import { EventEmitter } from "events";

declare module "@xmpp/client" {

  export function client (options: {
    service?: string,
    domain?: string,
    resource?: string,
    username?: string,
    password?: string,
    credentials?: (auth: ({ username: string, password: string }) => any, mechanism: string) => any
  }): XmppClient;

  type XmppClient = EventEmitter & {
    start: () => Promise<any>,
    stop: () => Promise<any>,
    send: (...args: any) => Promise<any>,
  }

  export function jid (): any;

  export function xml (...args: string | object): any;

  export namespace jid {
    class JID {
      constructor(...args: any[]);
      bare (...args: any[]): void;
      equals (...args: any[]): void;
      getDomain (...args: any[]): void;
      getLocal (...args: any[]): void;
      getResource (...args: any[]): void;
      setDomain (...args: any[]): void;
      setLocal (...args: any[]): void;
      setResource (...args: any[]): void;
      toString (...args: any[]): void;
    }

    function detectEscape (local: any): any;
    function equal (a: any, b: any): any;
    function escapeLocal (local: any): any;
    function jid (args: any): any;
    function parse (s: any): any;
    function unescapeLocal (local: any): any;
  }

  export namespace xml {
    class Element {
      constructor(...args: any[]);
      append (...args: any[]): void;
      prepend (...args: any[]): void;
      setAttrs (...args: any[]): void;
    }

    class Parser {
      constructor(...args: any[]);

      end (...args: any[]): void;

      onEndElement (...args: any[]): void;

      onStartElement (...args: any[]): void;

      onText (...args: any[]): void;

      write (...args: any[]): void;

      static XMLError (...args: any[]): void;

      static defaultMaxListeners: number;

      static init (): void;

      static listenerCount (emitter: any, type: any): any;

      static once (emitter: any, name: any): any;

      static usingDomains: boolean;

    }

    function XMLError (...args: any[]): void;

    function escapeXML (s: any): any;

    function escapeXMLText (s: any): any;

    function unescapeXML (s: any): any;

    function unescapeXMLText (s: any): any;

    function x (name: any, attrs: any, children: any): any;

    namespace Parser {
      class EventEmitter {
        constructor();

        addListener (type: any, listener: any): any;

        emit (type: any, args: any): any;

        eventNames (): any;

        getMaxListeners (): any;

        listenerCount (type: any): any;

        listeners (type: any): any;

        off (type: any, listener: any): any;

        on (type: any, listener: any): any;

        once (type: any, listener: any): any;

        prependListener (type: any, listener: any): any;

        prependOnceListener (type: any, listener: any): any;

        rawListeners (type: any): any;

        removeAllListeners (type: any, ...args: any[]): any;

        removeListener (type: any, listener: any): any;

        setMaxListeners (n: any): any;

        static EventEmitter: any;

        static defaultMaxListeners: number;

        static init (): void;

        static listenerCount (emitter: any, type: any): any;

        static once (emitter: any, name: any): any;

        static usingDomains: boolean;

      }

      namespace XMLError {
        const stackTraceLimit: number;
        function captureStackTrace (p0: any, p1: any): any;
      }
    }

    namespace XMLError {
      const stackTraceLimit: number;
      function captureStackTrace (p0: any, p1: any): any;

    }

  }
}

filipef101 avatar Jan 12 '20 14:01 filipef101

Any updates on this?

erodactyl avatar Jul 01 '20 14:07 erodactyl

I would be open to proceed with this but my knowledge of TypeScript is limited to using it and I expect in-depth knowledge will be required for xmpp.js type definitions.

Is anyone willing to contribute the type definitions and maintain them?

What would be the benefit of having the type definitions in this package rather than the ones available in https://github.com/DefinitelyTyped/DefinitelyTyped/ ?

sonnyp avatar Jul 02 '20 09:07 sonnyp

For modern typescript types, in an ambient context:

// xmpp__client.d.ts:
declare module "@xmpp/client" {
    import { EventEmitter } from "events";
    import jid from "@xmpp/jid";
    import xml from "@xmpp/xml";

    export function client(options: {
        service?: string;
        domain?: string;
        resource?: string;
        username?: string;
        password?: string;
        credentials?: ({
            auth,
            mechanism,
        }: {
            auth: ({
                username,
                password,
            }: {
                username: string;
                password: string;
            }) => any;
            mechanism: string;
        }) => any;
    }): XmppClient;

    interface XmppClient extends EventEmitter {
        start(): Promise<any>;
        stop(): Promise<any>;
        send(xml: xml.Element): Promise<any>;
        on(event: string | symbol, listener: (...args: any[]) => void): this;
        on(event: "stanza", listener: (stanza: xml.Element) => void): this;
        on(
            event: "status",
            listener: (
                newStatus:
                    | "online" // Indicates that `xmpp` is authenticated and addressable. It is emitted every time there is a successful (re)connection.
                    | "offline" // Indicates that `xmpp` is disconnected and no automatic attempt to reconnect will happen (after calling `xmpp.stop()`)
                    | "connecting" // Socket is connecting
                    | "connect" // Socket is connected
                    | "opening" // Stream is opening
                    | "open" // Stream is open
                    | "closing" // Stream is closing
                    | "close" // Stream is closed
                    | "disconnecting" // Socket is disconnecting
                    | "disconnect" // Socket is disconnected
            ) => void
        ): this;
        on(event: "online", listener: (address: jid.JID) => void): this;
        on(event: "offline", listener: () => void): this;
    }

    export import jid = jid;
    export import xml = xml;
}

Dessix avatar Jul 31 '20 05:07 Dessix

Any updates on @types 😐

JohnYepthomi avatar Aug 24 '22 16:08 JohnYepthomi

@JohnYepthomi What's wrong with all the @types/xmpp__* packages? Why can't you use them?

BendingBender avatar Aug 24 '22 20:08 BendingBender

Can't they be linked on this Github repo? Just curious. Anyways, thanks.

JohnYepthomi avatar Aug 29 '22 16:08 JohnYepthomi

I think we could move them here. @sonnyp Shall we move the types from DefinitelyTyped directly into this lib?

BendingBender avatar Aug 29 '22 16:08 BendingBender