fable-compiler / fable-import Goto Github PK
View Code? Open in Web Editor NEWFable bindings for JavaScript libraries
License: Apache License 2.0
Fable bindings for JavaScript libraries
License: Apache License 2.0
Hi!
I'm working my way through various configuration types and while in the previous bindings I could use
[<KeyValueList>]
type ApplicationOptions =
| BackgroundColor of int
now, it seems that
So using a Pojo record works
[<Pojo>]
type ApplicationOptions = {
backgroundColor: int
}
while using a union type makes the compiler angry
type ApplicationOptions =
| BackgroundColor of int
So what should I use?
Thanks!
I found this issue with VSCode bindings where window.withProgress
has Progress<obj>
in place where the original typings have Progress<{ message?: string; percentage?: number }>
.
This is quite easy to fix, but I hesitate, because this file looks like it was autogenerated, and if that's the case, it means that my manual fixes will be overwritten by the next autogeneration.
Any thoughts?
Upon installing 0.2.0 of Fable.Import.Node
, I am seeing:
/home/travis/build/jgrund/fable-jest/test/Matchers.test.fs(106,24): (106,28) error FSHARP: The value, constructor, namespace or type 'Node' is not defined.
,/home/travis/build/jgrund/fable-jest/test/Matchers.test.fs(109,13): (109,17) error FSHARP: The namespace or module 'Node' is not defined.,/home/travis/build/jgrund/fable-jest/test/Matchers.test.fs(109,4): (109,36) error FSHARP: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
Function type annotations are missing which makes it awkward to use some methods. Replace these with the correct type annotations.
It seems that many bindings, particularly the Electron bindings (but perhaps also the Browser bindings IIRC), are auto-generated and not particularly F# idiomatic. I'm thinking about type safety as well as other stuff (e.g. avoiding explicit callbacks in favour of async
/ promise
).
A couple of examples:
When using electron.remote.dialog.showOpenDialog
, it returns a ResizeArray<string>
that is undefined
if the user cancelled the dialog. The most F# idiomatic API here would be to return string list option
or string array option
, or at the very least a ResizeArray<string> option
if it has to be ResizeArray
for performance reasons.
fs.readFile
reads a file asynchronously and takes an explicit continuation callback. In F# it is more natural to use a CE (async
/promise
).
Some cases of obj
could be replaced with new types. For example, the property OpenDialogOptions.filters
(in the Electron bindings) is of type ResizeArray<obj> option
. According to the showOpenDialog documentation, this property is an array of FileFilter
which is a simple and well defined type.
Some cases of string
could be replaced with a StringEnum
. For example, the property OpenDialogOptions.properties
is of type ResizeArray<string> option
, but only supports a defined set of values, making a StringEnum
suitable.
The APIs are accessed through global objects (electron.remote.dialog.showOpenDialog
). In F# it would be more natural to access them through similarly named modules (Electron.Remote.Dialog.ShowOpenDialog
), One can argue that it's best keeping this as close to the official Electron API (and documentation) as possible, but on the other hand it often causes me some inconvenience trying to find the right object to "enter" the graph (e.g. electron
, which is defined in Fable.Import.electron_Extensions
, which puzzled me somewhat). It might also be the case that it's simply not possible in many cases to convert the API from object-based to module-based.
Fable does not hide the fact that it compiles to JS. This is both a great strength (it's fairly easy to interact with unsupported JS APIs, and devs have to learn a bit about the JS runtime environment anyway) and a significant weakness (non-trivial code needing several JS APIs, even supported ones through bindings such as in this project, may end up looking in part like JS code written with a weird and limiting syntax, and can cause troubles when functions can return e.g. undefined
unannounced through the type system). I think we all agree that type safety (cf. the first example) is important and should be ensured. I think most of you also agree that it's both safer, easier and more F# idiomatic to use list
(or even array
since it too can be pattern-matched) instead of ResizeArray
if performance allows. Personally, I'd like all APIs to "feel" like .NET and not like JS (F# is a .NET language, after all), but I can see "API feel" being a source of differing opinions.
In general: What do you think about making (at least certain parts of) the API/bindings more F# idiomatic? I'm particularly interested in cases like the return value of showOpenDialog
, where undefined
or null
are valid return values, but this fact is not part of the returned type.
I might be able to assist with this, but I'd need clear guidelines on what kinds of things are desirable and acceptable to change, and it would likely progress slowly due to my capacity in the foreseeable future. I can also make no promises as to how committed I can be to cleaning up everything (as opposed to just a few bits here and there to scratch my own itches), and I will not be able to continually maintain an F# idiomatic API as new bindings are needed for new JS API surfaces (if such maintenance is at all needed).
Note though that I think there are a lot of API changes that can be done and benefited from in isolation, so there is no strict need to do this "all at once" (except for the fact that all changes would likely be breaking, and it might be desirable to update as much as possible at once to avoid many major releases).
I think there is a breaking change in Fable2. This code fails to compile:
let nf = Fable.Import.Browser.Intl.NumberFormat.Create("en-us")
let formatted = nf.format(123456789.01)
printfn "formatted: %A" formatted
FABLE: Cannot resolve Fable.Import.Browser.Intl.NumberFormat
at the first line.
Fails both in the REPL, and in my project. But intellisense and tooltips do work both in the Repl and in VS Code:
Tried to create a failing test case, and looks like this code compiles and works in Fable 1.x. After updating to Fable 2, it is not 100% consistent, at least couldn't find docs how to test the imports, so just started hacking in the test folder...
In Pixi binding it's seems there is still reference for:
@whitetigle Do you confirm, it's the same as for pixi-particules binding ?
Please publish Pg
, SocketIo
, Uws
to nuget.
I propose to use this issue in order to track which repo has been extracted and where.
When everything has been extracted we could put the list directly in the README.md
Just a suggestion, looks cleaner IMO.
Working with the current bindings is not a good experience for developers. The ts2fable generated code is hard to read (recursive modules), missing imports, and generally a pain to use making developers spend hours and hours struggling before giving up or re-implement the binding manually themselves. This is hurting both the Fable community, and the idea of embracing the JS community. No one wants to patch auto-generated files so developers makes fixes for themselves that doesn't help others. Using ts2fable to generate the initial bindings is ok, but from then on it should be maintained manually (imo). So comments like // ts2fable 0.5.2
should be removed so developers get encouraged to work on them manually and improve them.
Hi!
I had to write the bindings for Waud JS library by hand and I ended up with the following
As you can see the code for the Waud type and static methods is clearly not what I expect I should be writing:
module Waud =
type Waud =
[<Emit("Waud.autoMute()")>]
static member autoMute() : unit = jsNative
[<Emit("Waud.destroy()")>]
static member destroy() : unit = jsNative
so how could I rewrite this kind of code in a proper fashion? Thanks!
As a funny note, this JS lib is generated from the Haxe transpiler! A great "mise en abîme"
references fable-compiler/ts2fable#290
babylonjs contains this:
interface Navigator {
mozGetVRDevices: (any: any) => any;
webkitGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void;
mozGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void;
msGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void;
webkitGetGamepads(): Gamepad[];
msGetGamepads(): Gamepad[];
webkitGamepads(): Gamepad[];
}
That causes an error:
If I F12 on MediaStreamConstraints
in Visual Studio in the babylon.d.ts file, I go to C:\Program Files (x86)\Microsoft SDKs\TypeScript\2.8\lib.dom.d.ts
.
So I think these types need to be added to Fable.Import.Browser
.
In the Nodejs bindings, we currently AutoOpen
Exports
inside which we have a bunch of let bound imports.
This is problematic as it is no longer possible to cleanly overload parts of a module since the module is now scoped as a let binding.
It seems like the ideal solution is to rename the let bound export (creating a variant between import and types).
This way it will still be possible to overload parts of a module.
According to the documentation of animejs: https://github.com/juliangarnier/anime
We can use import anime from animejs
to include the lib in our project. To take advantage fo treeshaking and also use webpack include the dependency we need to update the binding to import import
statements
Apologies if this is just me being dense, but as far as I can tell ValidityState.tooShort
does not exist where it should.
Could the Electron bindings be updated to Fable.Core 3? It's currently blocking a big update in cmeeren/fable-elmish-electron-material-ui-demo for Fable.Core 3 / Fable.React 5 compat/demo.
(Btw, the bindings are for Electron 0.37.7 and the most recent Electron version is 5.0, but that's another matter - they seem to work fine for Electron 4 as far as I've used them in the repo I mentioned.)
I'm looking for advice on how to version binding packages. Please yell at me if I should take this somewhere else.
This seems to me to be a fairly complex topic with no good answers. Bindings are created for a specific version of an npm package, and this should be communicated to users. The npm packages have their own semvers. At the same time, the bindings live their own life and can have breaking changes even though the npm package target hasn't changed at all (and vice versa - a breaking change in an npm package might not be breaking for the bindings). So one can't generally set the binding package version equal to the target npm package version and expect the binding package to still follow semver.
And with bindings that depend on other bindings, things become even worse. For example, I'm well underway with bindings for Electron 5. These depend on the Node bindings, because the Electron API depends on the Node API. Each version of Electron embeds a specific version of Node. So ideally, I should be able to specify that these bindings are for Electron 5 and depend on node bindings for Node X.Y. (Note the careful phrasing: The bindings don't depend directly on the Node bindings' version - although there might be breaking changes there, too - but rather on the Node binding's target Node version.)
I can't see any good solutions to this. Has anyone given any thought to these matters? Are there some solutions that are better/worse than others, or other caveats to be aware of?
tests for bindings should be added to https://github.com/fable-compiler/fable-import/tree/master/test/Node
Since F# has System.Exception
, I'm wondering if we should just use that (and extend it where necessary) in the node bindings.
I'm playing around with ServiceWorkers and self is limited to the Window class.
module App.SW
open Fable.Import.Browser
let self = self :?> ServiceWorker
self.addEventListener_install(fun installEvent ->
printfn "service worker installed, %A" installEvent
)
self.addEventListener_activate(fun activateEvent ->
printfn "service worker activated, %A" activateEvent
)
self.addEventListener_message(fun ev ->
printfn "%A" ev.data
)
addEventListener_install
doesn't work without the cast.
let [<Global>] self: Window = jsNative
Is not always true.
I'd like to send a PR, how should we solve this? Erased Union Type that capture both Window and ServiceWorker?
Hi,
i tried to use the LatLngExpression.ofLatLng
function in the Leaflet
module and i am getting an error:
error FABLE: Cannot find replacement for Leaflet.LatLngExpressionModule::ofLatLng
.
I suppose that is because the repo is "supposed" to only contain pure bindings and no helper code, but all the functions to convert between various DUs are actual implementations.
Or am i doing something wrong here and this should actually just work?
Since it is badly out of date I took the Fable.Import.VSCode.fs
file and redid the Paket bindings and the reference by hand, but now all the PromiseLike
s are type errors and the Fable.Import.JS
where it has been is depreciated. I am new to Fable so I am not sure whether PromiseLike
was supposed to be an alias or if it was a wholly different structure to Promise
. What should I do here?
What I want to do is go through the vscode-extension-samples and translate them to Fable from Typescript in order to get some practice for doing my own language plugin, but the bindings here are 3 years old and out of date so I am going to have to upgrade them along the way.
It is still an experimental property but wondering if there are plans to include it
See this. Crossposting it here to increase my chances of getting it answered.
I am really confused at the moment as to how to deal with inbuilt APIs. Importing 3rd party libraries is relatively clear to me, but vscode
gets passed in by the extension manager and I am not sure what to do here.
Before I can start work on the bindings for VSCode, I need to figure out how compilation of it would work first.
The latest commit 274ac05
of Fable.Import.Browser.fs
has the following opens
:
open System
open Fable.Import.JS
open Fable.Core
open System
I think it's supposed to be open Fable.Core.JS
since the announcement for 2.2 says
The new
Fable.Core
major release doesn't contain many new additions, but the main change is renamingFable.Import.JS
toFable.Core.JS
Then I have a problem that the compiler complains Fable.Import.JS
does not contain Float32Array
something.
Some methods are missing. Many take floats where ints would be more meaningful. I'm happy to tidy this up and add some StringEnums - just want to check that it's the right thing to do.
I'm not sure which of two Fable.Import.Express reps is right place to post this issue.
This is same issue as https://github.com/fable-compiler/fable-express/issues/5
this two lines of code gives compile time error:
open Fable.Import
let s = express.``static``
error FABLE: Cannot find replacement for Fable.Import.express.Globals::static
@alfonsogarciacaro Could we publish the new Fable.Import.Browser as 1.3.0 or 2.0 as it's improved a lit the API. Especially with for the addEventListener
:)
Hi there!
So I have new bindings for waud.js and paper.js libs. My question is simple: where should I put them?
More generally: what's the current policy for adding and registering bindings for Fable?
Thanks!
Hi there,
I found Fable.Import.Browser not including type definitions of EventSource.
It seems Fable.Import.Browser is the best module to place them considring that EventSource API is provided by each browser.
I'd be happy to submit a PR, but I'm not sure when I can get down to this.
In https://github.com/fable-compiler/fable-import/blob/master/Node/Https.fs https://github.com/fable-compiler/fable-import/blob/master/Node/Http.fs and https://github.com/fable-compiler/fable-import/blob/master/Node/Net.fs "port" variables should be of type int rather than float.
If someone could confirm that this is correct I can do a PR.
Hi!
I'm in the process of releasing the first version of bindings for Pixi.js in fable-import.
But before I do so, I have a question: I also have bindings for pixi particles and pixi-sound which are kind of optional child libraries yet important ones. I use all of them in samples-pixi
So shall I put them in the same pixi folder?
Is there a way to read Fable.Import.Pixi.fs file? I cannot identify functions which can be used.
Sorry if it's a noob question but I want to use Pixi.js in fsharp.
Sorry for noob question: what is the easy way to add custom headers in Fable.PowerPack.Fetch?
I apologize if the solution to my issue is simple, as I'm still learning Fable (and F# actually).
I'm trying to use the Electron ipcRenderer and ipcMain for inter/process communication (like I normally would in regular electron development). In my renderer I have something like this:
electron.ipcRenderer.send("Hello", ["World"])
Then in my Main.fs, I set up a listener:
electron.ipcMain.on("Hello", unbox(fun x -> printfn "Hello %A" x)) |> ignore
And when I execute, I get the text Hello [object Object]
(which I recognize very well from Javascript development.)
The type signature of of the 'send' function is (channel: string *, args: obj []) -> unit
So if i'm reading that correctly, the send function requires a string to representing the channel name, and arguments which is a list of Objects?
So my question is, how can I enforce a type when sending arguments through ipcRenderer send
and receive that same type in my callback function in ipcMain?
Also, is there any documentation for these import APIs? I was not able to find any.
@alfonsogarciacaro I remember a discussion where you said something like that:
In fable-import we should have only bindings and not helpers in it
That's a good point but we can't assure that the bindings will not in the future come with helpers. That's things are discovered when using the API and we can't predict future :)
So will that be a problem if we start a binding here and finally some days/weeks later it will come with helpers in it.
Should we put the binding in this repo ? Have a separate repo ? Should I create it under my account ?
Has anyone looked at breeze.js or anything similar with a view to producing a browser-hosted ORM in F#.
It's easy enough to just use something like breeze with a minimal fable import wrapper, but ideally one would want to integrate it fully into the F# world, leverage strong typing &c, and that looks like an interesting and potentially worthwhile challenge.
For anyone interested, breeze.js is an opensource javascript library which provides an entity-framework like ORM in javascript, and gets/puts data via ajax calls to a backend. The backend can be an existing web service if you produce your own adapter, but it's very easy to produce a one page web app which can serve an EF.core model in just the form expected by breeze, letting you write EF like code in javascript in the browser.
I'm currently playing with using breeze lightly bound to fable as the data source for an Elmish front-end - and will see how that goes first. But if I'm reinventing the wheel here, or going down a dead-end, it would be good to know!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.