@bufbuild/protoplugin 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -27
- package/dist/cjs/create-es-plugin.js +85 -9
- package/dist/cjs/ecmascript/custom-options.js +115 -0
- package/dist/cjs/ecmascript/gencommon.js +13 -16
- package/dist/cjs/ecmascript/generated-file.js +9 -12
- package/dist/cjs/ecmascript/index.js +6 -2
- package/dist/cjs/ecmascript/schema.js +24 -8
- package/dist/cjs/ecmascript/transpile.js +122 -0
- package/dist/esm/create-es-plugin.js +86 -10
- package/dist/esm/ecmascript/custom-options.js +109 -0
- package/dist/esm/ecmascript/gencommon.js +13 -16
- package/dist/esm/ecmascript/generated-file.js +9 -12
- package/dist/esm/ecmascript/index.js +2 -1
- package/dist/esm/ecmascript/schema.js +23 -8
- package/dist/esm/ecmascript/transpile.js +115 -0
- package/dist/types/create-es-plugin.d.ts +45 -2
- package/dist/types/ecmascript/custom-options.d.ts +32 -0
- package/dist/types/ecmascript/gencommon.d.ts +1 -3
- package/dist/types/ecmascript/generated-file.d.ts +12 -5
- package/dist/types/ecmascript/index.d.ts +3 -2
- package/dist/types/ecmascript/schema.d.ts +4 -3
- package/dist/types/ecmascript/transpile.d.ts +2 -0
- package/package.json +8 -6
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
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
13
|
-
|
|
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
|
-
|
|
19
|
+
- Exercise full control by writing your own JavaScript and declaration file
|
|
20
|
+
generators in addition to TypeScript.
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
|
|
28
|
-
|
|
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
|
-
|
|
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).
|
|
@@ -15,24 +15,84 @@
|
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.createEcmaScriptPlugin = void 0;
|
|
17
17
|
const schema_js_1 = require("./ecmascript/schema.js");
|
|
18
|
-
const
|
|
18
|
+
const transpile_js_1 = require("./ecmascript/transpile.js");
|
|
19
19
|
const error_js_1 = require("./error.js");
|
|
20
20
|
/**
|
|
21
21
|
* Create a new code generator plugin for ECMAScript.
|
|
22
22
|
* The plugin can generate JavaScript, TypeScript, or TypeScript declaration
|
|
23
23
|
* files.
|
|
24
24
|
*/
|
|
25
|
-
function createEcmaScriptPlugin(init
|
|
25
|
+
function createEcmaScriptPlugin(init) {
|
|
26
|
+
let transpileJs = false;
|
|
27
|
+
let transpileDts = false;
|
|
26
28
|
return {
|
|
27
29
|
name: init.name,
|
|
28
30
|
version: init.version,
|
|
29
31
|
run(req) {
|
|
30
|
-
|
|
31
|
-
const {
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
var _a;
|
|
33
|
+
const { targets, tsNocheck, bootstrapWkt, rewriteImports, keepEmptyFiles, } = parseParameter(req.parameter, init.parseOption);
|
|
34
|
+
const { schema, getFileInfo } = (0, schema_js_1.createSchema)(req, targets, init.name, init.version, tsNocheck, bootstrapWkt, rewriteImports, keepEmptyFiles);
|
|
35
|
+
const targetTs = schema.targets.includes("ts");
|
|
36
|
+
const targetJs = schema.targets.includes("js");
|
|
37
|
+
const targetDts = schema.targets.includes("dts");
|
|
38
|
+
// Generate TS files under the following conditions:
|
|
39
|
+
// - if they are explicitly specified as a target.
|
|
40
|
+
// - if js is specified as a target but no js generator is provided.
|
|
41
|
+
// - if dts is specified as a target, but no dts generator is provided.
|
|
42
|
+
// In the latter two cases, it is because we need the generated TS files
|
|
43
|
+
// to use for transpiling js and/or dts.
|
|
44
|
+
let tsFiles = [];
|
|
45
|
+
if (targetTs ||
|
|
46
|
+
(targetJs && !init.generateJs) ||
|
|
47
|
+
(targetDts && !init.generateDts)) {
|
|
48
|
+
init.generateTs(schema, "ts");
|
|
49
|
+
// Save off the generated TypeScript files so that we can pass these
|
|
50
|
+
// to the transpilation process if necessary. We do not want to pass
|
|
51
|
+
// JavaScript files for a few reasons:
|
|
52
|
+
// 1. Our usage of allowJs in the compiler options will cause issues
|
|
53
|
+
// with attempting to transpile .ts and .js files to the same location.
|
|
54
|
+
// 2. There should be no reason to transpile JS because generateTs
|
|
55
|
+
// functions are required, so users would never be able to only specify
|
|
56
|
+
// a generateJs function and expect to transpile declarations.
|
|
57
|
+
// 3. Transpiling is somewhat expensive and situations with an
|
|
58
|
+
// extremely large amount of files could have performance impacts.
|
|
59
|
+
tsFiles = getFileInfo();
|
|
60
|
+
}
|
|
61
|
+
if (targetJs) {
|
|
62
|
+
if (init.generateJs) {
|
|
63
|
+
init.generateJs(schema, "js");
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
transpileJs = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (targetDts) {
|
|
70
|
+
if (init.generateDts) {
|
|
71
|
+
init.generateDts(schema, "dts");
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
transpileDts = true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Get generated files. If ts was specified as a target, then we want
|
|
78
|
+
// all generated files. If ts was not specified, we still may have
|
|
79
|
+
// generated TypeScript files to assist in transpilation. If they were
|
|
80
|
+
// generated but not specified in the target out, we shouldn't produce
|
|
81
|
+
// these files in the CodeGeneratorResponse.
|
|
82
|
+
let files = getFileInfo();
|
|
83
|
+
if (!targetTs && tsFiles.length > 0) {
|
|
84
|
+
files = files.filter((file) => !tsFiles.some((tsFile) => tsFile.name === file.name));
|
|
85
|
+
}
|
|
86
|
+
// If either boolean is true, it means it was specified in the target out
|
|
87
|
+
// but no generate function was provided. This also means that we will
|
|
88
|
+
// have generated .ts files above.
|
|
89
|
+
if (transpileJs || transpileDts) {
|
|
90
|
+
const transpileFn = (_a = init.transpile) !== null && _a !== void 0 ? _a : transpile_js_1.transpile;
|
|
91
|
+
// Transpile the TypeScript files and add to the master list of files
|
|
92
|
+
const transpiledFiles = transpileFn(tsFiles, transpileJs, transpileDts);
|
|
93
|
+
files.push(...transpiledFiles);
|
|
94
|
+
}
|
|
95
|
+
return (0, schema_js_1.toResponse)(files);
|
|
36
96
|
},
|
|
37
97
|
};
|
|
38
98
|
}
|
|
@@ -41,6 +101,7 @@ function parseParameter(parameter, parseOption) {
|
|
|
41
101
|
let targets = ["js", "dts"];
|
|
42
102
|
let tsNocheck = true;
|
|
43
103
|
let bootstrapWkt = false;
|
|
104
|
+
let keepEmptyFiles = false;
|
|
44
105
|
const rewriteImports = [];
|
|
45
106
|
for (const { key, value } of splitParameter(parameter)) {
|
|
46
107
|
switch (key) {
|
|
@@ -98,6 +159,21 @@ function parseParameter(parameter, parseOption) {
|
|
|
98
159
|
rewriteImports.push({ pattern, target });
|
|
99
160
|
break;
|
|
100
161
|
}
|
|
162
|
+
case "keep_empty_files": {
|
|
163
|
+
switch (value) {
|
|
164
|
+
case "true":
|
|
165
|
+
case "1":
|
|
166
|
+
keepEmptyFiles = true;
|
|
167
|
+
break;
|
|
168
|
+
case "false":
|
|
169
|
+
case "0":
|
|
170
|
+
keepEmptyFiles = false;
|
|
171
|
+
break;
|
|
172
|
+
default:
|
|
173
|
+
throw new error_js_1.PluginOptionError(`${key}=${value}`);
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
101
177
|
default:
|
|
102
178
|
if (parseOption === undefined) {
|
|
103
179
|
throw new error_js_1.PluginOptionError(`${key}=${value}`);
|
|
@@ -111,7 +187,7 @@ function parseParameter(parameter, parseOption) {
|
|
|
111
187
|
break;
|
|
112
188
|
}
|
|
113
189
|
}
|
|
114
|
-
return { targets, tsNocheck, bootstrapWkt, rewriteImports };
|
|
190
|
+
return { targets, tsNocheck, bootstrapWkt, rewriteImports, keepEmptyFiles };
|
|
115
191
|
}
|
|
116
192
|
function splitParameter(parameter) {
|
|
117
193
|
if (parameter == undefined) {
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2021-2022 Buf Technologies, Inc.
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.findCustomEnumOption = exports.findCustomMessageOption = exports.findCustomScalarOption = void 0;
|
|
17
|
+
const protobuf_1 = require("@bufbuild/protobuf");
|
|
18
|
+
/**
|
|
19
|
+
* Returns the value of a custom option with a scalar type.
|
|
20
|
+
*
|
|
21
|
+
* If no option is found, returns undefined.
|
|
22
|
+
*/
|
|
23
|
+
function findCustomScalarOption(desc, extensionNumber, scalarType) {
|
|
24
|
+
const reader = createBinaryReader(desc, extensionNumber);
|
|
25
|
+
if (reader) {
|
|
26
|
+
switch (scalarType) {
|
|
27
|
+
case protobuf_1.ScalarType.INT32:
|
|
28
|
+
return reader.int32();
|
|
29
|
+
case protobuf_1.ScalarType.UINT32:
|
|
30
|
+
return reader.uint32();
|
|
31
|
+
case protobuf_1.ScalarType.SINT32:
|
|
32
|
+
return reader.sint32();
|
|
33
|
+
case protobuf_1.ScalarType.FIXED32:
|
|
34
|
+
return reader.fixed32();
|
|
35
|
+
case protobuf_1.ScalarType.SFIXED32:
|
|
36
|
+
return reader.sfixed32();
|
|
37
|
+
case protobuf_1.ScalarType.FLOAT:
|
|
38
|
+
return reader.float();
|
|
39
|
+
case protobuf_1.ScalarType.DOUBLE:
|
|
40
|
+
return reader.double();
|
|
41
|
+
case protobuf_1.ScalarType.INT64:
|
|
42
|
+
return reader.int64();
|
|
43
|
+
case protobuf_1.ScalarType.SINT64:
|
|
44
|
+
return reader.sint64();
|
|
45
|
+
case protobuf_1.ScalarType.SFIXED64:
|
|
46
|
+
return reader.sfixed64();
|
|
47
|
+
case protobuf_1.ScalarType.UINT64:
|
|
48
|
+
return reader.uint64();
|
|
49
|
+
case protobuf_1.ScalarType.FIXED64:
|
|
50
|
+
return reader.fixed64();
|
|
51
|
+
case protobuf_1.ScalarType.BOOL:
|
|
52
|
+
return reader.bool();
|
|
53
|
+
case protobuf_1.ScalarType.BYTES:
|
|
54
|
+
return reader.bytes();
|
|
55
|
+
case protobuf_1.ScalarType.STRING:
|
|
56
|
+
return reader.string();
|
|
57
|
+
default: {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
exports.findCustomScalarOption = findCustomScalarOption;
|
|
65
|
+
/**
|
|
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.
|
|
70
|
+
*
|
|
71
|
+
* If no options are found, returns undefined.
|
|
72
|
+
*
|
|
73
|
+
* If the message option is unable to be read or deserialized, an error will
|
|
74
|
+
* be thrown.
|
|
75
|
+
*/
|
|
76
|
+
function findCustomMessageOption(desc, extensionNumber, msgType) {
|
|
77
|
+
const reader = createBinaryReader(desc, extensionNumber);
|
|
78
|
+
if (reader) {
|
|
79
|
+
try {
|
|
80
|
+
const data = reader.bytes();
|
|
81
|
+
return msgType.fromBinary(data);
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
const innerMessage = e instanceof Error ? e.message : String(e);
|
|
85
|
+
throw new Error(`failed to access message option: ${innerMessage}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
exports.findCustomMessageOption = findCustomMessageOption;
|
|
91
|
+
/**
|
|
92
|
+
* Returns the value of a custom enum option for the given descriptor and
|
|
93
|
+
* extension number.
|
|
94
|
+
*
|
|
95
|
+
* If no options are found, returns undefined.
|
|
96
|
+
*/
|
|
97
|
+
function findCustomEnumOption(desc, extensionNumber) {
|
|
98
|
+
return findCustomScalarOption(desc, extensionNumber, protobuf_1.ScalarType.INT32);
|
|
99
|
+
}
|
|
100
|
+
exports.findCustomEnumOption = findCustomEnumOption;
|
|
101
|
+
/**
|
|
102
|
+
* Returns a binary reader for the given descriptor and extension number.
|
|
103
|
+
*/
|
|
104
|
+
function createBinaryReader(desc, extensionNumber) {
|
|
105
|
+
const opt = desc.proto.options;
|
|
106
|
+
let reader = undefined;
|
|
107
|
+
if (opt !== undefined) {
|
|
108
|
+
const unknownFields = protobuf_1.proto3.bin.listUnknownFields(opt);
|
|
109
|
+
const field = unknownFields.find((f) => f.no === extensionNumber);
|
|
110
|
+
if (field) {
|
|
111
|
+
reader = new protobuf_1.BinaryReader(field.data);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return reader;
|
|
115
|
+
}
|
|
@@ -103,10 +103,7 @@ function makeJsDoc(desc, indentation = "") {
|
|
|
103
103
|
case "enum_value":
|
|
104
104
|
text += `@generated from enum value: ${desc.declarationString()};`;
|
|
105
105
|
break;
|
|
106
|
-
case "
|
|
107
|
-
case "enum_field":
|
|
108
|
-
case "message_field":
|
|
109
|
-
case "map_field":
|
|
106
|
+
case "field":
|
|
110
107
|
text += `@generated from field: ${desc.declarationString()};`;
|
|
111
108
|
break;
|
|
112
109
|
default:
|
|
@@ -139,12 +136,12 @@ exports.makeJsDoc = makeJsDoc;
|
|
|
139
136
|
function getFieldTyping(field, file) {
|
|
140
137
|
const typing = [];
|
|
141
138
|
let optional = false;
|
|
142
|
-
switch (field.
|
|
143
|
-
case "
|
|
139
|
+
switch (field.fieldKind) {
|
|
140
|
+
case "scalar":
|
|
144
141
|
typing.push(scalarTypeScriptType(field.scalar));
|
|
145
142
|
optional = field.optional;
|
|
146
143
|
break;
|
|
147
|
-
case "
|
|
144
|
+
case "message": {
|
|
148
145
|
const baseType = getUnwrappedFieldType(field);
|
|
149
146
|
if (baseType !== undefined) {
|
|
150
147
|
typing.push(scalarTypeScriptType(baseType));
|
|
@@ -155,11 +152,11 @@ function getFieldTyping(field, file) {
|
|
|
155
152
|
optional = true;
|
|
156
153
|
break;
|
|
157
154
|
}
|
|
158
|
-
case "
|
|
155
|
+
case "enum":
|
|
159
156
|
typing.push(file.import(field.enum).toTypeOnly());
|
|
160
157
|
optional = field.optional;
|
|
161
158
|
break;
|
|
162
|
-
case "
|
|
159
|
+
case "map": {
|
|
163
160
|
let keyType;
|
|
164
161
|
switch (field.mapKey) {
|
|
165
162
|
case protobuf_1.ScalarType.INT32:
|
|
@@ -231,15 +228,15 @@ function literalString(value) {
|
|
|
231
228
|
}
|
|
232
229
|
exports.literalString = literalString;
|
|
233
230
|
function getFieldExplicitDefaultValue(field, protoInt64Symbol) {
|
|
234
|
-
switch (field.
|
|
235
|
-
case "
|
|
231
|
+
switch (field.fieldKind) {
|
|
232
|
+
case "enum": {
|
|
236
233
|
const value = field.enum.values.find((v) => v.number === field.getDefaultValue());
|
|
237
234
|
if (value !== undefined) {
|
|
238
235
|
return [value.parent, ".", localName(value)];
|
|
239
236
|
}
|
|
240
237
|
break;
|
|
241
238
|
}
|
|
242
|
-
case "
|
|
239
|
+
case "scalar": {
|
|
243
240
|
const defaultValue = field.getDefaultValue();
|
|
244
241
|
if (defaultValue === undefined) {
|
|
245
242
|
break;
|
|
@@ -293,7 +290,7 @@ function getFieldIntrinsicDefaultValue(field) {
|
|
|
293
290
|
typingInferrable: false,
|
|
294
291
|
};
|
|
295
292
|
}
|
|
296
|
-
if (field.
|
|
293
|
+
if (field.fieldKind == "map") {
|
|
297
294
|
return {
|
|
298
295
|
defaultValue: "{}",
|
|
299
296
|
typingInferrable: false,
|
|
@@ -302,8 +299,8 @@ function getFieldIntrinsicDefaultValue(field) {
|
|
|
302
299
|
let defaultValue = undefined;
|
|
303
300
|
let typingInferrable = false;
|
|
304
301
|
if (field.parent.file.syntax == "proto3") {
|
|
305
|
-
switch (field.
|
|
306
|
-
case "
|
|
302
|
+
switch (field.fieldKind) {
|
|
303
|
+
case "enum": {
|
|
307
304
|
if (!field.optional) {
|
|
308
305
|
const zeroValue = field.enum.values.find((v) => v.number === 0);
|
|
309
306
|
if (zeroValue === undefined) {
|
|
@@ -314,7 +311,7 @@ function getFieldIntrinsicDefaultValue(field) {
|
|
|
314
311
|
}
|
|
315
312
|
break;
|
|
316
313
|
}
|
|
317
|
-
case "
|
|
314
|
+
case "scalar":
|
|
318
315
|
if (!field.optional) {
|
|
319
316
|
typingInferrable = true;
|
|
320
317
|
if (field.scalar === protobuf_1.ScalarType.STRING) {
|
|
@@ -14,11 +14,10 @@
|
|
|
14
14
|
// limitations under the License.
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.createGeneratedFile = void 0;
|
|
17
|
-
const protobuf_1 = require("@bufbuild/protobuf");
|
|
18
17
|
const import_symbol_js_1 = require("./import-symbol.js");
|
|
19
18
|
const gencommon_js_1 = require("./gencommon.js");
|
|
20
19
|
const import_path_js_1 = require("./import-path.js");
|
|
21
|
-
function createGeneratedFile(name, importPath, createTypeImport, runtimeImports, preambleSettings) {
|
|
20
|
+
function createGeneratedFile(name, importPath, createTypeImport, runtimeImports, preambleSettings, keepEmpty) {
|
|
22
21
|
let preamble;
|
|
23
22
|
const el = [];
|
|
24
23
|
return {
|
|
@@ -35,22 +34,20 @@ function createGeneratedFile(name, importPath, createTypeImport, runtimeImports,
|
|
|
35
34
|
import(typeOrName, from) {
|
|
36
35
|
if (typeof typeOrName == "string") {
|
|
37
36
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
38
|
-
return (0, import_symbol_js_1.createImportSymbol)(
|
|
37
|
+
return (0, import_symbol_js_1.createImportSymbol)(typeOrName, from);
|
|
39
38
|
}
|
|
40
39
|
return createTypeImport(typeOrName);
|
|
41
40
|
},
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (content.length === 0) {
|
|
41
|
+
getFileInfo() {
|
|
42
|
+
const content = elToContent(el, importPath);
|
|
43
|
+
if (!keepEmpty && content.length === 0) {
|
|
45
44
|
return;
|
|
46
45
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
res.file.push(new protobuf_1.CodeGeneratorResponse_File({
|
|
51
|
-
name: name,
|
|
46
|
+
return {
|
|
47
|
+
name,
|
|
52
48
|
content,
|
|
53
|
-
|
|
49
|
+
preamble,
|
|
50
|
+
};
|
|
54
51
|
},
|
|
55
52
|
};
|
|
56
53
|
}
|
|
@@ -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.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; } });
|
|
@@ -28,3 +28,7 @@ Object.defineProperty(exports, "getFieldIntrinsicDefaultValue", { enumerable: tr
|
|
|
28
28
|
Object.defineProperty(exports, "getFieldTyping", { enumerable: true, get: function () { return gencommon_js_1.getFieldTyping; } });
|
|
29
29
|
Object.defineProperty(exports, "makeJsDoc", { enumerable: true, get: function () { return gencommon_js_1.makeJsDoc; } });
|
|
30
30
|
Object.defineProperty(exports, "literalString", { enumerable: true, get: function () { return gencommon_js_1.literalString; } });
|
|
31
|
+
var custom_options_js_1 = require("./custom-options.js");
|
|
32
|
+
Object.defineProperty(exports, "findCustomScalarOption", { enumerable: true, get: function () { return custom_options_js_1.findCustomScalarOption; } });
|
|
33
|
+
Object.defineProperty(exports, "findCustomMessageOption", { enumerable: true, get: function () { return custom_options_js_1.findCustomMessageOption; } });
|
|
34
|
+
Object.defineProperty(exports, "findCustomEnumOption", { enumerable: true, get: function () { return custom_options_js_1.findCustomEnumOption; } });
|
|
@@ -13,13 +13,13 @@
|
|
|
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.createSchema = void 0;
|
|
16
|
+
exports.toResponse = exports.createSchema = void 0;
|
|
17
17
|
const protobuf_1 = require("@bufbuild/protobuf");
|
|
18
18
|
const generated_file_js_1 = require("./generated-file.js");
|
|
19
19
|
const runtime_imports_js_1 = require("./runtime-imports.js");
|
|
20
20
|
const import_symbol_js_1 = require("./import-symbol.js");
|
|
21
21
|
const import_path_js_1 = require("./import-path.js");
|
|
22
|
-
function createSchema(request, targets, pluginName, pluginVersion, tsNocheck, bootstrapWkt, rewriteImports) {
|
|
22
|
+
function createSchema(request, targets, pluginName, pluginVersion, tsNocheck, bootstrapWkt, rewriteImports, keepEmptyFiles) {
|
|
23
23
|
const descriptorSet = (0, protobuf_1.createDescriptorSet)(request.protoFile);
|
|
24
24
|
const filesToGenerate = findFilesToGenerate(descriptorSet, request);
|
|
25
25
|
const runtime = (0, runtime_imports_js_1.createRuntimeImports)(bootstrapWkt);
|
|
@@ -42,22 +42,38 @@ function createSchema(request, targets, pluginName, pluginVersion, tsNocheck, bo
|
|
|
42
42
|
pluginVersion,
|
|
43
43
|
parameter: request.parameter,
|
|
44
44
|
tsNocheck,
|
|
45
|
-
});
|
|
45
|
+
}, keepEmptyFiles);
|
|
46
46
|
generatedFiles.push(genFile);
|
|
47
47
|
return genFile;
|
|
48
48
|
},
|
|
49
49
|
};
|
|
50
50
|
return {
|
|
51
51
|
schema,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
getFileInfo() {
|
|
53
|
+
return generatedFiles.flatMap((file) => {
|
|
54
|
+
const fileInfo = file.getFileInfo();
|
|
55
|
+
// undefined is returned if the file has no content
|
|
56
|
+
if (!fileInfo) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
return [fileInfo];
|
|
60
|
+
});
|
|
57
61
|
},
|
|
58
62
|
};
|
|
59
63
|
}
|
|
60
64
|
exports.createSchema = createSchema;
|
|
65
|
+
function toResponse(files) {
|
|
66
|
+
return new protobuf_1.CodeGeneratorResponse({
|
|
67
|
+
supportedFeatures: protobuf_1.protoInt64.parse(protobuf_1.CodeGeneratorResponse_Feature.PROTO3_OPTIONAL),
|
|
68
|
+
file: files.map((f) => {
|
|
69
|
+
if (f.preamble !== undefined) {
|
|
70
|
+
f.content = f.preamble + "\n" + f.content;
|
|
71
|
+
}
|
|
72
|
+
return f;
|
|
73
|
+
}),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
exports.toResponse = toResponse;
|
|
61
77
|
function findFilesToGenerate(descriptorSet, request) {
|
|
62
78
|
const missing = request.fileToGenerate.filter((fileToGenerate) => descriptorSet.files.every((file) => fileToGenerate !== file.name + ".proto"));
|
|
63
79
|
if (missing.length) {
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2021-2022 Buf Technologies, Inc.
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
16
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.transpile = void 0;
|
|
20
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
21
|
+
const vfs_1 = require("@typescript/vfs");
|
|
22
|
+
/* eslint-disable import/no-named-as-default-member */
|
|
23
|
+
// The default options used to auto-transpile if needed.
|
|
24
|
+
const defaultOptions = {
|
|
25
|
+
// Type checking
|
|
26
|
+
strict: false,
|
|
27
|
+
// modules
|
|
28
|
+
module: typescript_1.default.ModuleKind.ES2020,
|
|
29
|
+
moduleResolution: typescript_1.default.ModuleResolutionKind.NodeJs,
|
|
30
|
+
noResolve: true,
|
|
31
|
+
resolveJsonModule: false,
|
|
32
|
+
// emit
|
|
33
|
+
emitBOM: false,
|
|
34
|
+
importsNotUsedAsValues: typescript_1.default.ImportsNotUsedAsValues.Preserve,
|
|
35
|
+
newLine: typescript_1.default.NewLineKind.LineFeed,
|
|
36
|
+
preserveValueImports: false,
|
|
37
|
+
// JavaScript Support
|
|
38
|
+
allowJs: true,
|
|
39
|
+
checkJs: false,
|
|
40
|
+
// Language and Environment
|
|
41
|
+
lib: [],
|
|
42
|
+
moduleDetection: "force",
|
|
43
|
+
target: typescript_1.default.ScriptTarget.ES2017,
|
|
44
|
+
// Completeness
|
|
45
|
+
skipLibCheck: true,
|
|
46
|
+
skipDefaultLibCheck: false,
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Create a transpiler using the given compiler options, which will compile the
|
|
50
|
+
* content provided in the files array.
|
|
51
|
+
*
|
|
52
|
+
* Note: this library intentionally transpiles with a pinned older version of
|
|
53
|
+
* TypeScript for stability. This version is denoted in this workspace's
|
|
54
|
+
* package.json. For the default set of compiler options, we use a lenient
|
|
55
|
+
* set of options because the general goal is to emit code as best as we can.
|
|
56
|
+
* For a list of the options used, see `defaultOptions` above.
|
|
57
|
+
*
|
|
58
|
+
* If this is not desirable for plugin authors, they are free to provide their
|
|
59
|
+
* own transpile function as part of the plugin initialization. If one is
|
|
60
|
+
* provided, it will be invoked instead and the framework's auto-transpilation
|
|
61
|
+
* will be bypassed.
|
|
62
|
+
*
|
|
63
|
+
* In addition, note that there is a dependency on @typescript/vfs in the
|
|
64
|
+
* top-level package as well as this package. This is to avoid npm hoisting
|
|
65
|
+
* @typescript/vfs to the top-level node_modules directory, which then causes
|
|
66
|
+
* type mismatches when trying to use it with this package's version of
|
|
67
|
+
* TypeScript. Ideally we would use something like Yarn's nohoist here, but
|
|
68
|
+
* npm does not support that yet.
|
|
69
|
+
*/
|
|
70
|
+
function createTranspiler(options, files) {
|
|
71
|
+
const fsMap = (0, vfs_1.createDefaultMapFromNodeModules)({
|
|
72
|
+
target: options.target,
|
|
73
|
+
});
|
|
74
|
+
files.forEach((file) => {
|
|
75
|
+
fsMap.set(file.name, file.content);
|
|
76
|
+
});
|
|
77
|
+
const system = (0, vfs_1.createSystem)(fsMap);
|
|
78
|
+
const host = (0, vfs_1.createVirtualCompilerHost)(system, options, typescript_1.default);
|
|
79
|
+
return typescript_1.default.createProgram({
|
|
80
|
+
rootNames: [...fsMap.keys()],
|
|
81
|
+
options,
|
|
82
|
+
host: host.compilerHost,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function transpile(files, transpileJs, transpileDts) {
|
|
86
|
+
const options = Object.assign(Object.assign({}, defaultOptions), { declaration: transpileDts, emitDeclarationOnly: transpileDts && !transpileJs });
|
|
87
|
+
// Create the transpiler (a ts.Program object)
|
|
88
|
+
const program = createTranspiler(options, files);
|
|
89
|
+
const results = [];
|
|
90
|
+
let err;
|
|
91
|
+
const result = program.emit(undefined, (fileName, data, writeByteOrderMark, onError, sourceFiles) => {
|
|
92
|
+
// We have to go through some hoops here because the header we add to each
|
|
93
|
+
// file is not part of the AST. So we find the TypeScript file we
|
|
94
|
+
// generated for each emitted file and add the header to each output ourselves.
|
|
95
|
+
if (!sourceFiles) {
|
|
96
|
+
err = new Error(`unable to map emitted file "${fileName}" to a source file: missing source files`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (sourceFiles.length !== 1) {
|
|
100
|
+
err = new Error(`unable to map emitted file "${fileName}" to a source file: expected 1 source file, got ${sourceFiles.length}`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const file = files.find((x) => sourceFiles[0].fileName === x.name);
|
|
104
|
+
if (!file) {
|
|
105
|
+
err = new Error(`unable to map emitted file "${fileName}" to a source file: not found`);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
results.push({
|
|
109
|
+
name: fileName,
|
|
110
|
+
preamble: file.preamble,
|
|
111
|
+
content: data,
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
if (err) {
|
|
115
|
+
throw err;
|
|
116
|
+
}
|
|
117
|
+
if (result.emitSkipped) {
|
|
118
|
+
throw Error("An problem occurred during transpilation and files were not generated. Contact the plugin author for support.");
|
|
119
|
+
}
|
|
120
|
+
return results;
|
|
121
|
+
}
|
|
122
|
+
exports.transpile = transpile;
|