@tdxvolt/volt-client-grpc 0.18.3 → 0.18.5
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/lib/index.cjs +3208 -181
- package/package.json +5 -3
- package/scripts/generate-proto-assets.js +71 -0
- package/src/constants.js +2 -1
- package/src/grpc-call.js +7 -3
- package/src/proto-package-definition.js +184 -0
- package/src/proto-utils.js +40 -111
- package/src/volt-client-internal.js +5 -30
- package/src/volt-client.js +0 -57
- package/src/volt-proto-literals.js +2985 -0
- package/protobuf/README.md +0 -4
- package/protobuf/tdx/volt_api/data/v1/sqlite.proto +0 -43
- package/protobuf/tdx/volt_api/data/v1/sqlite_database_api.proto +0 -153
- package/protobuf/tdx/volt_api/data/v1/sqlite_server_api.proto +0 -50
- package/protobuf/tdx/volt_api/relay/v1/proxy_api.proto +0 -9
- package/protobuf/tdx/volt_api/relay/v1/relay_api.proto +0 -78
- package/protobuf/tdx/volt_api/sync/v1/sync.proto +0 -57
- package/protobuf/tdx/volt_api/volt/v1/discovery_api.proto +0 -35
- package/protobuf/tdx/volt_api/volt/v1/file.proto +0 -17
- package/protobuf/tdx/volt_api/volt/v1/file_api.proto +0 -165
- package/protobuf/tdx/volt_api/volt/v1/remote.proto +0 -93
- package/protobuf/tdx/volt_api/volt/v1/spark_api.proto +0 -121
- package/protobuf/tdx/volt_api/volt/v1/ssi.proto +0 -66
- package/protobuf/tdx/volt_api/volt/v1/ssi_api.proto +0 -214
- package/protobuf/tdx/volt_api/volt/v1/status.proto +0 -15
- package/protobuf/tdx/volt_api/volt/v1/terminal_api.proto +0 -42
- package/protobuf/tdx/volt_api/volt/v1/volt.proto +0 -666
- package/protobuf/tdx/volt_api/volt/v1/volt_api.proto +0 -1082
- package/protobuf/tdx/volt_api/volt/v1/wire_api.proto +0 -56
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.18.
|
|
6
|
+
"version": "0.18.5",
|
|
7
7
|
"description": "tdx Volt library for nodejs clients",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"exports": {
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
"files": [
|
|
17
17
|
"lib",
|
|
18
18
|
"src",
|
|
19
|
-
"
|
|
19
|
+
"scripts"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
+
"prebuild": "node ./scripts/generate-proto-assets.js",
|
|
22
23
|
"build": "rollup -c",
|
|
23
24
|
"dev": "rollup -c -w",
|
|
24
25
|
"prepare": "npm run build"
|
|
@@ -36,7 +37,6 @@
|
|
|
36
37
|
"author": "toby.ealden@gmail.com",
|
|
37
38
|
"license": "ISC",
|
|
38
39
|
"dependencies": {
|
|
39
|
-
"@grpc/proto-loader": "^0.7.13",
|
|
40
40
|
"@tdxvolt/volt-client-web": "^0.18.1",
|
|
41
41
|
"bent": "^7.3.12",
|
|
42
42
|
"builtin-modules": "^3.3.0",
|
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
"ip": "^1.1.5",
|
|
45
45
|
"jsonwebtoken": "^8.5.1",
|
|
46
46
|
"lodash": "^4.17.15",
|
|
47
|
+
"lodash.camelcase": "^4.3.0",
|
|
48
|
+
"protobufjs": "^7.4.0",
|
|
47
49
|
"uuid": "^8.1.0"
|
|
48
50
|
}
|
|
49
51
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Recursively load all `.proto` files in the `protobuf` directory.
|
|
2
|
+
//
|
|
3
|
+
|
|
4
|
+
import { readdirSync, statSync, readFileSync, writeFileSync } from "fs";
|
|
5
|
+
import { dirname, join } from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
const protoFolder = "../../../../tdxvolt-core/src/volt_api";
|
|
11
|
+
const folder = join(__dirname, protoFolder);
|
|
12
|
+
|
|
13
|
+
// Verify that the proto folder exists.
|
|
14
|
+
try {
|
|
15
|
+
statSync(folder);
|
|
16
|
+
} catch (e) {
|
|
17
|
+
console.error(`\nThe proto folder '${folder}' does not exist.`);
|
|
18
|
+
console.error(
|
|
19
|
+
`\nTo build this package, you must clone the https://github.com/tdxvolt/tdxvolt-core repository such that the folder structure resembles the following:`
|
|
20
|
+
);
|
|
21
|
+
console.error(`\ntdxvolt`);
|
|
22
|
+
console.error(` └── tdxvolt-core`);
|
|
23
|
+
console.error(` └── tdxvolt-js`);
|
|
24
|
+
console.error(`\n`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getProtoFiles(dir) {
|
|
29
|
+
let protoFiles = [];
|
|
30
|
+
|
|
31
|
+
const files = readdirSync(dir);
|
|
32
|
+
files.forEach((file) => {
|
|
33
|
+
const filePath = join(dir, file);
|
|
34
|
+
const stats = statSync(filePath);
|
|
35
|
+
if (stats.isDirectory()) {
|
|
36
|
+
protoFiles = protoFiles.concat(getProtoFiles(filePath));
|
|
37
|
+
} else if (file.endsWith(".proto")) {
|
|
38
|
+
protoFiles.push(filePath);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return protoFiles;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const protoFiles = getProtoFiles(folder);
|
|
46
|
+
|
|
47
|
+
// Load the contents of each proto file, and write as string literals
|
|
48
|
+
// to the 'volt-proto-literals.js' file.
|
|
49
|
+
let protoLiterals =
|
|
50
|
+
"/**\n * This file is generated by the 'generate-proto-assets.js' script.\n * Do not modify this file directly.\n */\n\n";
|
|
51
|
+
protoFiles.forEach((filePath) => {
|
|
52
|
+
// Escape backticks in the proto file.
|
|
53
|
+
const contents = readFileSync(filePath, "utf8").replace(/`/g, "\\`");
|
|
54
|
+
|
|
55
|
+
// Get the base file name without the extension.
|
|
56
|
+
filePath = filePath.split("/").pop();
|
|
57
|
+
|
|
58
|
+
protoLiterals += `export const ${filePath.replace(
|
|
59
|
+
".proto",
|
|
60
|
+
""
|
|
61
|
+
)} = \`${contents}\`;\n`;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Add an array that contains all the literals.
|
|
65
|
+
protoLiterals += `export const voltProtos = [${protoFiles
|
|
66
|
+
.map((filePath) => filePath.split("/").pop().replace(".proto", ""))
|
|
67
|
+
.join(", ")}];`;
|
|
68
|
+
|
|
69
|
+
writeFileSync(join(__dirname, "../src/volt-proto-literals.js"), protoLiterals);
|
|
70
|
+
|
|
71
|
+
console.log("Proto files loaded and written to 'volt-proto-literals.js'");
|
package/src/constants.js
CHANGED
|
@@ -7,7 +7,7 @@ export const constants = {
|
|
|
7
7
|
privateEncryptedKeyPrefix: "-----BEGIN ENCRYPTED PRIVATE KEY-----",
|
|
8
8
|
/**
|
|
9
9
|
* These top-level service types should map to a protobuf definition
|
|
10
|
-
* in
|
|
10
|
+
* in the volt-proto-literals.js file.
|
|
11
11
|
*/
|
|
12
12
|
serviceType: {
|
|
13
13
|
fileAPI: "tdx.volt_api.volt.v1.FileAPI",
|
|
@@ -15,6 +15,7 @@ export const constants = {
|
|
|
15
15
|
sqliteDatabaseAPI: "tdx.volt_api.data.v1.SqliteDatabaseAPI",
|
|
16
16
|
ssiAPI: "tdx.volt_api.volt.v1.SsiAPI",
|
|
17
17
|
relayAPI: "tdx.volt_api.relay.v1.RelayAPI",
|
|
18
|
+
terminalAPI: "tdx.volt_api.volt.v1.TerminalAPI",
|
|
18
19
|
voltAPI: "tdx.volt_api.volt.v1.VoltAPI",
|
|
19
20
|
wireAPI: "tdx.volt_api.volt.v1.WireAPI"
|
|
20
21
|
}
|
package/src/grpc-call.js
CHANGED
|
@@ -330,7 +330,7 @@ export default class GRPCCall extends EventEmitter {
|
|
|
330
330
|
this._encryptionKey = null;
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
-
start(grpcClient, request) {
|
|
333
|
+
start(grpcClient, request, unary = false) {
|
|
334
334
|
this._grpcClient = grpcClient;
|
|
335
335
|
|
|
336
336
|
if (typeof this._grpcClient[this._methodName] !== "function") {
|
|
@@ -441,8 +441,12 @@ export default class GRPCCall extends EventEmitter {
|
|
|
441
441
|
});
|
|
442
442
|
|
|
443
443
|
if (this._initialRequest.request) {
|
|
444
|
-
|
|
445
|
-
|
|
444
|
+
if (unary) {
|
|
445
|
+
this._call.end(this._initialRequest.request);
|
|
446
|
+
} else {
|
|
447
|
+
// Allow callee to attach event handlers before we actually send the initial payload.
|
|
448
|
+
process.nextTick(() => this._call.write(this._initialRequest.request));
|
|
449
|
+
}
|
|
446
450
|
}
|
|
447
451
|
|
|
448
452
|
return this;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* This is copied from the proto-loader package file @grpc/proto-loader/build/src/index.js,
|
|
4
|
+
* simply in order to export the createPackageDefinition function, which we need to be
|
|
5
|
+
* able to dynamically load protobuf from strings stored in the Volt database rather than
|
|
6
|
+
* from files.
|
|
7
|
+
*
|
|
8
|
+
* There doesn't seem to be any plans to export this function from the package itself,
|
|
9
|
+
* see https://github.com/grpc/grpc-node/issues/550.
|
|
10
|
+
*
|
|
11
|
+
* This is deemed to be low-risk as the protobuf code is not expected to change often.
|
|
12
|
+
*
|
|
13
|
+
* Used by `getServiceDescriptors` in `proto-utils.js`.
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import camelCase from "lodash.camelcase";
|
|
18
|
+
import Protobuf from "protobufjs";
|
|
19
|
+
import descriptor from "protobufjs/ext/descriptor/index.js";
|
|
20
|
+
|
|
21
|
+
const IDEMPOTENCY_UNKNOWN = "IDEMPOTENCY_UNKNOWN";
|
|
22
|
+
|
|
23
|
+
const descriptorOptions = {
|
|
24
|
+
longs: String,
|
|
25
|
+
enums: String,
|
|
26
|
+
bytes: String,
|
|
27
|
+
defaults: true,
|
|
28
|
+
oneofs: true,
|
|
29
|
+
json: true
|
|
30
|
+
};
|
|
31
|
+
function joinName(baseName, name) {
|
|
32
|
+
if (baseName === "") {
|
|
33
|
+
return name;
|
|
34
|
+
} else {
|
|
35
|
+
return baseName + "." + name;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function isHandledReflectionObject(obj) {
|
|
39
|
+
return (
|
|
40
|
+
obj instanceof Protobuf.Service ||
|
|
41
|
+
obj instanceof Protobuf.Type ||
|
|
42
|
+
obj instanceof Protobuf.Enum
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
function isNamespaceBase(obj) {
|
|
46
|
+
return obj instanceof Protobuf.Namespace || obj instanceof Protobuf.Root;
|
|
47
|
+
}
|
|
48
|
+
function getAllHandledReflectionObjects(obj, parentName) {
|
|
49
|
+
const objName = joinName(parentName, obj.name);
|
|
50
|
+
if (isHandledReflectionObject(obj)) {
|
|
51
|
+
return [[objName, obj]];
|
|
52
|
+
} else {
|
|
53
|
+
if (isNamespaceBase(obj) && typeof obj.nested !== "undefined") {
|
|
54
|
+
return Object.keys(obj.nested)
|
|
55
|
+
.map((name) => {
|
|
56
|
+
return getAllHandledReflectionObjects(obj.nested[name], objName);
|
|
57
|
+
})
|
|
58
|
+
.reduce(
|
|
59
|
+
(accumulator, currentValue) => accumulator.concat(currentValue),
|
|
60
|
+
[]
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
function createDeserializer(cls, options) {
|
|
67
|
+
return function deserialize(argBuf) {
|
|
68
|
+
return cls.toObject(cls.decode(argBuf), options);
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function createSerializer(cls) {
|
|
72
|
+
return function serialize(arg) {
|
|
73
|
+
if (Array.isArray(arg)) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Failed to serialize message: expected object with ${cls.name} structure, got array instead`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
const message = cls.fromObject(arg);
|
|
79
|
+
return cls.encode(message).finish();
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function mapMethodOptions(options) {
|
|
83
|
+
return (options || []).reduce(
|
|
84
|
+
(obj, item) => {
|
|
85
|
+
for (const [key, value] of Object.entries(item)) {
|
|
86
|
+
switch (key) {
|
|
87
|
+
case "uninterpreted_option":
|
|
88
|
+
obj.uninterpreted_option.push(item.uninterpreted_option);
|
|
89
|
+
break;
|
|
90
|
+
default:
|
|
91
|
+
obj[key] = value;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return obj;
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
deprecated: false,
|
|
98
|
+
idempotency_level: IDEMPOTENCY_UNKNOWN,
|
|
99
|
+
uninterpreted_option: []
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
function createMethodDefinition(method, serviceName, options, fileDescriptors) {
|
|
104
|
+
/* This is only ever called after the corresponding root.resolveAll(), so we
|
|
105
|
+
* can assume that the resolved request and response types are non-null */
|
|
106
|
+
const requestType = method.resolvedRequestType;
|
|
107
|
+
const responseType = method.resolvedResponseType;
|
|
108
|
+
return {
|
|
109
|
+
path: "/" + serviceName + "/" + method.name,
|
|
110
|
+
requestStream: !!method.requestStream,
|
|
111
|
+
responseStream: !!method.responseStream,
|
|
112
|
+
requestSerialize: createSerializer(requestType),
|
|
113
|
+
requestDeserialize: createDeserializer(requestType, options),
|
|
114
|
+
responseSerialize: createSerializer(responseType),
|
|
115
|
+
responseDeserialize: createDeserializer(responseType, options),
|
|
116
|
+
// TODO(murgatroid99): Find a better way to handle this
|
|
117
|
+
originalName: camelCase(method.name),
|
|
118
|
+
requestType: createMessageDefinition(requestType, fileDescriptors),
|
|
119
|
+
responseType: createMessageDefinition(responseType, fileDescriptors),
|
|
120
|
+
options: mapMethodOptions(method.parsedOptions)
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function createServiceDefinition(service, name, options, fileDescriptors) {
|
|
124
|
+
const def = {};
|
|
125
|
+
for (const method of service.methodsArray) {
|
|
126
|
+
def[method.name] = createMethodDefinition(
|
|
127
|
+
method,
|
|
128
|
+
name,
|
|
129
|
+
options,
|
|
130
|
+
fileDescriptors
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
return def;
|
|
134
|
+
}
|
|
135
|
+
function createMessageDefinition(message, fileDescriptors) {
|
|
136
|
+
const messageDescriptor = message.toDescriptor("proto3");
|
|
137
|
+
return {
|
|
138
|
+
format: "Protocol Buffer 3 DescriptorProto",
|
|
139
|
+
type: messageDescriptor.$type.toObject(
|
|
140
|
+
messageDescriptor,
|
|
141
|
+
descriptorOptions
|
|
142
|
+
),
|
|
143
|
+
fileDescriptorProtos: fileDescriptors
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function createEnumDefinition(enumType, fileDescriptors) {
|
|
147
|
+
const enumDescriptor = enumType.toDescriptor("proto3");
|
|
148
|
+
return {
|
|
149
|
+
format: "Protocol Buffer 3 EnumDescriptorProto",
|
|
150
|
+
type: enumDescriptor.$type.toObject(enumDescriptor, descriptorOptions),
|
|
151
|
+
fileDescriptorProtos: fileDescriptors
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* function createDefinition(obj: Protobuf.Service, name: string, options:
|
|
156
|
+
* Options): ServiceDefinition; function createDefinition(obj: Protobuf.Type,
|
|
157
|
+
* name: string, options: Options): MessageTypeDefinition; function
|
|
158
|
+
* createDefinition(obj: Protobuf.Enum, name: string, options: Options):
|
|
159
|
+
* EnumTypeDefinition;
|
|
160
|
+
*/
|
|
161
|
+
function createDefinition(obj, name, options, fileDescriptors) {
|
|
162
|
+
if (obj instanceof Protobuf.Service) {
|
|
163
|
+
return createServiceDefinition(obj, name, options, fileDescriptors);
|
|
164
|
+
} else if (obj instanceof Protobuf.Type) {
|
|
165
|
+
return createMessageDefinition(obj, fileDescriptors);
|
|
166
|
+
} else if (obj instanceof Protobuf.Enum) {
|
|
167
|
+
return createEnumDefinition(obj, fileDescriptors);
|
|
168
|
+
} else {
|
|
169
|
+
throw new Error("Type mismatch in reflection object handling");
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function createPackageDefinition(root, options) {
|
|
174
|
+
const def = {};
|
|
175
|
+
root.resolveAll();
|
|
176
|
+
const descriptorList = root.toDescriptor("proto3").file;
|
|
177
|
+
const bufferList = descriptorList.map((value) =>
|
|
178
|
+
Buffer.from(descriptor.FileDescriptorProto.encode(value).finish())
|
|
179
|
+
);
|
|
180
|
+
for (const [name, obj] of getAllHandledReflectionObjects(root, "")) {
|
|
181
|
+
def[name] = createDefinition(obj, name, options, bufferList);
|
|
182
|
+
}
|
|
183
|
+
return def;
|
|
184
|
+
}
|
package/src/proto-utils.js
CHANGED
|
@@ -1,130 +1,59 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import debug from "debug";
|
|
2
|
+
import protobuf from "protobufjs";
|
|
3
|
+
import { createPackageDefinition } from "./proto-package-definition.js";
|
|
4
|
+
import { voltProtos } from "./volt-proto-literals.js";
|
|
5
|
+
import { constants } from "./constants.js";
|
|
6
|
+
|
|
7
|
+
const log = debug("volt-client-grpc:proto-utils");
|
|
8
|
+
|
|
9
|
+
const voltServices = [
|
|
10
|
+
constants.serviceType.voltAPI,
|
|
11
|
+
constants.serviceType.fileAPI,
|
|
12
|
+
constants.serviceType.sqliteDatabaseAPI,
|
|
13
|
+
constants.serviceType.sqliteServerAPI,
|
|
14
|
+
constants.serviceType.ssiAPI,
|
|
15
|
+
constants.serviceType.relayAPI,
|
|
16
|
+
constants.serviceType.terminalAPI,
|
|
17
|
+
constants.serviceType.wireAPI
|
|
18
|
+
];
|
|
11
19
|
|
|
12
20
|
const defaultLoaderOptions = {
|
|
13
21
|
keepCase: true,
|
|
14
22
|
longs: String,
|
|
15
23
|
enums: String,
|
|
16
24
|
defaults: true,
|
|
17
|
-
oneofs: true
|
|
18
|
-
includeDirs: [defaultProtoPath],
|
|
25
|
+
oneofs: true
|
|
19
26
|
};
|
|
20
27
|
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
);
|
|
26
|
-
const descriptors = grpc.loadPackageDefinition(definition);
|
|
27
|
-
return descriptors;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function getProtoService(descriptors, servicePath) {
|
|
31
|
-
const serviceDef = getProp(descriptors, servicePath);
|
|
32
|
-
if (serviceDef?.service) {
|
|
33
|
-
return serviceDef.service;
|
|
34
|
-
} else {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function getServiceDescriptorsFromPath(
|
|
40
|
-
grpc,
|
|
41
|
-
protoPath,
|
|
42
|
-
servicePackageName,
|
|
43
|
-
opts,
|
|
44
|
-
) {
|
|
45
|
-
if (!opts) {
|
|
46
|
-
opts = { ...defaultLoaderOptions };
|
|
47
|
-
opts.includeDirs = [protoPath];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Extract the package components of the service proto package. The package name should be of the
|
|
51
|
-
// fully qualified proto path, e.g. tdx.volt_api.webcam.v1.WebcamControlAPI.
|
|
52
|
-
const protoServiceComponents = servicePackageName.split(".");
|
|
53
|
-
|
|
54
|
-
// The service name is the last component of the path.
|
|
55
|
-
const protoServiceName = protoServiceComponents.pop();
|
|
56
|
-
|
|
57
|
-
// The actual file name should match the snake case of the service name.
|
|
58
|
-
const protoFileName = `${snakeCase(protoServiceName).toLowerCase()}.proto`;
|
|
59
|
-
|
|
60
|
-
// The path to the proto file should match each component of the package name.
|
|
61
|
-
const serviceProtoPath = join(
|
|
62
|
-
protoPath,
|
|
63
|
-
...protoServiceComponents,
|
|
64
|
-
protoFileName,
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
let serviceDescriptors;
|
|
68
|
-
const descriptors = getProtoDescriptors(grpc, serviceProtoPath, opts);
|
|
69
|
-
if (descriptors) {
|
|
70
|
-
serviceDescriptors = getProtoService(descriptors, servicePackageName);
|
|
28
|
+
function getServiceDescriptors(service) {
|
|
29
|
+
let root = new protobuf.Root();
|
|
30
|
+
for (let protoFile of service.service_description.proto_file) {
|
|
31
|
+
protobuf.parse(protoFile.protobuf, root, defaultLoaderOptions);
|
|
71
32
|
}
|
|
72
33
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
function getServiceDescriptors(grpc, servicePackageName, opts) {
|
|
77
|
-
// Extract the package components of the service proto package. The package name should be of the
|
|
78
|
-
// fully qualified proto path, e.g. tdx.volt_api.webcam.v1.WebcamControlAPI.
|
|
79
|
-
const protoServiceComponents = servicePackageName.split(".");
|
|
80
|
-
|
|
81
|
-
// The service name is the last component of the path.
|
|
82
|
-
const protoServiceName = protoServiceComponents.pop();
|
|
34
|
+
// Create a package definition from the root object.
|
|
35
|
+
const packageDefinition = createPackageDefinition(root, defaultLoaderOptions);
|
|
83
36
|
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
defaultProtoPath,
|
|
90
|
-
...protoServiceComponents,
|
|
91
|
-
protoFileName,
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
let serviceDescriptors;
|
|
95
|
-
const descriptors = getProtoDescriptors(grpc, protoPath, opts);
|
|
96
|
-
if (descriptors) {
|
|
97
|
-
serviceDescriptors = getProtoService(descriptors, servicePackageName);
|
|
37
|
+
// Merge the service API definitions into a single object.
|
|
38
|
+
let serviceDescriptors = {};
|
|
39
|
+
for (let api of service.service_description.service_api) {
|
|
40
|
+
const packageDescriptors = packageDefinition[api];
|
|
41
|
+
serviceDescriptors = { ...serviceDescriptors, ...packageDescriptors };
|
|
98
42
|
}
|
|
99
43
|
|
|
100
44
|
return serviceDescriptors;
|
|
101
45
|
}
|
|
102
46
|
|
|
103
|
-
function
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
return methods;
|
|
114
|
-
}
|
|
47
|
+
function getBuiltInServiceDescriptors() {
|
|
48
|
+
// Create a placeholder service object for the Volt API service.
|
|
49
|
+
const voltServicePlaceholder = {
|
|
50
|
+
service_description: {
|
|
51
|
+
proto_file: voltProtos.map((proto) => ({ protobuf: proto })),
|
|
52
|
+
service_api: voltServices
|
|
53
|
+
}
|
|
54
|
+
};
|
|
115
55
|
|
|
116
|
-
|
|
117
|
-
for (let protoFile of service.service_description.proto_file) {
|
|
118
|
-
const filePath = join(protoPath, protoFile.file_path);
|
|
119
|
-
mkdirSync(dirname(filePath), { recursive: true });
|
|
120
|
-
writeFileSync(filePath, protoFile.protobuf);
|
|
121
|
-
}
|
|
56
|
+
return getServiceDescriptors(voltServicePlaceholder);
|
|
122
57
|
}
|
|
123
58
|
|
|
124
|
-
export {
|
|
125
|
-
createServiceProtobufFiles,
|
|
126
|
-
getServiceDescriptors,
|
|
127
|
-
getProtoDescriptors,
|
|
128
|
-
getProtoDescriptorMethods,
|
|
129
|
-
getServiceDescriptorsFromPath,
|
|
130
|
-
};
|
|
59
|
+
export { getServiceDescriptors, getBuiltInServiceDescriptors };
|
|
@@ -4,11 +4,9 @@ import ip from "ip";
|
|
|
4
4
|
import bent from "bent";
|
|
5
5
|
import lodash from "lodash";
|
|
6
6
|
import VoltConnection from "./volt-connection.js";
|
|
7
|
-
import { join } from "path";
|
|
8
7
|
import {
|
|
9
|
-
createServiceProtobufFiles,
|
|
10
8
|
getServiceDescriptors,
|
|
11
|
-
|
|
9
|
+
getBuiltInServiceDescriptors
|
|
12
10
|
} from "./proto-utils.js";
|
|
13
11
|
import { createClient as createGrpcClient } from "./grpc-utils.js";
|
|
14
12
|
import * as voltUtils from "./utils.js";
|
|
@@ -23,15 +21,6 @@ const { publicKeyToPem, removeCarriageReturn, signBase64 } = voltClientUtils;
|
|
|
23
21
|
const { filter, pick } = lodash;
|
|
24
22
|
|
|
25
23
|
const log = debug("volt-client-grpc:volt-client-internal");
|
|
26
|
-
const voltServices = [
|
|
27
|
-
constants.serviceType.voltAPI,
|
|
28
|
-
constants.serviceType.fileAPI,
|
|
29
|
-
constants.serviceType.sqliteDatabaseAPI,
|
|
30
|
-
constants.serviceType.sqliteServerAPI,
|
|
31
|
-
constants.serviceType.ssiAPI,
|
|
32
|
-
constants.serviceType.relayAPI,
|
|
33
|
-
constants.serviceType.wireAPI
|
|
34
|
-
];
|
|
35
24
|
|
|
36
25
|
function issueAuthenticate(authenticateRequest, ttl) {
|
|
37
26
|
// eslint-disable-next-line no-use-before-define
|
|
@@ -371,11 +360,8 @@ export function getVoltAPIClientInternal() {
|
|
|
371
360
|
? this._voltConfig.relay.address
|
|
372
361
|
: this._voltConfig.address;
|
|
373
362
|
log("creating cached VoltAPI service client on %s", serviceAddress);
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
const packageDescriptors = getServiceDescriptors(this._grpc, pkg);
|
|
377
|
-
serviceDescriptors = { ...serviceDescriptors, ...packageDescriptors };
|
|
378
|
-
});
|
|
363
|
+
|
|
364
|
+
const serviceDescriptors = getBuiltInServiceDescriptors();
|
|
379
365
|
|
|
380
366
|
this._cachedClient = createGrpcClient(
|
|
381
367
|
this._grpc,
|
|
@@ -396,20 +382,9 @@ export function getAPIClientInternal(service) {
|
|
|
396
382
|
const serviceAddress = this.isRelayed
|
|
397
383
|
? this._voltConfig.relay.address
|
|
398
384
|
: service.service_description.host_address;
|
|
399
|
-
|
|
400
|
-
createServiceProtobufFiles(service, "./service-proto");
|
|
401
|
-
|
|
402
385
|
log("creating API service client on %s", serviceAddress);
|
|
403
|
-
|
|
404
|
-
const
|
|
405
|
-
for (let api of service.service_description.service_api) {
|
|
406
|
-
const packageDescriptors = getServiceDescriptorsFromPath(
|
|
407
|
-
this._grpc,
|
|
408
|
-
fullProtoPath,
|
|
409
|
-
api
|
|
410
|
-
);
|
|
411
|
-
serviceDescriptors = { ...serviceDescriptors, ...packageDescriptors };
|
|
412
|
-
}
|
|
386
|
+
|
|
387
|
+
const serviceDescriptors = getServiceDescriptors(service);
|
|
413
388
|
|
|
414
389
|
this._cachedService[service.id] = createGrpcClient(
|
|
415
390
|
this._grpc,
|
package/src/volt-client.js
CHANGED
|
@@ -248,63 +248,6 @@ export class VoltClient extends EventEmitter {
|
|
|
248
248
|
});
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
/**
|
|
252
|
-
* Creates a GRPC client for the given Volt service description.
|
|
253
|
-
*
|
|
254
|
-
* Automatically handles remote connections.
|
|
255
|
-
*
|
|
256
|
-
* n.b. for this javascript client Protobuf definitions should conform to the recommended
|
|
257
|
-
* structure, which is that a package proto file resides in a folder path that matches the
|
|
258
|
-
* package name, and services contained in the package are named in in Pascal Case and using
|
|
259
|
-
* the suffix 'API'. For example the WebcamControlAPI in package tdx.volt_api.webcam.v1 should reside
|
|
260
|
-
* in a protobuf file at tdx/api/webcam/v1/webcam_control_api.proto
|
|
261
|
-
*
|
|
262
|
-
* @param {object} service a service description.
|
|
263
|
-
* @param {object} descriptors the service descriptors, must be specified unless the service
|
|
264
|
-
* packages are well-known Volt APIs.
|
|
265
|
-
*/
|
|
266
|
-
createServiceClient(service, descriptors) {
|
|
267
|
-
const pkg = service.service_description.service_api;
|
|
268
|
-
|
|
269
|
-
let serviceDescriptors;
|
|
270
|
-
if (descriptors) {
|
|
271
|
-
serviceDescriptors = descriptors;
|
|
272
|
-
} else {
|
|
273
|
-
serviceDescriptors = {};
|
|
274
|
-
pkg.forEach((svc) => {
|
|
275
|
-
log("adding service %s to service client", svc);
|
|
276
|
-
const packageDescriptors = getServiceDescriptors(this._grpc, svc);
|
|
277
|
-
serviceDescriptors = { ...serviceDescriptors, ...packageDescriptors };
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (this.isRelayed) {
|
|
282
|
-
if (!this._voltConfig?.relay?.address) {
|
|
283
|
-
throw new Error(
|
|
284
|
-
"Remote connection enabled but no Relay address - have you called start()?"
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// In remote mode => create a client using the discovered Relay address **and** passing the service reourceId
|
|
289
|
-
return createGrpcClient(
|
|
290
|
-
this._grpc,
|
|
291
|
-
serviceDescriptors,
|
|
292
|
-
this._voltConfig.relay.address,
|
|
293
|
-
this._credential,
|
|
294
|
-
false,
|
|
295
|
-
service.volt_id,
|
|
296
|
-
service.id
|
|
297
|
-
);
|
|
298
|
-
} else {
|
|
299
|
-
return createGrpcClient(
|
|
300
|
-
this._grpc,
|
|
301
|
-
serviceDescriptors,
|
|
302
|
-
service.service_description.address,
|
|
303
|
-
this._credential
|
|
304
|
-
);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
251
|
get isRelayed() {
|
|
309
252
|
return !!(this._voltConfig?.relay && this._voltConfig.id);
|
|
310
253
|
}
|