@bufbuild/protoplugin 0.2.0 → 0.3.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
@@ -1,38 +1,32 @@
1
1
  # @bufbuild/protoplugin
2
2
 
3
- This package helps to create your own code generator plugin.
3
+ This package helps to create your own code generator plugin using the
4
+ Protobuf-ES plugin framework.
4
5
 
5
- ## Protocol Buffers for ECMAScript
6
+ Protobuf-ES is a complete implementation of [Protocol Buffers](https://developers.google.com/protocol-buffers) in TypeScript, suitable for web browsers and Node.js.
6
7
 
7
- A complete implementation of [Protocol Buffers](https://developers.google.com/protocol-buffers)
8
- in TypeScript, suitable for web browsers and Node.js.
9
- Learn more at [github.com/bufbuild/protobuf-es](https://github.com/bufbuild/protobuf-es).
8
+ In addition to a full Protobuf runtime library, it also provides a code generator
9
+ `protoc-gen-es`, which utilizes a plugin framework to generate base types from
10
+ your Protobuf schema. It is fully compatible with both Buf and protoc compilers.
10
11
 
12
+ And now, you can write your own Protobuf-ES compatible plugins using this same
13
+ plugin framework with the `@bufbuild/protoplugin` package.
11
14
 
12
- It is a complete implementation of [Protocol Buffers](https://developers.google.com/protocol-buffers)
13
- in TypeScript, suitable for web browsers and Node.js.
15
+ With `@bufbuild/protoplugin`, you can generate your own TypeScript code tailored
16
+ to your project or needs. You also have various options for producing
17
+ JavaScript and TypeScript declaration files:
14
18
 
15
- For example, the following definition:
19
+ - Exercise full control by writing your own JavaScript and declaration file
20
+ generators in addition to TypeScript.
16
21
 
17
- ```protobuf
18
- message Person {
19
- string name = 1;
20
- int32 id = 2; // Unique ID number for this person.
21
- string email = 3;
22
- }
23
- ```
22
+ - Generate TypeScript files only and let the framework generate JavaScript and
23
+ declaration files automatically using our internal TypeScript compiler.
24
24
 
25
- Is compiled to an ECMAScript class that can be used like this:
25
+ - Generate TypeScript files only and bring your own TypeScript compiler, using
26
+ it to generate JavaScript and declaration files with your own version of
27
+ TypeScript and your own compiler options.
26
28
 
27
- ```typescript
28
- let pete = new Person({
29
- name: "pete",
30
- id: 123
31
- });
29
+ With `protoplugin`, you have all the tools at your disposal to produce ECMAScript-compliant
30
+ code.
32
31
 
33
- let bytes = pete.toBinary();
34
- pete = Person.fromBinary(bytes);
35
- pete = Person.fromJsonString('{"name": "pete", "id": 123}');
36
- ```
37
-
38
- Learn more at [github.com/bufbuild/protobuf-es](https://github.com/bufbuild/protobuf-es).
32
+ Get started now with our [plugin documentation](https://github.com/bufbuild/protobuf-es/blob/main/docs/writing_plugins.md).
@@ -20,8 +20,8 @@ const protobuf_1 = require("@bufbuild/protobuf");
20
20
  *
21
21
  * If no option is found, returns undefined.
22
22
  */
23
- function findCustomScalarOption(desc, id, scalarType) {
24
- const reader = createBinaryReader(desc, id);
23
+ function findCustomScalarOption(desc, extensionNumber, scalarType) {
24
+ const reader = createBinaryReader(desc, extensionNumber);
25
25
  if (reader) {
26
26
  switch (scalarType) {
27
27
  case protobuf_1.ScalarType.INT32:
@@ -63,15 +63,18 @@ function findCustomScalarOption(desc, id, scalarType) {
63
63
  }
64
64
  exports.findCustomScalarOption = findCustomScalarOption;
65
65
  /**
66
- * Returns the value of a custom message option for the given descriptor and ID.
67
- * The msgType param is then used to deserialize the message for returning to the caller.
66
+ * Returns the value of a custom message option for the given descriptor and
67
+ * extension number.
68
+ * The msgType param is then used to deserialize the message for returning to
69
+ * the caller.
68
70
  *
69
71
  * If no options are found, returns undefined.
70
72
  *
71
- * If the message option is unable to be read or deserialized, an error will be thrown.
73
+ * If the message option is unable to be read or deserialized, an error will
74
+ * be thrown.
72
75
  */
73
- function findCustomMessageOption(desc, id, msgType) {
74
- const reader = createBinaryReader(desc, id);
76
+ function findCustomMessageOption(desc, extensionNumber, msgType) {
77
+ const reader = createBinaryReader(desc, extensionNumber);
75
78
  if (reader) {
76
79
  try {
77
80
  const data = reader.bytes();
@@ -86,23 +89,24 @@ function findCustomMessageOption(desc, id, msgType) {
86
89
  }
87
90
  exports.findCustomMessageOption = findCustomMessageOption;
88
91
  /**
89
- * Returns the value of a custom enum option for the given descriptor and ID.
92
+ * Returns the value of a custom enum option for the given descriptor and
93
+ * extension number.
90
94
  *
91
95
  * If no options are found, returns undefined.
92
96
  */
93
- function findCustomEnumOption(desc, id) {
94
- return findCustomScalarOption(desc, id, protobuf_1.ScalarType.INT32);
97
+ function findCustomEnumOption(desc, extensionNumber) {
98
+ return findCustomScalarOption(desc, extensionNumber, protobuf_1.ScalarType.INT32);
95
99
  }
96
100
  exports.findCustomEnumOption = findCustomEnumOption;
97
101
  /**
98
- * Returns a binary reader for the given descriptor and field ID.
102
+ * Returns a binary reader for the given descriptor and extension number.
99
103
  */
100
- function createBinaryReader(desc, id) {
104
+ function createBinaryReader(desc, extensionNumber) {
101
105
  const opt = desc.proto.options;
102
106
  let reader = undefined;
103
107
  if (opt !== undefined) {
104
108
  const unknownFields = protobuf_1.proto3.bin.listUnknownFields(opt);
105
- const field = unknownFields.find((f) => f.no === id);
109
+ const field = unknownFields.find((f) => f.no === extensionNumber);
106
110
  if (field) {
107
111
  reader = new protobuf_1.BinaryReader(field.data);
108
112
  }
@@ -48,7 +48,7 @@ function makeFilePreamble(file, pluginName, pluginVersion, parameter, tsNoCheck)
48
48
  builder.push(`syntax ${file.syntax})\n`);
49
49
  builder.push("/* eslint-disable */\n");
50
50
  if (tsNoCheck) {
51
- builder.push("/* @ts-nocheck */\n");
51
+ builder.push("// @ts-nocheck\n");
52
52
  }
53
53
  builder.push("\n");
54
54
  writeLeadingComments(file.getPackageComments());
@@ -24,8 +24,21 @@ function createGeneratedFile(name, importPath, createTypeImport, runtimeImports,
24
24
  preamble(file) {
25
25
  preamble = (0, gencommon_js_1.makeFilePreamble)(file, preambleSettings.pluginName, preambleSettings.pluginVersion, preambleSettings.parameter, preambleSettings.tsNocheck);
26
26
  },
27
- print(...any) {
28
- printableToEl(any, el, createTypeImport, runtimeImports);
27
+ print(printableOrFragments, ...rest) {
28
+ let printables;
29
+ if (printableOrFragments != null &&
30
+ Object.prototype.hasOwnProperty.call(printableOrFragments, "raw")) {
31
+ // If called with a tagged template literal
32
+ printables = buildPrintablesFromFragments(printableOrFragments, rest);
33
+ }
34
+ else {
35
+ // If called with just an array of Printables
36
+ printables =
37
+ printableOrFragments != null
38
+ ? [printableOrFragments, ...rest]
39
+ : rest;
40
+ }
41
+ printableToEl(printables, el, createTypeImport, runtimeImports);
29
42
  el.push("\n");
30
43
  },
31
44
  export(name) {
@@ -56,7 +69,7 @@ function elToContent(el, importerPath) {
56
69
  const c = [];
57
70
  const symbolToIdentifier = processImports(el, importerPath, (typeOnly, from, names) => {
58
71
  const p = names.map(({ name, alias }) => alias == undefined ? name : `${name} as ${alias}`);
59
- const what = `{${p.join(", ")}}`;
72
+ const what = `{ ${p.join(", ")} }`;
60
73
  if (typeOnly) {
61
74
  c.push(`import type ${what} from ${(0, gencommon_js_1.literalString)(from)};\n`);
62
75
  }
@@ -119,6 +132,16 @@ function printableToEl(printables, el, createTypeImport, runtimeImports) {
119
132
  }
120
133
  }
121
134
  }
135
+ function buildPrintablesFromFragments(fragments, values) {
136
+ const printables = [];
137
+ fragments.forEach((fragment, i) => {
138
+ printables.push(fragment);
139
+ if (fragments.length - 1 !== i) {
140
+ printables.push(values[i]);
141
+ }
142
+ });
143
+ return printables;
144
+ }
122
145
  function processImports(el, importerPath, makeImportStatement) {
123
146
  // identifiers to use in the output
124
147
  const symbolToIdentifier = new Map();
@@ -13,14 +13,14 @@
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.findCustomEnumOption = exports.findCustomMessageOption = exports.findCustomScalarOption = exports.literalString = exports.makeJsDoc = exports.getFieldTyping = exports.getFieldIntrinsicDefaultValue = exports.getFieldExplicitDefaultValue = exports.createJsDocBlock = exports.localName = void 0;
16
+ exports.findCustomEnumOption = exports.findCustomMessageOption = exports.findCustomScalarOption = exports.literalString = exports.makeJsDoc = exports.getFieldTyping = exports.getFieldIntrinsicDefaultValue = exports.getFieldExplicitDefaultValue = exports.createJsDocBlock = exports.reifyWkt = exports.localName = void 0;
17
17
  const protobuf_1 = require("@bufbuild/protobuf");
18
18
  var target_js_1 = require("./target.js");
19
19
  var schema_js_1 = require("./schema.js");
20
20
  var runtime_imports_js_1 = require("./runtime-imports.js");
21
21
  var generated_file_js_1 = require("./generated-file.js");
22
22
  var import_symbol_js_1 = require("./import-symbol.js");
23
- exports.localName = protobuf_1.codegenInfo.localName;
23
+ exports.localName = protobuf_1.codegenInfo.localName, exports.reifyWkt = protobuf_1.codegenInfo.reifyWkt;
24
24
  var gencommon_js_1 = require("./gencommon.js");
25
25
  Object.defineProperty(exports, "createJsDocBlock", { enumerable: true, get: function () { return gencommon_js_1.createJsDocBlock; } });
26
26
  Object.defineProperty(exports, "getFieldExplicitDefaultValue", { enumerable: true, get: function () { return gencommon_js_1.getFieldExplicitDefaultValue; } });
@@ -36,6 +36,7 @@ function createRuntimeImports(bootstrapWkt) {
36
36
  ScalarType: infoToSymbol("ScalarType", bootstrapWkt),
37
37
  MethodKind: infoToSymbol("MethodKind", bootstrapWkt),
38
38
  MethodIdempotency: infoToSymbol("MethodIdempotency", bootstrapWkt),
39
+ IMessageTypeRegistry: infoToSymbol("IMessageTypeRegistry", bootstrapWkt),
39
40
  };
40
41
  }
41
42
  exports.createRuntimeImports = createRuntimeImports;
@@ -17,8 +17,8 @@ import { proto3, BinaryReader, ScalarType, } from "@bufbuild/protobuf";
17
17
  *
18
18
  * If no option is found, returns undefined.
19
19
  */
20
- export function findCustomScalarOption(desc, id, scalarType) {
21
- const reader = createBinaryReader(desc, id);
20
+ export function findCustomScalarOption(desc, extensionNumber, scalarType) {
21
+ const reader = createBinaryReader(desc, extensionNumber);
22
22
  if (reader) {
23
23
  switch (scalarType) {
24
24
  case ScalarType.INT32:
@@ -59,15 +59,18 @@ export function findCustomScalarOption(desc, id, scalarType) {
59
59
  return undefined;
60
60
  }
61
61
  /**
62
- * Returns the value of a custom message option for the given descriptor and ID.
63
- * The msgType param is then used to deserialize the message for returning to the caller.
62
+ * Returns the value of a custom message option for the given descriptor and
63
+ * extension number.
64
+ * The msgType param is then used to deserialize the message for returning to
65
+ * the caller.
64
66
  *
65
67
  * If no options are found, returns undefined.
66
68
  *
67
- * If the message option is unable to be read or deserialized, an error will be thrown.
69
+ * If the message option is unable to be read or deserialized, an error will
70
+ * be thrown.
68
71
  */
69
- export function findCustomMessageOption(desc, id, msgType) {
70
- const reader = createBinaryReader(desc, id);
72
+ export function findCustomMessageOption(desc, extensionNumber, msgType) {
73
+ const reader = createBinaryReader(desc, extensionNumber);
71
74
  if (reader) {
72
75
  try {
73
76
  const data = reader.bytes();
@@ -81,22 +84,23 @@ export function findCustomMessageOption(desc, id, msgType) {
81
84
  return undefined;
82
85
  }
83
86
  /**
84
- * Returns the value of a custom enum option for the given descriptor and ID.
87
+ * Returns the value of a custom enum option for the given descriptor and
88
+ * extension number.
85
89
  *
86
90
  * If no options are found, returns undefined.
87
91
  */
88
- export function findCustomEnumOption(desc, id) {
89
- return findCustomScalarOption(desc, id, ScalarType.INT32);
92
+ export function findCustomEnumOption(desc, extensionNumber) {
93
+ return findCustomScalarOption(desc, extensionNumber, ScalarType.INT32);
90
94
  }
91
95
  /**
92
- * Returns a binary reader for the given descriptor and field ID.
96
+ * Returns a binary reader for the given descriptor and extension number.
93
97
  */
94
- function createBinaryReader(desc, id) {
98
+ function createBinaryReader(desc, extensionNumber) {
95
99
  const opt = desc.proto.options;
96
100
  let reader = undefined;
97
101
  if (opt !== undefined) {
98
102
  const unknownFields = proto3.bin.listUnknownFields(opt);
99
- const field = unknownFields.find((f) => f.no === id);
103
+ const field = unknownFields.find((f) => f.no === extensionNumber);
100
104
  if (field) {
101
105
  reader = new BinaryReader(field.data);
102
106
  }
@@ -45,7 +45,7 @@ export function makeFilePreamble(file, pluginName, pluginVersion, parameter, tsN
45
45
  builder.push(`syntax ${file.syntax})\n`);
46
46
  builder.push("/* eslint-disable */\n");
47
47
  if (tsNoCheck) {
48
- builder.push("/* @ts-nocheck */\n");
48
+ builder.push("// @ts-nocheck\n");
49
49
  }
50
50
  builder.push("\n");
51
51
  writeLeadingComments(file.getPackageComments());
@@ -21,8 +21,21 @@ export function createGeneratedFile(name, importPath, createTypeImport, runtimeI
21
21
  preamble(file) {
22
22
  preamble = makeFilePreamble(file, preambleSettings.pluginName, preambleSettings.pluginVersion, preambleSettings.parameter, preambleSettings.tsNocheck);
23
23
  },
24
- print(...any) {
25
- printableToEl(any, el, createTypeImport, runtimeImports);
24
+ print(printableOrFragments, ...rest) {
25
+ let printables;
26
+ if (printableOrFragments != null &&
27
+ Object.prototype.hasOwnProperty.call(printableOrFragments, "raw")) {
28
+ // If called with a tagged template literal
29
+ printables = buildPrintablesFromFragments(printableOrFragments, rest);
30
+ }
31
+ else {
32
+ // If called with just an array of Printables
33
+ printables =
34
+ printableOrFragments != null
35
+ ? [printableOrFragments, ...rest]
36
+ : rest;
37
+ }
38
+ printableToEl(printables, el, createTypeImport, runtimeImports);
26
39
  el.push("\n");
27
40
  },
28
41
  export(name) {
@@ -52,7 +65,7 @@ function elToContent(el, importerPath) {
52
65
  const c = [];
53
66
  const symbolToIdentifier = processImports(el, importerPath, (typeOnly, from, names) => {
54
67
  const p = names.map(({ name, alias }) => alias == undefined ? name : `${name} as ${alias}`);
55
- const what = `{${p.join(", ")}}`;
68
+ const what = `{ ${p.join(", ")} }`;
56
69
  if (typeOnly) {
57
70
  c.push(`import type ${what} from ${literalString(from)};\n`);
58
71
  }
@@ -115,6 +128,16 @@ function printableToEl(printables, el, createTypeImport, runtimeImports) {
115
128
  }
116
129
  }
117
130
  }
131
+ function buildPrintablesFromFragments(fragments, values) {
132
+ const printables = [];
133
+ fragments.forEach((fragment, i) => {
134
+ printables.push(fragment);
135
+ if (fragments.length - 1 !== i) {
136
+ printables.push(values[i]);
137
+ }
138
+ });
139
+ return printables;
140
+ }
118
141
  function processImports(el, importerPath, makeImportStatement) {
119
142
  // identifiers to use in the output
120
143
  const symbolToIdentifier = new Map();
@@ -17,6 +17,6 @@ export {} from "./schema.js";
17
17
  export {} from "./runtime-imports.js";
18
18
  export {} from "./generated-file.js";
19
19
  export {} from "./import-symbol.js";
20
- export const { localName } = codegenInfo;
20
+ export const { localName, reifyWkt } = codegenInfo;
21
21
  export { createJsDocBlock, getFieldExplicitDefaultValue, getFieldIntrinsicDefaultValue, getFieldTyping, makeJsDoc, literalString, } from "./gencommon.js";
22
22
  export { findCustomScalarOption, findCustomMessageOption, findCustomEnumOption, } from "./custom-options.js";
@@ -33,6 +33,7 @@ export function createRuntimeImports(bootstrapWkt) {
33
33
  ScalarType: infoToSymbol("ScalarType", bootstrapWkt),
34
34
  MethodKind: infoToSymbol("MethodKind", bootstrapWkt),
35
35
  MethodIdempotency: infoToSymbol("MethodIdempotency", bootstrapWkt),
36
+ IMessageTypeRegistry: infoToSymbol("IMessageTypeRegistry", bootstrapWkt),
36
37
  };
37
38
  }
38
39
  function infoToSymbol(name, bootstrapWkt) {
@@ -5,22 +5,26 @@ import { Message, MessageType, ScalarType } from "@bufbuild/protobuf";
5
5
  *
6
6
  * If no option is found, returns undefined.
7
7
  */
8
- export declare function findCustomScalarOption<T extends ScalarType>(desc: AnyDesc, id: number, scalarType: T): ScalarValue<T> | undefined;
8
+ export declare function findCustomScalarOption<T extends ScalarType>(desc: AnyDesc, extensionNumber: number, scalarType: T): ScalarValue<T> | undefined;
9
9
  /**
10
- * Returns the value of a custom message option for the given descriptor and ID.
11
- * The msgType param is then used to deserialize the message for returning to the caller.
10
+ * Returns the value of a custom message option for the given descriptor and
11
+ * extension number.
12
+ * The msgType param is then used to deserialize the message for returning to
13
+ * the caller.
12
14
  *
13
15
  * If no options are found, returns undefined.
14
16
  *
15
- * If the message option is unable to be read or deserialized, an error will be thrown.
17
+ * If the message option is unable to be read or deserialized, an error will
18
+ * be thrown.
16
19
  */
17
- export declare function findCustomMessageOption<T extends Message<T>>(desc: AnyDesc, id: number, msgType: MessageType<T>): T | undefined;
20
+ export declare function findCustomMessageOption<T extends Message<T>>(desc: AnyDesc, extensionNumber: number, msgType: MessageType<T>): T | undefined;
18
21
  /**
19
- * Returns the value of a custom enum option for the given descriptor and ID.
22
+ * Returns the value of a custom enum option for the given descriptor and
23
+ * extension number.
20
24
  *
21
25
  * If no options are found, returns undefined.
22
26
  */
23
- export declare function findCustomEnumOption(desc: AnyDesc, id: number): number | undefined;
27
+ export declare function findCustomEnumOption(desc: AnyDesc, extensionNumber: number): number | undefined;
24
28
  /**
25
29
  * ScalarValue is a conditional type that pairs a ScalarType value with its concrete type.
26
30
  */
@@ -36,7 +36,13 @@ export interface GeneratedFile {
36
36
  * - ImportSymbol: Adds an import statement and prints the name of the symbol.
37
37
  * - DescMessage or DescEnum: Imports the type if necessary, and prints the name.
38
38
  */
39
- print(...any: Printable[]): void;
39
+ print(...printables: Printable[]): void;
40
+ /**
41
+ * Add a line of code to the file with tagged template literal and
42
+ * an optional array of Printables.
43
+ * See print(Printable[]) for behavior when printing Printable items.
44
+ */
45
+ print(fragments: TemplateStringsArray, ...printables: Printable[]): void;
40
46
  /**
41
47
  * Reserves an identifier in this file.
42
48
  */
@@ -3,6 +3,6 @@ export { Schema } from "./schema.js";
3
3
  export { RuntimeImports } from "./runtime-imports.js";
4
4
  export { GeneratedFile, FileInfo, Printable } from "./generated-file.js";
5
5
  export { ImportSymbol } from "./import-symbol.js";
6
- export declare const localName: typeof import("@bufbuild/protobuf/dist/types/private/names.js").localName;
6
+ export declare const localName: typeof import("@bufbuild/protobuf/dist/types/private/names.js").localName, reifyWkt: typeof import("@bufbuild/protobuf/dist/types/private/reify-wkt.js").reifyWkt;
7
7
  export { createJsDocBlock, getFieldExplicitDefaultValue, getFieldIntrinsicDefaultValue, getFieldTyping, makeJsDoc, literalString, } from "./gencommon.js";
8
8
  export { findCustomScalarOption, findCustomMessageOption, findCustomEnumOption, } from "./custom-options.js";
@@ -17,5 +17,6 @@ export interface RuntimeImports {
17
17
  ScalarType: ImportSymbol;
18
18
  MethodKind: ImportSymbol;
19
19
  MethodIdempotency: ImportSymbol;
20
+ IMessageTypeRegistry: ImportSymbol;
20
21
  }
21
22
  export declare function createRuntimeImports(bootstrapWkt: boolean): RuntimeImports;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bufbuild/protoplugin",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "license": "(Apache-2.0 AND BSD-3-Clause)",
5
5
  "description": "Helps to create your own Protocol Buffers code generators.",
6
6
  "repository": {
@@ -35,7 +35,7 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@bufbuild/protobuf": "0.2.0",
38
+ "@bufbuild/protobuf": "0.3.0",
39
39
  "@typescript/vfs": "^1.4.0",
40
40
  "typescript": "4.5.2"
41
41
  },