@bufbuild/protoplugin 0.0.10 → 0.1.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/dist/cjs/create-es-plugin.js +13 -3
- package/dist/cjs/ecmascript/generated-file.js +3 -46
- package/dist/cjs/ecmascript/import-path.js +144 -0
- package/dist/cjs/ecmascript/schema.js +5 -22
- package/dist/esm/create-es-plugin.js +13 -3
- package/dist/esm/ecmascript/generated-file.js +2 -45
- package/dist/esm/ecmascript/import-path.js +137 -0
- package/dist/esm/ecmascript/schema.js +5 -22
- package/dist/types/ecmascript/generated-file.d.ts +2 -2
- package/dist/types/ecmascript/import-path.d.ts +64 -0
- package/dist/types/ecmascript/schema.d.ts +3 -2
- package/package.json +6 -8
|
@@ -27,8 +27,8 @@ function createEcmaScriptPlugin(init, generateFn) {
|
|
|
27
27
|
name: init.name,
|
|
28
28
|
version: init.version,
|
|
29
29
|
run(req) {
|
|
30
|
-
const { targets, tsNocheck, bootstrapWkt } = parseParameter(req.parameter, init.parseOption);
|
|
31
|
-
const { schema, toResponse } = (0, schema_js_1.createSchema)(req, targets, init.name, init.version, tsNocheck, bootstrapWkt);
|
|
30
|
+
const { targets, tsNocheck, bootstrapWkt, rewriteImports } = parseParameter(req.parameter, init.parseOption);
|
|
31
|
+
const { schema, toResponse } = (0, schema_js_1.createSchema)(req, targets, init.name, init.version, tsNocheck, bootstrapWkt, rewriteImports);
|
|
32
32
|
generateFn(schema);
|
|
33
33
|
const res = new protobuf_1.CodeGeneratorResponse();
|
|
34
34
|
toResponse(res);
|
|
@@ -41,6 +41,7 @@ function parseParameter(parameter, parseOption) {
|
|
|
41
41
|
let targets = ["js", "dts"];
|
|
42
42
|
let tsNocheck = true;
|
|
43
43
|
let bootstrapWkt = false;
|
|
44
|
+
const rewriteImports = [];
|
|
44
45
|
for (const { key, value } of splitParameter(parameter)) {
|
|
45
46
|
switch (key) {
|
|
46
47
|
case "target":
|
|
@@ -88,6 +89,15 @@ function parseParameter(parameter, parseOption) {
|
|
|
88
89
|
throw new error_js_1.PluginOptionError(`${key}=${value}`);
|
|
89
90
|
}
|
|
90
91
|
break;
|
|
92
|
+
case "rewrite_imports": {
|
|
93
|
+
const parts = value.split(":");
|
|
94
|
+
if (parts.length !== 2) {
|
|
95
|
+
throw new error_js_1.PluginOptionError(`${key}=${value}`, "must be in the form of <pattern>:<target>");
|
|
96
|
+
}
|
|
97
|
+
const [pattern, target] = parts;
|
|
98
|
+
rewriteImports.push({ pattern, target });
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
91
101
|
default:
|
|
92
102
|
if (parseOption === undefined) {
|
|
93
103
|
throw new error_js_1.PluginOptionError(`${key}=${value}`);
|
|
@@ -101,7 +111,7 @@ function parseParameter(parameter, parseOption) {
|
|
|
101
111
|
break;
|
|
102
112
|
}
|
|
103
113
|
}
|
|
104
|
-
return { targets, tsNocheck, bootstrapWkt };
|
|
114
|
+
return { targets, tsNocheck, bootstrapWkt, rewriteImports };
|
|
105
115
|
}
|
|
106
116
|
function splitParameter(parameter) {
|
|
107
117
|
if (parameter == undefined) {
|
|
@@ -17,8 +17,8 @@ exports.createGeneratedFile = void 0;
|
|
|
17
17
|
const protobuf_1 = require("@bufbuild/protobuf");
|
|
18
18
|
const import_symbol_js_1 = require("./import-symbol.js");
|
|
19
19
|
const gencommon_js_1 = require("./gencommon.js");
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
const import_path_js_1 = require("./import-path.js");
|
|
21
|
+
function createGeneratedFile(name, importPath, createTypeImport, runtimeImports, preambleSettings) {
|
|
22
22
|
let preamble;
|
|
23
23
|
const el = [];
|
|
24
24
|
return {
|
|
@@ -55,16 +55,6 @@ function createGeneratedFile(name, createTypeImport, runtimeImports, preambleSet
|
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
exports.createGeneratedFile = createGeneratedFile;
|
|
58
|
-
const importPathExtension = ".js";
|
|
59
|
-
const knownExtensionsRE = /\.(js|ts|d.ts)$/;
|
|
60
|
-
const relativePathRE = /^\.{1,2}\//;
|
|
61
|
-
function deriveImportPath(filename) {
|
|
62
|
-
let importPath = filename.replace(knownExtensionsRE, importPathExtension);
|
|
63
|
-
if (!relativePathRE.test(importPath)) {
|
|
64
|
-
importPath = "./" + importPath;
|
|
65
|
-
}
|
|
66
|
-
return importPath;
|
|
67
|
-
}
|
|
68
58
|
function elToContent(el, importerPath) {
|
|
69
59
|
const c = [];
|
|
70
60
|
const symbolToIdentifier = processImports(el, importerPath, (typeOnly, from, names) => {
|
|
@@ -221,7 +211,7 @@ function processImports(el, importerPath, makeImportStatement) {
|
|
|
221
211
|
// should never happen
|
|
222
212
|
continue;
|
|
223
213
|
}
|
|
224
|
-
const from = makeImportPathRelative(importerPath, s.from);
|
|
214
|
+
const from = (0, import_path_js_1.makeImportPathRelative)(importerPath, s.from);
|
|
225
215
|
if (i.types.size > 0) {
|
|
226
216
|
makeImportStatement(true, from, buildNames(i.types));
|
|
227
217
|
}
|
|
@@ -231,39 +221,6 @@ function processImports(el, importerPath, makeImportStatement) {
|
|
|
231
221
|
}
|
|
232
222
|
return symbolToIdentifier;
|
|
233
223
|
}
|
|
234
|
-
// makeImportPathRelative makes an import path relative to the file importing
|
|
235
|
-
// it. For example, consider the following files:
|
|
236
|
-
// - foo/foo.js
|
|
237
|
-
// - baz.js
|
|
238
|
-
// If foo.js wants to import baz.js, we return ../baz.js
|
|
239
|
-
function makeImportPathRelative(importer, importPath) {
|
|
240
|
-
if (!relativePathRE.test(importPath)) {
|
|
241
|
-
// We don't touch absolute imports, like @bufbuild/protobuf
|
|
242
|
-
return importPath;
|
|
243
|
-
}
|
|
244
|
-
let a = importer
|
|
245
|
-
.replace(/^\.\//, "")
|
|
246
|
-
.split("/")
|
|
247
|
-
.filter((p) => p.length > 0)
|
|
248
|
-
.slice(0, -1);
|
|
249
|
-
let b = importPath
|
|
250
|
-
.replace(/^\.\//, "")
|
|
251
|
-
.split("/")
|
|
252
|
-
.filter((p) => p.length > 0);
|
|
253
|
-
let matchingPartCount = 0;
|
|
254
|
-
for (let l = Math.min(a.length, b.length); matchingPartCount < l; matchingPartCount++) {
|
|
255
|
-
if (a[matchingPartCount] !== b[matchingPartCount]) {
|
|
256
|
-
break;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
a = a.slice(matchingPartCount);
|
|
260
|
-
b = b.slice(matchingPartCount);
|
|
261
|
-
const c = a
|
|
262
|
-
.map(() => "..")
|
|
263
|
-
.concat(b)
|
|
264
|
-
.join("/");
|
|
265
|
-
return relativePathRE.test(c) ? c : "./" + c;
|
|
266
|
-
}
|
|
267
224
|
function literalNumber(value) {
|
|
268
225
|
if (Number.isNaN(value)) {
|
|
269
226
|
return "globalThis.Number.NaN";
|
|
@@ -0,0 +1,144 @@
|
|
|
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.makeImportPathRelative = exports.deriveImportPath = exports.relativePathRE = exports.makeImportPath = exports.rewriteImportPath = void 0;
|
|
17
|
+
const protobuf_1 = require("@bufbuild/protobuf");
|
|
18
|
+
const cache = new WeakMap();
|
|
19
|
+
/**
|
|
20
|
+
* Apply import rewrites to the given path.
|
|
21
|
+
*/
|
|
22
|
+
function rewriteImportPath(importPath, rewriteImports) {
|
|
23
|
+
let ri = cache.get(rewriteImports);
|
|
24
|
+
if (ri === undefined) {
|
|
25
|
+
ri = rewriteImports.map(({ pattern, target }) => {
|
|
26
|
+
return {
|
|
27
|
+
pattern: starToRegExp(pattern),
|
|
28
|
+
target,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
cache.set(rewriteImports, ri);
|
|
32
|
+
}
|
|
33
|
+
for (const { pattern, target } of ri) {
|
|
34
|
+
if (pattern.test(importPath)) {
|
|
35
|
+
return (target.replace(/\/$/, "") + importPath.replace(exports.relativePathRE, "/"));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return importPath;
|
|
39
|
+
}
|
|
40
|
+
exports.rewriteImportPath = rewriteImportPath;
|
|
41
|
+
function starToRegExp(star) {
|
|
42
|
+
const r = ["^"];
|
|
43
|
+
for (let i = 0; i < star.length; i++) {
|
|
44
|
+
switch (star[i]) {
|
|
45
|
+
case "*":
|
|
46
|
+
if (star[i + 1] === "*" && star[i + 2] === "/") {
|
|
47
|
+
i += 2;
|
|
48
|
+
r.push("([^\\/]+\\/)*");
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
r.push("[^\\/]*");
|
|
52
|
+
break;
|
|
53
|
+
case ".":
|
|
54
|
+
case "+":
|
|
55
|
+
case "?":
|
|
56
|
+
case "^":
|
|
57
|
+
case "$":
|
|
58
|
+
case "{":
|
|
59
|
+
case "}":
|
|
60
|
+
case "(":
|
|
61
|
+
case ")":
|
|
62
|
+
case "|":
|
|
63
|
+
case "[":
|
|
64
|
+
case "]":
|
|
65
|
+
case "\\":
|
|
66
|
+
r.push("\\", star[i]);
|
|
67
|
+
break;
|
|
68
|
+
default:
|
|
69
|
+
r.push(star[i]);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
r.push("$");
|
|
74
|
+
return new RegExp(r.join(""));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Returns the import path for files generated by the base type generator
|
|
78
|
+
* protoc-gen-es.
|
|
79
|
+
*/
|
|
80
|
+
function makeImportPath(file, bootstrapWkt, filesToGenerate) {
|
|
81
|
+
// Well-known types are published with the runtime package. We usually want
|
|
82
|
+
// the generated code to import them from the runtime package, with the
|
|
83
|
+
// following exceptions:
|
|
84
|
+
// 1. We are bootstrapping the runtime package via the plugin option
|
|
85
|
+
// "bootstrap_wkt". In that case, we cannot refer to the runtime package
|
|
86
|
+
// itself.
|
|
87
|
+
// 2. We were explicitly asked to generate the well-known type.
|
|
88
|
+
if (!bootstrapWkt &&
|
|
89
|
+
!filesToGenerate.includes(file) &&
|
|
90
|
+
protobuf_1.codegenInfo.wktSourceFiles.includes(file.name + ".proto")) {
|
|
91
|
+
return protobuf_1.codegenInfo.packageName;
|
|
92
|
+
}
|
|
93
|
+
return "./" + file.name + "_pb.js";
|
|
94
|
+
}
|
|
95
|
+
exports.makeImportPath = makeImportPath;
|
|
96
|
+
exports.relativePathRE = /^\.{1,2}\//;
|
|
97
|
+
/**
|
|
98
|
+
* Derives an ECMAScript module import path from a file path. For example,
|
|
99
|
+
* the path `foo/bar.ts` is transformed into `./foo/bar.js`.
|
|
100
|
+
*/
|
|
101
|
+
function deriveImportPath(filename) {
|
|
102
|
+
let importPath = filename.replace(/\.(js|ts|d.ts)$/, ".js");
|
|
103
|
+
if (!exports.relativePathRE.test(importPath)) {
|
|
104
|
+
importPath = "./" + importPath;
|
|
105
|
+
}
|
|
106
|
+
return importPath;
|
|
107
|
+
}
|
|
108
|
+
exports.deriveImportPath = deriveImportPath;
|
|
109
|
+
/**
|
|
110
|
+
* Makes an import path relative to the file importing it. For example,
|
|
111
|
+
* consider the following files:
|
|
112
|
+
* - foo/foo.js
|
|
113
|
+
* - baz.js
|
|
114
|
+
* If foo.js wants to import baz.js, we return ../baz.js
|
|
115
|
+
*/
|
|
116
|
+
function makeImportPathRelative(importer, importPath) {
|
|
117
|
+
if (!exports.relativePathRE.test(importPath)) {
|
|
118
|
+
// We don't touch absolute imports, like @bufbuild/protobuf
|
|
119
|
+
return importPath;
|
|
120
|
+
}
|
|
121
|
+
let a = importer
|
|
122
|
+
.replace(/^\.\//, "")
|
|
123
|
+
.split("/")
|
|
124
|
+
.filter((p) => p.length > 0)
|
|
125
|
+
.slice(0, -1);
|
|
126
|
+
let b = importPath
|
|
127
|
+
.replace(/^\.\//, "")
|
|
128
|
+
.split("/")
|
|
129
|
+
.filter((p) => p.length > 0);
|
|
130
|
+
let matchingPartCount = 0;
|
|
131
|
+
for (let l = Math.min(a.length, b.length); matchingPartCount < l; matchingPartCount++) {
|
|
132
|
+
if (a[matchingPartCount] !== b[matchingPartCount]) {
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
a = a.slice(matchingPartCount);
|
|
137
|
+
b = b.slice(matchingPartCount);
|
|
138
|
+
const c = a
|
|
139
|
+
.map(() => "..")
|
|
140
|
+
.concat(b)
|
|
141
|
+
.join("/");
|
|
142
|
+
return exports.relativePathRE.test(c) ? c : "./" + c;
|
|
143
|
+
}
|
|
144
|
+
exports.makeImportPathRelative = makeImportPathRelative;
|
|
@@ -18,13 +18,14 @@ 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
23
|
const descriptorSet = (0, protobuf_1.createDescriptorSet)(request.protoFile);
|
|
23
24
|
const filesToGenerate = findFilesToGenerate(descriptorSet, request);
|
|
24
25
|
const runtime = (0, runtime_imports_js_1.createRuntimeImports)(bootstrapWkt);
|
|
25
26
|
const createTypeImport = (desc) => {
|
|
26
27
|
const name = protobuf_1.codegenInfo.localName(desc);
|
|
27
|
-
const from = makeImportPath(desc.file, bootstrapWkt, filesToGenerate);
|
|
28
|
+
const from = (0, import_path_js_1.rewriteImportPath)((0, import_path_js_1.makeImportPath)(desc.file, bootstrapWkt, filesToGenerate), rewriteImports);
|
|
28
29
|
return (0, import_symbol_js_1.createImportSymbol)(name, from);
|
|
29
30
|
};
|
|
30
31
|
const generatedFiles = [];
|
|
@@ -35,7 +36,8 @@ function createSchema(request, targets, pluginName, pluginVersion, tsNocheck, bo
|
|
|
35
36
|
files: filesToGenerate,
|
|
36
37
|
allFiles: descriptorSet.files,
|
|
37
38
|
generateFile(name) {
|
|
38
|
-
const
|
|
39
|
+
const importPath = (0, import_path_js_1.rewriteImportPath)((0, import_path_js_1.deriveImportPath)(name), rewriteImports);
|
|
40
|
+
const genFile = (0, generated_file_js_1.createGeneratedFile)(name, importPath, createTypeImport, runtime, {
|
|
39
41
|
pluginName,
|
|
40
42
|
pluginVersion,
|
|
41
43
|
parameter: request.parameter,
|
|
@@ -63,22 +65,3 @@ function findFilesToGenerate(descriptorSet, request) {
|
|
|
63
65
|
}
|
|
64
66
|
return descriptorSet.files.filter((file) => request.fileToGenerate.includes(file.name + ".proto"));
|
|
65
67
|
}
|
|
66
|
-
/**
|
|
67
|
-
* Returns the import path for files generated by the base type generator
|
|
68
|
-
* protoc-gen-es.
|
|
69
|
-
*/
|
|
70
|
-
function makeImportPath(file, bootstrapWkt, filesToGenerate) {
|
|
71
|
-
// Well-known types are published with the runtime package. We usually want
|
|
72
|
-
// the generated code to import them from the runtime package, with the
|
|
73
|
-
// following exceptions:
|
|
74
|
-
// 1. We are bootstrapping the runtime package via the plugin option
|
|
75
|
-
// "bootstrap_wkt". In that case, we cannot refer to the runtime package
|
|
76
|
-
// itself.
|
|
77
|
-
// 2. We were explicitly asked to generate the well-known type.
|
|
78
|
-
if (!bootstrapWkt &&
|
|
79
|
-
!filesToGenerate.includes(file) &&
|
|
80
|
-
protobuf_1.codegenInfo.wktSourceFiles.includes(file.name + ".proto")) {
|
|
81
|
-
return protobuf_1.codegenInfo.packageName;
|
|
82
|
-
}
|
|
83
|
-
return "./" + file.name + "_pb.js";
|
|
84
|
-
}
|
|
@@ -24,8 +24,8 @@ export function createEcmaScriptPlugin(init, generateFn) {
|
|
|
24
24
|
name: init.name,
|
|
25
25
|
version: init.version,
|
|
26
26
|
run(req) {
|
|
27
|
-
const { targets, tsNocheck, bootstrapWkt } = parseParameter(req.parameter, init.parseOption);
|
|
28
|
-
const { schema, toResponse } = createSchema(req, targets, init.name, init.version, tsNocheck, bootstrapWkt);
|
|
27
|
+
const { targets, tsNocheck, bootstrapWkt, rewriteImports } = parseParameter(req.parameter, init.parseOption);
|
|
28
|
+
const { schema, toResponse } = createSchema(req, targets, init.name, init.version, tsNocheck, bootstrapWkt, rewriteImports);
|
|
29
29
|
generateFn(schema);
|
|
30
30
|
const res = new CodeGeneratorResponse();
|
|
31
31
|
toResponse(res);
|
|
@@ -37,6 +37,7 @@ function parseParameter(parameter, parseOption) {
|
|
|
37
37
|
let targets = ["js", "dts"];
|
|
38
38
|
let tsNocheck = true;
|
|
39
39
|
let bootstrapWkt = false;
|
|
40
|
+
const rewriteImports = [];
|
|
40
41
|
for (const { key, value } of splitParameter(parameter)) {
|
|
41
42
|
switch (key) {
|
|
42
43
|
case "target":
|
|
@@ -84,6 +85,15 @@ function parseParameter(parameter, parseOption) {
|
|
|
84
85
|
throw new PluginOptionError(`${key}=${value}`);
|
|
85
86
|
}
|
|
86
87
|
break;
|
|
88
|
+
case "rewrite_imports": {
|
|
89
|
+
const parts = value.split(":");
|
|
90
|
+
if (parts.length !== 2) {
|
|
91
|
+
throw new PluginOptionError(`${key}=${value}`, "must be in the form of <pattern>:<target>");
|
|
92
|
+
}
|
|
93
|
+
const [pattern, target] = parts;
|
|
94
|
+
rewriteImports.push({ pattern, target });
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
87
97
|
default:
|
|
88
98
|
if (parseOption === undefined) {
|
|
89
99
|
throw new PluginOptionError(`${key}=${value}`);
|
|
@@ -97,7 +107,7 @@ function parseParameter(parameter, parseOption) {
|
|
|
97
107
|
break;
|
|
98
108
|
}
|
|
99
109
|
}
|
|
100
|
-
return { targets, tsNocheck, bootstrapWkt };
|
|
110
|
+
return { targets, tsNocheck, bootstrapWkt, rewriteImports };
|
|
101
111
|
}
|
|
102
112
|
function splitParameter(parameter) {
|
|
103
113
|
if (parameter == undefined) {
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
import { CodeGeneratorResponse_File, } from "@bufbuild/protobuf";
|
|
15
15
|
import { createImportSymbol } from "./import-symbol.js";
|
|
16
16
|
import { literalString, makeFilePreamble } from "./gencommon.js";
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
import { makeImportPathRelative } from "./import-path.js";
|
|
18
|
+
export function createGeneratedFile(name, importPath, createTypeImport, runtimeImports, preambleSettings) {
|
|
19
19
|
let preamble;
|
|
20
20
|
const el = [];
|
|
21
21
|
return {
|
|
@@ -51,16 +51,6 @@ export function createGeneratedFile(name, createTypeImport, runtimeImports, prea
|
|
|
51
51
|
},
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
-
const importPathExtension = ".js";
|
|
55
|
-
const knownExtensionsRE = /\.(js|ts|d.ts)$/;
|
|
56
|
-
const relativePathRE = /^\.{1,2}\//;
|
|
57
|
-
function deriveImportPath(filename) {
|
|
58
|
-
let importPath = filename.replace(knownExtensionsRE, importPathExtension);
|
|
59
|
-
if (!relativePathRE.test(importPath)) {
|
|
60
|
-
importPath = "./" + importPath;
|
|
61
|
-
}
|
|
62
|
-
return importPath;
|
|
63
|
-
}
|
|
64
54
|
function elToContent(el, importerPath) {
|
|
65
55
|
const c = [];
|
|
66
56
|
const symbolToIdentifier = processImports(el, importerPath, (typeOnly, from, names) => {
|
|
@@ -227,39 +217,6 @@ function processImports(el, importerPath, makeImportStatement) {
|
|
|
227
217
|
}
|
|
228
218
|
return symbolToIdentifier;
|
|
229
219
|
}
|
|
230
|
-
// makeImportPathRelative makes an import path relative to the file importing
|
|
231
|
-
// it. For example, consider the following files:
|
|
232
|
-
// - foo/foo.js
|
|
233
|
-
// - baz.js
|
|
234
|
-
// If foo.js wants to import baz.js, we return ../baz.js
|
|
235
|
-
function makeImportPathRelative(importer, importPath) {
|
|
236
|
-
if (!relativePathRE.test(importPath)) {
|
|
237
|
-
// We don't touch absolute imports, like @bufbuild/protobuf
|
|
238
|
-
return importPath;
|
|
239
|
-
}
|
|
240
|
-
let a = importer
|
|
241
|
-
.replace(/^\.\//, "")
|
|
242
|
-
.split("/")
|
|
243
|
-
.filter((p) => p.length > 0)
|
|
244
|
-
.slice(0, -1);
|
|
245
|
-
let b = importPath
|
|
246
|
-
.replace(/^\.\//, "")
|
|
247
|
-
.split("/")
|
|
248
|
-
.filter((p) => p.length > 0);
|
|
249
|
-
let matchingPartCount = 0;
|
|
250
|
-
for (let l = Math.min(a.length, b.length); matchingPartCount < l; matchingPartCount++) {
|
|
251
|
-
if (a[matchingPartCount] !== b[matchingPartCount]) {
|
|
252
|
-
break;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
a = a.slice(matchingPartCount);
|
|
256
|
-
b = b.slice(matchingPartCount);
|
|
257
|
-
const c = a
|
|
258
|
-
.map(() => "..")
|
|
259
|
-
.concat(b)
|
|
260
|
-
.join("/");
|
|
261
|
-
return relativePathRE.test(c) ? c : "./" + c;
|
|
262
|
-
}
|
|
263
220
|
function literalNumber(value) {
|
|
264
221
|
if (Number.isNaN(value)) {
|
|
265
222
|
return "globalThis.Number.NaN";
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// Copyright 2021-2022 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
|
+
import { codegenInfo } from "@bufbuild/protobuf";
|
|
15
|
+
const cache = new WeakMap();
|
|
16
|
+
/**
|
|
17
|
+
* Apply import rewrites to the given path.
|
|
18
|
+
*/
|
|
19
|
+
export function rewriteImportPath(importPath, rewriteImports) {
|
|
20
|
+
let ri = cache.get(rewriteImports);
|
|
21
|
+
if (ri === undefined) {
|
|
22
|
+
ri = rewriteImports.map(({ pattern, target }) => {
|
|
23
|
+
return {
|
|
24
|
+
pattern: starToRegExp(pattern),
|
|
25
|
+
target,
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
cache.set(rewriteImports, ri);
|
|
29
|
+
}
|
|
30
|
+
for (const { pattern, target } of ri) {
|
|
31
|
+
if (pattern.test(importPath)) {
|
|
32
|
+
return (target.replace(/\/$/, "") + importPath.replace(relativePathRE, "/"));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return importPath;
|
|
36
|
+
}
|
|
37
|
+
function starToRegExp(star) {
|
|
38
|
+
const r = ["^"];
|
|
39
|
+
for (let i = 0; i < star.length; i++) {
|
|
40
|
+
switch (star[i]) {
|
|
41
|
+
case "*":
|
|
42
|
+
if (star[i + 1] === "*" && star[i + 2] === "/") {
|
|
43
|
+
i += 2;
|
|
44
|
+
r.push("([^\\/]+\\/)*");
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
r.push("[^\\/]*");
|
|
48
|
+
break;
|
|
49
|
+
case ".":
|
|
50
|
+
case "+":
|
|
51
|
+
case "?":
|
|
52
|
+
case "^":
|
|
53
|
+
case "$":
|
|
54
|
+
case "{":
|
|
55
|
+
case "}":
|
|
56
|
+
case "(":
|
|
57
|
+
case ")":
|
|
58
|
+
case "|":
|
|
59
|
+
case "[":
|
|
60
|
+
case "]":
|
|
61
|
+
case "\\":
|
|
62
|
+
r.push("\\", star[i]);
|
|
63
|
+
break;
|
|
64
|
+
default:
|
|
65
|
+
r.push(star[i]);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
r.push("$");
|
|
70
|
+
return new RegExp(r.join(""));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Returns the import path for files generated by the base type generator
|
|
74
|
+
* protoc-gen-es.
|
|
75
|
+
*/
|
|
76
|
+
export function makeImportPath(file, bootstrapWkt, filesToGenerate) {
|
|
77
|
+
// Well-known types are published with the runtime package. We usually want
|
|
78
|
+
// the generated code to import them from the runtime package, with the
|
|
79
|
+
// following exceptions:
|
|
80
|
+
// 1. We are bootstrapping the runtime package via the plugin option
|
|
81
|
+
// "bootstrap_wkt". In that case, we cannot refer to the runtime package
|
|
82
|
+
// itself.
|
|
83
|
+
// 2. We were explicitly asked to generate the well-known type.
|
|
84
|
+
if (!bootstrapWkt &&
|
|
85
|
+
!filesToGenerate.includes(file) &&
|
|
86
|
+
codegenInfo.wktSourceFiles.includes(file.name + ".proto")) {
|
|
87
|
+
return codegenInfo.packageName;
|
|
88
|
+
}
|
|
89
|
+
return "./" + file.name + "_pb.js";
|
|
90
|
+
}
|
|
91
|
+
export const relativePathRE = /^\.{1,2}\//;
|
|
92
|
+
/**
|
|
93
|
+
* Derives an ECMAScript module import path from a file path. For example,
|
|
94
|
+
* the path `foo/bar.ts` is transformed into `./foo/bar.js`.
|
|
95
|
+
*/
|
|
96
|
+
export function deriveImportPath(filename) {
|
|
97
|
+
let importPath = filename.replace(/\.(js|ts|d.ts)$/, ".js");
|
|
98
|
+
if (!relativePathRE.test(importPath)) {
|
|
99
|
+
importPath = "./" + importPath;
|
|
100
|
+
}
|
|
101
|
+
return importPath;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Makes an import path relative to the file importing it. For example,
|
|
105
|
+
* consider the following files:
|
|
106
|
+
* - foo/foo.js
|
|
107
|
+
* - baz.js
|
|
108
|
+
* If foo.js wants to import baz.js, we return ../baz.js
|
|
109
|
+
*/
|
|
110
|
+
export function makeImportPathRelative(importer, importPath) {
|
|
111
|
+
if (!relativePathRE.test(importPath)) {
|
|
112
|
+
// We don't touch absolute imports, like @bufbuild/protobuf
|
|
113
|
+
return importPath;
|
|
114
|
+
}
|
|
115
|
+
let a = importer
|
|
116
|
+
.replace(/^\.\//, "")
|
|
117
|
+
.split("/")
|
|
118
|
+
.filter((p) => p.length > 0)
|
|
119
|
+
.slice(0, -1);
|
|
120
|
+
let b = importPath
|
|
121
|
+
.replace(/^\.\//, "")
|
|
122
|
+
.split("/")
|
|
123
|
+
.filter((p) => p.length > 0);
|
|
124
|
+
let matchingPartCount = 0;
|
|
125
|
+
for (let l = Math.min(a.length, b.length); matchingPartCount < l; matchingPartCount++) {
|
|
126
|
+
if (a[matchingPartCount] !== b[matchingPartCount]) {
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
a = a.slice(matchingPartCount);
|
|
131
|
+
b = b.slice(matchingPartCount);
|
|
132
|
+
const c = a
|
|
133
|
+
.map(() => "..")
|
|
134
|
+
.concat(b)
|
|
135
|
+
.join("/");
|
|
136
|
+
return relativePathRE.test(c) ? c : "./" + c;
|
|
137
|
+
}
|
|
@@ -15,13 +15,14 @@ import { codegenInfo, CodeGeneratorResponse_Feature, createDescriptorSet, protoI
|
|
|
15
15
|
import { createGeneratedFile } from "./generated-file.js";
|
|
16
16
|
import { createRuntimeImports } from "./runtime-imports.js";
|
|
17
17
|
import { createImportSymbol } from "./import-symbol.js";
|
|
18
|
-
|
|
18
|
+
import { deriveImportPath, makeImportPath, rewriteImportPath, } from "./import-path.js";
|
|
19
|
+
export function createSchema(request, targets, pluginName, pluginVersion, tsNocheck, bootstrapWkt, rewriteImports) {
|
|
19
20
|
const descriptorSet = createDescriptorSet(request.protoFile);
|
|
20
21
|
const filesToGenerate = findFilesToGenerate(descriptorSet, request);
|
|
21
22
|
const runtime = createRuntimeImports(bootstrapWkt);
|
|
22
23
|
const createTypeImport = (desc) => {
|
|
23
24
|
const name = codegenInfo.localName(desc);
|
|
24
|
-
const from = makeImportPath(desc.file, bootstrapWkt, filesToGenerate);
|
|
25
|
+
const from = rewriteImportPath(makeImportPath(desc.file, bootstrapWkt, filesToGenerate), rewriteImports);
|
|
25
26
|
return createImportSymbol(name, from);
|
|
26
27
|
};
|
|
27
28
|
const generatedFiles = [];
|
|
@@ -32,7 +33,8 @@ export function createSchema(request, targets, pluginName, pluginVersion, tsNoch
|
|
|
32
33
|
files: filesToGenerate,
|
|
33
34
|
allFiles: descriptorSet.files,
|
|
34
35
|
generateFile(name) {
|
|
35
|
-
const
|
|
36
|
+
const importPath = rewriteImportPath(deriveImportPath(name), rewriteImports);
|
|
37
|
+
const genFile = createGeneratedFile(name, importPath, createTypeImport, runtime, {
|
|
36
38
|
pluginName,
|
|
37
39
|
pluginVersion,
|
|
38
40
|
parameter: request.parameter,
|
|
@@ -59,22 +61,3 @@ function findFilesToGenerate(descriptorSet, request) {
|
|
|
59
61
|
}
|
|
60
62
|
return descriptorSet.files.filter((file) => request.fileToGenerate.includes(file.name + ".proto"));
|
|
61
63
|
}
|
|
62
|
-
/**
|
|
63
|
-
* Returns the import path for files generated by the base type generator
|
|
64
|
-
* protoc-gen-es.
|
|
65
|
-
*/
|
|
66
|
-
function makeImportPath(file, bootstrapWkt, filesToGenerate) {
|
|
67
|
-
// Well-known types are published with the runtime package. We usually want
|
|
68
|
-
// the generated code to import them from the runtime package, with the
|
|
69
|
-
// following exceptions:
|
|
70
|
-
// 1. We are bootstrapping the runtime package via the plugin option
|
|
71
|
-
// "bootstrap_wkt". In that case, we cannot refer to the runtime package
|
|
72
|
-
// itself.
|
|
73
|
-
// 2. We were explicitly asked to generate the well-known type.
|
|
74
|
-
if (!bootstrapWkt &&
|
|
75
|
-
!filesToGenerate.includes(file) &&
|
|
76
|
-
codegenInfo.wktSourceFiles.includes(file.name + ".proto")) {
|
|
77
|
-
return codegenInfo.packageName;
|
|
78
|
-
}
|
|
79
|
-
return "./" + file.name + "_pb.js";
|
|
80
|
-
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DescEnum, DescFile, DescMessage } from "@bufbuild/protobuf";
|
|
2
2
|
import { CodeGeneratorResponse } from "@bufbuild/protobuf";
|
|
3
3
|
import type { ImportSymbol } from "./import-symbol.js";
|
|
4
|
-
import type { RuntimeImports } from "./runtime-imports";
|
|
4
|
+
import type { RuntimeImports } from "./runtime-imports.js";
|
|
5
5
|
/**
|
|
6
6
|
* All types that can be passed to GeneratedFile.print()
|
|
7
7
|
*/
|
|
@@ -54,7 +54,7 @@ export interface GenerateFileToResponse {
|
|
|
54
54
|
toResponse(res: CodeGeneratorResponse): void;
|
|
55
55
|
}
|
|
56
56
|
declare type CreateTypeImportFn = (desc: DescMessage | DescEnum) => ImportSymbol;
|
|
57
|
-
export declare function createGeneratedFile(name: string, createTypeImport: CreateTypeImportFn, runtimeImports: RuntimeImports, preambleSettings: {
|
|
57
|
+
export declare function createGeneratedFile(name: string, importPath: string, createTypeImport: CreateTypeImportFn, runtimeImports: RuntimeImports, preambleSettings: {
|
|
58
58
|
pluginName: string;
|
|
59
59
|
pluginVersion: string;
|
|
60
60
|
parameter: string | undefined;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { DescFile } from "@bufbuild/protobuf";
|
|
2
|
+
/**
|
|
3
|
+
* A configuration for rewriting import paths, a feature mainly used for
|
|
4
|
+
* remote code generation in the BSR npm registry, which makes it possible
|
|
5
|
+
* to serve the output of a BSR module and a plugin in an individual package.
|
|
6
|
+
*
|
|
7
|
+
* All plugins based on @bufbuild/protoplugin support the option
|
|
8
|
+
* "rewrite_imports", which is parsed into this type. The option can be given
|
|
9
|
+
* multiple times, in the form of `rewrite_imports=<pattern>:<target>`.
|
|
10
|
+
*
|
|
11
|
+
* The pattern is a very reduced subset of glob:
|
|
12
|
+
* - `*` matches zero or more characters except `/`.
|
|
13
|
+
* - `**` matches zero or more path elements, where an element is one or more
|
|
14
|
+
* characters with a trailing `/`.
|
|
15
|
+
*
|
|
16
|
+
* The target is typically a npm package name, for example `@scope/pkg`.
|
|
17
|
+
*
|
|
18
|
+
* If any generated file imports from a path matching one of the patterns, the
|
|
19
|
+
* import path is rewritten to the corresponding target, by prepending the
|
|
20
|
+
* target to the import path (after replacing any leading ./ or ../ from the
|
|
21
|
+
* import path with / first).
|
|
22
|
+
*
|
|
23
|
+
* Note that the pattern is matched against the import path before it is made
|
|
24
|
+
* relative to the file importing it. The first matching pattern wins.
|
|
25
|
+
*
|
|
26
|
+
* For example, the pattern `./foo/**\/*_pb.js` (escaped for block comment!)
|
|
27
|
+
* matches:
|
|
28
|
+
* - ./foo/bar_pb.js
|
|
29
|
+
* - ./foo/bar/baz_pb.js
|
|
30
|
+
*
|
|
31
|
+
* But neither of:
|
|
32
|
+
* - ./bar_pb.js
|
|
33
|
+
* - ./foo/bar_xx.js
|
|
34
|
+
*
|
|
35
|
+
* With the target `@scope/pkg`, the import path `./foo/bar_pb.js` is
|
|
36
|
+
* transformed to `@scope/pkg/foo/bar_pb.js`.
|
|
37
|
+
*/
|
|
38
|
+
export declare type RewriteImports = {
|
|
39
|
+
pattern: string;
|
|
40
|
+
target: string;
|
|
41
|
+
}[];
|
|
42
|
+
/**
|
|
43
|
+
* Apply import rewrites to the given path.
|
|
44
|
+
*/
|
|
45
|
+
export declare function rewriteImportPath(importPath: string, rewriteImports: RewriteImports): string;
|
|
46
|
+
/**
|
|
47
|
+
* Returns the import path for files generated by the base type generator
|
|
48
|
+
* protoc-gen-es.
|
|
49
|
+
*/
|
|
50
|
+
export declare function makeImportPath(file: DescFile, bootstrapWkt: boolean, filesToGenerate: DescFile[]): string;
|
|
51
|
+
export declare const relativePathRE: RegExp;
|
|
52
|
+
/**
|
|
53
|
+
* Derives an ECMAScript module import path from a file path. For example,
|
|
54
|
+
* the path `foo/bar.ts` is transformed into `./foo/bar.js`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function deriveImportPath(filename: string): string;
|
|
57
|
+
/**
|
|
58
|
+
* Makes an import path relative to the file importing it. For example,
|
|
59
|
+
* consider the following files:
|
|
60
|
+
* - foo/foo.js
|
|
61
|
+
* - baz.js
|
|
62
|
+
* If foo.js wants to import baz.js, we return ../baz.js
|
|
63
|
+
*/
|
|
64
|
+
export declare function makeImportPathRelative(importer: string, importPath: string): string;
|
|
@@ -2,7 +2,8 @@ import type { CodeGeneratorRequest, DescFile } from "@bufbuild/protobuf";
|
|
|
2
2
|
import { CodeGeneratorResponse } from "@bufbuild/protobuf";
|
|
3
3
|
import type { GeneratedFile } from "./generated-file.js";
|
|
4
4
|
import { RuntimeImports } from "./runtime-imports.js";
|
|
5
|
-
import type { Target } from "./target";
|
|
5
|
+
import type { Target } from "./target.js";
|
|
6
|
+
import { RewriteImports } from "./import-path.js";
|
|
6
7
|
/**
|
|
7
8
|
* Schema describes the files and types that the plugin is requested to
|
|
8
9
|
* generate.
|
|
@@ -37,5 +38,5 @@ interface SchemaController {
|
|
|
37
38
|
schema: Schema;
|
|
38
39
|
toResponse: (res: CodeGeneratorResponse) => void;
|
|
39
40
|
}
|
|
40
|
-
export declare function createSchema(request: CodeGeneratorRequest, targets: Target[], pluginName: string, pluginVersion: string, tsNocheck: boolean, bootstrapWkt: boolean): SchemaController;
|
|
41
|
+
export declare function createSchema(request: CodeGeneratorRequest, targets: Target[], pluginName: string, pluginVersion: string, tsNocheck: boolean, bootstrapWkt: boolean, rewriteImports: RewriteImports): SchemaController;
|
|
41
42
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bufbuild/protoplugin",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.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": {
|
|
@@ -12,20 +12,18 @@
|
|
|
12
12
|
"scripts": {
|
|
13
13
|
"clean": "rm -rf ./dist/cjs/* ./dist/esm/* ./dist/types/*",
|
|
14
14
|
"build": "npm run build:cjs && npm run build:esm+types",
|
|
15
|
-
"build:cjs": "
|
|
16
|
-
"build:esm+types": "
|
|
15
|
+
"build:cjs": "../../node_modules/typescript/bin/tsc --project tsconfig.json --module commonjs --outDir ./dist/cjs && echo >./dist/cjs/package.json '{\"type\":\"commonjs\"}'",
|
|
16
|
+
"build:esm+types": "../../node_modules/typescript/bin/tsc --project tsconfig.json --module ES2015 --outDir ./dist/esm --declaration --declarationDir ./dist/types"
|
|
17
17
|
},
|
|
18
18
|
"type": "module",
|
|
19
19
|
"exports": {
|
|
20
20
|
".": {
|
|
21
21
|
"import": "./dist/esm/index.js",
|
|
22
|
-
"require": "./dist/cjs/index.js"
|
|
23
|
-
"default": "./dist/esm/index.js"
|
|
22
|
+
"require": "./dist/cjs/index.js"
|
|
24
23
|
},
|
|
25
24
|
"./ecmascript": {
|
|
26
25
|
"import": "./dist/esm/ecmascript/index.js",
|
|
27
|
-
"require": "./dist/cjs/ecmascript/index.js"
|
|
28
|
-
"default": "./dist/esm/ecmascript/index.js"
|
|
26
|
+
"require": "./dist/cjs/ecmascript/index.js"
|
|
29
27
|
}
|
|
30
28
|
},
|
|
31
29
|
"types": "./dist/types/index.d.ts",
|
|
@@ -37,7 +35,7 @@
|
|
|
37
35
|
}
|
|
38
36
|
},
|
|
39
37
|
"dependencies": {
|
|
40
|
-
"@bufbuild/protobuf": "0.0
|
|
38
|
+
"@bufbuild/protobuf": "0.1.0"
|
|
41
39
|
},
|
|
42
40
|
"devDependencies": {
|
|
43
41
|
"typescript": "^4.7.4"
|