Move dependencies to package.bzl

Simplifies user install instructions and puts us in control of versions of transitive deps

Signed-off-by: Alex Eagle <alexeagle@google.com>
Closes #256
PiperOrigin-RevId: 208665583
diff --git a/README.md b/README.md
index ab6437d..23a25b9 100644
--- a/README.md
+++ b/README.md
@@ -35,71 +35,36 @@
 containing:
 
 ```python
-# TypeScript rules depend on running Node.js.
-http_archive(
-    name = "build_bazel_rules_nodejs",
-    urls = ["https://github.com/bazelbuild/rules_nodejs/archive/0.11.3.zip"],
-    strip_prefix = "rules_nodejs-0.11.3",
-    sha256 = "e8842fa5f5e38f2c826167ff94323d4b5aabd13217cee867d971d6f860cfd730"
-)
-
-# build_bazel_rules_nodejs depends on skylib
-http_archive(
-    name = "bazel_skylib",
-    urls = ["https://github.com/bazelbuild/bazel-skylib/archive/0.3.1.zip"],
-    strip_prefix = "bazel-skylib-0.3.1",
-    sha256 = "95518adafc9a2b656667bbf517a952e54ce7f350779d0dd95133db4eb5c27fb1",
-)
-
-# ts_web_test depends on the web testing rules to provision browsers.
-http_archive(
-    name = "io_bazel_rules_webtesting",
-    urls = ["https://github.com/bazelbuild/rules_webtesting/archive/0.2.1.zip"],
-    strip_prefix = "rules_webtesting-0.2.1",
-    sha256 = "7d490aadff9b5262e5251fa69427ab2ffd1548422467cb9f9e1d110e2c36f0fa",
-)
-
-# ts_devserver depends on the Go rules.
-# See https://github.com/bazelbuild/rules_go#setup for the latest version.
-http_archive(
-    name = "io_bazel_rules_go",
-    urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.13.0/rules_go-0.13.0.tar.gz"],
-    sha256 = "ba79c532ac400cefd1859cbc8a9829346aa69e3b99482cd5a54432092cbc3933",
-)
-
-# go_repository is defined in bazel_gazelle
-http_archive(
-    name = "bazel_gazelle",
-    urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/0.13.0/bazel-gazelle-0.13.0.tar.gz"],
-    sha256 = "bc653d3e058964a5a26dcad02b6c72d7d63e6bb88d94704990b908a1445b8758",
-)
-
 # Include @bazel/typescript in package.json#devDependencies
 local_repository(
     name = "build_bazel_rules_typescript",
     path = "node_modules/@bazel/typescript",
 )
 
-load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
+# Fetch our Bazel dependencies that aren't distributed on npm
+load("@build_bazel_rules_typescript//:package.bzl", "rules_typescript_dependencies")
+rules_typescript_dependencies()
+
+# Setup TypeScript toolchain
+load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
+ts_setup_workspace()
 
 # Point to the package.json file so Bazel can run the package manager for you.
+load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
 node_repositories(package_json = ["//:package.json"])
 
+# Setup Go toolchain
 load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
-
 go_rules_dependencies()
 go_register_toolchains()
 
+# Setup web testing, choose browsers we can test on
 load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
 
 web_test_repositories()
 browser_repositories(
     chromium = True,
 )
-
-load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
-
-ts_setup_workspace()
 ```
 
 We recommend using the Yarn package manager, because it has a built-in command
