@bufbuild/protoc-gen-es 1.5.1 → 1.7.0

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
@@ -98,12 +98,25 @@ By default, [protoc-gen-es](https://www.npmjs.com/package/@bufbuild/protoc-gen-e
98
98
  uses a `.js` file extensions in import paths, even in TypeScript files.
99
99
 
100
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
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
103
103
  in import paths with the given value. For example, set
104
104
 
105
- - `import_extension=none` to remove the `.js` extension
106
- - `import_extension=.ts` to replace the `.js` extension with `.ts`
105
+ - `import_extension=none` to remove the `.js` extension.
106
+ - `import_extension=.ts` to replace the `.js` extension with `.ts`.
107
+
108
+ ### `js_import_style`
109
+
110
+ By default, [protoc-gen-es](https://www.npmjs.com/package/@bufbuild/protoc-gen-es)
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
114
+ `require()` calls.
115
+
116
+ Possible values:
117
+ - `js_import_style=module` generate ECMAScript `import` / `export` statements -
118
+ the default behavior.
119
+ - `js_import_style=legacy_commonjs` generate CommonJS `require()` calls.
107
120
 
108
121
 
109
122
  ### `keep_empty_files=true`
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bufbuild/protoc-gen-es",
3
- "version": "1.5.1",
3
+ "version": "1.7.0",
4
4
  "description": "Protocol Buffers code generator for ECMAScript",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -20,11 +20,11 @@
20
20
  },
21
21
  "preferUnplugged": true,
22
22
  "dependencies": {
23
- "@bufbuild/protobuf": "^1.5.1",
24
- "@bufbuild/protoplugin": "1.5.1"
23
+ "@bufbuild/protobuf": "^1.7.0",
24
+ "@bufbuild/protoplugin": "1.7.0"
25
25
  },
26
26
  "peerDependencies": {
27
- "@bufbuild/protobuf": "1.5.1"
27
+ "@bufbuild/protobuf": "1.7.0"
28
28
  },
29
29
  "peerDependenciesMeta": {
30
30
  "@bufbuild/protobuf": {
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- // Copyright 2021-2023 Buf Technologies, Inc.
2
+ // Copyright 2021-2024 Buf Technologies, Inc.
3
3
  //
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // you may not use this file except in compliance with the License.
@@ -26,19 +26,22 @@ function generateDts(schema) {
26
26
  for (const message of file.messages) {
27
27
  generateMessage(schema, f, message);
28
28
  }
29
- // We do not generate anything for services, and we do not support extensions at this time
29
+ for (const extension of file.extensions) {
30
+ generateExtension(schema, f, extension);
31
+ }
32
+ // We do not generate anything for services
30
33
  }
31
34
  }
32
35
  exports.generateDts = generateDts;
33
36
  // prettier-ignore
34
37
  function generateEnum(schema, f, enumeration) {
35
- f.print((0, ecmascript_1.makeJsDoc)(enumeration));
38
+ f.print(f.jsDoc(enumeration));
36
39
  f.print("export declare enum ", enumeration, " {");
37
40
  for (const value of enumeration.values) {
38
41
  if (enumeration.values.indexOf(value) > 0) {
39
42
  f.print();
40
43
  }
41
- f.print((0, ecmascript_1.makeJsDoc)(value, " "));
44
+ f.print(f.jsDoc(value, " "));
42
45
  f.print(" ", (0, ecmascript_1.localName)(value), " = ", value.number, ",");
43
46
  }
44
47
  f.print("}");
@@ -48,7 +51,7 @@ function generateEnum(schema, f, enumeration) {
48
51
  function generateMessage(schema, f, message) {
49
52
  const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, message.file);
50
53
  const { PartialMessage, FieldList, Message, PlainMessage, BinaryReadOptions, JsonReadOptions, JsonValue } = schema.runtime;
51
- f.print((0, ecmascript_1.makeJsDoc)(message));
54
+ f.print(f.jsDoc(message));
52
55
  f.print("export declare class ", message, " extends ", Message, "<", message, "> {");
53
56
  for (const member of message.members) {
54
57
  switch (member.kind) {
@@ -65,7 +68,7 @@ function generateMessage(schema, f, message) {
65
68
  f.print();
66
69
  generateWktMethods(schema, f, message);
67
70
  f.print(" static readonly runtime: typeof ", protoN, ";");
68
- f.print(' static readonly typeName = ', (0, ecmascript_1.literalString)(message.typeName), ';');
71
+ f.print(' static readonly typeName = ', f.string(message.typeName), ';');
69
72
  f.print(" static readonly fields: ", FieldList, ";");
70
73
  // In case we start supporting options, we have to surface them here
71
74
  //f.print(" static readonly options: { readonly [extensionName: string]: ", rt.JsonValue, " } = {};")
@@ -86,17 +89,19 @@ function generateMessage(schema, f, message) {
86
89
  for (const nestedMessage of message.nestedMessages) {
87
90
  generateMessage(schema, f, nestedMessage);
88
91
  }
89
- // We do not support extensions at this time
92
+ for (const nestedExtension of message.nestedExtensions) {
93
+ generateExtension(schema, f, nestedExtension);
94
+ }
90
95
  }
91
96
  // prettier-ignore
92
97
  function generateOneof(schema, f, oneof) {
93
- f.print((0, ecmascript_1.makeJsDoc)(oneof, " "));
98
+ f.print(f.jsDoc(oneof, " "));
94
99
  f.print(" ", (0, ecmascript_1.localName)(oneof), ": {");
95
100
  for (const field of oneof.fields) {
96
101
  if (oneof.fields.indexOf(field) > 0) {
97
102
  f.print(` } | {`);
98
103
  }
99
- f.print((0, ecmascript_1.makeJsDoc)(field, " "));
104
+ f.print(f.jsDoc(field, " "));
100
105
  const { typing } = (0, ecmascript_1.getFieldTyping)(field, f);
101
106
  f.print(` value: `, typing, `;`);
102
107
  f.print(` case: "`, (0, ecmascript_1.localName)(field), `";`);
@@ -104,7 +109,7 @@ function generateOneof(schema, f, oneof) {
104
109
  f.print(` } | { case: undefined; value?: undefined };`);
105
110
  }
106
111
  function generateField(schema, f, field) {
107
- f.print((0, ecmascript_1.makeJsDoc)(field, " "));
112
+ f.print(f.jsDoc(field, " "));
108
113
  const e = [];
109
114
  e.push(" ", (0, ecmascript_1.localName)(field));
110
115
  const { typing, optional } = (0, ecmascript_1.getFieldTyping)(field, f);
@@ -118,6 +123,13 @@ function generateField(schema, f, field) {
118
123
  f.print(e);
119
124
  }
120
125
  // prettier-ignore
126
+ function generateExtension(schema, f, ext) {
127
+ const { typing } = (0, ecmascript_1.getFieldTyping)(ext, f);
128
+ f.print(f.jsDoc(ext));
129
+ f.print(f.exportDecl("declare const", ext), ": ", schema.runtime.Extension, "<", ext.extendee, ", ", typing, ">;");
130
+ f.print();
131
+ }
132
+ // prettier-ignore
121
133
  function generateWktMethods(schema, f, message) {
122
134
  const ref = (0, ecmascript_1.reifyWkt)(message);
123
135
  if (ref === undefined) {
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- // Copyright 2021-2023 Buf Technologies, Inc.
2
+ // Copyright 2021-2024 Buf Technologies, Inc.
3
3
  //
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- // Copyright 2021-2023 Buf Technologies, Inc.
2
+ // Copyright 2021-2024 Buf Technologies, Inc.
3
3
  //
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
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.generateFieldInfo = exports.generateJs = void 0;
16
+ exports.getFieldInfoLiteral = exports.generateFieldInfo = exports.generateJs = void 0;
17
17
  const protobuf_1 = require("@bufbuild/protobuf");
18
18
  const ecmascript_1 = require("@bufbuild/protoplugin/ecmascript");
19
19
  const editions_js_1 = require("./editions.js");
@@ -27,26 +27,29 @@ function generateJs(schema) {
27
27
  for (const message of file.messages) {
28
28
  generateMessage(schema, f, message);
29
29
  }
30
- // We do not generate anything for services, and we do not support extensions at this time
30
+ for (const extension of file.extensions) {
31
+ generateExtension(schema, f, extension);
32
+ }
33
+ // We do not generate anything for services
31
34
  }
32
35
  }
33
36
  exports.generateJs = generateJs;
34
37
  // prettier-ignore
35
38
  function generateEnum(schema, f, enumeration) {
36
39
  const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, enumeration.file);
37
- f.print((0, ecmascript_1.makeJsDoc)(enumeration));
38
- f.print("export const ", enumeration, " = ", protoN, ".makeEnum(");
40
+ f.print(f.jsDoc(enumeration));
41
+ f.print(f.exportDecl("const", enumeration), " = ", protoN, ".makeEnum(");
39
42
  f.print(` "`, enumeration.typeName, `",`);
40
43
  f.print(` [`);
41
44
  if (enumeration.sharedPrefix === undefined) {
42
45
  for (const value of enumeration.values) {
43
- f.print(" {no: ", value.number, ", name: ", (0, ecmascript_1.literalString)(value.name), "},");
46
+ f.print(" {no: ", value.number, ", name: ", f.string(value.name), "},");
44
47
  }
45
48
  }
46
49
  else {
47
50
  for (const value of enumeration.values) {
48
51
  const localName = value.name.substring(enumeration.sharedPrefix.length);
49
- f.print(" {no: ", value.number, ", name: ", (0, ecmascript_1.literalString)(value.name), ", localName: ", (0, ecmascript_1.literalString)(localName), "},");
52
+ f.print(" {no: ", value.number, ", name: ", f.string(value.name), ", localName: ", f.string(localName), "},");
50
53
  }
51
54
  }
52
55
  f.print(` ],`);
@@ -56,9 +59,9 @@ function generateEnum(schema, f, enumeration) {
56
59
  // prettier-ignore
57
60
  function generateMessage(schema, f, message) {
58
61
  const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, message.file);
59
- f.print((0, ecmascript_1.makeJsDoc)(message));
60
- f.print("export const ", message, " = ", protoN, ".makeMessageType(");
61
- f.print(` `, (0, ecmascript_1.literalString)(message.typeName), `,`);
62
+ f.print(f.jsDoc(message));
63
+ f.print(f.exportDecl("const", message), " = ", protoN, ".makeMessageType(");
64
+ f.print(` `, f.string(message.typeName), `,`);
62
65
  if (message.fields.length == 0) {
63
66
  f.print(" [],");
64
67
  }
@@ -74,7 +77,7 @@ function generateMessage(schema, f, message) {
74
77
  .makeMessageType(message.typeName, []).name;
75
78
  if (needsLocalName) {
76
79
  // local name is not inferrable from the type name, we need to provide it
77
- f.print(` {localName: `, (0, ecmascript_1.literalString)((0, ecmascript_1.localName)(message)), `},`);
80
+ f.print(` {localName: `, f.string((0, ecmascript_1.localName)(message)), `},`);
78
81
  }
79
82
  f.print(");");
80
83
  f.print();
@@ -86,15 +89,25 @@ function generateMessage(schema, f, message) {
86
89
  for (const nestedMessage of message.nestedMessages) {
87
90
  generateMessage(schema, f, nestedMessage);
88
91
  }
89
- // We do not support extensions at this time
92
+ for (const nestedExtension of message.nestedExtensions) {
93
+ generateExtension(schema, f, nestedExtension);
94
+ }
90
95
  }
91
96
  // prettier-ignore
92
97
  function generateFieldInfo(schema, f, field) {
93
- const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, field.parent.file);
98
+ f.print(" ", getFieldInfoLiteral(schema, field), ",");
99
+ }
100
+ exports.generateFieldInfo = generateFieldInfo;
101
+ // prettier-ignore
102
+ function getFieldInfoLiteral(schema, field) {
103
+ const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, field.kind == "extension" ? field.file : field.parent.file);
94
104
  const e = [];
95
- e.push(" { no: ", field.number, `, name: "`, field.name, `", `);
96
- if (field.jsonName !== undefined) {
97
- e.push(`jsonName: "`, field.jsonName, `", `);
105
+ e.push("{ no: ", field.number, `, `);
106
+ if (field.kind == "field") {
107
+ e.push(`name: "`, field.name, `", `);
108
+ if (field.jsonName !== undefined) {
109
+ e.push(`jsonName: "`, field.jsonName, `", `);
110
+ }
98
111
  }
99
112
  switch (field.fieldKind) {
100
113
  case "scalar":
@@ -147,10 +160,26 @@ function generateFieldInfo(schema, f, field) {
147
160
  if (typeof lastE == "string" && lastE.endsWith(", ")) {
148
161
  e[e.length - 1] = lastE.substring(0, lastE.length - 2);
149
162
  }
150
- e.push(" },");
151
- f.print(...e);
163
+ e.push(" }");
164
+ return e;
165
+ }
166
+ exports.getFieldInfoLiteral = getFieldInfoLiteral;
167
+ // prettier-ignore
168
+ function generateExtension(schema, f, ext) {
169
+ const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, ext.file);
170
+ f.print(f.jsDoc(ext));
171
+ f.print(f.exportDecl("const", ext), " = ", protoN, ".makeExtension(");
172
+ f.print(" ", f.string(ext.typeName), ", ");
173
+ f.print(" ", ext.extendee, ", ");
174
+ if (ext.fieldKind == "scalar") {
175
+ f.print(" ", getFieldInfoLiteral(schema, ext), ",");
176
+ }
177
+ else {
178
+ f.print(" () => (", getFieldInfoLiteral(schema, ext), "),");
179
+ }
180
+ f.print(");");
181
+ f.print();
152
182
  }
153
- exports.generateFieldInfo = generateFieldInfo;
154
183
  // prettier-ignore
155
184
  function generateWktMethods(schema, f, message) {
156
185
  var _a;
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- // Copyright 2021-2023 Buf Technologies, Inc.
2
+ // Copyright 2021-2024 Buf Technologies, Inc.
3
3
  //
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- // Copyright 2021-2023 Buf Technologies, Inc.
2
+ // Copyright 2021-2024 Buf Technologies, Inc.
3
3
  //
4
4
  // Licensed under the Apache License, Version 2.0 (the "License");
5
5
  // you may not use this file except in compliance with the License.
@@ -28,20 +28,23 @@ function generateTs(schema) {
28
28
  for (const message of file.messages) {
29
29
  generateMessage(schema, f, message);
30
30
  }
31
- // We do not generate anything for services, and we do not support extensions at this time
31
+ for (const extension of file.extensions) {
32
+ generateExtension(schema, f, extension);
33
+ }
34
+ // We do not generate anything for services
32
35
  }
33
36
  }
34
37
  exports.generateTs = generateTs;
35
38
  // prettier-ignore
36
39
  function generateEnum(schema, f, enumeration) {
37
40
  const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, enumeration.file);
38
- f.print((0, ecmascript_1.makeJsDoc)(enumeration));
39
- f.print("export enum ", enumeration, " {");
41
+ f.print(f.jsDoc(enumeration));
42
+ f.print(f.exportDecl("enum", enumeration), " {");
40
43
  for (const value of enumeration.values) {
41
44
  if (enumeration.values.indexOf(value) > 0) {
42
45
  f.print();
43
46
  }
44
- f.print((0, ecmascript_1.makeJsDoc)(value, " "));
47
+ f.print(f.jsDoc(value, " "));
45
48
  f.print(" ", (0, ecmascript_1.localName)(value), " = ", value.number, ",");
46
49
  }
47
50
  f.print("}");
@@ -57,8 +60,8 @@ function generateEnum(schema, f, enumeration) {
57
60
  function generateMessage(schema, f, message) {
58
61
  const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, message.file);
59
62
  const { PartialMessage, FieldList, Message, PlainMessage, BinaryReadOptions, JsonReadOptions, JsonValue } = schema.runtime;
60
- f.print((0, ecmascript_1.makeJsDoc)(message));
61
- f.print("export class ", message, " extends ", Message, "<", message, "> {");
63
+ f.print(f.jsDoc(message));
64
+ f.print(f.exportDecl("class", message), " extends ", Message, "<", message, "> {");
62
65
  for (const member of message.members) {
63
66
  switch (member.kind) {
64
67
  case "oneof":
@@ -77,7 +80,7 @@ function generateMessage(schema, f, message) {
77
80
  f.print();
78
81
  generateWktMethods(schema, f, message);
79
82
  f.print(" static readonly runtime: typeof ", protoN, " = ", protoN, ";");
80
- f.print(' static readonly typeName = ', (0, ecmascript_1.literalString)(message.typeName), ';');
83
+ f.print(' static readonly typeName = ', f.string(message.typeName), ';');
81
84
  f.print(" static readonly fields: ", FieldList, " = ", protoN, ".util.newFieldList(() => [");
82
85
  for (const field of message.fields) {
83
86
  (0, javascript_js_1.generateFieldInfo)(schema, f, field);
@@ -110,17 +113,19 @@ function generateMessage(schema, f, message) {
110
113
  for (const nestedMessage of message.nestedMessages) {
111
114
  generateMessage(schema, f, nestedMessage);
112
115
  }
113
- // We do not support extensions at this time
116
+ for (const nestedExtension of message.nestedExtensions) {
117
+ generateExtension(schema, f, nestedExtension);
118
+ }
114
119
  }
115
120
  // prettier-ignore
116
121
  function generateOneof(schema, f, oneof) {
117
- f.print((0, ecmascript_1.makeJsDoc)(oneof, " "));
122
+ f.print(f.jsDoc(oneof, " "));
118
123
  f.print(" ", (0, ecmascript_1.localName)(oneof), ": {");
119
124
  for (const field of oneof.fields) {
120
125
  if (oneof.fields.indexOf(field) > 0) {
121
126
  f.print(` } | {`);
122
127
  }
123
- f.print((0, ecmascript_1.makeJsDoc)(field, " "));
128
+ f.print(f.jsDoc(field, " "));
124
129
  const { typing } = (0, ecmascript_1.getFieldTyping)(field, f);
125
130
  f.print(` value: `, typing, `;`);
126
131
  f.print(` case: "`, (0, ecmascript_1.localName)(field), `";`);
@@ -128,7 +133,7 @@ function generateOneof(schema, f, oneof) {
128
133
  f.print(` } | { case: undefined; value?: undefined } = { case: undefined };`);
129
134
  }
130
135
  function generateField(schema, f, field) {
131
- f.print((0, ecmascript_1.makeJsDoc)(field, " "));
136
+ f.print(f.jsDoc(field, " "));
132
137
  const e = [];
133
138
  e.push(" ", (0, ecmascript_1.localName)(field));
134
139
  const { defaultValue, typingInferrable } = (0, ecmascript_1.getFieldIntrinsicDefaultValue)(field);
@@ -146,6 +151,23 @@ function generateField(schema, f, field) {
146
151
  f.print(e);
147
152
  }
148
153
  // prettier-ignore
154
+ function generateExtension(schema, f, ext) {
155
+ const protoN = (0, editions_js_1.getNonEditionRuntime)(schema, ext.file);
156
+ const { typing } = (0, ecmascript_1.getFieldTyping)(ext, f);
157
+ f.print(f.jsDoc(ext));
158
+ f.print(f.exportDecl("const", ext), " = ", protoN, ".makeExtension<", ext.extendee, ", ", typing, ">(");
159
+ f.print(" ", f.string(ext.typeName), ", ");
160
+ f.print(" ", ext.extendee, ", ");
161
+ if (ext.fieldKind == "scalar") {
162
+ f.print(" ", (0, javascript_js_1.getFieldInfoLiteral)(schema, ext), ",");
163
+ }
164
+ else {
165
+ f.print(" () => (", (0, javascript_js_1.getFieldInfoLiteral)(schema, ext), "),");
166
+ }
167
+ f.print(");");
168
+ f.print();
169
+ }
170
+ // prettier-ignore
149
171
  function generateWktMethods(schema, f, message) {
150
172
  var _a;
151
173
  const ref = (0, ecmascript_1.reifyWkt)(message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bufbuild/protoc-gen-es",
3
- "version": "1.5.1",
3
+ "version": "1.7.0",
4
4
  "description": "Protocol Buffers code generator for ECMAScript",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -20,11 +20,11 @@
20
20
  },
21
21
  "preferUnplugged": true,
22
22
  "dependencies": {
23
- "@bufbuild/protobuf": "^1.5.1",
24
- "@bufbuild/protoplugin": "1.5.1"
23
+ "@bufbuild/protobuf": "^1.7.0",
24
+ "@bufbuild/protoplugin": "1.7.0"
25
25
  },
26
26
  "peerDependencies": {
27
- "@bufbuild/protobuf": "1.5.1"
27
+ "@bufbuild/protobuf": "1.7.0"
28
28
  },
29
29
  "peerDependenciesMeta": {
30
30
  "@bufbuild/protobuf": {
@@ -1,4 +1,4 @@
1
- // Copyright 2021-2023 Buf Technologies, Inc.
1
+ // Copyright 2021-2024 Buf Technologies, Inc.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ import type {
18
18
  DescMessage,
19
19
  DescOneof,
20
20
  } from "@bufbuild/protobuf";
21
+ import { DescExtension } from "@bufbuild/protobuf";
21
22
  import type {
22
23
  GeneratedFile,
23
24
  Printable,
@@ -25,9 +26,7 @@ import type {
25
26
  } from "@bufbuild/protoplugin/ecmascript";
26
27
  import {
27
28
  getFieldTyping,
28
- literalString,
29
29
  localName,
30
- makeJsDoc,
31
30
  reifyWkt,
32
31
  } from "@bufbuild/protoplugin/ecmascript";
33
32
  import { getNonEditionRuntime } from "./editions.js";
@@ -42,19 +41,22 @@ export function generateDts(schema: Schema) {
42
41
  for (const message of file.messages) {
43
42
  generateMessage(schema, f, message);
44
43
  }
45
- // We do not generate anything for services, and we do not support extensions at this time
44
+ for (const extension of file.extensions) {
45
+ generateExtension(schema, f, extension);
46
+ }
47
+ // We do not generate anything for services
46
48
  }
47
49
  }
48
50
 
49
51
  // prettier-ignore
50
52
  function generateEnum(schema: Schema, f: GeneratedFile, enumeration: DescEnum) {
51
- f.print(makeJsDoc(enumeration));
53
+ f.print(f.jsDoc(enumeration));
52
54
  f.print("export declare enum ", enumeration, " {");
53
55
  for (const value of enumeration.values) {
54
56
  if (enumeration.values.indexOf(value) > 0) {
55
57
  f.print();
56
58
  }
57
- f.print(makeJsDoc(value, " "));
59
+ f.print(f.jsDoc(value, " "));
58
60
  f.print(" ", localName(value), " = ", value.number, ",");
59
61
  }
60
62
  f.print("}");
@@ -73,7 +75,7 @@ function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage)
73
75
  JsonReadOptions,
74
76
  JsonValue
75
77
  } = schema.runtime;
76
- f.print(makeJsDoc(message));
78
+ f.print(f.jsDoc(message));
77
79
  f.print("export declare class ", message, " extends ", Message, "<", message, "> {");
78
80
  for (const member of message.members) {
79
81
  switch (member.kind) {
@@ -90,7 +92,7 @@ function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage)
90
92
  f.print();
91
93
  generateWktMethods(schema, f, message);
92
94
  f.print(" static readonly runtime: typeof ", protoN, ";");
93
- f.print(' static readonly typeName = ', literalString(message.typeName), ';');
95
+ f.print(' static readonly typeName = ', f.string(message.typeName), ';');
94
96
  f.print(" static readonly fields: ", FieldList, ";");
95
97
  // In case we start supporting options, we have to surface them here
96
98
  //f.print(" static readonly options: { readonly [extensionName: string]: ", rt.JsonValue, " } = {};")
@@ -111,18 +113,20 @@ function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage)
111
113
  for (const nestedMessage of message.nestedMessages) {
112
114
  generateMessage(schema, f, nestedMessage);
113
115
  }
114
- // We do not support extensions at this time
116
+ for (const nestedExtension of message.nestedExtensions) {
117
+ generateExtension(schema, f, nestedExtension);
118
+ }
115
119
  }
116
120
 
117
121
  // prettier-ignore
118
122
  function generateOneof(schema: Schema, f: GeneratedFile, oneof: DescOneof) {
119
- f.print(makeJsDoc(oneof, " "));
123
+ f.print(f.jsDoc(oneof, " "));
120
124
  f.print(" ", localName(oneof), ": {");
121
125
  for (const field of oneof.fields) {
122
126
  if (oneof.fields.indexOf(field) > 0) {
123
127
  f.print(` } | {`);
124
128
  }
125
- f.print(makeJsDoc(field, " "));
129
+ f.print(f.jsDoc(field, " "));
126
130
  const { typing } = getFieldTyping(field, f);
127
131
  f.print(` value: `, typing, `;`);
128
132
  f.print(` case: "`, localName(field), `";`);
@@ -131,7 +135,7 @@ function generateOneof(schema: Schema, f: GeneratedFile, oneof: DescOneof) {
131
135
  }
132
136
 
133
137
  function generateField(schema: Schema, f: GeneratedFile, field: DescField) {
134
- f.print(makeJsDoc(field, " "));
138
+ f.print(f.jsDoc(field, " "));
135
139
  const e: Printable = [];
136
140
  e.push(" ", localName(field));
137
141
  const { typing, optional } = getFieldTyping(field, f);
@@ -144,6 +148,18 @@ function generateField(schema: Schema, f: GeneratedFile, field: DescField) {
144
148
  f.print(e);
145
149
  }
146
150
 
151
+ // prettier-ignore
152
+ function generateExtension(
153
+ schema: Schema,
154
+ f: GeneratedFile,
155
+ ext: DescExtension,
156
+ ) {
157
+ const { typing } = getFieldTyping(ext, f);
158
+ f.print(f.jsDoc(ext));
159
+ f.print(f.exportDecl("declare const", ext), ": ", schema.runtime.Extension, "<", ext.extendee, ", ", typing, ">;");
160
+ f.print();
161
+ }
162
+
147
163
  // prettier-ignore
148
164
  function generateWktMethods(schema: Schema, f: GeneratedFile, message: DescMessage) {
149
165
  const ref = reifyWkt(message);
package/src/editions.ts CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2021-2023 Buf Technologies, Inc.
1
+ // Copyright 2021-2024 Buf Technologies, Inc.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
package/src/javascript.ts CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2021-2023 Buf Technologies, Inc.
1
+ // Copyright 2021-2024 Buf Technologies, Inc.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -12,7 +12,12 @@
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
 
15
- import type { DescEnum, DescField, DescMessage } from "@bufbuild/protobuf";
15
+ import type {
16
+ DescEnum,
17
+ DescExtension,
18
+ DescField,
19
+ DescMessage,
20
+ } from "@bufbuild/protobuf";
16
21
  import {
17
22
  FieldDescriptorProto_Type,
18
23
  LongType,
@@ -27,9 +32,7 @@ import type {
27
32
  } from "@bufbuild/protoplugin/ecmascript";
28
33
  import {
29
34
  getFieldExplicitDefaultValue,
30
- literalString,
31
35
  localName,
32
- makeJsDoc,
33
36
  reifyWkt,
34
37
  } from "@bufbuild/protoplugin/ecmascript";
35
38
  import { getNonEditionRuntime } from "./editions.js";
@@ -44,25 +47,28 @@ export function generateJs(schema: Schema) {
44
47
  for (const message of file.messages) {
45
48
  generateMessage(schema, f, message);
46
49
  }
47
- // We do not generate anything for services, and we do not support extensions at this time
50
+ for (const extension of file.extensions) {
51
+ generateExtension(schema, f, extension);
52
+ }
53
+ // We do not generate anything for services
48
54
  }
49
55
  }
50
56
 
51
57
  // prettier-ignore
52
58
  function generateEnum(schema: Schema, f: GeneratedFile, enumeration: DescEnum) {
53
59
  const protoN = getNonEditionRuntime(schema, enumeration.file);
54
- f.print(makeJsDoc(enumeration));
55
- f.print("export const ", enumeration, " = ", protoN, ".makeEnum(")
60
+ f.print(f.jsDoc(enumeration));
61
+ f.print(f.exportDecl("const", enumeration), " = ", protoN, ".makeEnum(")
56
62
  f.print(` "`, enumeration.typeName, `",`)
57
63
  f.print(` [`)
58
64
  if (enumeration.sharedPrefix === undefined) {
59
65
  for (const value of enumeration.values) {
60
- f.print(" {no: ", value.number, ", name: ", literalString(value.name), "},")
66
+ f.print(" {no: ", value.number, ", name: ", f.string(value.name), "},")
61
67
  }
62
68
  } else {
63
69
  for (const value of enumeration.values) {
64
70
  const localName = value.name.substring(enumeration.sharedPrefix.length);
65
- f.print(" {no: ", value.number, ", name: ", literalString(value.name), ", localName: ", literalString(localName), "},")
71
+ f.print(" {no: ", value.number, ", name: ", f.string(value.name), ", localName: ", f.string(localName), "},")
66
72
  }
67
73
  }
68
74
  f.print(` ],`)
@@ -73,9 +79,9 @@ function generateEnum(schema: Schema, f: GeneratedFile, enumeration: DescEnum) {
73
79
  // prettier-ignore
74
80
  function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage) {
75
81
  const protoN = getNonEditionRuntime(schema, message.file);
76
- f.print(makeJsDoc(message));
77
- f.print("export const ", message, " = ", protoN, ".makeMessageType(")
78
- f.print(` `, literalString(message.typeName), `,`)
82
+ f.print(f.jsDoc(message));
83
+ f.print(f.exportDecl("const", message), " = ", protoN, ".makeMessageType(")
84
+ f.print(` `, f.string(message.typeName), `,`)
79
85
  if (message.fields.length == 0) {
80
86
  f.print(" [],")
81
87
  } else {
@@ -90,7 +96,7 @@ function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage)
90
96
  .makeMessageType(message.typeName, []).name;
91
97
  if (needsLocalName) {
92
98
  // local name is not inferrable from the type name, we need to provide it
93
- f.print(` {localName: `, literalString(localName(message)), `},`)
99
+ f.print(` {localName: `, f.string(localName(message)), `},`)
94
100
  }
95
101
  f.print(");")
96
102
  f.print()
@@ -102,22 +108,32 @@ function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage)
102
108
  for (const nestedMessage of message.nestedMessages) {
103
109
  generateMessage(schema, f, nestedMessage);
104
110
  }
105
- // We do not support extensions at this time
111
+ for (const nestedExtension of message.nestedExtensions) {
112
+ generateExtension(schema, f, nestedExtension);
113
+ }
114
+ }
115
+
116
+ // prettier-ignore
117
+ export function generateFieldInfo(schema: Schema, f: GeneratedFile, field: DescField | DescExtension) {
118
+ f.print(" ", getFieldInfoLiteral(schema, field), ",");
106
119
  }
107
120
 
108
121
  // prettier-ignore
109
- export function generateFieldInfo(schema: Schema, f: GeneratedFile, field: DescField) {
110
- const protoN = getNonEditionRuntime(schema, field.parent.file);
122
+ export function getFieldInfoLiteral(schema: Schema, field: DescField | DescExtension): Printable {
123
+ const protoN = getNonEditionRuntime(schema, field.kind == "extension" ? field.file : field.parent.file);
111
124
  const e: Printable = [];
112
- e.push(" { no: ", field.number, `, name: "`, field.name, `", `);
113
- if (field.jsonName !== undefined) {
114
- e.push(`jsonName: "`, field.jsonName, `", `);
125
+ e.push("{ no: ", field.number, `, `);
126
+ if (field.kind == "field") {
127
+ e.push(`name: "`, field.name, `", `);
128
+ if (field.jsonName !== undefined) {
129
+ e.push(`jsonName: "`, field.jsonName, `", `);
130
+ }
115
131
  }
116
132
  switch (field.fieldKind) {
117
133
  case "scalar":
118
134
  e.push(`kind: "scalar", T: `, field.scalar, ` /* ScalarType.`, ScalarType[field.scalar], ` */, `);
119
135
  if (field.longType != LongType.BIGINT) {
120
- e.push(`L: `, field.longType, ` /* LongType.`, LongType[field.longType], ` */, `);
136
+ e.push(`L: `, field.longType, ` /* LongType.`, LongType[field.longType], ` */, `);
121
137
  }
122
138
  break;
123
139
  case "map":
@@ -164,8 +180,28 @@ export function generateFieldInfo(schema: Schema, f: GeneratedFile, field: DescF
164
180
  if (typeof lastE == "string" && lastE.endsWith(", ")) {
165
181
  e[e.length - 1] = lastE.substring(0, lastE.length - 2);
166
182
  }
167
- e.push(" },");
168
- f.print(...e);
183
+ e.push(" }");
184
+ return e;
185
+ }
186
+
187
+ // prettier-ignore
188
+ function generateExtension(
189
+ schema: Schema,
190
+ f: GeneratedFile,
191
+ ext: DescExtension,
192
+ ) {
193
+ const protoN = getNonEditionRuntime(schema, ext.file);
194
+ f.print(f.jsDoc(ext));
195
+ f.print(f.exportDecl("const", ext), " = ", protoN, ".makeExtension(");
196
+ f.print(" ", f.string(ext.typeName), ", ");
197
+ f.print(" ", ext.extendee, ", ");
198
+ if (ext.fieldKind == "scalar") {
199
+ f.print(" ", getFieldInfoLiteral(schema, ext), ",");
200
+ } else {
201
+ f.print(" () => (", getFieldInfoLiteral(schema, ext), "),");
202
+ }
203
+ f.print(");");
204
+ f.print();
169
205
  }
170
206
 
171
207
  // prettier-ignore
@@ -1,4 +1,4 @@
1
- // Copyright 2021-2023 Buf Technologies, Inc.
1
+ // Copyright 2021-2024 Buf Technologies, Inc.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
package/src/typescript.ts CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2021-2023 Buf Technologies, Inc.
1
+ // Copyright 2021-2024 Buf Technologies, Inc.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
14
14
 
15
15
  import type {
16
16
  DescEnum,
17
+ DescExtension,
17
18
  DescField,
18
19
  DescMessage,
19
20
  DescOneof,
@@ -27,12 +28,10 @@ import type {
27
28
  import {
28
29
  getFieldIntrinsicDefaultValue,
29
30
  getFieldTyping,
30
- literalString,
31
31
  localName,
32
- makeJsDoc,
33
32
  reifyWkt,
34
33
  } from "@bufbuild/protoplugin/ecmascript";
35
- import { generateFieldInfo } from "./javascript.js";
34
+ import { generateFieldInfo, getFieldInfoLiteral } from "./javascript.js";
36
35
  import { getNonEditionRuntime } from "./editions.js";
37
36
 
38
37
  export function generateTs(schema: Schema) {
@@ -45,20 +44,23 @@ export function generateTs(schema: Schema) {
45
44
  for (const message of file.messages) {
46
45
  generateMessage(schema, f, message);
47
46
  }
48
- // We do not generate anything for services, and we do not support extensions at this time
47
+ for (const extension of file.extensions) {
48
+ generateExtension(schema, f, extension);
49
+ }
50
+ // We do not generate anything for services
49
51
  }
50
52
  }
51
53
 
52
54
  // prettier-ignore
53
55
  function generateEnum(schema: Schema, f: GeneratedFile, enumeration: DescEnum) {
54
56
  const protoN = getNonEditionRuntime(schema, enumeration.file);
55
- f.print(makeJsDoc(enumeration));
56
- f.print("export enum ", enumeration, " {");
57
+ f.print(f.jsDoc(enumeration));
58
+ f.print(f.exportDecl("enum", enumeration), " {");
57
59
  for (const value of enumeration.values) {
58
60
  if (enumeration.values.indexOf(value) > 0) {
59
61
  f.print();
60
62
  }
61
- f.print(makeJsDoc(value, " "));
63
+ f.print(f.jsDoc(value, " "));
62
64
  f.print(" ", localName(value), " = ", value.number, ",");
63
65
  }
64
66
  f.print("}");
@@ -83,8 +85,8 @@ function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage)
83
85
  JsonReadOptions,
84
86
  JsonValue
85
87
  } = schema.runtime;
86
- f.print(makeJsDoc(message));
87
- f.print("export class ", message, " extends ", Message, "<", message, "> {");
88
+ f.print(f.jsDoc(message));
89
+ f.print(f.exportDecl("class", message), " extends ", Message, "<", message, "> {");
88
90
  for (const member of message.members) {
89
91
  switch (member.kind) {
90
92
  case "oneof":
@@ -103,7 +105,7 @@ function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage)
103
105
  f.print();
104
106
  generateWktMethods(schema, f, message);
105
107
  f.print(" static readonly runtime: typeof ", protoN, " = ", protoN, ";");
106
- f.print(' static readonly typeName = ', literalString(message.typeName), ';');
108
+ f.print(' static readonly typeName = ', f.string(message.typeName), ';');
107
109
  f.print(" static readonly fields: ", FieldList, " = ", protoN, ".util.newFieldList(() => [");
108
110
  for (const field of message.fields) {
109
111
  generateFieldInfo(schema, f, field);
@@ -136,18 +138,20 @@ function generateMessage(schema: Schema, f: GeneratedFile, message: DescMessage)
136
138
  for (const nestedMessage of message.nestedMessages) {
137
139
  generateMessage(schema, f, nestedMessage);
138
140
  }
139
- // We do not support extensions at this time
141
+ for (const nestedExtension of message.nestedExtensions) {
142
+ generateExtension(schema, f, nestedExtension);
143
+ }
140
144
  }
141
145
 
142
146
  // prettier-ignore
143
147
  function generateOneof(schema: Schema, f: GeneratedFile, oneof: DescOneof) {
144
- f.print(makeJsDoc(oneof, " "));
148
+ f.print(f.jsDoc(oneof, " "));
145
149
  f.print(" ", localName(oneof), ": {");
146
150
  for (const field of oneof.fields) {
147
151
  if (oneof.fields.indexOf(field) > 0) {
148
152
  f.print(` } | {`);
149
153
  }
150
- f.print(makeJsDoc(field, " "));
154
+ f.print(f.jsDoc(field, " "));
151
155
  const { typing } = getFieldTyping(field, f);
152
156
  f.print(` value: `, typing, `;`);
153
157
  f.print(` case: "`, localName(field), `";`);
@@ -156,7 +160,7 @@ function generateOneof(schema: Schema, f: GeneratedFile, oneof: DescOneof) {
156
160
  }
157
161
 
158
162
  function generateField(schema: Schema, f: GeneratedFile, field: DescField) {
159
- f.print(makeJsDoc(field, " "));
163
+ f.print(f.jsDoc(field, " "));
160
164
  const e: Printable = [];
161
165
  e.push(" ", localName(field));
162
166
  const { defaultValue, typingInferrable } =
@@ -174,6 +178,27 @@ function generateField(schema: Schema, f: GeneratedFile, field: DescField) {
174
178
  f.print(e);
175
179
  }
176
180
 
181
+ // prettier-ignore
182
+ function generateExtension(
183
+ schema: Schema,
184
+ f: GeneratedFile,
185
+ ext: DescExtension,
186
+ ) {
187
+ const protoN = getNonEditionRuntime(schema, ext.file);
188
+ const { typing } = getFieldTyping(ext, f);
189
+ f.print(f.jsDoc(ext));
190
+ f.print(f.exportDecl("const", ext), " = ", protoN, ".makeExtension<", ext.extendee, ", ", typing, ">(");
191
+ f.print(" ", f.string(ext.typeName), ", ");
192
+ f.print(" ", ext.extendee, ", ");
193
+ if (ext.fieldKind == "scalar") {
194
+ f.print(" ", getFieldInfoLiteral(schema, ext), ",");
195
+ } else {
196
+ f.print(" () => (", getFieldInfoLiteral(schema, ext), "),");
197
+ }
198
+ f.print(");");
199
+ f.print();
200
+ }
201
+
177
202
  // prettier-ignore
178
203
  function generateWktMethods(schema: Schema, f: GeneratedFile, message: DescMessage) {
179
204
  const ref = reifyWkt(message);