Skip to main content

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.

Setup#

npm 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 templates#

The table below lists the generation templates that are officially supported by the BSR:

TemplateWhat it generates
protocolbuffers/jsJavaScript code stubs (.js)
grpc/webJavaScript 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/protocolbuffers_go_acme_paymentapis
Output
npm ERR! code EINVALIDPACKAGENAMEnpm ERR! Invalid package name "google.golang.org/protobuf" of package "google.golang.org/protobuf@v1.28.1": name can only contain URL-friendly characters.

Installing packages#

With 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 names#

The BSR npm registry has a special syntax for package names:

Syntax for package names
Examples
npm install @buf/protocolbuffers_js_acme_petapisnpm install @buf/grpc_web_acme_paymentapis
Legend:constant{variable}

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:

TemplateBuf modulePackage name
grpc/webacme/petapis@buf/grpc_web_acme_petapis
protocolbuffers/jsbufbuild/buf@buf/protocolbuffers_js_bufbuild_buf
protocolbuffers/jsacme/paymentapis@buf/protocolbuffers_js_acme_paymentapis

Package versions#

By 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:

Package version syntax
Examples
1.3.51.2.26
Legend:constant{variable}

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 form v1, 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
Specific version installation syntax
npm install @buf/{templateOwner}_{templateName}_{moduleOwner}_{moduleName}@{packageVersion}
Examples
npm install @buf/protocolbuffers_js_acme_paymentapis@1.1.2npm install @buf/grpc_web_acme_petapis@1.2.1
Legend:constant{variable}

Using private packages#

To 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:

npmrc token syntax
//npm.buf.build/:_authToken={token}
Example//npm.buf.build/:_authToken=84612b6cbe8f4...
Legend:constant{variable}

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 managers#

Because 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 limitations#

The BSR npm registry has a few limitations that you should be aware of.

Yarn compatibility#

Yarn 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 dependencies#

If 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 rewrites#

If 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 filepathPath of generated fileAcceptable?
foo/bar.protofoo/bar.js
foo/bar.protofoo/bar_pb.js
foo/bar.protofoo/bar_pb.ts
foo/bar.protofoo/bar_grpc.d.ts
foo/bar.protofoo-bar.js
foo/bar.protosome/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.