Skip to content
This repository has been archived by the owner on Feb 27, 2023. It is now read-only.

How to version bindings? #82

Open
cmeeren opened this issue Jun 16, 2019 · 8 comments
Open

How to version bindings? #82

cmeeren opened this issue Jun 16, 2019 · 8 comments

Comments

@cmeeren
Copy link

cmeeren commented Jun 16, 2019

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?

@alfonsogarciacaro
Copy link
Member

Yes, this is a difficult problem an at the moment we don't have a specific mechanism for it. As far as I know Typescript has nothing for this either (although maybe they use npm version dependencies when distributing the declarations). The only way for now to communicate the version the bindings are covering is to add it in a comment on the top of the declarations.

@Zaid-Ajaj
Copy link
Member

A while ago I proposed a solution as an external CLI tool: this tool would generate a dependency graph of nuget packages and the top-level npm packages they depend upon. Running the tool would generate a report such as

Fable.DateFunctions requires npm dependency date-fns >= 1.3 but it was not installed
Fable.React requires npm dependencies [react >= 16.8.0, react-dom >= 16.8.0] but they were not installed

The report tells about the npm package that you need to install instead of having to read the documentation, but it could also go as far as running the commands required to actually install what is needed.

We already know how to generate a dependency graph of nuget packages, library authors would need to include information about npm packages they depend upon which is possible by adding a PropertyGroup to the project file of the library, for example Fable.React would include this in the project file:

<PropertyGroup>
   <NpmDependencies>
       <NpmPackage Name="react" Version=">= 16.8.0" />
       <NpmPackage Name="react-dom" Version=">= 16.8.0" />
   </NpmDependencies>
</PropertyGroup>

This means after generating the dependency graph of nuget packages, the CLI tool would go and read the NpmDependencies section in fsproj and add it as metadata to the graph then the tool would parse either package-lock.json or yarn.lock to check if the dependency is installed.

The graph generated would look something like this:

 App
  | 
  | -- Fable.DateFunctions 
           | -- Fable.Core
           | -- npm (date-fns >= 1.3.0)
  | -- Fable.React
           | -- Fable.Core 
           | -- npm (react >= 16.8.0)
           | -- npm (react-dom >= 16.8.0)

This CLI tool is not "new package manager" it just gathers information from what nuget and npm have already gathered in the project and look for missing dependencies.

Unfortunately I haven't had the time to prototype this but it has been on my mind for quite a while now

@alfonsogarciacaro
Copy link
Member

That'd be great @Zaid-Ajaj! Although please note Fable doesn't create an actual dependency graph for Nuget packages, it just makes a simple sorting to put all the sources in compilation order. But that's probably enough for this use case anyways :)

@Zaid-Ajaj
Copy link
Member

Indeed I don't need a graph really, even the unsorted list should be enough because I only need project file paths (project being compiled + dependencies + transitive dependencies) to read their corresponding npm package dependencies.

Then the CLI tool needs to locate package-lock.json or yarn.lock (needs a parser) to get all available installed packages to check whether something is missing or needs to be updated (using semver compare function)

I think I will take a stab at it 😉

@alfonsogarciacaro
Copy link
Member

alfonsogarciacaro commented Jun 19, 2019

Parsing the lock file is going to be tricky. package-lock.json may be easier, but I think the format of yarn.lock is not guaranteed to be stable. I'd recommend just checking for explicit dependencies in the package.json to have something working without having to spend too much time on it. You can also use the semver library to verify the versions.

@Zaid-Ajaj
Copy link
Member

Yeah I might start with just the top-level package.json dependencies and see how it goes

@Zaid-Ajaj
Copy link
Member

Introducing Femto, an experimental version of this CLI tool that verifies the compatibility of npm packages used by Fable bindings:
femto

@Zaid-Ajaj
Copy link
Member

Approaching Nirvana with the help of @MangelMaxime of course!

femto

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants