Создание Javascript классов, которые ожидают "новое" ключевое слово на KotlinJS - PullRequest
3 голосов
/ 25 апреля 2020

с учетом следующего javascript кода (частично взятого из документации сервера Apollo) он создает экземпляр ApolloServer и запускает его.


const {ApolloServer} = require('apollo-server')

const server = new ApolloServer({ ... });

server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}`);
});

Теперь рассмотрим возможность репликации того же поведения с использованием KotlinJS. Во-первых, Kotlin не имеет ключевого слова "new" и вызов ApolloServer(), как и ожидалось, не будет работать, но вызовет ошибку (TypeError: Конструктор класса ApolloServer не может быть вызван без 'new').

// We can banally represent part of the code above like:
external fun require(module: String): dynamic
val ApolloServer = require("apollo-server").ApolloServer

// ApolloServer is a js class

Объявление внешнего класса, такого как:

external open class ApolloServer() {
    open fun listen(vararg opts: Any): Promise<Any>
    operator fun invoke(): Any
}

и установка его в качестве типа ApolloServer, не помогает.

Как мы реплицируем вызов "new ApolloServer ()"?

1 Ответ

0 голосов
/ 27 апреля 2020

Для решения этой проблемы я нашел интересный подход, основанный на аннотации JsModule. Нам нужно создать файл Kotlin, представляющий тот модуль javascript, который мы хотим импортировать, в моем случае «apollo-server».

@file:JsModule("apollo-server")
@file:JsNonModule
package com.package

import kotlin.js.Promise

external interface ServerInfo {
    var address: String
    var family: String
    var url: String
    var subscriptionsUrl: String
    var port: dynamic /* Number | String */
        get() = definedExternally
        set(value) = definedExternally
    var subscriptionsPath: String
    var server: Any
}

external open class ApolloServer(config: Any? /* ApolloServerExpressConfig & `T$0` */) : Any {
    open var httpServer: Any
    open var cors: Any
    open var onHealthCheck: Any
    open var createServerInfo: Any
    open fun applyMiddleware()
    open fun listen(vararg opts: Any): Promise<ServerInfo>
    open fun stop(): Promise<Unit>
}

С помощью приведенного выше кода мы в основном описываем то, что ожидаем найти в модуле apollo-server и как сопоставить его с Kotlin.

В нашей основной функции Kotlin нам не нужно указывать какие-либо require (...), а просто использовать наш ApolloServer класс вроде:

    ApolloServer(null).listen().then {
       console.log(it)
    }

При использовании этого подхода Kotlin будет правильно его переносить, используя новое ключевое слово в javascript.

Извлечение транспонированной версии:

  function main$lambda(it) {
    console.log(it);
    return Unit;
  }
  function main() {
    (new ApolloServer(null)).listen().then(main$lambda);
  }

Этот код является только примером, ApolloServer не будет инициализирован без надлежащей конфигурации, в этом случае, например, содержится конфигурация с нулевым значением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...