diff --git a/WORKSPACE b/WORKSPACE
index 0bc4275..72df6fd 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -13,21 +13,15 @@
 # limitations under the License.
 
 workspace(name = "build_bazel_rules_typescript")
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
-http_archive(
-    name = "build_bazel_rules_nodejs",
-    urls = ["https://github.com/bazelbuild/rules_nodejs/archive/0.11.3.zip"],
-    strip_prefix = "rules_nodejs-0.11.3",
-    sha256 = "e8842fa5f5e38f2c826167ff94323d4b5aabd13217cee867d971d6f860cfd730"
+load(
+    "@build_bazel_rules_typescript//:package.bzl",
+    "rules_typescript_dependencies",
+    "rules_typescript_dev_dependencies",
 )
 
-http_archive(
-    name = "bazel_skylib",
-    urls = ["https://github.com/bazelbuild/bazel-skylib/archive/0.3.1.zip"],
-    strip_prefix = "bazel-skylib-0.3.1",
-    sha256 = "95518adafc9a2b656667bbf517a952e54ce7f350779d0dd95133db4eb5c27fb1",
-)
+rules_typescript_dependencies()
+rules_typescript_dev_dependencies()
 
 load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories", "yarn_install")
 
@@ -50,32 +44,6 @@
   package_json = ["//:package.json"],
   preserve_symlinks = True)
 
-http_archive(
-    name = "io_bazel_rules_go",
-    urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.13.0/rules_go-0.13.0.tar.gz"],
-    sha256 = "ba79c532ac400cefd1859cbc8a9829346aa69e3b99482cd5a54432092cbc3933",
-)
-
-http_archive(
-    name = "io_bazel",
-    urls = ["https://github.com/bazelbuild/bazel/releases/download/0.9.0/bazel-0.9.0-dist.zip"],
-    sha256 = "efb28fed4ffcfaee653e0657f6500fc4cbac61e32104f4208da385676e76312a",
-)
-
-http_archive(
-    name = "bazel_gazelle",
-    urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/0.13.0/bazel-gazelle-0.13.0.tar.gz"],
-    sha256 = "bc653d3e058964a5a26dcad02b6c72d7d63e6bb88d94704990b908a1445b8758",
-)
-
-BAZEL_BUILDTOOLS_VERSION = "0.12.0"
-
-http_archive(
-    name = "com_github_bazelbuild_buildtools",
-    url = "https://github.com/bazelbuild/buildtools/archive/%s.zip" % BAZEL_BUILDTOOLS_VERSION,
-    strip_prefix = "buildtools-%s" % BAZEL_BUILDTOOLS_VERSION,
-    sha256 = "ec495cbd19238c9dc488fd65ca1fee56dcb1a8d6d56ee69a49f2ebe69826c261",
-)
 
 load("@io_bazel_rules_go//go:def.bzl", "go_rules_dependencies", "go_register_toolchains")
 
@@ -87,13 +55,6 @@
 
 gazelle_dependencies()
 
-http_archive(
-    name = "io_bazel_rules_webtesting",
-    urls = ["https://github.com/bazelbuild/rules_webtesting/archive/0.2.1.zip"],
-    strip_prefix = "rules_webtesting-0.2.1",
-    sha256 = "7d490aadff9b5262e5251fa69427ab2ffd1548422467cb9f9e1d110e2c36f0fa",
-)
-
 load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
 
 web_test_repositories()
@@ -103,31 +64,19 @@
     firefox = True,
 )
 
-load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace", "check_rules_typescript_version")
+load(
+    "@build_bazel_rules_typescript//:defs.bzl",
+    "ts_setup_workspace",
+    "check_rules_typescript_version",
+)
 
 ts_setup_workspace()
 
 # Test that check_rules_typescript_version works as expected
 check_rules_typescript_version("0.15.3")
 
-#############################################
-# Dependencies for generating documentation #
-#############################################
-
-http_archive(
-    name = "io_bazel_rules_sass",
-    urls = ["https://github.com/bazelbuild/rules_sass/archive/0.0.3.zip"],
-    strip_prefix = "rules_sass-0.0.3",
-    sha256 = "8fa98e7b48a5837c286a1ea254b5a5c592fced819ee9fe4fdd759768d97be868",
-)
+# Dependencies for generating documentation
 load("@io_bazel_rules_sass//sass:sass.bzl", "sass_repositories")
 sass_repositories()
