pesy icon indicating copy to clipboard operation
pesy copied to clipboard

New conventions based on feedback from @jaredly

Open jordwalke opened this issue 6 years ago • 11 comments

@prometheansacrifice

@jaredly gave some good feedback about how many moving parts there are even with pesy. In some cases, there's some ways to make those much less noisy or require less explanation.

In other cases, there's not much we can do:

Why do packages need to be named package-name and then the namespaces/files be named PackageName?

The reason is that packages end up in file paths, and not all file systems are case sensitive. If publishing to npm they even mandate that everything be lowercase. With some changes to esy, we could maybe fix that. But it would be weird and different than npm. Not necessarily bad.

How about making the public library name the same as the module name so they're both LikeThis?

I think that has the same problem. The library name ends up in file paths so it has to be like-this when the module name is LikeThis

Okay, what can we do to simplify?

One great simplification is to use pesy to hide public library names and make people basically think they're just supplying require paths! We do that by making the public library names correspond directly to their paths inside their packages.

{
  "name": "my-package",
  "build": "dune build -p #{self.name}",
  "buildDirs": {
    "lib/here": {
      "namespace": "Foo",
      "require": ["my-package/lib/there"]
    },
    "lib/there": {   },
    "bin/my-binary.exe": {
      "require": ["my-package/lib/here", "@reason-native/console"]
    }
  }
}

You wouldn't even have to specify a namespace most of the time. You could even infer it from the library path (so "lib/this-path" could automatically have namespace ThisPath).

So what's going on is that packages at "lib/there" are actually getting a dune public_nameofmy-package.lib.there`.

This is really nice because it makes it feel a lot like npm - they're just require paths like they've always been using. The only difference is that they have to specify them in the package.json per directory instead of per file which is actually kind of nice because it gives you a bird's eye view of your project.

jordwalke avatar Jan 16 '19 11:01 jordwalke

I think using my-package/lib/there instead of my-package.lib.there. I clearly remember spending sometime how subpackages where named relative to one another because I hadn't read findlib docs. This is so much more intuitive. Easier onboarding! I'm glad that the next set of users will have on less thing to know/read just to get started.

About bin/my-binary.exe: I have a slight discomfort looking at this. Is the .exe supposed to help us internally figure if the package is a lib or a binary? Also, this shouldn't prompt the user to use .lib similarly for libraries. As users, we tend to generalise and consistent patterns are easy to understand, isn't it?

ManasJayanth avatar Jan 16 '19 12:01 ManasJayanth

Good feedback. Please specify what you would rather have instead of that for bin conventions.

jordwalke avatar Jan 17 '19 23:01 jordwalke

    "path/to/exe-package": {
      "main": "MyBinary.re",
      "require": ["my-package/lib/here", "@reason-native/console"]
    }

MyBinary is the name of the main file ie MyBinary.re which creates MyBinary.exe. This way keys always have path to the package.

Rationale: libraries are a collection of .re files (unless there's single entry that can abstract/make some re files private, which needs to be handled differently I think). Executables are a collection of .re files that are bundled with one particular .re acting as the main. Sort of like C's main() function or the file mentioned as bin in package.json in npm packages.

Considering that we are used to referring to main file in npm binaries as bin and libraries as main, we should consider the following too

    "path/to/lib-package": {
      "main": "LibPackage.re",
      "require": ["my-package/lib/here", "@reason-native/console"]
    }
    "path/to/exe-package": {
      "bin": "SomeMainFile.re",
      "require": ["my-package/lib/here", "@reason-native/console"]
    }

This inverts things a bit: what is considered main in the native world is entry point for libs in npm packages. While I don't think we should force users to specify a main file, some might want to hide/privatise a couple .re files. In that case, we expect them to specify the entry file with main.

ManasJayanth avatar Jan 18 '19 04:01 ManasJayanth

hmmm I think I'd prefer having a canonical "default main filename", similar to how nodejs has index.js. rust has mod.rs, for example. I'd be happy with Index.re being the "entry point" for both libraries and executables

jaredly avatar Jan 18 '19 23:01 jaredly

@jaredly How do we differentiate between exe and a lib?

I like that the config would look simpler

    "path/to/exe-package": {
      "require": ["my-package/lib/here", "@reason-native/console"]
    }
    "path/to/lib-package": {
      "require": ["my-package/lib/here", "@reason-native/console"]
    }

Correct me if I'm wrong, the bin and lib would be installed as exe-package.exe and lib-package.lib behind the scenes, right?. So the package that wants to consume the lib would look like

    "path/to/consuming-package": {
      "require": ["path/to/lib-package"]
    }

Sounds great to me. And I'm guessing its okay for the user to override this behaviour with a main or a bin field.

Taking this one step further: I think we could allow relative paths too

    "lib/here": {
      "namespace": "Foo",
      "require": ["../there"]
    },
    "lib/there": {   },

ManasJayanth avatar Jan 19 '19 03:01 ManasJayanth

For libraries, I think the best defaulting is that if you don't specify an entrypoint, then one is created for you out of all the modules. If you want to mark things private then you make an entrypoint.

    "path/to/exe-package": {
      "require": ["my-package/lib/here", "@reason-native/console"]
   }
   "path/to/lib-package": {
     "require": ["my-package/lib/here", "@reason-native/console"]
   }

Correct me if I'm wrong, the bin and lib would be installed as exe-package.exe and lib-package.lib behind the scenes, right?. So the package that wants to consume the lib would look like

The library would actually be installed as package-name.path.to.lib-package behind the scenes. I don't know what the binary would be installed as behind the scenes because I think we need some way to specify the name of the binary or use a convention which is what we're discussing here.

Taking this one step further: I think we could allow relative paths too

Yes, I do think that would be nice.

jordwalke avatar Jan 21 '19 09:01 jordwalke

If libraries are defaulted to a bundling of all the modules then they won't always have a "main" field, then we get in a situation where binaries must have some way to be distinguished as binaries:

In this case, we can't know which are libraries and which are binaries.

   "path/to/exe-package": {
      "require": ["my-package/lib/here", "@reason-native/console"]
   }
   "path/to/lib-package": {
     "require": ["my-package/lib/here", "@reason-native/console"]
   

jordwalke avatar Jan 21 '19 09:01 jordwalke

We can introduce the bin property like npm as we discussed.

ManasJayanth avatar Jan 21 '19 10:01 ManasJayanth

Okay so it would be like:

   "path/to/exe-package/": {
      "bin": "SomeEntrypoint.re",
      "require": ["my-package/lib/here", "@reason-native/console"]
   }
   "path/to/lib-package": {
     "require": ["my-package/lib/here", "@reason-native/console"]
 }

And maybe you could do "bin": "SomeEntrypoint.re as binary-name.exe" if you want to be able to customize the binary name instead of SomeEntrypoint.exe?

In this proposal the bin field is required every time you want to mark something a binary.

jordwalke avatar Jan 21 '19 10:01 jordwalke

SomeEntrypoint.re as binary-name.exe

:+1:

In this proposal the bin field is required every time you want to mark something a binary.

Agreed.

ManasJayanth avatar Jan 21 '19 10:01 ManasJayanth

SomeEntrypoint.re as binary-name.exe

While it can lead to confusion in a case insensitve file system, I do believe we should allow SomeEntrypoint.exe by default without having to specify the alternative kebab cased binary-name.exe

ManasJayanth avatar Jan 21 '19 10:01 ManasJayanth