Skip to content
This repository has been archived by the owner on Sep 16, 2021. It is now read-only.

Using a genrule as dep of ts_library #201

Closed
prestonvanloon opened this issue May 11, 2018 · 8 comments
Closed

Using a genrule as dep of ts_library #201

prestonvanloon opened this issue May 11, 2018 · 8 comments

Comments

@prestonvanloon
Copy link

Why is it enforced that JS files generated by genrule cannot be used as a dep in ts_library?

("%s is neither a TypeScript nor a JS producing rule." % dep.label) +

I'm specifically trying to build a workaround for bazel-contrib/rules_nodejs#201

BUILD.bazel

proto_library(
  name = "proto",
  srcs = [
    "message.proto",
  ],
  visibility = ["//visibility:public"],
)

# Can't use the proto_library above...
# This requires grpc_tools_node_protoc to be in PATH
genrule(
  name = "js_proto",
  srcs = [
    "message.proto",
  ],
  cmd = "grpc_tools_node_protoc --js_out=import_style=commonjs,binary:$(@D)/.. --grpc_out=$(@D)/.. " +
        "--plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` $(location message.proto)",
  outs = [
    "message_pb.js",
    "message_grpc_pb.js",
  ],
  visibility = ["//visibility:public"],
)

ts_library(
  srcs = [ 
    "main.ts",
  ],
  deps = [
     ":js_proto", # fail!
  ],
)
@alexeagle
Copy link
Contributor

it's because ts_library assumes it can get either devmode JS or prodmode JS from the transitive closure of the deps. The former uses named UMD modules for faster concatenation in the devserver, and is down-leveled for browsers. The latter is intended for bundling optimizers and uses ES modules and ESnext syntax.

There ought to be some way to make a TS -> JS dependency edge, but we need to think about that some more.

For this particular use case, maybe what you want is a dependency on a ts_proto_library? http://tsetse.info/api/protobufjs/ts_proto_library.html#ts_proto_library

OR, the grpc codegen could generate TypeScript instead. @mrmeku is working on a grpc layer for TS, maybe he can give some guidance.

@prestonvanloon
Copy link
Author

Yes, ts_proto_library would solve my problem! Trying it out now. Does it output grpc layer too?

@alexeagle
Copy link
Contributor

No, ts_proto_library doesn't do anything with grpc yet. I'm not sure who would create the .d.ts for proto services, it seems like grpc doesn't want to: grpc/grpc#6630 (comment)

@kalbasit
Copy link
Contributor

@prestonvanloon have you figured out a way to do this?

@prestonvanloon
Copy link
Author

@kalbasit I was able to use ts_proto_library to achieve what I wanted. It doesn't include gRPC, but I used the npm module grpc.

So I wasn't able to use the genrule, but I did find another way to achieve what I wanted to do: A typescript gRPC node.js server.

@alexeagle
Copy link
Contributor

Thanks @prestonvanloon

@stefanobaghino-da
Copy link

I can't use ts_proto_library: we are using a different plugin to generate TypeScript typings and protobuf.ts is not a viable option (due to protobufjs/protobuf.js#1113). Is there a way to bundle arbitrary JavaScript source files and TypeScript typings so that they are accepted by ts_library? I tried using both npm_package and js_library but neither worked, both yielding the same error:

//workspace/path/to:some-target is neither a TypeScript nor a JS producing rule.
Dependencies must be ts_library

@stefanobaghino-da
Copy link

stefanobaghino-da commented Feb 28, 2019

As a follow-up attempt, I tried to "trick" ts_library into thinking the output was indeed coming from a rule that has a js attribute. I'm fairly sure it's a safe assumption in my case, as I just want to use the rule to compile TypeScript and I'm not interested into serving this directly (it's a very simple library that targets Node.js that I want to compile and package).

I wrote my own rule (which I assume would not work at runtime, but it looks like it's failing during the analysis phase):

JsInfo=provider(fields=["js"])

def _js_library(ctx):
    ctx.action(
        command = "true",
        inputs = ctx.files.srcs,
        outputs = [ctx.outputs.js]
    )
    return [JsInfo(
        js=True
    )]

js_library = rule(
    implementation = _js_library,
    attrs = {
        "srcs": attr.label_list(allow_files = True),
        "js": attr.bool(default=True),
    },
    outputs = {
        "js": "%{name}",
    }
)

I tried (in succession) to add a js attribute to the rule, the js field to the implementation provider and as a rule output. None of the approaches worked and the ts_library reported again that the dependency was neither a TypeScript nor a JS producing rule.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants