<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Akihiro Urushihara</title>
    <description>The latest articles on Forem by Akihiro Urushihara (@uakihir0).</description>
    <link>https://forem.com/uakihir0</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F483366%2Fc2f21ea9-01bc-4a49-bdf5-c6c0fc1d0ccc.png</url>
      <title>Forem: Akihiro Urushihara</title>
      <link>https://forem.com/uakihir0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/uakihir0"/>
    <language>en</language>
    <item>
      <title>Multi-platform libraries built with Kotlin Multiplatform (KMP)</title>
      <dc:creator>Akihiro Urushihara</dc:creator>
      <pubDate>Thu, 14 Mar 2024 18:10:58 +0000</pubDate>
      <link>https://forem.com/uakihir0/multi-platform-libraries-built-with-kotlin-multiplatform-kmp-39e1</link>
      <guid>https://forem.com/uakihir0/multi-platform-libraries-built-with-kotlin-multiplatform-kmp-39e1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Are you building libraries?&lt;/strong&gt; When I create services, I always try to extract domains as libraries whenever possible. Also, if the library is generally useful, I want to release it as open-source software (OSS). So, what kind of technology stack would you use at that time? That's where &lt;a href="https://kotlinlang.org/docs/multiplatform.html" rel="noopener noreferrer"&gt;Kotlin Multiplatform&lt;/a&gt; comes in. Kotlin Multiplatform is a framework that allows you to create things for various platforms using Kotlin. Writing libraries in the modern language Kotlin allows them to be used on various platforms, so you can share code between server and frontend, and it should be very attractive to be able to run in various languages as OSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kotlin Multiplatform
&lt;/h2&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://kotlinlang.org/docs/multiplatform.html" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkotlinlang.org%2Fassets%2Fimages%2Fopen-graph%2Fdocs.png" height="auto" class="m-0"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://kotlinlang.org/docs/multiplatform.html" rel="noopener noreferrer" class="c-link"&gt;
          Kotlin Multiplatform | Kotlin Documentation
        &lt;/a&gt;
      &lt;/h2&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkotlinlang.org%2Fassets%2Fimages%2Ffavicon.svg%3Fv2"&gt;
        kotlinlang.org
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;With &lt;a href="https://kotlinlang.org/docs/multiplatform.html" rel="noopener noreferrer"&gt;Kotlin Multiplatform&lt;/a&gt;, you can build mainly three types of builds for different environments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kotlin/JVM

&lt;ul&gt;
&lt;li&gt;For JVM environments such as Java and Kotlin&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Kotlin/JS

&lt;ul&gt;
&lt;li&gt;For JavaScript environments such as browsers&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Kotlin/Native

&lt;ul&gt;
&lt;li&gt;For native execution environments such as iOS, MacOS, and Windows&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In this way, with Kotlin Multiplatform, you can create libraries that work in the above environments. However, Kotlin Multiplatform can only run libraries made for Kotlin Multiplatform, and for example, you cannot use a library written in Java with Kotlin Multiplatform. Therefore, there are some &lt;strong&gt;parts where implementation is not straightforward, such as when the necessary functionality for writing a library is not available and you have to create it yourself.&lt;/strong&gt; Here, I will introduce some implementation points (I will add more points if necessary).&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Challenges
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Desired functionality library does not exist!
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;There's nothing you can do.&lt;/strong&gt; However, Kotlin's official provides several libraries, so the scope that can be achieved using them is by no means small. Also, &lt;a href="https://github.com/AAkira/Kotlin-Multiplatform-Libraries" rel="noopener noreferrer"&gt;AAkira/Kotlin-Multiplatform-Libraries&lt;/a&gt; introduces several famous libraries created with Kotlin Multiplatform, which can be helpful. However, it can be quite disappointing when certain environments are not supported. &lt;strong&gt;But let's think of it as an opportunity! Let's become the first person to implement it!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  There's absolutely no documentation!
&lt;/h3&gt;

&lt;p&gt;Really, even if you look at the official documentation, you might not understand how to implement it. &lt;strong&gt;Well, to be precise, you can implement it, but you don't know how to deploy it.&lt;/strong&gt; Or, you may not understand how to use Gradle, the build tool. Since there's no specific place to look, you'll have to try your best to search online, so please refer to the project I created.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/uakihir0" rel="noopener noreferrer"&gt;
        uakihir0
      &lt;/a&gt; / &lt;a href="https://github.com/uakihir0/kmisskey" rel="noopener noreferrer"&gt;
        kmisskey
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Kotlin multiplatform Misskey library.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/uakihir0/kmisskey./docs/README_ja.md" rel="noopener noreferrer"&gt;日本語&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;kmisskey&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/34d84dc71a81cf246d2812f0a128bbb10404a7b7e256a9d697ab07594885cb31/68747470733a2f2f696d672e736869656c64732e696f2f6d6176656e2d6d657461646174612f763f6d6574616461746155726c3d68747470732533412532462532467265706f2e72657073792e696f2532466d766e25324675616b69686972302532467075626c6963253246776f726b253246736f6369616c6875622532466b6d6973736b6579253246636f72652532466d6176656e2d6d657461646174612e786d6c"&gt;&lt;img src="https://camo.githubusercontent.com/34d84dc71a81cf246d2812f0a128bbb10404a7b7e256a9d697ab07594885cb31/68747470733a2f2f696d672e736869656c64732e696f2f6d6176656e2d6d657461646174612f763f6d6574616461746155726c3d68747470732533412532462532467265706f2e72657073792e696f2532466d766e25324675616b69686972302532467075626c6963253246776f726b253246736f6369616c6875622532466b6d6973736b6579253246636f72652532466d6176656e2d6d657461646174612e786d6c" alt="Maven metadata URL"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/8e473421d0b64f67969d29ae3f5d959b0fadf19a289a424f5512e88499afd3b8/687474703a2f2f696d672e736869656c64732e696f2f62616467652f2d6a732d4638444235442e737667"&gt;&lt;img src="https://camo.githubusercontent.com/8e473421d0b64f67969d29ae3f5d959b0fadf19a289a424f5512e88499afd3b8/687474703a2f2f696d672e736869656c64732e696f2f62616467652f2d6a732d4638444235442e737667" alt="badge"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/a14bdf13f54d05dd84487481c44f7d5a394c7738f846984d6dcd2c51b0749693/687474703a2f2f696d672e736869656c64732e696f2f62616467652f2d6a766d2d4442343133442e737667"&gt;&lt;img src="https://camo.githubusercontent.com/a14bdf13f54d05dd84487481c44f7d5a394c7738f846984d6dcd2c51b0749693/687474703a2f2f696d672e736869656c64732e696f2f62616467652f2d6a766d2d4442343133442e737667" alt="badge"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/357a086606eb9c0372515b69e5b7845d6a66d7af22f38889e60a51cb44c43972/687474703a2f2f696d672e736869656c64732e696f2f62616467652f2d696f732d4344434443442e737667"&gt;&lt;img src="https://camo.githubusercontent.com/357a086606eb9c0372515b69e5b7845d6a66d7af22f38889e60a51cb44c43972/687474703a2f2f696d672e736869656c64732e696f2f62616467652f2d696f732d4344434443442e737667" alt="badge"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/a34549acfbc29ada665ee0f59348b80a8db2492dfbbaf5a0fd862b7e9fafb4c6/687474703a2f2f696d672e736869656c64732e696f2f62616467652f2d6d61636f732d3131313131312e737667"&gt;&lt;img src="https://camo.githubusercontent.com/a34549acfbc29ada665ee0f59348b80a8db2492dfbbaf5a0fd862b7e9fafb4c6/687474703a2f2f696d672e736869656c64732e696f2f62616467652f2d6d61636f732d3131313131312e737667" alt="badge"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This library is a Misskey client library that supports &lt;a href="https://kotlinlang.org/docs/multiplatform.html" rel="nofollow noopener noreferrer"&gt;Kotlin Multiplatform&lt;/a&gt;.&lt;/strong&gt;
It depends on &lt;a href="https://github.com/uakihir0/khttpclient" rel="noopener noreferrer"&gt;khttpclient&lt;/a&gt; and internally uses Ktor Client
Therefore, this library is available on Kotlin Multiplatform and platforms supported by Ktor Client
The behavior on each platform depends on &lt;a href="https://github.com/uakihir0/khttpclient" rel="noopener noreferrer"&gt;khttpclient&lt;/a&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Below is how to use it in Kotlin with Gradle on supported platforms.
&lt;strong&gt;If you want to use it on Apple platforms, please refer to &lt;a href="https://github.com/uakihir0/kmisskey-cocoapods" rel="noopener noreferrer"&gt;kmisskey-cocoapods&lt;/a&gt;.&lt;/strong&gt;
&lt;strong&gt;Also, for usage in JavaScript, please refer to &lt;a href="https://github.com/uakihir0/kmisskey.js" rel="noopener noreferrer"&gt;kmsskey.js&lt;/a&gt;.&lt;/strong&gt;
Please refer to the test code for how to use each API.&lt;/p&gt;
&lt;div class="highlight highlight-source-kotlin notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;repositories {
    mavenCentral()
