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

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
@@ -91,19 +91,18 @@ By default, we generate JavaScript and TypeScript declaration files, which
91
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
- ### `import_extension=.js`
94
+ ### `import_extension`
95
95
 
96
96
  By default, [protoc-gen-es](https://www.npmjs.com/package/@bufbuild/protoc-gen-es)
97
97
  (and all other plugins based on [@bufbuild/protoplugin](https://www.npmjs.com/package/@bufbuild/protoplugin))
98
- uses a `.js` file extensions in import paths, even in TypeScript files.
98
+ does not add a file extensions to import paths.
99
99
 
100
- This is unintuitive, but necessary for [ECMAScript modules in Node.js](https://www.typescriptlang.org/docs/handbook/esm-node.html).
101
- Unfortunately, not all bundlers and tools have caught up yet, and Deno
102
- requires `.ts`. With this plugin option, you can replace `.js` extensions
100
+ Some environments require an import extension. For example, using [ECMAScript modules in Node.js](https://www.typescriptlang.org/docs/handbook/esm-node.html) requires the `.js` extension, and Deno requires `.ts`. With this plugin option, you can add `.js`/`.ts` extensions
103
101
  in import paths with the given value. For example, set
104
102
 
105
- - `import_extension=none` to remove the `.js` extension.
106
- - `import_extension=.ts` to replace the `.js` extension with `.ts`.
103
+ - `import_extension=.js` to add the `.js` extension.
104
+ - `import_extension=.ts` to add the `.ts` extension.
105
+ - `import_extension=none` to not add an extension. (Default)
107
106
 
108
107
  ### `js_import_style`
109
108
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bufbuild/protoc-gen-es",
3
- "version": "2.0.0-alpha.1",
3
+ "version": "2.0.0-alpha.2",
4
4
  "description": "Protocol Buffers code generator for ECMAScript",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -20,15 +20,19 @@
20
20
  },
21
21
  "preferUnplugged": true,
22
22
  "dependencies": {
23
- "@bufbuild/protobuf": "^2.0.0-alpha.1",
24
- "@bufbuild/protoplugin": "2.0.0-alpha.1"
23
+ "@bufbuild/protobuf": "^2.0.0-alpha.2",
24
+ "@bufbuild/protoplugin": "2.0.0-alpha.2"
25
25
  },
26
26
  "peerDependencies": {
27
- "@bufbuild/protobuf": "2.0.0-alpha.1"
27
+ "@bufbuild/protobuf": "2.0.0-alpha.2"
28
28
  },
29
29
  "peerDependenciesMeta": {
30
30
  "@bufbuild/protobuf": {
31
31
  "optional": true
32
32
  }
33
- }
33
+ },
34
+ "files": [
35
+ "dist/**",
36
+ "bin/**"
37
+ ]
34
38
  }
@@ -38,8 +38,9 @@ function generateTs(schema) {
38
38
  f.preamble(file);
39
39
  const { GenDescFile } = f.runtime.codegen;
40
40
  const fileDesc = f.importDesc(file);
41
+ generateDescDoc(f, file);
41
42
  f.print(f.exportDecl("const", fileDesc.name), ": ", GenDescFile, " = ", pure);
42
- f.print(" ", getFileDescCall(f, file), ";");
43
+ f.print(" ", getFileDescCall(f, file, schema), ";");
43
44
  f.print();
44
45
  for (const desc of schema.typesInFile(file)) {
45
46
  switch (desc.kind) {
@@ -47,10 +48,8 @@ function generateTs(schema) {
47
48
  generateMessageShape(f, desc, "ts");
48
49
  const { GenDescMessage, messageDesc } = f.runtime.codegen;
49
50
  const MessageShape = f.importShape(desc);
50
- const fileDesc = f.importDesc(file);
51
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, ".");
52
+ generateDescDoc(f, desc);
54
53
  const call = (0, util_1.functionCall)(messageDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
55
54
  f.print(f.exportDecl("const", name), ": ", GenDescMessage, "<", MessageShape, ">", " = ", pure);
56
55
  f.print(" ", call, ";");
@@ -61,8 +60,7 @@ function generateTs(schema) {
61
60
  generateEnumShape(f, desc);
62
61
  const { GenDescEnum, enumDesc } = f.runtime.codegen;
63
62
  const EnumShape = f.importShape(desc);
64
- const fileDesc = f.importDesc(file);
65
- f.print("// Describes the ", desc.toString(), ".");
63
+ generateDescDoc(f, desc);
66
64
  const name = f.importDesc(desc).name;
67
65
  const call = (0, util_1.functionCall)(enumDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
68
66
  f.print(f.exportDecl("const", name), ": ", GenDescEnum, "<", EnumShape, ">", " = ", pure);
@@ -74,8 +72,8 @@ function generateTs(schema) {
74
72
  const { GenDescExtension, extDesc } = f.runtime.codegen;
75
73
  const name = f.importDesc(desc).name;
76
74
  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)]);
75
+ const V = (0, util_1.fieldTypeScriptType)(desc).typing;
76
+ const call = (0, util_1.functionCall)(extDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
79
77
  f.print(f.jsDoc(desc));
80
78
  f.print(f.exportDecl("const", name), ": ", GenDescExtension, "<", E, ", ", V, ">", " = ", pure);
81
79
  f.print(" ", call, ";");
@@ -85,7 +83,7 @@ function generateTs(schema) {
85
83
  case "service": {
86
84
  const { GenDescService, serviceDesc } = f.runtime.codegen;
87
85
  const name = f.importDesc(desc).name;
88
- const call = (0, util_1.functionCall)(serviceDesc, [f.importDesc(file), ...(0, codegenv1_1.pathInFileDesc)(desc)]);
86
+ const call = (0, util_1.functionCall)(serviceDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
89
87
  f.print(f.jsDoc(desc));
90
88
  f.print(f.exportDecl("const", name), ": ", GenDescService, "<", getServiceShapeExpr(f, desc), "> = ", pure);
91
89
  f.print(" ", call, ";");
@@ -102,16 +100,16 @@ function generateJs(schema) {
102
100
  const f = schema.generateFile(file.name + "_pb.js");
103
101
  f.preamble(file);
104
102
  const fileDesc = f.importDesc(file);
103
+ generateDescDoc(f, file);
105
104
  f.print(f.exportDecl("const", fileDesc.name), " = ", pure);
106
- f.print(" ", getFileDescCall(f, file), ";");
105
+ f.print(" ", getFileDescCall(f, file, schema), ";");
107
106
  f.print();
108
107
  for (const desc of schema.typesInFile(file)) {
109
108
  switch (desc.kind) {
110
109
  case "message": {
111
110
  const { messageDesc } = f.runtime.codegen;
112
- const MessageShape = f.importShape(desc);
113
111
  const name = f.importDesc(desc).name;
114
- f.print("// Describes the ", desc.toString(), ". Use `create(", name, ")` to create a new ", MessageShape.name, ".");
112
+ generateDescDoc(f, desc);
115
113
  const call = (0, util_1.functionCall)(messageDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
116
114
  f.print(f.exportDecl("const", name), " = ", pure);
117
115
  f.print(" ", call, ";");
@@ -122,7 +120,7 @@ function generateJs(schema) {
122
120
  // generate descriptor
123
121
  {
124
122
  const { enumDesc } = f.runtime.codegen;
125
- f.print("// Describes the ", desc.toString(), ".");
123
+ generateDescDoc(f, desc);
126
124
  const name = f.importDesc(desc).name;
127
125
  const call = (0, util_1.functionCall)(enumDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
128
126
  f.print(f.exportDecl("const", name), " = ", pure);
@@ -143,7 +141,7 @@ function generateJs(schema) {
143
141
  case "extension": {
144
142
  const { extDesc } = f.runtime.codegen;
145
143
  const name = f.importDesc(desc).name;
146
- const call = (0, util_1.functionCall)(extDesc, [f.importDesc(desc.file), ...(0, codegenv1_1.pathInFileDesc)(desc)]);
144
+ const call = (0, util_1.functionCall)(extDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
147
145
  f.print(f.jsDoc(desc));
148
146
  f.print(f.exportDecl("const", name), " = ", pure);
149
147
  f.print(" ", call, ";");
@@ -154,7 +152,7 @@ function generateJs(schema) {
154
152
  const { serviceDesc } = f.runtime.codegen;
155
153
  const name = f.importDesc(desc).name;
156
154
  f.print(f.jsDoc(desc));
157
- const call = (0, util_1.functionCall)(serviceDesc, [f.importDesc(desc.file), ...(0, codegenv1_1.pathInFileDesc)(desc)]);
155
+ const call = (0, util_1.functionCall)(serviceDesc, [fileDesc, ...(0, codegenv1_1.pathInFileDesc)(desc)]);
158
156
  f.print(f.exportDecl("const", name), " = ", pure);
159
157
  f.print(" ", call, ";");
160
158
  f.print();
@@ -171,6 +169,7 @@ function generateDts(schema) {
171
169
  f.preamble(file);
172
170
  const { GenDescFile } = f.runtime.codegen;
173
171
  const fileDesc = f.importDesc(file);
172
+ generateDescDoc(f, file);
174
173
  f.print(f.exportDecl("declare const", fileDesc.name), ": ", GenDescFile, ";");
175
174
  f.print();
176
175
  for (const desc of schema.typesInFile(file)) {
@@ -180,7 +179,7 @@ function generateDts(schema) {
180
179
  const { GenDescMessage } = f.runtime.codegen;
181
180
  const MessageShape = f.importShape(desc);
182
181
  const name = f.importDesc(desc).name;
183
- f.print("// Describes the ", desc.toString(), ". Use `create(", name, ")` to create a new ", MessageShape.name, ".");
182
+ generateDescDoc(f, desc);
184
183
  f.print(f.exportDecl("declare const", name), ": ", GenDescMessage, "<", MessageShape, ">", ";");
185
184
  f.print();
186
185
  break;
@@ -189,7 +188,7 @@ function generateDts(schema) {
189
188
  generateEnumShape(f, desc);
190
189
  const { GenDescEnum } = f.runtime.codegen;
191
190
  const EnumShape = f.importShape(desc);
192
- f.print("// Describes the ", desc.toString(), ".");
191
+ generateDescDoc(f, desc);
193
192
  const name = f.importDesc(desc).name;
194
193
  f.print(f.exportDecl("declare const", name), ": ", GenDescEnum, "<", EnumShape, ">;");
195
194
  f.print();
@@ -199,7 +198,7 @@ function generateDts(schema) {
199
198
  const { GenDescExtension } = f.runtime.codegen;
200
199
  const name = f.importDesc(desc).name;
201
200
  const E = f.importShape(desc.extendee);
202
- const V = (0, util_1.getFieldTypeInfo)(desc).typing;
201
+ const V = (0, util_1.fieldTypeScriptType)(desc).typing;
203
202
  f.print(f.jsDoc(desc));
204
203
  f.print(f.exportDecl("declare const", name), ": ", GenDescExtension, "<", E, ", ", V, ">;");
205
204
  f.print();
@@ -217,9 +216,39 @@ function generateDts(schema) {
217
216
  }
218
217
  }
219
218
  }
219
+ function generateDescDoc(f, desc) {
220
+ let lines;
221
+ switch (desc.kind) {
222
+ case "file":
223
+ lines = [`Describes the ${desc.toString()}.`];
224
+ break;
225
+ case "message":
226
+ lines = [
227
+ `Describes the ${desc.toString()}.`,
228
+ `Use \`create(${f.importDesc(desc).name})\` to create a new message.`,
229
+ ];
230
+ break;
231
+ case "enum":
232
+ lines = [`Describes the ${desc.toString()}.`];
233
+ break;
234
+ }
235
+ const deprecated = desc.deprecated || (0, reflect_1.parentTypes)(desc).some((d) => d.deprecated);
236
+ if (deprecated) {
237
+ lines.push("@deprecated");
238
+ }
239
+ f.print({
240
+ kind: "es_jsdoc",
241
+ text: lines.join("\n"),
242
+ });
243
+ }
220
244
  // prettier-ignore
221
- function getFileDescCall(f, file) {
222
- const info = (0, codegenv1_1.embedFileDesc)(file);
245
+ function getFileDescCall(f, file, schema) {
246
+ // Schema provides files with source retention options. Since we do not want to
247
+ // embed source retention options in generated code, we use FileDescriptorProto
248
+ // messages from CodeGeneratorRequest.proto_file instead.
249
+ const sourceFile = file.proto;
250
+ const runtimeFile = schema.proto.protoFile.find(f => f.name == sourceFile.name);
251
+ const info = (0, codegenv1_1.embedFileDesc)(runtimeFile !== null && runtimeFile !== void 0 ? runtimeFile : sourceFile);
223
252
  if (info.bootable && !f.runtime.create.from.startsWith("@bufbuild/protobuf")) {
224
253
  // google/protobuf/descriptor.proto is embedded as a plain object when
225
254
  // bootstrapping to avoid recursion
@@ -247,7 +276,7 @@ function getServiceShapeExpr(f, service) {
247
276
  print("{");
248
277
  for (const method of service.methods) {
249
278
  print(f.jsDoc(method, " "));
250
- print(" ", (0, reflect_1.localName)(method), ": {");
279
+ print(" ", method.localName, ": {");
251
280
  print(" kind: ", f.string(method.methodKind), ";");
252
281
  print(" I: ", f.importShape(method.input), ";");
253
282
  print(" O: ", f.importShape(method.output), ";");
@@ -265,7 +294,7 @@ function generateEnumShape(f, enumeration) {
265
294
  f.print();
266
295
  }
267
296
  f.print(f.jsDoc(value, " "));
268
- f.print(" ", (0, reflect_1.localName)(value), " = ", value.number, ",");
297
+ f.print(" ", value.localName, " = ", value.number, ",");
269
298
  }
270
299
  f.print("}");
271
300
  f.print();
@@ -280,26 +309,26 @@ function generateMessageShape(f, message, target) {
280
309
  switch (member.kind) {
281
310
  case "oneof":
282
311
  f.print(f.jsDoc(member, " "));
283
- f.print(" ", (0, reflect_1.localName)(member), ": {");
312
+ f.print(" ", member.localName, ": {");
284
313
  for (const field of member.fields) {
285
314
  if (member.fields.indexOf(field) > 0) {
286
315
  f.print(` } | {`);
287
316
  }
288
317
  f.print(f.jsDoc(field, " "));
289
- const { typing } = (0, util_1.getFieldTypeInfo)(field);
318
+ const { typing } = (0, util_1.fieldTypeScriptType)(field);
290
319
  f.print(` value: `, typing, `;`);
291
- f.print(` case: "`, (0, reflect_1.localName)(field), `";`);
320
+ f.print(` case: "`, field.localName, `";`);
292
321
  }
293
322
  f.print(` } | { case: undefined; value?: undefined };`);
294
323
  break;
295
324
  default: {
296
325
  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, ";");
326
+ const { typing, optional } = (0, util_1.fieldTypeScriptType)(member);
327
+ if (optional) {
328
+ f.print(" ", member.localName, "?: ", typing, ";");
300
329
  }
301
330
  else {
302
- f.print(" ", (0, reflect_1.localName)(member), "?: ", typing, ";");
331
+ f.print(" ", member.localName, ": ", typing, ";");
303
332
  }
304
333
  break;
305
334
  }
@@ -13,36 +13,16 @@
13
13
  // See the License for the specific language governing permissions and
14
14
  // limitations under the License.
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.arrayLiteral = exports.functionCall = exports.getFieldTypeInfo = exports.fieldUsesPrototype = void 0;
16
+ exports.arrayLiteral = exports.functionCall = exports.fieldTypeScriptType = void 0;
17
17
  const reflect_1 = require("@bufbuild/protobuf/reflect");
18
18
  const wkt_1 = require("@bufbuild/protobuf/wkt");
19
- /**
20
- * Tells whether a field uses the prototype chain for field presence.
21
- * Behavior must match with the counterpart in @bufbuild/protobuf.
22
- */
23
- function fieldUsesPrototype(field) {
24
- if (field.parent.file.edition != wkt_1.Edition.EDITION_PROTO2) {
25
- return false;
26
- }
27
- if (field.fieldKind != "scalar" && field.fieldKind != "enum") {
28
- return false;
29
- }
30
- if (field.oneof) {
31
- return false;
32
- }
33
- // proto2 singular scalar and enum fields use an initial value on the prototype chain
34
- return true;
35
- }
36
- exports.fieldUsesPrototype = fieldUsesPrototype;
37
- function getFieldTypeInfo(field) {
19
+ function fieldTypeScriptType(field) {
38
20
  const typing = [];
39
- let typingInferrableFromZeroValue;
40
21
  let optional = false;
41
22
  switch (field.fieldKind) {
42
23
  case "scalar":
43
24
  typing.push((0, reflect_1.scalarTypeScriptType)(field.scalar, field.longType));
44
- optional = field.optional;
45
- typingInferrableFromZeroValue = true;
25
+ optional = field.proto.proto3Optional;
46
26
  break;
47
27
  case "message": {
48
28
  if (!field.oneof && (0, wkt_1.isWrapperDesc)(field.message)) {
@@ -56,7 +36,6 @@ function getFieldTypeInfo(field) {
56
36
  });
57
37
  }
58
38
  optional = true;
59
- typingInferrableFromZeroValue = true;
60
39
  break;
61
40
  }
62
41
  case "enum":
@@ -64,12 +43,10 @@ function getFieldTypeInfo(field) {
64
43
  kind: "es_shape_ref",
65
44
  desc: field.enum,
66
45
  });
67
- optional = field.optional;
68
- typingInferrableFromZeroValue = true;
46
+ optional = field.proto.proto3Optional;
69
47
  break;
70
48
  case "list":
71
49
  optional = false;
72
- typingInferrableFromZeroValue = false;
73
50
  switch (field.listKind) {
74
51
  case "enum":
75
52
  typing.push({
@@ -122,14 +99,13 @@ function getFieldTypeInfo(field) {
122
99
  break;
123
100
  }
124
101
  typing.push("{ [key: ", keyType, "]: ", valueType, " }");
125
- typingInferrableFromZeroValue = false;
126
102
  optional = false;
127
103
  break;
128
104
  }
129
105
  }
130
- return { typing, optional, typingInferrableFromZeroValue };
106
+ return { typing, optional };
131
107
  }
132
- exports.getFieldTypeInfo = getFieldTypeInfo;
108
+ exports.fieldTypeScriptType = fieldTypeScriptType;
133
109
  function functionCall(fn, args, typeParams) {
134
110
  let tp = [];
135
111
  if (typeParams !== undefined && typeParams.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bufbuild/protoc-gen-es",
3
- "version": "2.0.0-alpha.1",
3
+ "version": "2.0.0-alpha.2",
4
4
  "description": "Protocol Buffers code generator for ECMAScript",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -20,15 +20,19 @@
20
20
  },
21
21
  "preferUnplugged": true,
22
22
  "dependencies": {
23
- "@bufbuild/protobuf": "^2.0.0-alpha.1",
24
- "@bufbuild/protoplugin": "2.0.0-alpha.1"
23
+ "@bufbuild/protobuf": "^2.0.0-alpha.2",
24
+ "@bufbuild/protoplugin": "2.0.0-alpha.2"
25
25
  },
26
26
  "peerDependencies": {
27
- "@bufbuild/protobuf": "2.0.0-alpha.1"
27
+ "@bufbuild/protobuf": "2.0.0-alpha.2"
28
28
  },
29
29
  "peerDependenciesMeta": {
30
30
  "@bufbuild/protobuf": {
31
31
  "optional": true
32
32
  }
33
- }
33
+ },
34
+ "files": [
35
+ "dist/**",
36
+ "bin/**"
37
+ ]
34
38
  }
@@ -1,336 +0,0 @@
1
- // Copyright 2021-2024 Buf Technologies, Inc.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
14
-
15
- import type {
16
- DescEnum,
17
- DescFile,
18
- DescMessage,
19
- DescService,
20
- } from "@bufbuild/protobuf";
21
- import { localName } from "@bufbuild/protobuf/reflect";
22
- import { embedFileDesc, pathInFileDesc } from "@bufbuild/protobuf/codegenv1";
23
- import { createEcmaScriptPlugin } from "@bufbuild/protoplugin";
24
- import type {
25
- Schema,
26
- GeneratedFile,
27
- Printable,
28
- Target,
29
- } from "@bufbuild/protoplugin/ecmascript";
30
- import {
31
- arrayLiteral,
32
- fieldUsesPrototype,
33
- functionCall,
34
- getFieldTypeInfo,
35
- } from "./util";
36
- import { version } from "../package.json";
37
-
38
- export const protocGenEs = createEcmaScriptPlugin({
39
- name: "protoc-gen-es",
40
- version: `v${String(version)}`,
41
- generateTs,
42
- generateJs,
43
- generateDts,
44
- });
45
-
46
- // This annotation informs bundlers that the succeeding function call is free of
47
- // side effects. This means the symbol can be removed from the module during
48
- // tree-shaking if it is unused.
49
- // See https://github.com/bufbuild/protobuf-es/pull/470
50
- const pure = "/*@__PURE__*/";
51
-
52
- // prettier-ignore
53
- function generateTs(schema: Schema) {
54
- for (const file of schema.files) {
55
- const f = schema.generateFile(file.name + "_pb.ts");
56
- f.preamble(file);
57
- const { GenDescFile } = f.runtime.codegen;
58
- const fileDesc = f.importDesc(file);
59
- f.print(f.exportDecl("const", fileDesc.name), ": ", GenDescFile, " = ", pure);
60
- f.print(" ", getFileDescCall(f, file), ";");
61
- f.print();
62
- for (const desc of schema.typesInFile(file)) {
63
- switch (desc.kind) {
64
- case "message": {
65
- generateMessageShape(f, desc, "ts");
66
- const {GenDescMessage, messageDesc} = f.runtime.codegen;
67
- const MessageShape = f.importShape(desc);
68
- const fileDesc = f.importDesc(file);
69
- const name = f.importDesc(desc).name;
70
- f.print("// Describes the ", desc.toString(), ".");
71
- f.print("// Use `create(", name, ")` to create a new ", MessageShape.name, ".");
72
- const call = functionCall(messageDesc, [fileDesc, ...pathInFileDesc(desc)]);
73
- f.print(f.exportDecl("const", name), ": ", GenDescMessage, "<", MessageShape, ">", " = ", pure);
74
- f.print(" ", call, ";");
75
- f.print();
76
- break;
77
- }
78
- case "enum": {
79
- generateEnumShape(f, desc);
80
- const {GenDescEnum, enumDesc} = f.runtime.codegen;
81
- const EnumShape = f.importShape(desc);
82
- const fileDesc = f.importDesc(file);
83
- f.print("// Describes the ", desc.toString(), ".");
84
- const name = f.importDesc(desc).name;
85
- const call = functionCall(enumDesc, [fileDesc, ...pathInFileDesc(desc)]);
86
- f.print(f.exportDecl("const", name), ": ", GenDescEnum, "<", EnumShape, ">", " = ", pure);
87
- f.print(" ", call, ";");
88
- f.print();
89
- break;
90
- }
91
- case "extension": {
92
- const { GenDescExtension, extDesc } = f.runtime.codegen;
93
- const name = f.importDesc(desc).name;
94
- const E = f.importShape(desc.extendee);
95
- const V = getFieldTypeInfo(desc).typing;
96
- const call = functionCall(extDesc, [f.importDesc(file), ...pathInFileDesc(desc)]);
97
- f.print(f.jsDoc(desc));
98
- f.print(f.exportDecl("const", name), ": ", GenDescExtension, "<", E, ", ", V, ">", " = ", pure);
99
- f.print(" ", call, ";");
100
- f.print();
101
- break;
102
- }
103
- case "service": {
104
- const { GenDescService, serviceDesc} = f.runtime.codegen;
105
- const name = f.importDesc(desc).name;
106
- const call = functionCall(serviceDesc, [f.importDesc(file), ...pathInFileDesc(desc)]);
107
- f.print(f.jsDoc(desc));
108
- f.print(f.exportDecl("const", name), ": ", GenDescService, "<", getServiceShapeExpr(f, desc), "> = ", pure);
109
- f.print(" ", call, ";");
110
- f.print();
111
- break;
112
- }
113
- }
114
- }
115
- }
116
- }
117
-
118
- // prettier-ignore
119
- function generateJs(schema: Schema) {
120
- for (const file of schema.files) {
121
- const f = schema.generateFile(file.name + "_pb.js");
122
- f.preamble(file);
123
- const fileDesc = f.importDesc(file);
124
- f.print(f.exportDecl("const", fileDesc.name), " = ", pure);
125
- f.print(" ", getFileDescCall(f, file), ";");
126
- f.print();
127
- for (const desc of schema.typesInFile(file)) {
128
- switch (desc.kind) {
129
- case "message": {
130
- const { messageDesc} = f.runtime.codegen;
131
- const MessageShape = f.importShape(desc);
132
- const name = f.importDesc(desc).name;
133
- f.print("// Describes the ", desc.toString(), ". Use `create(", name, ")` to create a new ", MessageShape.name, ".");
134
- const call = functionCall(messageDesc, [fileDesc, ...pathInFileDesc(desc)]);
135
- f.print(f.exportDecl("const", name), " = ", pure);
136
- f.print(" ", call, ";");
137
- f.print();
138
- break;
139
- }
140
- case "enum": {
141
- // generate descriptor
142
- {
143
- const { enumDesc } = f.runtime.codegen;
144
- f.print("// Describes the ", desc.toString(), ".");
145
- const name = f.importDesc(desc).name;
146
- const call = functionCall(enumDesc, [fileDesc, ...pathInFileDesc(desc)]);
147
- f.print(f.exportDecl("const", name), " = ", pure);
148
- f.print(" ", call, ";");
149
- f.print();
150
- }
151
- // declare TypeScript enum
152
- {
153
- f.print(f.jsDoc(desc));
154
- const { tsEnum } = f.runtime.codegen;
155
- const call = functionCall(tsEnum, [f.importDesc(desc)]);
156
- f.print(f.exportDecl("const", f.importShape(desc).name), " = ", pure);
157
- f.print(" ", call, ";");
158
- f.print();
159
- }
160
- break;
161
- }
162
- case "extension": {
163
- const { extDesc } = f.runtime.codegen;
164
- const name = f.importDesc(desc).name;
165
- const call = functionCall(extDesc, [f.importDesc(desc.file), ...pathInFileDesc(desc)]);
166
- f.print(f.jsDoc(desc));
167
- f.print(f.exportDecl("const", name), " = ", pure);
168
- f.print(" ", call, ";");
169
- f.print();
170
- break;
171
- }
172
- case "service": {
173
- const { serviceDesc} = f.runtime.codegen;
174
- const name = f.importDesc(desc).name;
175
- f.print(f.jsDoc(desc));
176
- const call = functionCall(serviceDesc, [f.importDesc(desc.file), ...pathInFileDesc(desc)]);
177
- f.print(f.exportDecl("const", name), " = ", pure);
178
- f.print(" ", call, ";");
179
- f.print();
180
- break;
181
- }
182
- }
183
- }
184
- }
185
- }
186
-
187
- // prettier-ignore
188
- function generateDts(schema: Schema) {
189
- for (const file of schema.files) {
190
- const f = schema.generateFile(file.name + "_pb.d.ts");
191
- f.preamble(file);
192
- const { GenDescFile } = f.runtime.codegen;
193
- const fileDesc = f.importDesc(file);
194
- f.print(f.exportDecl("declare const", fileDesc.name), ": ", GenDescFile, ";");
195
- f.print();
196
- for (const desc of schema.typesInFile(file)) {
197
- switch (desc.kind) {
198
- case "message": {
199
- generateMessageShape(f, desc, "dts");
200
- const { GenDescMessage } = f.runtime.codegen;
201
- const MessageShape = f.importShape(desc);
202
- const name = f.importDesc(desc).name;
203
- f.print("// Describes the ", desc.toString(), ". Use `create(", name, ")` to create a new ", MessageShape.name, ".");
204
- f.print(f.exportDecl("declare const", name), ": ", GenDescMessage, "<", MessageShape, ">", ";");
205
- f.print();
206
- break;
207
- }
208
- case "enum": {
209
- generateEnumShape(f, desc);
210
- const { GenDescEnum } = f.runtime.codegen;
211
- const EnumShape = f.importShape(desc);
212
- f.print("// Describes the ", desc.toString(), ".");
213
- const name = f.importDesc(desc).name;
214
- f.print(f.exportDecl("declare const", name), ": ", GenDescEnum, "<", EnumShape, ">;");
215
- f.print();
216
- break;
217
- }
218
- case "extension": {
219
- const { GenDescExtension } = f.runtime.codegen;
220
- const name = f.importDesc(desc).name;
221
- const E = f.importShape(desc.extendee);
222
- const V = getFieldTypeInfo(desc).typing;
223
- f.print(f.jsDoc(desc));
224
- f.print(f.exportDecl("declare const", name), ": ", GenDescExtension, "<", E, ", ", V, ">;");
225
- f.print();
226
- break;
227
- }
228
- case "service": {
229
- const { GenDescService } = f.runtime.codegen;
230
- const name = f.importDesc(desc).name;
231
- f.print(f.jsDoc(desc));
232
- f.print(f.exportDecl("declare const", name), ": ", GenDescService, "<", getServiceShapeExpr(f, desc), ">;");
233
- f.print();
234
- break;
235
- }
236
- }
237
- }
238
- }
239
- }
240
-
241
- // prettier-ignore
242
- function getFileDescCall(f: GeneratedFile, file: DescFile) {
243
- const info = embedFileDesc(file);
244
- if (info.bootable && !f.runtime.create.from.startsWith("@bufbuild/protobuf")) {
245
- // google/protobuf/descriptor.proto is embedded as a plain object when
246
- // bootstrapping to avoid recursion
247
- return functionCall(f.runtime.codegen.boot, [JSON.stringify(info.boot())]);
248
- }
249
- const { fileDesc } = f.runtime.codegen;
250
- if (file.dependencies.length > 0) {
251
- const deps: Printable = file.dependencies.map((f) => ({
252
- kind: "es_desc_ref",
253
- desc: f,
254
- }));
255
- return functionCall(fileDesc, [
256
- f.string(info.base64()),
257
- arrayLiteral(deps),
258
- ]);
259
- }
260
- return functionCall(fileDesc, [f.string(info.base64())]);
261
- }
262
-
263
- // prettier-ignore
264
- function getServiceShapeExpr(f: GeneratedFile, service: DescService): Printable {
265
- const p: Printable[] = [];
266
- function print(...printables: Printable[]) {
267
- p.push(...printables, "\n");
268
- }
269
- print("{");
270
- for (const method of service.methods) {
271
- print(f.jsDoc(method, " "));
272
- print(" ", localName(method), ": {");
273
- print(" kind: ", f.string(method.methodKind), ";");
274
- print(" I: ", f.importShape(method.input), ";");
275
- print(" O: ", f.importShape(method.output), ";");
276
- print(" },");
277
- }
278
- print("}");
279
- return p;
280
- }
281
-
282
- // prettier-ignore
283
- function generateEnumShape(f: GeneratedFile, enumeration: DescEnum) {
284
- f.print(f.jsDoc(enumeration));
285
- f.print(f.exportDecl("enum", f.importShape(enumeration).name), " {");
286
- for (const value of enumeration.values) {
287
- if (enumeration.values.indexOf(value) > 0) {
288
- f.print();
289
- }
290
- f.print(f.jsDoc(value, " "));
291
- f.print(" ", localName(value), " = ", value.number, ",");
292
- }
293
- f.print("}");
294
- f.print();
295
- }
296
-
297
- // prettier-ignore
298
- function generateMessageShape(f: GeneratedFile, message: DescMessage, target: Extract<Target, "ts" | "dts">) {
299
- const { Message } = f.runtime;
300
- const declaration = target == "ts" ? "type" : "declare type";
301
- f.print(f.jsDoc(message));
302
- f.print(f.exportDecl(declaration, f.importShape(message).name), " = ", Message, "<", f.string(message.typeName), "> & {");
303
- for (const member of message.members) {
304
- switch (member.kind) {
305
- case "oneof":
306
- f.print(f.jsDoc(member, " "));
307
- f.print(" ", localName(member), ": {");
308
- for (const field of member.fields) {
309
- if (member.fields.indexOf(field) > 0) {
310
- f.print(` } | {`);
311
- }
312
- f.print(f.jsDoc(field, " "));
313
- const { typing } = getFieldTypeInfo(field);
314
- f.print(` value: `, typing, `;`);
315
- f.print(` case: "`, localName(field), `";`);
316
- }
317
- f.print(` } | { case: undefined; value?: undefined };`);
318
- break;
319
- default: {
320
- f.print(f.jsDoc(member, " "));
321
- const {typing, optional} = getFieldTypeInfo(member);
322
- if (fieldUsesPrototype(member) || !optional) {
323
- f.print(" ", localName(member), ": ", typing, ";");
324
- } else {
325
- f.print(" ", localName(member), "?: ", typing, ";");
326
- }
327
- break;
328
- }
329
- }
330
- if (message.members.indexOf(member) < message.members.length - 1) {
331
- f.print();
332
- }
333
- }
334
- f.print("};");
335
- f.print();
336
- }
package/src/util.ts DELETED
@@ -1,176 +0,0 @@
1
- // Copyright 2021-2024 Buf Technologies, Inc.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
14
-
15
- import type { DescExtension, DescField } from "@bufbuild/protobuf";
16
- import {
17
- LongType,
18
- ScalarType,
19
- scalarTypeScriptType,
20
- } from "@bufbuild/protobuf/reflect";
21
- import { Edition, isWrapperDesc } from "@bufbuild/protobuf/wkt";
22
- import type { Printable } from "@bufbuild/protoplugin/ecmascript";
23
-
24
- /**
25
- * Tells whether a field uses the prototype chain for field presence.
26
- * Behavior must match with the counterpart in @bufbuild/protobuf.
27
- */
28
- export function fieldUsesPrototype(field: DescField): field is DescField & {
29
- fieldKind: "scalar" | "enum";
30
- oneof: undefined;
31
- repeated: false;
32
- } {
33
- if (field.parent.file.edition != Edition.EDITION_PROTO2) {
34
- return false;
35
- }
36
- if (field.fieldKind != "scalar" && field.fieldKind != "enum") {
37
- return false;
38
- }
39
- if (field.oneof) {
40
- return false;
41
- }
42
- // proto2 singular scalar and enum fields use an initial value on the prototype chain
43
- return true;
44
- }
45
-
46
- export function getFieldTypeInfo(field: DescField | DescExtension): {
47
- typing: Printable;
48
- optional: boolean;
49
- typingInferrableFromZeroValue: boolean;
50
- } {
51
- const typing: Printable = [];
52
- let typingInferrableFromZeroValue: boolean;
53
- let optional = false;
54
- switch (field.fieldKind) {
55
- case "scalar":
56
- typing.push(scalarTypeScriptType(field.scalar, field.longType));
57
- optional = field.optional;
58
- typingInferrableFromZeroValue = true;
59
- break;
60
- case "message": {
61
- if (!field.oneof && isWrapperDesc(field.message)) {
62
- const baseType = field.message.fields[0].scalar;
63
- typing.push(scalarTypeScriptType(baseType, LongType.BIGINT));
64
- } else {
65
- typing.push({
66
- kind: "es_shape_ref",
67
- desc: field.message,
68
- });
69
- }
70
- optional = true;
71
- typingInferrableFromZeroValue = true;
72
- break;
73
- }
74
- case "enum":
75
- typing.push({
76
- kind: "es_shape_ref",
77
- desc: field.enum,
78
- });
79
- optional = field.optional;
80
- typingInferrableFromZeroValue = true;
81
- break;
82
- case "list":
83
- optional = false;
84
- typingInferrableFromZeroValue = false;
85
- switch (field.listKind) {
86
- case "enum":
87
- typing.push(
88
- {
89
- kind: "es_shape_ref",
90
- desc: field.enum,
91
- },
92
- "[]",
93
- );
94
- break;
95
- case "scalar":
96
- typing.push(scalarTypeScriptType(field.scalar, field.longType), "[]");
97
- break;
98
- case "message": {
99
- typing.push(
100
- {
101
- kind: "es_shape_ref",
102
- desc: field.message,
103
- },
104
- "[]",
105
- );
106
- break;
107
- }
108
- }
109
- break;
110
- case "map": {
111
- let keyType: string;
112
- switch (field.mapKey) {
113
- case ScalarType.INT32:
114
- case ScalarType.FIXED32:
115
- case ScalarType.UINT32:
116
- case ScalarType.SFIXED32:
117
- case ScalarType.SINT32:
118
- keyType = "number";
119
- break;
120
- default:
121
- keyType = "string";
122
- break;
123
- }
124
- let valueType: Printable;
125
- switch (field.mapKind) {
126
- case "scalar":
127
- valueType = scalarTypeScriptType(field.scalar, LongType.BIGINT);
128
- break;
129
- case "message":
130
- valueType = {
131
- kind: "es_shape_ref",
132
- desc: field.message,
133
- };
134
- break;
135
- case "enum":
136
- valueType = {
137
- kind: "es_shape_ref",
138
- desc: field.enum,
139
- };
140
- break;
141
- }
142
- typing.push("{ [key: ", keyType, "]: ", valueType, " }");
143
- typingInferrableFromZeroValue = false;
144
- optional = false;
145
- break;
146
- }
147
- }
148
- return { typing, optional, typingInferrableFromZeroValue };
149
- }
150
-
151
- export function functionCall(
152
- fn: Printable,
153
- args: Printable[],
154
- typeParams?: Printable[],
155
- ): Printable {
156
- let tp: Printable = [];
157
- if (typeParams !== undefined && typeParams.length > 0) {
158
- tp = ["<", commaSeparate(typeParams), ">"];
159
- }
160
- return [fn, ...tp, "(", commaSeparate(args), ")"];
161
- }
162
-
163
- export function arrayLiteral(elements: Printable[]): Printable {
164
- return ["[", commaSeparate(elements), "]"];
165
- }
166
-
167
- function commaSeparate(elements: Printable[]): Printable {
168
- const r: Printable[] = [];
169
- for (let i = 0; i < elements.length; i++) {
170
- r.push(elements[i]);
171
- if (i < elements.length - 1) {
172
- r.push(", ");
173
- }
174
- }
175
- return r;
176
- }
package/tsconfig.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "files": ["src/protoc-gen-es-plugin.ts"],
3
- "extends": "../../tsconfig.base.json",
4
- "compilerOptions": {
5
- // We import the plugin's version number from package.json
6
- "resolveJsonModule": true,
7
- // This package is CommonJS
8
- "verbatimModuleSyntax": false,
9
- "module": "CommonJS",
10
- "moduleResolution": "Node10"
11
- }
12
- }