-
-http_archive(
-    name = "io_bazel_skydoc",
-    urls = ["https://github.com/bazelbuild/skydoc/archive/0ef7695c9d70084946a3e99b89ad5a99ede79580.zip"],
-    strip_prefix = "skydoc-0ef7695c9d70084946a3e99b89ad5a99ede79580",
-    sha256 = "491f9e142b870b18a0ec8eb3d66636eeceabe5f0c73025706c86f91a1a2acb4d",
-)
 load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
 skydoc_repositories()
diff --git a/defs.bzl b/defs.bzl
index 1981392..0a1fc15 100644
--- a/defs.bzl
+++ b/defs.bzl
@@ -24,7 +24,8 @@
      _ts_web_test = "ts_web_test_macro",
      _ts_web_test_suite = "ts_web_test_suite")
 load("//internal/protobufjs:ts_proto_library.bzl", _ts_proto_library = "ts_proto_library")
-load("//:package.bzl", _check_rules_typescript_version = "check_rules_typescript_version")
+load("//:package.bzl", "VERSION")
+load("@build_bazel_rules_nodejs//internal/common:check_version.bzl", "check_version")
 
 ts_setup_workspace = _ts_setup_workspace
 ts_library = _ts_library
@@ -37,4 +38,24 @@
 # DO NOT ADD MORE rules here unless they appear in the generated docsite.
 # Run yarn skydoc to re-generate the docsite.
 
-check_rules_typescript_version = _check_rules_typescript_version
+def check_rules_typescript_version(minimum_version_string):
+    """
+    Verify that a minimum build_bazel_rules_typescript is loaded a WORKSPACE.
+
+    This should be called from the `WORKSPACE` file so that the build fails as
+    early as possible. For example:
+
+    ```
+    # in WORKSPACE:
+    load("@build_bazel_rules_typescript//:defs.bzl", "check_rules_typescript_version")
+    check_rules_typescript_version("0.15.3")
+    ```
+
+    Args:
+      minimum_version_string: a string indicating the minimum version
+    """
+    if not check_version(VERSION, minimum_version_string):
+        fail("\nCurrent build_bazel_rules_typescript version is {}, expected at least {}\n".format(
+            VERSION,
+            minimum_version_string,
+        ))
diff --git a/package.bzl b/package.bzl
index f2a9032..27095a0 100644
--- a/package.bzl
+++ b/package.bzl
@@ -18,7 +18,7 @@
 against a minimum dependent build_bazel_rules_typescript version.
 """
 
-load("@build_bazel_rules_nodejs//internal/common:check_version.bzl", "check_version")
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 # This version is synced with the version in package.json.
 # It will be automatically synced via the npm "version" script
@@ -26,24 +26,100 @@
 # process. See `Releasing` section in README.md.
 VERSION = "0.15.3"
 
-def check_rules_typescript_version(minimum_version_string):
+def rules_typescript_dependencies():
     """
-    Verify that a minimum build_bazel_rules_typescript is loaded a WORKSPACE.
+    Fetch our transitive dependencies.
 
