-
Notifications
You must be signed in to change notification settings - Fork 351
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Publish/import proto dependencies as npm packages #58
Comments
Yeah, I've generally felt the same way, i.e. it doesn't seem great for every artifact to re-output codegen for every referenced proto. However, I'm not really sure what the alternative is though, b/c there is a real lack of standardized / recommended mapping between how a I.e. if my import { Timestamp } from "./google/protobuf/timestamp"; If the import was from an npm package, which I think is what you're suggesting, what should that import be? Maybe this could only be done by config, i.e. telling ts-proto via a command line arg/something that "for our company, we've published I dunno. Really open to ideas here. Basically how to map a proto import to, as you said, "the project that defines it" (and also its npm package). |
We've sort of dealt with this problem for our own protobuf plugin for Kotlin. Our generator actually publishes the well-known types itself. Downstream projects pull in the generated source along with the proto files needed for further local codegen (using the protobuf-gradle-plugin). Both are packaged into the JAR file. We include this dependency automatically when you use the code generator. What that could look like here is a separate package on npm (" You're right that there's no great convention for where these things go. Kotlin/Java have packages, but JS doesn't quite have that. I suppose ts-proto could map files into directories by protobuf package since JS doesn't care about relative file location so long as imports are pointing to the right places? Right now I'm using Gradle to run ts-proto, like this: plugins {
java // needed for protobuf plugin
id("com.google.protobuf") version "0.8.11"
}
protobuf {
plugins {
id("ts") {
path = "node_modules/.bin/protoc-gen-ts_proto"
}
}
generateProtoTasks {
all().forEach { task ->
task.plugins {
id("ts")
}
}
}
}
dependencies {
protobuf("jar-that-cotains-our-proto-files")
} which throws generated code into e.g. We do get these nice imports in generated files: import { Timestamp } from '../../../../../../google/protobuf/timestamp'; and I'm not sure how that would mess with things. Presumably if we changed our output directory to match whatever the canonical package declared, these would resolve correctly? |
Yeah, looks like Google's JS generator also simply generates everything, so I'm not sure this is really addressable. Thanks! |
Yeah, I think this is a good idea. Maybe something like And maybe anything that wasn't well-known, the package name was something like I think that would work okay.
I think this would end up being:
Which would work without any wrinkles around relative/etc. paths. Granted, if ts-proto users opt'd into this "use packages mode", they'd have to make sure any proto file they referenced also had an entry in their package.json file. I'm not going to work on this right now, but I think this is a good idea and something we could have eventually, so I'm going to go ahead and re-open it. |
Fair enough. We chose to call that module "core" because the protobuf JAR that we used to generate it contains the definitions for the well-known types in Looks like the "@" prefix has traction on NPM, so |
Right, that is a big wrinkle, i.e. how would ts-proto "know" (for either the well-known types or internal company types) "which types from separate files are generated 'together' and which are not". I.e. one tempting rule-of-thumb would be that, since all of the well-known types have the same proto package, But I'm not sure how that translates over to internal types, like if you have a proto package like I.e. for internal types, each separate project/repository would have to use it's own proto package, i.e. But maybe that'd be fine? Maybe that's what most protobuf users are already doing? I don't have a ton/really any data points about "proto package <--> project / repository proto file" naming conventions. That said, the "proto package --> npm module" convention is so tempting, maybe that is what ts-proto should just go ahead and implement, and assume that users like yourself that want to use this feature would setup their proto package naming convention appropriately. |
Well, they almost have the same proto package. Other files included in that collection include the plugin definitions in We do make that assumption about the We do have split packages where we define protos in different projects in the same protobuf package. We could, however, define them in different protobuf packages and use the package override I mentioned above to put them in the right Kotlin package, allowing them to use both of these features at once - live in the same Kotlin package, and be reference-able from multiple NPM packages. The tough part remains projects that use more than one protobuf package and how to resolve the imports in downstream projects. |
@stephenh I'm running into this still - it tries to import from I was thinking it might make sense to instead remap that import to |
@stephenh This is what I'm using in the meantime: https://github.com/aperturerobotics/ts-proto-common-types
|
@paralin cool, that makes sense... in theory @pcj 's #597 would allow setting up
If by Like would the npm-published ts-proto is, for better or worse, such a swiss army knife of options, that I'm just assuming each user/company would have to setup their own repo of |
@stephenh That works, but I would expect the "built-in" types to "just work" without a special remap. For example in protobuf-go it automatically references the Go package implementing those types. They have a assertion which ensures that the Go package imported matches the same major version of the generated code. |
@paralin sure, I understand the desire, but link me to the options that protobuf-go supports? Just scanning their docs, I see maybe three or four ( Afaict none seem to affect protobuf-go's output as materially as "this (And even if we decided to ship the superset of "include all the methods", and rely on tree shaking to drop unused ones, there are still options like oneof, exact types, use optional, etc., that very materially affect the output in breaking changes ways.) Granted, this is my fault for starting ts-proto down the "swiss army knife of options" approach, but it is what it is (albeit in response to users specifically asking/providing PRs for various styles). So I get how/why protobuf-go can do this, but still assert its not realistic for ts-proto, short of only working with a very specific / blessed configuration of options that users are restricted from changing. |
@stephenh The main requirement is when importing the Timestamp type from somewhere to another ts-proto message. If the TImestamp type itself is generated with a "blessed set of default options" that should be fine. Because the types that import the Timestamp don't really care about anything other than:
.. everything else doesn't matter. If there were a common package which implemented these 3 functions in one hand-written file and the Timestamp class with the "blessed defaults", and a "index.ts" exporting all of it, it would no longer be necessary to include these things in the generate code (just import them instead). |
I'm experimenting with ts-proto and it looks really good! I had a question about the generated files. It looks like ts-proto generates all files supplied by the CodeGeneratorRequest's assembled list of topologically sorted dependencies (
proto_file
).This works great for standalone projects, but if I want to generate and publish artifacts, ideally they don't include all dependencies. That way I can publish two artifacts but only have one copy of generated dependencies from one used in the other. For example StringValue is generated everywhere, but it should only be generated once - in the project that defines it.
Would it make sense to include an option that generates files only from
files_to_generate
? Ideally I think this would be the default behavior, but it would break backwards compatibility.The text was updated successfully, but these errors were encountered: