refactor: update node toolchain to provider File objects instead of paths
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index 125d80d..5ad6c48 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -33,15 +33,14 @@
     - "//..."
     test_targets:
     - "//..."
-  # Temporarily disabled MacOS tests until pre-existing failure can be investigated.
-  # macos-smoke:
-  #   name: macos
-  #   platform: macos
-  #   working_directory: "e2e/smoke"
-  #   build_targets:
-  #   - "//..."
-  #   test_targets:
-  #   - "//..."
+  macos-smoke:
+    name: macos-smoke
+    platform: macos
+    working_directory: "e2e/smoke"
+    build_targets:
+    - "//..."
+    test_targets:
+    - "//..."
   windows-smoke:
     name: windows-smoke
     platform: windows
diff --git a/.bazelversion b/.bazelversion
index f3b5af3..21c8c7b 100644
--- a/.bazelversion
+++ b/.bazelversion
@@ -1 +1 @@
-6.1.1
+7.1.1
diff --git a/WORKSPACE b/WORKSPACE
index 08389a2..700970c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -35,13 +35,13 @@
 # The order matters because Bazel will provide the first registered toolchain when a rule asks Bazel to select it
 # This applies to the resolved_toolchain
 nodejs_register_toolchains(
-    name = "node16",
-    node_version = "16.5.0",
+    name = "node17",
+    node_version = "17.9.1",
 )
 
 nodejs_register_toolchains(
-    name = "node15",
-    node_version = "15.14.0",
+    name = "node16",
+    node_version = "16.20.2",
 )
 
 http_archive(
diff --git a/docs/Core.md b/docs/Core.md
index 3588d38..ac4af2d 100644
--- a/docs/Core.md
+++ b/docs/Core.md
@@ -17,8 +17,8 @@
 **USAGE**
 
 <pre>
-node_repositories(<a href="#node_repositories-name">name</a>, <a href="#node_repositories-node_download_auth">node_download_auth</a>, <a href="#node_repositories-node_repositories">node_repositories</a>, <a href="#node_repositories-node_urls">node_urls</a>, <a href="#node_repositories-node_version">node_version</a>, <a href="#node_repositories-platform">platform</a>,
-                  <a href="#node_repositories-repo_mapping">repo_mapping</a>, <a href="#node_repositories-use_nvmrc">use_nvmrc</a>)
+node_repositories(<a href="#node_repositories-name">name</a>, <a href="#node_repositories-node_download_auth">node_download_auth</a>, <a href="#node_repositories-node_repositories">node_repositories</a>, <a href="#node_repositories-node_urls">node_urls</a>, <a href="#node_repositories-node_version">node_version</a>,
+                  <a href="#node_repositories-node_version_from_nvmrc">node_version_from_nvmrc</a>, <a href="#node_repositories-platform">platform</a>, <a href="#node_repositories-repo_mapping">repo_mapping</a>)
 </pre>
 
 To be run in user's WORKSPACE to install rules_nodejs dependencies.
@@ -84,7 +84,7 @@
 
 <h4 id="node_repositories-node_download_auth">node_download_auth</h4>
 
-(*<a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a>*): auth to use for all url requests
+(*<a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a>*): Auth to use for all url requests
 Example: {"type": "basic", "login": "<UserName>", "password": "<Password>" }
 
 Defaults to `{}`
@@ -102,21 +102,31 @@
 
 <h4 id="node_repositories-node_urls">node_urls</h4>
 
-(*List of strings*): custom list of URLs to use to download NodeJS
+(*List of strings*): Custom list of URLs to use to download NodeJS.
 
 Each entry is a template for downloading a node distribution.
 
 The `{version}` parameter is substituted with the `node_version` attribute,
 and `{filename}` with the matching entry from the `node_repositories` attribute.
 
-Defaults to `["https://nodejs.org/dist/v{version}/{filename}"]`
+If not set then `https://nodejs.org/dist/v{version}/{filename}` is used
+
+Defaults to `[]`
 
 <h4 id="node_repositories-node_version">node_version</h4>
 
-(*String*): the specific version of NodeJS to install
+(*String*): The specific version of NodeJS to install
 
 Defaults to `"18.20.0"`
 
+<h4 id="node_repositories-node_version_from_nvmrc">node_version_from_nvmrc</h4>
+
+(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): The local path of the .nvmrc file containing the version of node
+
+If set then also set node_version to the version found in the .nvmrc file.
+
+Defaults to `None`
+
 <h4 id="node_repositories-platform">platform</h4>
 
 (*String*): Internal use only. Which platform to install as a toolchain. If unset, we assume the repository is named nodejs_[platform]
@@ -128,21 +138,13 @@
 (*<a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a>, mandatory*): A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`).
 
 
-<h4 id="node_repositories-use_nvmrc">use_nvmrc</h4>
-
-(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): the local path of the .nvmrc file containing the version of node
-
-If set then also set node_version to the version found in the .nvmrc file.
-
-Defaults to `None`
-
 
 ## node_toolchain
 
 **USAGE**
 
 <pre>
-node_toolchain(<a href="#node_toolchain-name">name</a>, <a href="#node_toolchain-headers">headers</a>, <a href="#node_toolchain-npm">npm</a>, <a href="#node_toolchain-npm_files">npm_files</a>, <a href="#node_toolchain-npm_path">npm_path</a>, <a href="#node_toolchain-target_tool">target_tool</a>, <a href="#node_toolchain-target_tool_path">target_tool_path</a>)
+node_toolchain(<a href="#node_toolchain-name">name</a>, <a href="#node_toolchain-headers">headers</a>, <a href="#node_toolchain-node">node</a>, <a href="#node_toolchain-node_path">node_path</a>, <a href="#node_toolchain-npm">npm</a>, <a href="#node_toolchain-npm_files">npm_files</a>, <a href="#node_toolchain-npm_path">npm_path</a>)
 </pre>
 
 Defines a node toolchain for a platform.
@@ -157,7 +159,7 @@
 
 node_toolchain(
     name = "node_toolchain",
-    target_tool = "//some/path/bin/node",
+    node = "//some/path/bin/node",
 )
 ```
 
@@ -195,37 +197,37 @@
 
 <h4 id="node_toolchain-headers">headers</h4>
 
-(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): A cc_library that contains the Node/v8 header files for this target platform.
+(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): cc_library that contains the Node/v8 header files
 
 Defaults to `None`
 
+<h4 id="node_toolchain-node">node</h4>
+
+(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): Node.js executable
+
+Defaults to `None`
+
+<h4 id="node_toolchain-node_path">node_path</h4>
+
+(*String*): Path to Node.js executable file
+
+Defaults to `""`
+
 <h4 id="node_toolchain-npm">npm</h4>
 
-(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): A hermetically downloaded npm executable target for this target's platform.
+(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): Npm JavaScript entry point
 
 Defaults to `None`
 
 <h4 id="node_toolchain-npm_files">npm_files</h4>
 
-(*<a href="https://bazel.build/docs/build-ref.html#labels">List of labels</a>*): Files required in runfiles to run npm.
+(*<a href="https://bazel.build/docs/build-ref.html#labels">List of labels</a>*): Additional files required to run npm
 
 Defaults to `[]`
 
 <h4 id="node_toolchain-npm_path">npm_path</h4>
 
-(*String*): Path to an existing npm executable for this target's platform.
-
-Defaults to `""`
-
-<h4 id="node_toolchain-target_tool">target_tool</h4>
-
-(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): A hermetically downloaded nodejs executable target for this target's platform.
-
-Defaults to `None`
-
-<h4 id="node_toolchain-target_tool_path">target_tool_path</h4>
-
-(*String*): Path to an existing nodejs executable for this target's platform.
+(*String*): Path to npm JavaScript entry point
 
 Defaults to `""`
 
diff --git a/docs/Toolchains.md b/docs/Toolchains.md
index befe3a2..fa1c0ed 100644
--- a/docs/Toolchains.md
+++ b/docs/Toolchains.md
@@ -6,35 +6,13 @@
 
 If you have an advanced use-case and want to use a version of node not supported by this repository, you can also register your own toolchains.
 
-## Node.js binary for the target platform
-
-Sometimes your target platform (where your software runs) is different from the host platform (where you run Bazel) or execution platform (where Bazel actions run).
-The most common case is developing a docker image on MacOS, which will execute in a Linux container.
-
-Our toolchain support is conditional on the execution platform, as it's meant for running nodejs tools during the build.
-It is not needed for this use case. Instead, simply select the nodejs you want to include in the runtime.
-
-For example, rules_docker has a `nodejs_image` rule, which takes a `node_repository_name` attribute indicating
-which nodejs binary you want to include in the image. `nodejs_linux_amd64` is the value you'd use.
-
-## Cross-compilation
-
-Bazel Toolchains are intended to support cross-compilation, e.g. building a linux binary from mac or windows.
-Most JavaScript use cases produce platform-independent code,
-but the exception is native modules which use [node-gyp](https://github.com/nodejs/node-gyp).
-Any native modules will still be fetched and built, by npm/yarn, for your host platform,
-so they will not work on the target platform.
-The workaround is to perform the npm_install inside a docker container so that it produces modules for the target platform.
-
-Follow https://github.com/bazelbuild/rules_nodejs/issues/506 for updates on support for node-gyp cross-compilation.
-
 ## Registering a custom toolchain
 
 To run a custom toolchain (i.e., to run a node binary not supported by the built-in toolchains), you'll need four things:
 
 1) A rule which can build or load a node binary from your repository
    (a checked-in binary or a build using a relevant [`rules_foreign_cc` build rule](https://bazelbuild.github.io/rules_foreign_cc/) will do nicely).
-2) A [`node_toolchain` rule](Core.html#node_toolchain) which depends on your binary defined in step 1 as its `target_tool`.
+2) A [`node_toolchain` rule](Core.html#node_toolchain) which depends on your binary defined in step 1 as its `node`.
 3) A [`toolchain` rule](https://bazel.build/reference/be/platform#toolchain) that depends on your `node_toolchain` rule defined in step 2 as its `toolchain`
    and on `@rules_nodejs//nodejs:toolchain_type` as its `toolchain_type`. Make sure to define appropriate platform restrictions as described in the
    documentation for the `toolchain` rule.
@@ -43,6 +21,6 @@
 
 Examples of steps 2-4 can be found in the [documentation for `node_toolchain`](Core.html#node_toolchain).
 
-If necessary, you can substitute building the node binary as part of the build with using a locally installed version by skipping step 1 and replacing step 2 with:
+If necessary, you can substitute building the node binary as part of the build with using a locally nstalled version by skipping step 1 and replacing step 2 with:
 
-2) A `node_toolchain` rule which has the path of the system binary as its `target_tool_path`
\ No newline at end of file
+2) A `node_toolchain` rule which has the path of the system binary as its `node_path`
diff --git a/e2e/nodejs_host/.bazelversion b/e2e/nodejs_host/.bazelversion
new file mode 100644
index 0000000..21c8c7b
--- /dev/null
+++ b/e2e/nodejs_host/.bazelversion
@@ -0,0 +1 @@
+7.1.1
diff --git a/e2e/nodejs_host/.nvmrc b/e2e/nodejs_host/.nvmrc
index 23d9c36..cb406c6 100644
--- a/e2e/nodejs_host/.nvmrc
+++ b/e2e/nodejs_host/.nvmrc
@@ -1 +1 @@
-16.13.2
+16.20.2
diff --git a/e2e/nodejs_host/MODULE.bazel b/e2e/nodejs_host/MODULE.bazel
index 5b0a986..b5d659c 100644
--- a/e2e/nodejs_host/MODULE.bazel
+++ b/e2e/nodejs_host/MODULE.bazel
@@ -21,19 +21,25 @@
 # https://github.com/bazelbuild/rules_nodejs/blob/5.8.0/nodejs/repositories.bzl#L11
 node.toolchain()
 node.toolchain(
-    name = "node16",
-    node_version = "16.5.0",
+    name = "node14",
+    node_version = "14.19.0",
 )
-
-# TODO: nvmrc test like WORKSPACE?
+node.toolchain(
+    name = "node16_nvmrc",
+    node_version_from_nvmrc = "//:.nvmrc",
+)
 
 # FIXME(6.0): a repo rule with name=foo should create a repo named @foo, not @foo_toolchains
 use_repo(
     node,
-    "node16_darwin_amd64",
-    "node16_linux_amd64",
-    "node16_toolchains",
-    "node16_windows_amd64",
+    "node16_nvmrc_darwin_amd64",
+    "node16_nvmrc_linux_amd64",
+    "node16_nvmrc_toolchains",
+    "node16_nvmrc_windows_amd64",
+    "node14_darwin_amd64",
+    "node14_linux_amd64",
+    "node14_toolchains",
+    "node14_windows_amd64",
     "nodejs_darwin_amd64",
     "nodejs_linux_amd64",
     "nodejs_windows_amd64",
diff --git a/e2e/nodejs_host/WORKSPACE b/e2e/nodejs_host/WORKSPACE
index 92f5c71..70df57f 100644
--- a/e2e/nodejs_host/WORKSPACE
+++ b/e2e/nodejs_host/WORKSPACE
@@ -16,9 +16,7 @@
     path = "../..",
 )
 
-load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains", "rules_nodejs_dependencies")
-
-rules_nodejs_dependencies()
+load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")
 
 # Create the default node toolchain
 nodejs_register_toolchains()
@@ -31,5 +29,5 @@
 
 nodejs_register_toolchains(
     name = "node16_nvmrc",
-    use_nvmrc = "//:.nvmrc",
+    node_version_from_nvmrc = "//:.nvmrc",
 )
diff --git a/e2e/smoke/.bazelversion b/e2e/smoke/.bazelversion
new file mode 100644
index 0000000..21c8c7b
--- /dev/null
+++ b/e2e/smoke/.bazelversion
@@ -0,0 +1 @@
+7.1.1
diff --git a/e2e/smoke/BUILD.bazel b/e2e/smoke/BUILD.bazel
index b2ab2ec..7754c89 100644
--- a/e2e/smoke/BUILD.bazel
+++ b/e2e/smoke/BUILD.bazel
@@ -209,15 +209,15 @@
 # Files used in test cases later that contain the correct nodejs version
 # that is imported into the workspace.
 write_file(
-    name = "write_node_version_15",
-    out = "expected_node_15",
-    content = ["v15.14.0"],
+    name = "write_node_version_16",
+    out = "expected_node_16",
+    content = ["v16.20.2"],
 )
 
 write_file(
-    name = "write_node_version_16",
-    out = "expected_node_16",
-    content = ["v16.5.0"],
+    name = "write_node_version_17",
+    out = "expected_node_17",
+    content = ["v17.9.1"],
 )
 
 # To see what nodejs version is used by default
@@ -239,26 +239,6 @@
 # Output contains the version number of node that is used.
 # This is used in tests later to verify the toolchain specified is resolved correctly
 my_nodejs(
-    name = "run_15",
-    out = "thing_toolchain_15",
-    entry_point = "version.js",
-    # using the select statement will download toolchains for all three platforms
-    # you can also just provide an individual toolchain if you don't want to download them all
-    toolchain = select({
-        "@bazel_tools//src/conditions:linux_x86_64": "@node15_linux_amd64//:node_toolchain",
-        "@bazel_tools//src/conditions:darwin": "@node15_darwin_amd64//:node_toolchain",
-        "@bazel_tools//src/conditions:windows": "@node15_windows_amd64//:node_toolchain",
-    }),
-)
-
-# Section of test the verify the toolchain work as expected matching node version used with expected
-diff_test(
-    name = "test_node_version_15",
-    file1 = "write_node_version_15",
-    file2 = "thing_toolchain_15",
-)
-
-my_nodejs(
     name = "run_16",
     out = "thing_toolchain_16",
     entry_point = "version.js",
@@ -271,12 +251,32 @@
     }),
 )
 