-    This should be called from the `WORKSPACE` file so that the build fails as
-    early as possible. For example:
-
-    ```
-    # in WORKSPACE:
-    load("@build_bazel_rules_typescript//:defs.bzl", "check_rules_typescript_version")
-    check_rules_typescript_version("0.15.3")
-    ```
-
-    Args:
-      minimum_version_string: a string indicating the minimum version
+    If the user wants to get a different version of these, they can just fetch it
+    from their WORKSPACE before calling this function, or not call this function at all.
     """
-    if not check_version(VERSION, minimum_version_string):
-        fail("\nCurrent build_bazel_rules_typescript version is {}, expected at least {}\n".format(
-            VERSION,
-            minimum_version_string,
-        ))
+
+    # TypeScript compiler runs on node.js runtime
+    _maybe(
+        http_archive,
+        name = "build_bazel_rules_nodejs",
+        urls = ["https://github.com/bazelbuild/rules_nodejs/archive/0.11.5.zip"],
+        strip_prefix = "rules_nodejs-0.11.5",
+        sha256 = "985bf908faa72cc4638c356a99d19ccac223e5dcd8dae695e3157e5c00f53489",
+    )
+
+    # ts_web_test depends on the web testing rules to provision browsers.
+    _maybe(
+        http_archive,
+        name = "io_bazel_rules_webtesting",
+        urls = ["https://github.com/bazelbuild/rules_webtesting/archive/0.2.1.zip"],
+        strip_prefix = "rules_webtesting-0.2.1",
+        sha256 = "7d490aadff9b5262e5251fa69427ab2ffd1548422467cb9f9e1d110e2c36f0fa",
+    )
+
+    # ts_devserver depends on the Go rules.
+    # See https://github.com/bazelbuild/rules_go#setup for the latest version.
+    _maybe(
+        http_archive,
+        name = "io_bazel_rules_go",
+        urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.13.0/rules_go-0.13.0.tar.gz"],
+        sha256 = "ba79c532ac400cefd1859cbc8a9829346aa69e3b99482cd5a54432092cbc3933",
+    )
+
+    # go_repository is defined in bazel_gazelle
+    _maybe(
+        http_archive,
+        name = "bazel_gazelle",
+        urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/0.13.0/bazel-gazelle-0.13.0.tar.gz"],
+        sha256 = "bc653d3e058964a5a26dcad02b6c72d7d63e6bb88d94704990b908a1445b8758",
+    )
+
+    ###############################################
+    # Repeat the dependencies of rules_nodejs here!
+    # We can't load() from rules_nodejs yet, because we've only just fetched it.
+    # But we also don't want to make users load and call the rules_nodejs_dependencies
+    # function because we can do that for them, mostly hiding the transitive dependency.
+    _maybe(
+        http_archive,
+        name = "bazel_skylib",
+        url = "https://github.com/bazelbuild/bazel-skylib/archive/0.3.1.zip",
+        strip_prefix = "bazel-skylib-0.3.1",
+        sha256 = "95518adafc9a2b656667bbf517a952e54ce7f350779d0dd95133db4eb5c27fb1",
+    )
+
+def rules_typescript_dev_dependencies():
+    """
+    Fetch dependencies needed for local development, but not needed by users.
+
+    These are in this file to keep version information in one place, and make the WORKSPACE
+    shorter.
+    """
+    http_archive(
+        name = "io_bazel",
+        urls = ["https://github.com/bazelbuild/bazel/releases/download/0.9.0/bazel-0.9.0-dist.zip"],
+        sha256 = "efb28fed4ffcfaee653e0657f6500fc4cbac61e32104f4208da385676e76312a",
+    )
+
+    http_archive(
+        name = "com_github_bazelbuild_buildtools",
+        url = "https://github.com/bazelbuild/buildtools/archive/0.12.0.zip",
+        strip_prefix = "buildtools-0.12.0",
+        sha256 = "ec495cbd19238c9dc488fd65ca1fee56dcb1a8d6d56ee69a49f2ebe69826c261",
+    )
+
+    #############################################
+    # Dependencies for generating documentation #
+    #############################################
+
+    http_archive(
+        name = "io_bazel_rules_sass",
+        urls = ["https://github.com/bazelbuild/rules_sass/archive/0.0.3.zip"],
+        strip_prefix = "rules_sass-0.0.3",
+        sha256 = "8fa98e7b48a5837c286a1ea254b5a5c592fced819ee9fe4fdd759768d97be868",
+    )
+
+    http_archive(
+        name = "io_bazel_skydoc",
+        urls = ["https://github.com/bazelbuild/skydoc/archive/0ef7695c9d70084946a3e99b89ad5a99ede79580.zip"],
+        strip_prefix = "skydoc-0ef7695c9d70084946a3e99b89ad5a99ede79580",
+        sha256 = "491f9e142b870b18a0ec8eb3d66636eeceabe5f0c73025706c86f91a1a2acb4d",
+    )
+
+def _maybe(repo_rule, name, **kwargs):
+    if name not in native.existing_rules():
+        repo_rule(name = name, **kwargs)