-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
147 lines (117 loc) · 3.76 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
const Promise = require('bluebird');
const os = require('os');
const fs = require('fs');
const path = require('path');
const rimraf = Promise.promisify(require('rimraf'));
const protobuf = require('protobufjs');
const loaderUtils = require('loader-utils');
const exe_ext = process.platform === 'win32' ? '.exe' : '';
const grpcToolsDir = path.join(path.dirname(require.resolve('grpc-tools')), 'bin');
const protoc = path.join(grpcToolsDir, 'protoc' + exe_ext);
const protocGrpcPlugin = path.join(grpcToolsDir, 'grpc_node_plugin' + exe_ext);
const tmpDir = path.join(os.tmpdir(), `grpc-loader-`);
const readFile = Promise.promisify(fs.readFile);
const writeFile = Promise.promisify(fs.writeFile);
const mkdtemp = Promise.promisify(fs.mkdtemp);
const execFile = Promise.promisify(require('child_process').execFile, {
multiArgs: true
});
function toUnixPath(str) {
return str.replace(/\\/g, '\/');
}
async function getGeneratedFile(srcPath, dir) {
const filePath = path.basename(srcPath).replace(/\.[^/.]+$/, '');
const protocFilePath = path.join(dir, `${filePath}_pb.js`);
const grpcFilePath = path.join(dir, `${filePath}_grpc_pb.js`);
const grpcFileData = await readFile(grpcFilePath, 'utf8');
return {
protocFilePath,
grpcFilePath,
grpcFileData,
};
}
function createTmpDir() {
return mkdtemp(tmpDir);
}
function removeTmpDir(dir) {
return rimraf(dir);
}
function generateOutput(protocFilePath, grpcFilePath) {
return `
exports.services = require('!!${grpcFilePath}');
exports.messages = require('!!${protocFilePath}');
`;
}
async function processStatic() {
const dir = await createTmpDir();
try {
const [stdout, stderr] = await execFile(
protoc, [
`--proto_path=${path.dirname(this.resourcePath)}`,
`--js_out=import_style=commonjs,binary:${dir}`,
`--grpc_out=${dir}`,
`--plugin=protoc-gen-grpc=${protocGrpcPlugin}`,
this.resourcePath,
], {
encoding: 'utf8'
});
if (stderr) this.emitError(stderr);
const {
protocFilePath,
grpcFilePath,
grpcFileData,
} = await getGeneratedFile(this.resourcePath, dir);
const protocFileName = path.basename(protocFilePath, '.js');
const unixProtocFilePath = toUnixPath(protocFilePath);
const unixGrpcFilePath = toUnixPath(grpcFilePath);
// don't process the result
const grpcFileContent = grpcFileData.replace(`require('./${protocFileName}.js');`, `require('!!${unixProtocFilePath}');`);
await writeFile(grpcFilePath, grpcFileContent);
return generateOutput(unixProtocFilePath, unixGrpcFilePath);
} catch (err) {
removeTmpDir(dir);
throw err;
}
}
function pickProps(o, props) {
return props.reduce((m, k) => {
m[k] = o[k];
return m;
}, {});
}
function pickGrpcProps(opts) {
return pickProps(opts, [
'convertFieldsToCamelCase',
'binaryAsBase64',
'longsAsStrings',
'enumsAsStrings',
]);
}
async function processDynamic(grpcOpts) {
const protoObj = await protobuf.load(this.resourcePath);
const jsonDescriptor = JSON.stringify(protoObj.toJSON());
return `
const grpc = require('grpc');
const protobuf = require('protobufjs');
const opts = JSON.parse('${JSON.stringify(grpcOpts)}');
module.exports = grpc.loadObject(protobuf.Root.fromJSON(JSON.parse('${jsonDescriptor}')), opts);
`;
}
const defaultOptions = {
static: true,
};
module.exports = async function(source) {
if (this.cacheable) this.cacheable();
const options = Object.assign({},
defaultOptions,
loaderUtils.getOptions(this),
);
const callback = this.async();
let result = '';
try {
result = await (options.static ? processStatic : processDynamic).call(this, pickGrpcProps(options));
} catch (err) {
callback(err);
}
callback(null, result);
};