+# Section of test the verify the toolchain work as expected matching node version used with expected
 diff_test(
     name = "test_node_version_16",
     file1 = "write_node_version_16",
     file2 = "thing_toolchain_16",
 )
 
+my_nodejs(
+    name = "run_17",
+    out = "thing_toolchain_17",
+    entry_point = "version.js",
+    # using the select statement will download toolchains for all three platforms
+    # you can also just provide an individual toolchain if you don't want to download them all
+    toolchain = select({
+        "@bazel_tools//src/conditions:linux_x86_64": "@node17_linux_amd64//:node_toolchain",
+        "@bazel_tools//src/conditions:darwin": "@node17_darwin_amd64//:node_toolchain",
+        "@bazel_tools//src/conditions:windows": "@node17_windows_amd64//:node_toolchain",
+    }),
+)
+
+diff_test(
+    name = "test_node_version_17",
+    file1 = "write_node_version_17",
+    file2 = "thing_toolchain_17",
+)
+
 cc_binary(
     name = "using_headers_test",
     srcs = ["using_headers.cc"],
diff --git a/e2e/smoke/MODULE.bazel b/e2e/smoke/MODULE.bazel
index ce862b2..75a782f 100644
--- a/e2e/smoke/MODULE.bazel
+++ b/e2e/smoke/MODULE.bazel
@@ -7,9 +7,9 @@
 )
 
 bazel_dep(name = "rules_nodejs", version = "0.0.0", dev_dependency = True)
