rules_nodejs icon indicating copy to clipboard operation
rules_nodejs copied to clipboard

Monorepo: is it possible to read dependencies from package.json?

Open spion opened this issue 7 years ago • 2 comments

I read through the docs but I couldn't figure out how to set up bazel for a classic lerna / yarn monorepo. Specifically, I can't figure out if its possible to read the dependencies for a bazel rule from another file i.e. package.json

What I like is to avoid duplication of specifying the dependencies twice, once in package.json for npm/yarn publishing and consumption/installation by other users, and once in Bazel for building via TypeScript in the right order.

Ideally I would have deps be generated from reading the toplevel package.json workspaces entry globs, filtered through the individual package's own dependencies and devDependencies as specified in package.json

spion avatar Dec 22 '18 14:12 spion

I believe what you could do is to write a Bazel macro that takes dependencies as parameters, and based on these dependencies:

  • instantiates the ts_library rule
  • populates the replacements parameters of npm_package accordingly, so that a placeholder in your package.json is replaced by the actual dependencies.

Something along these lines:

def _format_dep(name, version):
    name = "@prefix/" + name[11:]
    return "\"{}\": \"^{}\"".format(name, version)

def my_ts_library(name, deps = [], dev_deps = [], **kwargs):

    ts_library(
        name = name,
        deps = deps + dev_deps,
        **kwargs
    )

    replacements = {
        "\"DEPS_PLACEHOLDER\": \"\"": ",\n    ".join(
            [
                _format_dep(dep, "0.0.1") for dep in deps 
                if dep.startswith("//packages/")
            ]
        ),
        "\"DEV_DEPS_PLACEHOLDER\": \"\"": ",\n    ".join(
            [
                _format_dep(dep, "0.0.1") for dep in dev_deps
                if dep.startswith("//packages/")
            ]
        ),
    }

    npm_package(
        name = name + "-package",
        srcs = [":package.json"],
        deps = [":" + name] + deps,
        replacements = replacements,
    )

With a package.json formatted as:

{
  "name": "@prefix/mypackage",
  "version": "0.0.0-PLACEHOLDER",
  "dependencies": {
    "DEPS_PLACEHOLDER": ""
  },
  "devDependencies": {
    "DEV_DEPS_PLACEHOLDER": ""
  }
}

Alternatively, I would write a genfile rule generating the package.json file based on your dependencies

pierreis avatar Jan 29 '19 22:01 pierreis

You're right, the deps are repeated right now. In google, we don't use package.json files at all, so we accidentally brought that idiom with us. I think the best thing is for you to write package.json files in each package, and something like Gazelle generates BUILD files so that Bazel understands the package too.

alexeagle avatar Sep 23 '19 20:09 alexeagle

No longer in scope for rules_nodejs

gregmagolan avatar Jun 08 '24 21:06 gregmagolan