Search code examples
kotlinkotlin-js-interop

Kotlin/JS unable to create bindings for jwt-decode library


So, I'm kind of new to Kotlin/JS and I'm trying to create Kotlin bindings for the jwt-decode library.

Here are the Kotlin bindings I've written:

/**
 * A Kotlin definition for the jwt-decode library's invalid token error class
 */
external class InvalidTokenError : Throwable

/**
 * A Kotlin definition for the jwt-decode library's jwt decode options interface
 */
external interface JwtDecodeOptions {
    var header: Boolean?
        get() = definedExternally
        set(value) = definedExternally
}

/**
 * A Kotlin definition for the jwt-decode library's jwt header interface
 */
external interface JwtHeader {
    var typ: String?
        get() = definedExternally
        set(value) = definedExternally
    var alg: String?
        get() = definedExternally
        set(value) = definedExternally
    var kid: String?
        get() = definedExternally
        set(value) = definedExternally
}

/**
 * A Kotlin definition for the jwt-decode library's jwt payload interface
 */
external interface JwtPayload {
    var iss: String?
        get() = definedExternally
        set(value) = definedExternally
    var sub: String?
        get() = definedExternally
        set(value) = definedExternally
    var aud: dynamic // Array<String> or String
        get() = definedExternally
        set(value) = definedExternally
    var exp: Long?
        get() = definedExternally
        set(value) = definedExternally
    var nbf: Long?
        get() = definedExternally
        set(value) = definedExternally
    var iat: Long?
        get() = definedExternally
        set(value) = definedExternally
    var jti: String?
        get() = definedExternally
        set(value) = definedExternally
}

/**
 * A Kotlin definition for the jwt-decode library's jwt decode function
 */
@JsModule("jwt-decode")
@JsNonModule
external fun <T> jwtDecode(token: String, options: JwtDecodeOptions = definedExternally): T

Here's how I've imported the library in my gradle build script:

implementation(npm("jwt-decode", jwtDecodeVersion))

This apparently is not correct because when I try to use the library in the following way:

val payload: JwtPayload = try {
    jwtDecode(token)
} catch (exc: InvalidTokenError) {
    console.log(exc.message)
}

I get the following error:

InvalidTokenError is not defined

Using only the function like this:

val payload: JwtPayload = jwtDecode(token)

Yields:

jwtDecode is not a function


Solution

  • So, I managed to solve the problem.

    By looking at the following file of the library, I noticed that it was exporting an object instead of a single function:

    import jwtDecode, { InvalidTokenError } from "./index";
    
    const wrapper = jwtDecode;
    wrapper.default = jwtDecode;
    wrapper.InvalidTokenError = InvalidTokenError;
    export default wrapper;
    

    Therefore, I made the @JsModule and @JsNonModule annotations apply to the package instead (https://kotlinlang.org/docs/js-modules.html#apply-jsmodule-to-packages):

    @file:JsModule("jwt-decode")
    @file:JsNonModule
    

    I also needed to add the following annotation to the definition of the jwtDecode function, since it was assigned to the default property on the exported object:

    @JsName("default")
    external fun <T> jwtDecode(token: String, options: JwtDecodeOptions = definedExternally): T