-bazel_dep(name = "bazel_skylib", version = "1.4.1", dev_dependency = True)
-bazel_dep(name = "aspect_bazel_lib", version = "1.30.2", dev_dependency = True)
-bazel_dep(name = "platforms", version = "0.0.5", dev_dependency = True)
+bazel_dep(name = "bazel_skylib", version = "1.5.0", dev_dependency = True)
+bazel_dep(name = "aspect_bazel_lib", version = "2.6.1", dev_dependency = True)
+bazel_dep(name = "platforms", version = "0.0.9", dev_dependency = True)
 
 local_path_override(
     module_name = "rules_nodejs",
@@ -21,22 +21,23 @@
 # Note, this gets the default version of Node.js from
 # https://github.com/bazelbuild/rules_nodejs/blob/5.8.0/nodejs/repositories.bzl#L11
 node.toolchain(
-    name = "node16",
-    node_version = "16.5.0",
+    name = "node17",
+    node_version = "17.9.1",
 )
 node.toolchain(
-    name = "node15",
-    node_version = "15.14.0",
+    name = "node16",
+    node_version = "16.20.2",
 )
 
 # FIXME(6.0): a repo rule with name=foo should create a repo named @foo, not @foo_toolchains
 use_repo(
     node,
-    "node15_darwin_amd64",
-    "node15_linux_amd64",
-    "node15_windows_amd64",
     "node16_darwin_amd64",
     "node16_linux_amd64",
     "node16_toolchains",
     "node16_windows_amd64",
+    "node17_darwin_amd64",
+    "node17_linux_amd64",
+    "node17_toolchains",
+    "node17_windows_amd64",
 )
diff --git a/e2e/smoke/WORKSPACE.bazel b/e2e/smoke/WORKSPACE.bazel
index a2cdfb1..8a99105 100644
--- a/e2e/smoke/WORKSPACE.bazel
+++ b/e2e/smoke/WORKSPACE.bazel
@@ -18,20 +18,18 @@
 
 aspect_bazel_lib_dependencies()
 
-load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains", "rules_nodejs_dependencies")
-
-rules_nodejs_dependencies()
+load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")
 
 # The order matters because Bazel will provide the first registered toolchain when a rule asks Bazel to select it
 # This applies to the resolved_toolchain
 nodejs_register_toolchains(
-    name = "node16",
-    node_version = "16.5.0",
+    name = "node17",
+    node_version = "17.9.1",
 )
 
 nodejs_register_toolchains(
-    name = "node15",
-    node_version = "15.14.0",
+    name = "node16",
+    node_version = "16.20.2",
 )
 
 http_archive(
diff --git a/e2e/smoke/defs.bzl b/e2e/smoke/defs.bzl
index c7b372b..7d9ad4a 100644
--- a/e2e/smoke/defs.bzl
+++ b/e2e/smoke/defs.bzl
@@ -6,8 +6,8 @@
     else:
         toolchain = ctx.toolchains["@rules_nodejs//nodejs:toolchain_type"].nodeinfo
     ctx.actions.run(
-        inputs = toolchain.tool_files + [ctx.file.entry_point],
-        executable = toolchain.target_tool_path,
+        inputs = [ctx.file.entry_point],
+        executable = toolchain.node,
         arguments = [ctx.file.entry_point.path, ctx.outputs.out.path],
         outputs = [ctx.outputs.out],
     )
diff --git a/nodejs/extensions.bzl b/nodejs/extensions.bzl
index 3d2fc8b..4c24004 100644
--- a/nodejs/extensions.bzl
+++ b/nodejs/extensions.bzl
@@ -14,7 +14,7 @@
                     # Prioritize the root-most registration of the default node toolchain version and
                     # ignore any further registrations (modules are processed breadth-first)
                     continue
-                if toolchain.node_version == registrations[toolchain.name]:
+                if toolchain.node_version == registrations[toolchain.name].node_version and toolchain.node_version_from_nvmrc == registrations[toolchain.name].node_version_from_nvmrc:
                     # No problem to register a matching toolchain twice
                     continue
                 fail("Multiple conflicting toolchains declared for name {} ({} and {})".format(
@@ -23,12 +23,16 @@
                     registrations[toolchain.name],
                 ))
             else:
-                registrations[toolchain.name] = toolchain.node_version
+                registrations[toolchain.name] = struct(
+                    node_version = toolchain.node_version,
+                    node_version_from_nvmrc = toolchain.node_version_from_nvmrc,
+                )
 
-    for name, node_version in registrations.items():
+    for k, v in registrations.items():
         nodejs_register_toolchains(
-            name = name,
-            node_version = node_version,
+            name = k,
+            node_version = v.node_version,
+            node_version_from_nvmrc = v.node_version_from_nvmrc,
             register = False,
         )
 
@@ -44,6 +48,13 @@
                 doc = "Version of the Node.js interpreter",
                 default = DEFAULT_NODE_VERSION,
             ),
+            "node_version_from_nvmrc": attr.label(
+                allow_single_file = True,
+                default = None,
+                doc = """the local path of the .nvmrc file containing the version of node
+
+                If set then also set node_version to the version found in the .nvmrc file.""",
+            ),
         }),
     },
 )
