I'm trying to update wrappers 529 to 806. First q...
# javascript
v
I'm trying to update wrappers 529 to 806. First question:
OutgoingHttpHeaders
used to be
typealias OutgoingHttpHeaders = Dict
, so it was used like
Copy code
additionalHeaders = recordOf(
    "Content-Type" to "application/x-www-form-urlencoded",
    "User-Agent" to "Setup WSL GitHub Action"
)
how do you do it now that it is a
sealed external interface OutgoingHttpHeaders : Dict
? Like this?
Copy code
additionalHeaders = jso {
    set("Content-Type", "application/x-www-form-urlencoded")
    this["User-Agent"] = "Setup WSL GitHub Action"
}
And next question, is it intended that
node.http.IncomingMessage.statusCode
which used to be
Number?
now is
Double?
? I had
if (response.message.statusCode != 200)
which now does not compile anymore.
And similar for
Process.exit
you now have to give
String
or
Double
as argument, when before it was
Number
, so
process.exit(1)
does no longer compile
h
If you use Kotlin 2.0.20, afaik, you should be able to use JsPlainObjects
v
Which of the three messages answers this? I guess the first?
h
Yes
For the other number changes, fill a bug and wait for a new version πŸ˜… or change your code, because the translator of kotlin-wrappers is changing and often breaks some code…
v
I'm on 2.0.20 yes, that I updated first πŸ™‚
Assuming you mean this: https://github.com/JetBrains/kotlin/tree/master/plugins/js-plain-objects I don't actually see what you mean exactly how that would help. Besides that the sense in using the kotlin-wrappers is not needing to define and maintain the external definitions myself, isn't it? πŸ™‚
h
Okay, took a look at OutgoingHeaders and it's not annotated, like https://github.com/JetBrains/kotlin-wrappers/blob/master/kotlin-actions-toolkit/src/jsMain/generated/actions/http/client/RequestOptions.kt With this annotation, the kotlin compiler generates a function overload and you don't need jso/recordOf. But without this annotation, you still need jso.
Copy code
val requestOptions = RequestOptions(maxRetries = 3)
But again, this function will only be generated with JsPlainObjects
v
Ah, so the wrappers project uses
JsPlainObject
, it is just missing on
OutgoingHttpHeaders
, I see, thanks. Besides that it would not actually help in my case, as
user-agent
is only there as comment and
content-type
not even as comment. πŸ˜„ So even if it had
JsPlainObject
I would need to use
jso { ... }
in my case. Which
jso
line do you think is more idiomatic? The
set(..., ...)
or the
this[...] = ...
? Or is there another option I'm not aware of?
h
Yes, exactly. If it’s missing, fill a bug, and they will fix it. jso just creates an empty js object and casts the receiver, so set vs this is from the dict interface here and it’s only a matter of code style/preference. IMHO I would add a inline extension getter to have somehow type safety/hide it.
v
Of course it's a matter of code-style, that's why I ask what you think is more idiomatic πŸ™‚
t
In Kotlin
2.1.0
we will generate missed accessors for properties like this
And it will look like this:
Copy code
additionalHeaders = jso {
    contentType = "application/x-www-form-urlencoded"
    userAgent = "Setup WSL GitHub Action"
}
Or even
Copy code
additionalHeaders = OutgoingHttpHeaders(
    contentType = "application/x-www-form-urlencoded"
    userAgent = "Setup WSL GitHub Action"
)
v
Oh, but we need to wait for 2.1? 😞 What is missing?
t
Dash support in property names without warnings
v
I see
t
Solution for now - add strict extensions for
OutgoingHttpHeaders
PR is welcome
v
what are "strict extensions"?
PRs are always welcome πŸ˜„
t
Copy code
var OutgoingHttpHeaders.contentType: String
    get() = asDynamic()["content-type"]
    set(value) {
        asDynamic()["content-type"] = value
    }
