ts_devserver support for injecting script tags

Closes #332

PiperOrigin-RevId: 225922286
diff --git a/internal/devserver/ts_devserver.bzl b/internal/devserver/ts_devserver.bzl
index 1cafabf..fe4d254 100644
--- a/internal/devserver/ts_devserver.bzl
+++ b/internal/devserver/ts_devserver.bzl
@@ -22,6 +22,10 @@
     "@build_bazel_rules_nodejs//internal/js_library:js_library.bzl",
     "write_amd_names_shim",
 )
+load(
+    "@build_bazel_rules_nodejs//internal/web_package:web_package.bzl",
+    "html_asset_inject",
+)
 
 def _ts_devserver(ctx):
     files = depset()
@@ -76,6 +80,17 @@
     devserver_runfiles += ctx.files.static_files
     devserver_runfiles += script_files
 
+    if ctx.file.index_html:
+        injected_index = ctx.actions.declare_file("index.html")
+        html_asset_inject(
+            ctx.file.index_html,
+            ctx.actions,
+            ctx.executable._injector,
+            [f.path for f in ctx.files.static_files] + [ctx.attr.serving_path],
+            injected_index,
+        )
+        devserver_runfiles += [injected_index]
+
     serving_arg = ""
     if ctx.attr.serving_path:
         serving_arg = "-serving_path=%s" % ctx.attr.serving_path
@@ -127,13 +142,20 @@
             aspects = [sources_aspect],
         ),
         "serving_path": attr.string(
+            default = "/_ts_scripts.js",
             doc = """The path you can request from the client HTML which serves the JavaScript bundle.
-            If you don't specify one, the JavaScript can be loaded at /_/ts_scripts.js""",
+            If you don't specify one, the JavaScript can be loaded at /_ts_scripts.js""",
         ),
         "data": attr.label_list(
             doc = "Dependencies that can be require'd while the server is running",
             allow_files = True,
         ),
+        "index_html": attr.label(
+            allow_single_file = True,
+            doc = """An index.html file, we'll inject the script tag for the bundle,
+            as well as script tags for .js static_files and link tags for .css
+            static_files""",
+        ),
         "static_files": attr.label_list(
             doc = """Arbitrary files which to be served, such as index.html.
             They are served relative to the package where this rule is declared.""",
@@ -173,6 +195,11 @@
             executable = True,
             cfg = "host",
         ),
+        "_injector": attr.label(
+            default = "@build_bazel_rules_nodejs//internal/web_package:injector",
+            executable = True,
+            cfg = "host",
+        ),
     },
     outputs = {
         "manifest": "%{name}.MF",
diff --git a/package.bzl b/package.bzl
index 544e5a8..dcc75a3 100644
--- a/package.bzl
+++ b/package.bzl
@@ -38,9 +38,9 @@
     _maybe(
         http_archive,
         name = "build_bazel_rules_nodejs",
-        urls = ["https://github.com/bazelbuild/rules_nodejs/archive/0.16.2.zip"],
-        strip_prefix = "rules_nodejs-0.16.2",
-        sha256 = "9b72bb0aea72d7cbcfc82a01b1e25bf3d85f791e790ddec16c65e2d906382ee0",
+        # TODO(alexeagle): update after next release
+        urls = ["https://github.com/bazelbuild/rules_nodejs/archive/5efe8067c83ce81273dbd1f69303ad8cee88e5de.zip"],
+        strip_prefix = "rules_nodejs-5efe8067c83ce81273dbd1f69303ad8cee88e5de",
     )
 
     # ts_web_test depends on the web testing rules to provision browsers.