Search code examples
reasonbucklescriptbsconfig

Creating a Reason package with a different namespace name than the NPM package


I started creating a native Reason unit test library, inspired by RSpec (I did one for F# previously)

I wanted to call the library Respect, but since there was already an npm package named "respect", I named the npm library "re-respect". But my bsconfig.json specifies the package name as respect

{
  "name": "Respect",
  "version": "0.1.0",
  "namespace": true,
  "sources": [
    {"dir": "src"},
    {
      "dir": "tests",
      "type": "dev"
    }
  ],
  "bs-dependencies" : [
      // add your bs-dependencies here 
  ]
}

I pushed the package, and imported it from a test project, where I reference the Respect namespace. I have this reason source file in the project:

open Respect.Dsl;

describe "Foo" [
  it "has a test" (fun _ => ())
] |> register;

!rootContext |> run;

Building the code with npm run build works fine, but when I run the tests, I get the error:

module.js:529
    throw err;
    ^

Error: Cannot find module 'Respect/lib/js/src/dsl.js'
    at Function.Module._resolveFilename (module.js:527:15)
    ...

The error is clear - the npm package is installed in node_modules/re-respect not node_modules/Respect where it tries to find the code.

Am I trying to do something I shouldn't? Should my root namespace follow the NPM package name? Do I need to find a new name?

p.s. as I'm writing this, I'm realizing that there is a difference between the version no in package.json and bsconfig.json - but I doubt that is the source of the problem.


Solution

  • I recommend the following:

    • Turn off namespacing for your project
    • Keep the re-respect name for your npm library and for the bsconfig.json file
    • Keep a file Respect.re as the main module of your project. It will be exposed publicly as the Respect module and users can access it as the main module

    The key takeaway here is that you don't always need namespacing, especially if your project naturally fits under a single main module.

    Edit: for your Dsl nested module you may want to keep it inside the Respect.re file as a syntactically nested module:

    /* Respect.re */
    module Dsl = {
      ...
    };
    

    Or you may want to keep it in its own file, that's fine, you'll just need to do a little more legwork in that case, by making sure you namespace and then alias it manually:

    /* Respect_dsl.re */
    ...
    
    /* Respect.re */
    module Dsl = Respect_dsl;
    
    ...
    

    Then users will be able to access it just as before as Respect.Dsl.