and so on
File name -
OutgoingHttpHeaders.ext.kt
v
As, so manual and not waved in the Karakum generation, will see whether I find time to do something, or at least for the two I need. πŸ˜„
t
It's just temp file, while
2.1.0
isn't released
πŸ‘Œ 1
v
Hm, and what about
node.fs.writeFile
? It used to be
Copy code
suspend fun writeFile(
    file: PathLike, /* | FileHandle */
    data: Any, /* string | NodeJS.ArrayBufferView | Iterable<string | NodeJS.ArrayBufferView> | AsyncIterable<string | NodeJS.ArrayBufferView> | Stream */
    options: WriteFileOptions,
)
and I used it like
Copy code
writeFile(assetFilePath, asset.source, jso<WriteFileOptions> {
    mode = asset.permissions
})
where
assetFilePath
is
String
and
asset.source
is
node.buffer.Buffer
. Now
writeFile
got split into multiple signatures, but none accepts
Buffer
as
data
,
WriteFileOptions
does not accept
mode
anymore, and "Type argument is not within its bounds. Expected: Any Found: WriteFileOptions /* = Any? */" :-/
Oh, it is now
WriteFileAsyncOptions
while the old one is still there but just an alias for
Any?
. o_O
So, is it intentional that
WriteFileOptions
is still there or a bug? And should there be an overload accepting
Buffer
or do I need to transform it somehow?
Hm, seems
Buffer
should implement
ArrayBufferView
if I'm not mistaken
t
I see
Buffer
in child types πŸ˜‰
v
Indeed, why is it not accepted then?
Oh, it is ambiguous 😞
t
Buffer
implements both 🧌
v
Argh, about time we finally get union types in Kotliln 😠
Can there be anything done in the wrappers about it, or do I need to cast?
Hm, and why is
asset.source as ArrayBufferView
an "Unchecked cast to external interface: Buffer to ArrayBufferView" ?
t
Can there be anything done in the wrappers about it, or do I need to cast?
Do you mean in Kotlin? πŸ˜‰
Hm, and why is
asset.source as ArrayBufferView
an "Unchecked cast to external interface: Buffer to ArrayBufferView" ?
No runtime = no cast πŸ™‚
v
So unless we have union types, I need to do
asset.source.unsafeCast<ArrayBufferView>()
, correct?
e
If you use Kotlin 2.0.20, afaik, you should be able to use JsPlainObjects
Nope, the plugin has to be bundled with the IDEA distribution first. Otherwise you'll see errors in K2 mode.
t
Strict variant:
Copy code
asset.source.let<ArrayBufferView> { it }
unsafeCast
isn't recommended 🀨
e
So unless we have union types, I need to do
asset.source.unsafeCast<ArrayBufferView>()
, correct?
A workaround would be renaming the named parameter. Specifying the argument name would then get rid of the ambiguity.
unsafeCast
isn't recommended
unsafeCast
-ing is still the best approach in certain scenarios. I don't like going down the route of using overly complex solution for a simple cast.
v
asset.source.let<ArrayBufferView> { it }
does not compile, it would be
asset.source.let<ArrayBufferView, ArrayBufferView> { it }
. And for that you then get "Redundant 'let' call could be removed" :-/
e
Use
unsafeCast
. It's there for this exact reason
If you really want to go the extra mile, wrap
unsafeCast
in a more appropriately named function.
v
asset.source.run<ArrayBufferView, ArrayBufferView> { this }
does not have an IJ finding tough πŸ˜„
t
asset.source.run<_, ArrayBufferView> { this }
?
e
Looking at it in a PR review would have me looking perplexed. Stick to the simple route.
t
> Stick to the simple route. PR with pretty extension in Kotlin Wrappers is welcome (as always)!
v
val Buffer.asArrayBufferView: ArrayBufferView get() = run { this }
Now it works with
asset.source.asArrayBufferView
t
run
is redundant
v
Ah, indeed,
val Buffer.asArrayBufferView: ArrayBufferView get() = this
, now we become pretty finally πŸ˜„
Thanks for your quick and thorough help as always πŸ™‚
πŸ˜€ 1
t
<http://asset.source.as|asset.source.as><ArrayBufferView>()
with
as
in wrappers
Otherwise @Edoardo Luppi will see
unsafeCast
on reviews πŸ˜‰
And will loose type checks 😬
v
<http://asset.source.as|asset.source.as><ArrayBufferView>()
with
as
in wrappers
I might be blind, where is it? IJ doesn't want to find it
e
What I meant is I prefer to use
unsafeCast
over creating additional functions, which seems unnecessary to me. With
unsafeCast
you're making your intent clear, that is, I'm casting it to that type because I'm confident in what I'm doing
t
> I might be blind, where is it? In future PR from @Vampire πŸ˜‰
v
Oh, I see πŸ˜„
But that's then not different from
unsafeCast
, is it?
t
What I meant is I prefer to use
unsafeCast
over creating additional functions, which seems unnecessary to me.
Unnecessary type checking?
But that's then not different from
unsafeCast
, is it?
it will check types
v
I see
t
safeCast()
πŸ™‚
e
But what's the reason to check
Buffer
is indeed an
ArrayBufferView
. In this specific case, casting is performed to avoid the overload ambiguity.
v
Argh,
as
is of course a keyword
So
fun <T> T.safeCast(): T = this
it is and then
asset.source.safeCast<ArrayBufferView>()
No I just need to find out why
Copy code
additionalHeaders = jso {
    this["Content-Type"] = "application/x-www-form-urlencoded"
    this["User-Agent"] = "Setup WSL GitHub Action"
}
indeed did not work πŸ˜•
e
Copy code
val additionalHeaders = jso<Record<String, String>> {
  this["Content-Type"] = "application/x-www-form-urlencoded"
  this["User-Agent"] = "Setup WSL GitHub Action"
}
Starting from 2.1.0, you'll be able to create a function like
Copy code
record {
  `Content-Type` = "application/x-www-form-urlencoded"
  `User-Agent` = "Setup WSL GitHub Action"
}
t
safeCast already exists 😞
OutgoingHttpHeaders
fixed πŸŽ‰
upcast
extension on board!
v
Nice, thanks. πŸ™‚
πŸ™‚ 1