diff --git a/nodejs/repositories.bzl b/nodejs/repositories.bzl
index 17f4d98..16c83e4 100644
--- a/nodejs/repositories.bzl
+++ b/nodejs/repositories.bzl
@@ -77,8 +77,7 @@
 
 _ATTRS = {
     "node_download_auth": attr.string_dict(
-        default = {},
-        doc = """auth to use for all url requests
+        doc = """Auth to use for all url requests
 Example: {\"type\": \"basic\", \"login\": \"<UserName>\", \"password\": \"<Password>\" }
 """,
     ),
@@ -92,25 +91,23 @@
 """,
     ),
     "node_urls": attr.string_list(
-        default = [
-            "https://nodejs.org/dist/v{version}/{filename}",
-        ],
-        doc = """custom list of URLs to use to download NodeJS
+        doc = """Custom list of URLs to use to download NodeJS.
 
 Each entry is a template for downloading a node distribution.
 
 The `{version}` parameter is substituted with the `node_version` attribute,
 and `{filename}` with the matching entry from the `node_repositories` attribute.
+
+If not set then `https://nodejs.org/dist/v{version}/{filename}` is used
 """,
     ),
     "node_version": attr.string(
         default = DEFAULT_NODE_VERSION,
-        doc = "the specific version of NodeJS to install",
+        doc = "The specific version of NodeJS to install",
     ),
-    "use_nvmrc": attr.label(
+    "node_version_from_nvmrc": attr.label(
         allow_single_file = True,
-        default = None,
-        doc = """the local path of the .nvmrc file containing the version of node
+        doc = """The local path of the .nvmrc file containing the version of node
 
 If set then also set node_version to the version found in the .nvmrc file.""",
     ),
@@ -149,8 +146,8 @@
 
     node_version = repository_ctx.attr.node_version
 
-    if repository_ctx.attr.use_nvmrc:
-        node_version = str(repository_ctx.read(repository_ctx.attr.use_nvmrc)).strip()
+    if repository_ctx.attr.node_version_from_nvmrc:
+        node_version = str(repository_ctx.read(repository_ctx.attr.node_version_from_nvmrc)).strip()
 
     _verify_version_is_valid(node_version)
 
@@ -166,6 +163,8 @@
         return
 
     node_urls = repository_ctx.attr.node_urls
+    if not node_urls:
+        node_urls = ["https://nodejs.org/dist/v{version}/{filename}"]
 
     # Download node & npm
     version_host_os = "%s-%s" % (node_version, host_os)
@@ -355,7 +354,7 @@
 load("@rules_nodejs//nodejs:toolchain.bzl", "node_toolchain")
 node_toolchain(
     name = "node_toolchain",
-    target_tool = ":node_bin",
+    node = ":node_bin",
     npm = ":npm",
     npm_files = [":npm_files"],
     headers = ":headers",
@@ -430,7 +429,3 @@
         name = name + "_toolchains",
         user_node_repository_name = name,
     )
-
-def rules_nodejs_dependencies():
-    # This is a no-op, but we keep it around for backwards compatibility.
-    return True
diff --git a/nodejs/toolchain.bzl b/nodejs/toolchain.bzl
index 5655730..22fb874 100644
--- a/nodejs/toolchain.bzl
+++ b/nodejs/toolchain.bzl
@@ -18,14 +18,11 @@
 NodeInfo = provider(
     doc = "Information about how to invoke the node executable.",
     fields = {
-        "target_tool_path": "Path to the nodejs executable for this target's platform.",
-        "tool_files": """Files required in runfiles to make the nodejs executable available.
-
-May be empty if the target_tool_path points to a locally installed node binary.""",
-        "npm_path": "Path to the npm executable for this target's platform.",
-        "npm_files": """Files required in runfiles to make the npm executable available.
-
-May be empty if the npm_path points to a locally installed npm binary.""",
+        "node": "Node.js executable File",
+        "node_path": "Path to Node.js executable; if set then 'node' is ignored",
+        "npm": "Npm JavaScript entry point File",
+        "npm_path": "Path to npm JavaScript entry point",
+        "npm_files": """Additional files required to run npm""",
         "headers": """\
 (struct) Information about the header files, with fields:
   * providers_map: a dict of string to provider instances. The key should be
@@ -50,50 +47,30 @@
     },
 )
 
-# Avoid using non-normalized paths (workspace/../other_workspace/path)
-def _to_manifest_path(ctx, file):
-    if file.short_path.startswith("../"):
-        return "external/" + file.short_path[3:]
-    else:
-        return ctx.workspace_name + "/" + file.short_path
-
 def _node_toolchain_impl(ctx):
-    if ctx.attr.target_tool and ctx.attr.target_tool_path:
-        fail("Can only set one of target_tool or target_tool_path but both were set.")
-    if not ctx.attr.target_tool and not ctx.attr.target_tool_path:
-        fail("Must set one of target_tool or target_tool_path.")
+    if ctx.attr.node and ctx.attr.node_path:
+        fail("Can only set one of node or node_path but both were set.")
+    if not ctx.attr.node and not ctx.attr.node_path:
+        fail("Must set one of node or node_path.")
     if ctx.attr.npm and ctx.attr.npm_path:
         fail("Can only set one of npm or npm_path but both were set.")
 
-    tool_files = []
-    target_tool_path = ctx.attr.target_tool_path
-
-    if ctx.attr.target_tool:
-        tool_files = [ctx.file.target_tool]
-        target_tool_path = _to_manifest_path(ctx, ctx.file.target_tool)
-
-    npm_files = []
-    npm_path = ctx.attr.npm_path
-
-    if ctx.attr.npm:
-        npm_files = depset([ctx.file.npm] + ctx.files.npm_files).to_list()
-        npm_path = _to_manifest_path(ctx, ctx.file.npm)
-
     # Make the $(NODE_PATH) variable available in places like genrules.
     # See https://docs.bazel.build/versions/main/be/make-variables.html#custom_variables
     template_variables = platform_common.TemplateVariableInfo({
-        "NODE_PATH": target_tool_path,
-        "NPM_PATH": npm_path,
+        "NODE_PATH": ctx.file.node.path if ctx.attr.node else ctx.attr.node_path,
+        "NPM_PATH": ctx.file.npm.path if ctx.attr.npm else ctx.attr.npm_path,
     })
     default = DefaultInfo(
-        files = depset(tool_files),
-        runfiles = ctx.runfiles(files = tool_files),
+        files = depset([ctx.file.node]) if ctx.attr.node else depset(),
+        runfiles = ctx.runfiles(files = [ctx.file.node] if ctx.attr.node else []),
     )
     nodeinfo = NodeInfo(
-        target_tool_path = target_tool_path,
-        tool_files = tool_files,
-        npm_path = npm_path,
-        npm_files = npm_files,
+        node = ctx.file.node,
+        node_path = ctx.attr.node_path,
+        npm = ctx.file.npm,
+        npm_path = ctx.attr.npm_path,
+        npm_files = depset([ctx.file.npm] + ctx.files.npm_files) if ctx.attr.npm else depset(),
         headers = struct(
             providers_map = {
                 "CcInfo": ctx.attr.headers[CcInfo],
@@ -118,30 +95,27 @@
 node_toolchain = rule(
     implementation = _node_toolchain_impl,
     attrs = {
-        "target_tool": attr.label(
-            doc = "A hermetically downloaded nodejs executable target for this target's platform.",
-            mandatory = False,
+        "node": attr.label(
+            doc = "Node.js executable",
+            executable = True,
+            cfg = "exec",
             allow_single_file = True,
         ),
-        "target_tool_path": attr.string(
-            doc = "Path to an existing nodejs executable for this target's platform.",
-            mandatory = False,
+        "node_path": attr.string(
+            doc = "Path to Node.js executable file",
         ),
         "npm": attr.label(
-            doc = "A hermetically downloaded npm executable target for this target's platform.",
-            mandatory = False,
+            doc = "Npm JavaScript entry point",
             allow_single_file = True,
         ),
         "npm_path": attr.string(
-            doc = "Path to an existing npm executable for this target's platform.",
-            mandatory = False,
+            doc = "Path to npm JavaScript entry point",
         ),
         "npm_files": attr.label_list(
-            doc = "Files required in runfiles to run npm.",
-            mandatory = False,
+            doc = "Additional files required to run npm",
         ),
         "headers": attr.label(
-            doc = "A cc_library that contains the Node/v8 header files for this target platform.",
+            doc = "cc_library that contains the Node/v8 header files",
         ),
     },
     doc = """Defines a node toolchain for a platform.
@@ -156,7 +130,7 @@
 
 node_toolchain(
     name = "node_toolchain",
-    target_tool = "//some/path/bin/node",
+    node = "//some/path/bin/node",
 )
 ```
 
diff --git a/repositories.bzl b/repositories.bzl
index 08f4865..61917ea 100644
--- a/repositories.bzl
+++ b/repositories.bzl
@@ -19,7 +19,6 @@
 
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
-load("//nodejs:repositories.bzl", "rules_nodejs_dependencies")
 
 def rules_nodejs_dev_dependencies():
     """
@@ -29,8 +28,6 @@
     shorter.
     """
 
-    rules_nodejs_dependencies()
-
     maybe(
         http_archive,
         name = "bazel_skylib",