&lt;span class="pl-k"&gt;+&lt;/span&gt;   maven { url &lt;span class="pl-k"&gt;=&lt;/span&gt; uri(&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;https://repo.repsy.io/mvn/uakihir0/public&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;) }
}

dependencies {
&lt;span class="pl-k"&gt;+&lt;/span&gt;   implementation(&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;work.socialhub.kmisskey:core:0.0.1-SNAPSHOT&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;)
&lt;span class="pl-k"&gt;+&lt;/span&gt;   implementation(&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;work.socialhub.kmisskey:stream:0.0.1-SNAPSHOT&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;)
}&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Authentication&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;Using MiAuth, request the URL for users to authenticate as follows.&lt;/p&gt;
&lt;div class="highlight highlight-source-kotlin notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;val&lt;/span&gt; misskey &lt;span class="pl-k"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;MisskeyFactory&lt;/span&gt;.instance(&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;HOST&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;)
&lt;span class="pl-k"&gt;val&lt;/span&gt; response &lt;span class="pl-k"&gt;=&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/uakihir0/kmisskey" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This library is a client library for &lt;a href="https://misskey-hub.net/en/" rel="noopener noreferrer"&gt;Misskey&lt;/a&gt;, a Japanese social networking service. You can easily access Misskey's API using this library. The code above is Kotlin Multiplatform code, which can be run in Kotlin/JVM environments. For Kotlin/Native's iOS and MacOS, you can use &lt;a href="https://github.com/uakihir0/kmisskey-cocoapods" rel="noopener noreferrer"&gt;kmisskey-cocoapods&lt;/a&gt; built from the &lt;a href="https://github.com/uakihir0/kmisskey" rel="noopener noreferrer"&gt;kmisskey&lt;/a&gt; library and install it via Cocoapods. For Kotlin/JS targeting JavaScript, you can use &lt;a href="https://github.com/uakihir0/kmisskey.js" rel="noopener noreferrer"&gt;kmisskey.js&lt;/a&gt; and install it via npm. The build methods for each are described in Github Actions, so please check them along with Gradle.&lt;/p&gt;

&lt;h3&gt;
  
  
  (Reference) How can the library be used?
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/uakihir0/kmisskey" rel="noopener noreferrer"&gt;kmisskey&lt;/a&gt; library created with Kotlin Multiplatform can be executed with the following code. One of the charms of Kotlin Multiplatform is that you can run similar code on almost any platform.&lt;/p&gt;

&lt;h4&gt;
  
  
  Kotlin/JVM
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Kotlin&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;work.socialhub.kmisskey.KmisskeyFactory&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;work.socialhub.kmisskey.api.request.i.IRequest&lt;/span&gt;
&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;misskey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;KmisskeyFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"https://misskey.io"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"CLIENT_SECRET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"ACCESS_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;misskey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;i&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IRequest&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Kotlin/Native (iOS/MacOS)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Swift&lt;/span&gt;
&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="n"&gt;kmisskey&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;misskey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;KmisskeyFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nv"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"https://misskey.io"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"CLIENT_SECRET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;userAccessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ACCESS_TOKEN"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;misskey&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;i&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;CoreIRequest&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Kotlin/JS (JavaScript)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// TypeScript&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;kmisskey&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kmisskey-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;KmisskeyFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;kmisskey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;work&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;socialhub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kmisskey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KmisskeyFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;IRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;kmisskey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;work&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;socialhub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kmisskey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;KmisskeyFactory&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;misskey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instanceUserAccessToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://misskey.io&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CLIENT_SECRET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;misskey&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;me&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IRequest&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Coroutine behavior in Kotlin/JS
&lt;/h3&gt;

&lt;p&gt;There are some challenging aspects to coroutines in Kotlin/JS for browsers. &lt;strong&gt;The biggest challenge is that the &lt;code&gt;runBlocking&lt;/code&gt; function cannot be used in Kotlin/JS browser builds.&lt;/strong&gt; &lt;code&gt;runBlocking&lt;/code&gt; roughly converts asynchronous code execution to synchronous execution, and within &lt;code&gt;runBlocking&lt;/code&gt;, you can execute asynchronous code (suspend functions). However, this conversion to synchronous execution cannot be done for browser environments that operate on a single thread, and writing &lt;code&gt;runBlocking&lt;/code&gt; in the code will result in an error.&lt;/p&gt;

&lt;p&gt;So, you might think, why not just provide asynchronous functions (suspend functions) as a library? However, &lt;strong&gt;suspend functions do not support the &lt;code&gt;@JsExport&lt;/code&gt; annotation, which explicitly exports them in JavaScript, and these functions cannot be represented in JavaScript.&lt;/strong&gt; Also, suspend functions are output in a slightly cumbersome form when used in Java, so it may be simpler to provide them as blocking functions in the library. (This is a personal opinion.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On the other hand, Kotlin/JS provides the &lt;code&gt;Promise&lt;/code&gt; class for asynchronous execution, which corresponds to JavaScript's &lt;code&gt;Promise&lt;/code&gt;, and by returning this model, you can return asynchronous processing in synchronous functions.&lt;/strong&gt; Since this &lt;code&gt;Promise&lt;/code&gt; class is from JavaScript, you can proceed with processing as usual using functions like &lt;code&gt;then&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, how can the same code return data itself in Kotlin/JS and return a &lt;code&gt;Promise&lt;/code&gt; in Kotlin/JS? You might wonder. In Kotlin/JS, there is a special type called &lt;code&gt;dynamic&lt;/code&gt;, which, like JavaScript, accepts any type without causing an error. &lt;strong&gt;Using this &lt;code&gt;dynamic&lt;/code&gt; type, let's rewrite something equivalent to &lt;code&gt;runBlocking&lt;/code&gt; for Kotlin/JS.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// commonMain&lt;/span&gt;
&lt;span class="n"&gt;expect&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;runBlocking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="nc"&gt;CoroutineScope&lt;/span&gt;&lt;span class="p"&gt;.()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;

&lt;span class="c1"&gt;// jsMain&lt;/span&gt;
&lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;runBlocking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="nc"&gt;CoroutineScope&lt;/span&gt;&lt;span class="p"&gt;.()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;dynamic&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Suppress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OPT_IN_USAGE"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;GlobalScope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;promise&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, it's important to note that the &lt;code&gt;Promise&lt;/code&gt; returned with &lt;code&gt;dynamic&lt;/code&gt; is not the original type &lt;code&gt;T&lt;/code&gt;, so if you touch the value of this &lt;code&gt;Promise&lt;/code&gt; incorrectly, it will result in a runtime&lt;/p&gt;

&lt;p&gt;error! Therefore, make sure that functions returning this &lt;code&gt;Promise&lt;/code&gt; always return the value itself in the library. Also, in Kotlin/JS, since TypeScript type definitions are included, you need to rewrite the definition to a type wrapped with &lt;code&gt;Promise&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Writing libraries with &lt;a href="https://kotlinlang.org/docs/multiplatform.html" rel="noopener noreferrer"&gt;Kotlin Multiplatform&lt;/a&gt; is quite fun and great! When it comes to Kotlin Multiplatform, it often focuses on use cases like Kotlin Multiplatform Mobile, where iOS and Android apps are packaged together, and it's not often seen to create shared libraries. So please challenge yourself! And if you release that library as OSS, please let me know!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>swift</category>
    </item>
  </channel>
</rss>
