@bufbuild/protoc-gen-es 1.8.0 → 2.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@ The code generator plugin for Protocol Buffers for ECMAScript. Learn more about
4
4
 
5
5
  ## Installation
6
6
 
7
- `protoc-gen-es` generates base types - messages and enumerations - from your Protocol Buffer
7
+ `protoc-gen-es` generates base types - messages and enumerations - from your Protocol Buffer
8
8
  schema. The generated code requires the runtime library [@bufbuild/protobuf](https://www.npmjs.com/package/@bufbuild/protobuf). It is compatible with Protocol Buffer compilers like [buf](https://github.com/bufbuild/buf) and [protoc](https://github.com/protocolbuffers/protobuf/releases).
9
9
 
10
10
  To install the plugin and the runtime library, run:
@@ -15,7 +15,7 @@ npm install @bufbuild/protobuf
15
15
  ```
16
16
 
17
17
  We use peer dependencies to ensure that code generator and runtime library are
18
- compatible with each other. Note that npm installs them automatically, but yarn
18
+ compatible with each other. Note that npm installs them automatically, but yarn
19
19
  and pnpm do not.
20
20
 
21
21
 
@@ -37,7 +37,7 @@ plugins:
37
37
  # This will invoke protoc-gen-es and write output to src/gen
38
38
  - plugin: es
39
39
  out: src/gen
40
- opt:
40
+ opt:
41
41
  # Add more plugin options here
42
42
  - target=ts
43
43
  ```
@@ -49,7 +49,7 @@ npx buf generate
49
49
  ```
50
50
 
51
51
  Note that `buf` can generate from various [inputs](https://docs.buf.build/reference/inputs),
52
- not just local protobuf files.
52
+ not just local protobuf files.
53
53
 
54
54
 
55
55
  ### With protoc
@@ -65,7 +65,7 @@ PATH=$PATH:$(pwd)/node_modules/.bin \
65
65
  Note that we are adding `node_modules/.bin` to the `$PATH`, so that the protocol
66
66
  buffer compiler can find them. This happens automatically with npm scripts.
67
67
 
68
- Since yarn v2 and above does not use a `node_modules` directory, you need to
68
+ Since yarn v2 and above does not use a `node_modules` directory, you need to
69
69
  change the variable a bit:
70
70
 
71
71
  ```bash
@@ -88,7 +88,7 @@ Multiple values can be given by separating them with `+`, for example
88
88
  `target=js+dts`.
89
89
 
90
90
  By default, we generate JavaScript and TypeScript declaration files, which
91
- produces the smallest code size and is the most compatible with various
91
+ produces the smallest code size and is the most compatible with various
92
92
  bundler configurations. If you prefer to generate TypeScript, use `target=ts`.
93
93
 
94
94
  ### `import_extension=.js`
@@ -109,12 +109,12 @@ in import paths with the given value. For example, set
109
109
 
110
110
  By default, [protoc-gen-es](https://www.npmjs.com/package/@bufbuild/protoc-gen-es)
111
111
  (and all other plugins based on [@bufbuild/protoplugin](https://www.npmjs.com/package/@bufbuild/protoplugin))
112
- generate ECMAScript `import` and `export` statements. For use cases where
113
- CommonJS is difficult to avoid, this option can be used to generate CommonJS
112
+ generate ECMAScript `import` and `export` statements. For use cases where
113
+ CommonJS is difficult to avoid, this option can be used to generate CommonJS
114
114
  `require()` calls.
115
115
 
116
116
  Possible values:
117
- - `js_import_style=module` generate ECMAScript `import` / `export` statements -
117
+ - `js_import_style=module` generate ECMAScript `import` / `export` statements -
118
118
  the default behavior.
119
119
  - `js_import_style=legacy_commonjs` generate CommonJS `require()` calls.
120
120
 
@@ -127,13 +127,12 @@ empty files, to allow for smooth interoperation with Bazel and similar
127
127
  tooling that requires all output files to be declared ahead of time.
128
128
  Unless you use Bazel, it is very unlikely that you need this option.
129
129
 
130
- ### `ts_nocheck=false`
130
+ ### `ts_nocheck=true`
131
131
 
132
- By default, [protoc-gen-es](https://www.npmjs.com/package/@bufbuild/protoc-gen-es)
133
- (and all other plugins based on [@bufbuild/protoplugin](https://www.npmjs.com/package/@bufbuild/protoplugin))
134
- generate an annotation at the top of each file: `// @ts-nocheck`.
132
+ [protoc-gen-es](https://www.npmjs.com/package/@bufbuild/protoc-gen-es) generates
133
+ valid TypeScript for current versions of the TypeScript compiler with standard
134
+ settings.
135
135
 
136
- We generate the annotation to support a wide range of compiler configurations and
137
- future changes to the language. But there can be situations where the annotation
138
- shadows an underlying problem, for example an unresolvable import. To remove
139
- the annotation and to enable type checks, set the plugin option `ts_nocheck=false`.
136
+ In case you use compiler settings that yield an error for generated code, you
137
+ can set the plugin option `ts_nocheck=true`. This will generate an annotation at
138
+ the top of each file to skip type checks: `// @ts-nocheck`.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bufbuild/protoc-gen-es",
3
- "version": "1.8.0",
3
+ "version": "2.0.0-alpha.1",
4
4
  "description": "Protocol Buffers code generator for ECMAScript",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -16,15 +16,15 @@
16
16
  },
17
17
  "scripts": {
18
18
  "clean": "rm -rf ./dist/cjs/*",
19
- "build": "../../node_modules/typescript/bin/tsc --project tsconfig.json --module commonjs --outDir ./dist/cjs"
19
+ "build": "../../node_modules/typescript/bin/tsc --project tsconfig.json --outDir ./dist/cjs"
20
20
  },
21
21
  "preferUnplugged": true,
22
22
  "dependencies": {
23
- "@bufbuild/protobuf": "^1.8.0",
24
- "@bufbuild/protoplugin": "1.8.0"
23
+ "@bufbuild/protobuf": "^2.0.0-alpha.1",
24
+ "@bufbuild/protoplugin": "2.0.0-alpha.1"
25
25
  },
26
26
  "peerDependencies": {
27
- "@bufbuild/protobuf": "1.8.0"
27
+ "@bufbuild/protobuf": "2.0.0-alpha.1"
28
28
  },
29
29
  "peerDependenciesMeta": {
30
30
  "@bufbuild/protobuf": {
@@ -14,15 +14,300 @@
14
14
  // limitations under the License.
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.protocGenEs = void 0;
17
+ const reflect_1 = require("@bufbuild/protobuf/reflect");
18
+ const codegenv1_1 = require("@bufbuild/protobuf/codegenv1");
17
19
  const protoplugin_1 = require("@bufbuild/protoplugin");
18
- const typescript_js_1 = require("./typescript.js");
19
- const javascript_js_1 = require("./javascript.js");
20
- const declaration_js_1 = require("./declaration.js");
20
+ const util_1 = require("./util");
21
21
  const package_json_1 = require("../package.json");
22
22
  exports.protocGenEs = (0, protoplugin_1.createEcmaScriptPlugin)({
23
23
  name: "protoc-gen-es",
24
24
  version: `v${String(package_json_1.version)}`,
25
- generateTs: typescript_js_1.generateTs,
26
- generateJs: javascript_js_1.generateJs,
27
- generateDts: declaration_js_1.generateDts,
25
+ generateTs,
26
+ generateJs,
27
+ generateDts,
28
28
  });
29
+ // This annotation informs bundlers that the succeeding function call is free of
30
+ // side effects. This means the symbol can be removed from the module during
31
+ // tree-shaking if it is unused.
32
+ // See https://github.com/bufbuild/protobuf-es/pull/470
33
+ const pure = "/*@__PURE__*/";
34
+ // prettier-ignore
35
+ function generateTs(schema) {
36
+ for (const file of schema.files) {
37
+ const f = schema.generateFile(file.name + "_pb.ts");
38
+ f.preamble(file);
39
+ const { GenDescFile } = f.runtime.codegen;
40
+ const fileDesc = f.importDesc(file);
41
+ f.print(f.exportDecl("const", fileDesc.name), ": ", GenDescFile, " = ", pure);
42
+ f.print(" ", getFileDescCall(f, file), ";");
43
+ f.print();
44
+ for (const desc of schema.typesInFile(file)) {
45
+ switch (desc.kind) {
46
+ case "message": {
47
+ generateMessageShape(f, desc, "ts");
48
+ const { GenDescMessage, messageDesc } = f.runtime.codegen;
49
+ const MessageShape = f.importShape(desc);
50
+ const fileDesc = f.importDesc(file);
51
+ const name = f.importDesc(desc).name;
52
+ f.print("// Describes the ", desc.toString(), ".");
53
+ f.print("// Use `create(", name, ")` to create a new ", MessageShape.name, ".");
54
+ const call = (0, util_1.functionCall)(messageDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
55
+ f.print(f.exportDecl("const", name), ": ", GenDescMessage, "<", MessageShape, ">", " = ", pure);
56
+ f.print(" ", call, ";");
57
+ f.print();
58
+ break;
59
+ }
60
+ case "enum": {
61
+ generateEnumShape(f, desc);
62
+ const { GenDescEnum, enumDesc } = f.runtime.codegen;
63
+ const EnumShape = f.importShape(desc);
64
+ const fileDesc = f.importDesc(file);
65
+ f.print("// Describes the ", desc.toString(), ".");
66
+ const name = f.importDesc(desc).name;
67
+ const call = (0, util_1.functionCall)(enumDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
68
+ f.print(f.exportDecl("const", name), ": ", GenDescEnum, "<", EnumShape, ">", " = ", pure);
69
+ f.print(" ", call, ";");
70
+ f.print();
71
+ break;
72
+ }
73
+ case "extension": {
74
+ const { GenDescExtension, extDesc } = f.runtime.codegen;
75
+ const name = f.importDesc(desc).name;
76
+ const E = f.importShape(desc.extendee);
77
+ const V = (0, util_1.getFieldTypeInfo)(desc).typing;
78
+ const call = (0, util_1.functionCall)(extDesc, [f.importDesc(file), ...(0, codegenv1_1.pathInFileDesc)(desc)]);
79
+ f.print(f.jsDoc(desc));
80
+ f.print(f.exportDecl("const", name), ": ", GenDescExtension, "<", E, ", ", V, ">", " = ", pure);
81
+ f.print(" ", call, ";");
82
+ f.print();
83
+ break;
84
+ }
85
+ case "service": {
86
+ const { GenDescService, serviceDesc } = f.runtime.codegen;
87
+ const name = f.importDesc(desc).name;
88
+ const call = (0, util_1.functionCall)(serviceDesc, [f.importDesc(file), ...(0, codegenv1_1.pathInFileDesc)(desc)]);
89
+ f.print(f.jsDoc(desc));
90
+ f.print(f.exportDecl("const", name), ": ", GenDescService, "<", getServiceShapeExpr(f, desc), "> = ", pure);
91
+ f.print(" ", call, ";");
92
+ f.print();
93
+ break;
94
+ }
95
+ }
96
+ }
97
+ }
98
+ }
99
+ // prettier-ignore
100
+ function generateJs(schema) {
101
+ for (const file of schema.files) {
102
+ const f = schema.generateFile(file.name + "_pb.js");
103
+ f.preamble(file);
104
+ const fileDesc = f.importDesc(file);
105
+ f.print(f.exportDecl("const", fileDesc.name), " = ", pure);
106
+ f.print(" ", getFileDescCall(f, file), ";");
107
+ f.print();
108
+ for (const desc of schema.typesInFile(file)) {
109
+ switch (desc.kind) {
110
+ case "message": {
111
+ const { messageDesc } = f.runtime.codegen;
112
+ const MessageShape = f.importShape(desc);
113
+ const name = f.importDesc(desc).name;
114
+ f.print("// Describes the ", desc.toString(), ". Use `create(", name, ")` to create a new ", MessageShape.name, ".");
115
+ const call = (0, util_1.functionCall)(messageDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
116
+ f.print(f.exportDecl("const", name), " = ", pure);
117
+ f.print(" ", call, ";");
118
+ f.print();
119
+ break;
120
+ }
121
+ case "enum": {
122
+ // generate descriptor
123
+ {
124
+ const { enumDesc } = f.runtime.codegen;
125
+ f.print("// Describes the ", desc.toString(), ".");
126
+ const name = f.importDesc(desc).name;
127
+ const call = (0, util_1.functionCall)(enumDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
128
+ f.print(f.exportDecl("const", name), " = ", pure);
129
+ f.print(" ", call, ";");
130
+ f.print();
131
+ }
132
+ // declare TypeScript enum
133
+ {
134
+ f.print(f.jsDoc(desc));
135
+ const { tsEnum } = f.runtime.codegen;
136
+ const call = (0, util_1.functionCall)(tsEnum, [f.importDesc(desc)]);
137
+ f.print(f.exportDecl("const", f.importShape(desc).name), " = ", pure);
138
+ f.print(" ", call, ";");
139
+ f.print();
140
+ }
141
+ break;
142
+ }
143
+ case "extension": {
144
+ const { extDesc } = f.runtime.codegen;
145
+ const name = f.importDesc(desc).name;
146
+ const call = (0, util_1.functionCall)(extDesc, [f.importDesc(desc.file), ...(0, codegenv1_1.pathInFileDesc)(desc)]);
147
+ f.print(f.jsDoc(desc));
148
+ f.print(f.exportDecl("const", name), " = ", pure);
149
+ f.print(" ", call, ";");
150
+ f.print();
151
+ break;
152
+ }
153
+ case "service": {
154
+ const { serviceDesc } = f.runtime.codegen;
155
+ const name = f.importDesc(desc).name;
156
+ f.print(f.jsDoc(desc));
157
+ const call = (0, util_1.functionCall)(serviceDesc, [f.importDesc(desc.file), ...(0, codegenv1_1.pathInFileDesc)(desc)]);
158
+ f.print(f.exportDecl("const", name), " = ", pure);
159
+ f.print(" ", call, ";");
160
+ f.print();
161
+ break;
162
+ }
163
+ }
164
+ }
165
+ }
166
+ }
167
+ // prettier-ignore
168
+ function generateDts(schema) {
169
+ for (const file of schema.files) {
170
+ const f = schema.generateFile(file.name + "_pb.d.ts");
171
+ f.preamble(file);
172
+ const { GenDescFile } = f.runtime.codegen;
173
+ const fileDesc = f.importDesc(file);
174
+ f.print(f.exportDecl("declare const", fileDesc.name), ": ", GenDescFile, ";");
175
+ f.print();
176
+ for (const desc of schema.typesInFile(file)) {
177
+ switch (desc.kind) {
178
+ case "message": {
179
+ generateMessageShape(f, desc, "dts");
180
+ const { GenDescMessage } = f.runtime.codegen;
181
+ const MessageShape = f.importShape(desc);
182
+ const name = f.importDesc(desc).name;
183
+ f.print("// Describes the ", desc.toString(), ". Use `create(", name, ")` to create a new ", MessageShape.name, ".");
184
+ f.print(f.exportDecl("declare const", name), ": ", GenDescMessage, "<", MessageShape, ">", ";");
185
+ f.print();
186
+ break;
187
+ }
188
+ case "enum": {
189
+ generateEnumShape(f, desc);
190
+ const { GenDescEnum } = f.runtime.codegen;
191
+ const EnumShape = f.importShape(desc);
192
+ f.print("// Describes the ", desc.toString(), ".");
193
+ const name = f.importDesc(desc).name;
194
+ f.print(f.exportDecl("declare const", name), ": ", GenDescEnum, "<", EnumShape, ">;");
195
+ f.print();
196
+ break;
197
+ }
198
+ case "extension": {
199
+ const { GenDescExtension } = f.runtime.codegen;
200
+ const name = f.importDesc(desc).name;
201
+ const E = f.importShape(desc.extendee);
202
+ const V = (0, util_1.getFieldTypeInfo)(desc).typing;
203
+ f.print(f.jsDoc(desc));
204
+ f.print(f.exportDecl("declare const", name), ": ", GenDescExtension, "<", E, ", ", V, ">;");
205
+ f.print();
206
+ break;
207
+ }
208
+ case "service": {
209
+ const { GenDescService } = f.runtime.codegen;
210
+ const name = f.importDesc(desc).name;
211
+ f.print(f.jsDoc(desc));
212
+ f.print(f.exportDecl("declare const", name), ": ", GenDescService, "<", getServiceShapeExpr(f, desc), ">;");
213
+ f.print();
214
+ break;
215
+ }
216
+ }
217
+ }
218
+ }
219
+ }
220
+ // prettier-ignore
221
+ function getFileDescCall(f, file) {
222
+ const info = (0, codegenv1_1.embedFileDesc)(file);
223
+ if (info.bootable && !f.runtime.create.from.startsWith("@bufbuild/protobuf")) {
224
+ // google/protobuf/descriptor.proto is embedded as a plain object when
225
+ // bootstrapping to avoid recursion
226
+ return (0, util_1.functionCall)(f.runtime.codegen.boot, [JSON.stringify(info.boot())]);
227
+ }
228
+ const { fileDesc } = f.runtime.codegen;
229
+ if (file.dependencies.length > 0) {
230
+ const deps = file.dependencies.map((f) => ({
231
+ kind: "es_desc_ref",
232
+ desc: f,
233
+ }));
234
+ return (0, util_1.functionCall)(fileDesc, [
235
+ f.string(info.base64()),
236
+ (0, util_1.arrayLiteral)(deps),
237
+ ]);
238
+ }
239
+ return (0, util_1.functionCall)(fileDesc, [f.string(info.base64())]);
240
+ }
241
+ // prettier-ignore
242
+ function getServiceShapeExpr(f, service) {
243
+ const p = [];
244
+ function print(...printables) {
245
+ p.push(...printables, "\n");
246
+ }
247
+ print("{");
248
+ for (const method of service.methods) {
249
+ print(f.jsDoc(method, " "));
250
+ print(" ", (0, reflect_1.localName)(method), ": {");
251
+ print(" kind: ", f.string(method.methodKind), ";");
252
+ print(" I: ", f.importShape(method.input), ";");
253
+ print(" O: ", f.importShape(method.output), ";");
254
+ print(" },");
255
+ }
256
+ print("}");
257
+ return p;
258
+ }
259
+ // prettier-ignore
260
+ function generateEnumShape(f, enumeration) {
261
+ f.print(f.jsDoc(enumeration));
262
+ f.print(f.exportDecl("enum", f.importShape(enumeration).name), " {");
263
+ for (const value of enumeration.values) {
264
+ if (enumeration.values.indexOf(value) > 0) {
265
+ f.print();
266
+ }
267
+ f.print(f.jsDoc(value, " "));
268
+ f.print(" ", (0, reflect_1.localName)(value), " = ", value.number, ",");
269
+ }
270
+ f.print("}");
271
+ f.print();
272
+ }
273
+ // prettier-ignore
274
+ function generateMessageShape(f, message, target) {
275
+ const { Message } = f.runtime;
276
+ const declaration = target == "ts" ? "type" : "declare type";
277
+ f.print(f.jsDoc(message));
278
+ f.print(f.exportDecl(declaration, f.importShape(message).name), " = ", Message, "<", f.string(message.typeName), "> & {");
279
+ for (const member of message.members) {
280
+ switch (member.kind) {
281
+ case "oneof":
282
+ f.print(f.jsDoc(member, " "));
283
+ f.print(" ", (0, reflect_1.localName)(member), ": {");
284
+ for (const field of member.fields) {
285
+ if (member.fields.indexOf(field) > 0) {
286
+ f.print(` } | {`);
287
+ }
288
+ f.print(f.jsDoc(field, " "));
289
+ const { typing } = (0, util_1.getFieldTypeInfo)(field);
290
+ f.print(` value: `, typing, `;`);
291
+ f.print(` case: "`, (0, reflect_1.localName)(field), `";`);
292
+ }
293
+ f.print(` } | { case: undefined; value?: undefined };`);
294
+ break;
295
+ default: {
296
+ f.print(f.jsDoc(member, " "));
297
+ const { typing, optional } = (0, util_1.getFieldTypeInfo)(member);
298
+ if ((0, util_1.fieldUsesPrototype)(member) || !optional) {
299
+ f.print(" ", (0, reflect_1.localName)(member), ": ", typing, ";");
300
+ }
301
+ else {
302
+ f.print(" ", (0, reflect_1.localName)(member), "?: ", typing, ";");
303
+ }
304
+ break;
305
+ }
306
+ }
307
+ if (message.members.indexOf(member) < message.members.length - 1) {
308
+ f.print();
309
+ }
310
+ }
311
+ f.print("};");
312
+ f.print();
313
+ }