JavaScript/TypeScript
Breaking changes
Remote code generation for JavaScript and TypeScript is currently in alpha. Although you're free to experiment with it, be aware that Buf may introduce breaking changes that could impact your workflows.
The Buf Schema Registry (BSR) supports remote code generation for JavaScript and TypeScript. With this feature, you can push Buf modules to the BSR and install code stubs generated from those modules using dependency management tools like npm and Yarn. JavaScript and TypeScript source code generated by the BSR is hosted on the BSR's npm registry at npm.buf.build
.
With this feature, you no longer need to maintain Protobuf files or runtime dependencies like protoc plugins—in fact, JavaScript and TypeScript developers can avoid local code generation altogether for any Buf modules that have been pushed to the BSR.
#
Setupnpm is configured to use the public npm registry at registry.npmjs.org by default. To configure npm to use Buf's npm registry at npm.buf.build in addition to the default registry, use this command to set your npm config:
$ npm config set @buf:registry https://npm.buf.build
This binds the @buf
package scope to the BSR and updates your global .npmrc
accordingly.
You can configure Yarn in an analogous way:
$ yarn config set @buf:registry https://npm.buf.build
#
Available templatesThe table below lists the generation templates that are officially supported by the BSR:
Template | What it generates |
---|---|
protocolbuffers/js | JavaScript code stubs (.js ) |
grpc/web | JavaScript code stubs (.js ), TypeScript type definitions (.d.ts ) |
In addition to these official templates, you can use any templates you like with npm—including templates that you upload yourself—provided that those templates generate valid JavaScript and/or TypeScript declaration files. Templates that generate invalid code aren't supported. This operation, for example, would fail because the template, protocolbuffers/go
, isn't supported:
$ npm install @buf/protocol_buffers_go_acme_paymentapis
Outputnpm ERR! code E400npm ERR! 400 Bad Request - GET https://npm.buf.build/@buf%2fprotocol_buffers_go_acme_paymentapis
#
Installing packagesWith your npm config set, you can install @buf/*
packages in any standard npm project. Here's an example installation command:
$ npm install @buf/protocolbuffers_js_acme_paymentapis
Slow installation?
You may notice that installing packages from the BSR npm registry using npm install
can take longer than installing from the standard npm registry. This happens because packages are generated "on the fly"—that is, they're built upon request and then cached. The first npm install
typically takes longer than subsequent requests.
#
Package namesThe BSR npm registry has a special syntax for package names:
In the first example, @buf/protocolbuffers_js_acme_petapis
, the BSR applies the protocolbuffers/js
template to the acme/petapis
module and thus generates JavaScript code stubs for the Protobuf definitions in that module.
This table shows some example template/module name combinations and the resulting package name:
Template | Buf module | Package name |
---|---|---|
grpc/web | acme/petapis | @buf/grpc_web_acme_petapis |
protocolbuffers/js | bufbuild/buf | @buf/protocolbuffers_js_bufbuild_buf |
protocolbuffers/js | acme/paymentapis | @buf/protocolbuffers_js_acme_paymentapis |
#
Package versionsBy default, when you npm install
a Buf module, the BSR generates code from the most recent reference for the module. But you can also install a specific package version using npm's standard @
syntax:
$ npm install @buf/protocolbuffers_js_acme_paymentapis@1.1.2
Package version syntax is based on the BSR's concept of synthetic versions:
With package versions:
- The major version is always 1.
- The minor version (3 in the first example) corresponds to the template version (without the
v
prefix). Template versions increase monotonically and have the formv1
,v2
,v3
... - The patch version (5 in the first example) corresponds to the module, which is identified by a commit sequence ID that's incremented each time a new version of a module is pushed.
This command, for example, applies version 1 of the protocolbuffers/js
template to a commit with an ID of 2 (the second commit pushed to the module):
$ npm install @buf/protocolbuffers_js_acme_paymentapis@1.1.2
#
Using private packagesTo install npm packages generated from private Buf modules, you need to configure npm to send an authentication token with each request to the BSR npm registry. Add a line with this syntax to your .npmrc
file:
You can use an existing auth token or generate a new one. To create a new one, log into the BSR, navigate to your user settings page, and click Create Token.
#
Other package managersBecause the Buf npm registry implements npm's public registry API, you should be able to use it with package management tools outside of npm, such as Yarn and pnpm, though with some known limitations.
#
Known limitationsThe BSR npm registry has a few limitations that you should be aware of.
#
Yarn compatibilityYarn versions greater than v1.10.0 and less than v2 are not supported. These versions of Yarn require the shasum
field in the dist object to be set, but the BSR can't compute a digest without generating the code for all possible versions of the package.
#
Runtime dependenciesIf you're creating your own plugins, you can use labels to declare runtime dependencies for plugins. The BSR npm registry currently supports semantic versioning for versions, like 0.1.0
or 1.2.3-SNAPSHOT
, but not semver ranges like >=1.2.7
or <1.3.0
.
#
Import rewritesIf the module you request has dependencies, the npm registry rewrites any relative import paths so that they point to the package with a full package name. Here's an example rewrite:
// generated importrequire("../../google/storage/v1/storage_pb.js");
// replacementrequire("@buf/grpc_web_googleapis_googleapis/google/storage/v1/storage_pb.js");
What this means in practice is that files generated by Protobuf plugins must use the same path as their .proto
counterparts, although suffixes like _pb
and additional file extensions are allowed. The table below shows an original Protobuf filepath (foo/bar.proto
) and which generated filepaths would be acceptable (or not).
Proto filepath | Path of generated file | Acceptable? |
---|---|---|
foo/bar.proto | foo/bar.js | ✅ |
foo/bar.proto | foo/bar_pb.js | ✅ |
foo/bar.proto | foo/bar_pb.ts | ✅ |
foo/bar.proto | foo/bar_grpc.d.ts | ✅ |
foo/bar.proto | foo-bar.js | ❌ |
foo/bar.proto | some/other/path.ts | ❌ |
If you're a plugin author, be sure to heed this naming structure; otherwise, consumers of your APIs are likely to experience broken imports.