allserver 2.4.1 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/package.json +14 -14
- package/src/client/AllserverClient.js +37 -10
- package/src/server/Allserver.js +15 -6
- package/src/server/GrpcTransport.js +0 -2
- package/src/server/HttpTransport.js +1 -0
- package/src/util.js +1 -0
package/README.md
CHANGED
|
@@ -6,8 +6,11 @@ Think of Remote Procedure Calls using exactly the same client and server code bu
|
|
|
6
6
|
|
|
7
7
|
Should be used in (micro)services where JavaScript is able to run - your computer, Docker, k8s, virtual machines, serverless functions (Lambdas, Google Cloud Functions, Azure Functions, etc), RaspberryPI, SharedWorker, thread, you name it.
|
|
8
8
|
|
|
9
|
+
> Uber [moved](https://www.infoq.com/news/2023/10/uber-up-cloud-microservices/) most of its containerized microservices from µDeploy to a new multi-cloud platform named Up in preparation for migrating a considerable portion of its compute footprint to the cloud. **The company spent two years** working on making its many microservices portable to migrate between different computing infrastructures and container management platforms.
|
|
10
|
+
|
|
9
11
|
Superpowers the `Allserver` gives you:
|
|
10
12
|
|
|
13
|
+
- Move your code around infrastructures, deployment types, runtimes, platforms, etc with ease.
|
|
11
14
|
- Call gRPC server methods from browser/curl/Postman.
|
|
12
15
|
- Run your HTTP server as gRPC with a single line change (almost).
|
|
13
16
|
- Serve same logic via HTTP and gRPC (or more) simultaneously in the same node.js process.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "allserver",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Multi-protocol simple RPC server and [optional] client. Boilerplate-less. Opinionated. Minimalistic. DX-first.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"author": "Vasyl Boroviak",
|
|
35
35
|
"license": "MIT",
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@grpc/grpc-js": "
|
|
38
|
-
"@grpc/proto-loader": "
|
|
39
|
-
"bullmq": "
|
|
40
|
-
"express": "
|
|
41
|
-
"micro": "
|
|
42
|
-
"node-fetch": "
|
|
37
|
+
"@grpc/grpc-js": "1",
|
|
38
|
+
"@grpc/proto-loader": "0",
|
|
39
|
+
"bullmq": "3 - 5",
|
|
40
|
+
"express": "4",
|
|
41
|
+
"micro": "10",
|
|
42
|
+
"node-fetch": "2"
|
|
43
43
|
},
|
|
44
44
|
"peerDependenciesMeta": {
|
|
45
45
|
"@grpc/grpc-js": {
|
|
@@ -62,17 +62,17 @@
|
|
|
62
62
|
}
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@grpc/grpc-js": "^1.
|
|
66
|
-
"@grpc/proto-loader": "^0.
|
|
67
|
-
"bullmq": "^
|
|
65
|
+
"@grpc/grpc-js": "^1.13.4",
|
|
66
|
+
"@grpc/proto-loader": "^0.8.0",
|
|
67
|
+
"bullmq": "^5.56.9",
|
|
68
68
|
"cls-hooked": "^4.2.2",
|
|
69
|
-
"eslint": "^8.
|
|
70
|
-
"express": "^4.
|
|
69
|
+
"eslint": "^8.57.1",
|
|
70
|
+
"express": "^4.21.2",
|
|
71
71
|
"lambda-local": "^1.7.3",
|
|
72
72
|
"micro": "^10.0.1",
|
|
73
|
-
"mocha": "^
|
|
73
|
+
"mocha": "^11.7.1",
|
|
74
74
|
"node-fetch": "^2.6.9",
|
|
75
|
-
"nyc": "^
|
|
75
|
+
"nyc": "^17.1.0",
|
|
76
76
|
"prettier": "^2.1.1"
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
@@ -141,6 +141,8 @@ module.exports = require("stampit")({
|
|
|
141
141
|
[p]: {
|
|
142
142
|
// The protocol implementation strategy.
|
|
143
143
|
transport: null,
|
|
144
|
+
// The maximum time to wait until returning the ALLSERVER_CLIENT_TIMEOUT error. 0 means - no timeout.
|
|
145
|
+
timeout: 0,
|
|
144
146
|
// Disable any exception throwing when calling any methods. Otherwise, throws network and server errors.
|
|
145
147
|
neverThrow: true,
|
|
146
148
|
// Automatically find (introspect) and call corresponding remote procedures. Use only the methods defined in client side.
|
|
@@ -173,6 +175,7 @@ module.exports = require("stampit")({
|
|
|
173
175
|
{
|
|
174
176
|
uri,
|
|
175
177
|
transport,
|
|
178
|
+
timeout,
|
|
176
179
|
neverThrow,
|
|
177
180
|
dynamicMethods,
|
|
178
181
|
autoIntrospect,
|
|
@@ -183,6 +186,7 @@ module.exports = require("stampit")({
|
|
|
183
186
|
},
|
|
184
187
|
{ stamp }
|
|
185
188
|
) {
|
|
189
|
+
this[p].timeout = timeout != null ? timeout : this[p].timeout;
|
|
186
190
|
this[p].neverThrow = neverThrow != null ? neverThrow : this[p].neverThrow;
|
|
187
191
|
this[p].dynamicMethods = dynamicMethods != null ? dynamicMethods : this[p].dynamicMethods;
|
|
188
192
|
this[p].autoIntrospect = autoIntrospect != null ? autoIntrospect : this[p].autoIntrospect;
|
|
@@ -203,8 +207,8 @@ module.exports = require("stampit")({
|
|
|
203
207
|
this[p].transport = getTransport()({ uri });
|
|
204
208
|
}
|
|
205
209
|
|
|
206
|
-
if (before) this[p].before = [].concat(
|
|
207
|
-
if (after) this[p].after = [].concat(
|
|
210
|
+
if (before) this[p].before = [].concat(this[p].before).concat(before).filter(isFunction);
|
|
211
|
+
if (after) this[p].after = [].concat(this[p].after).concat(after).filter(isFunction);
|
|
208
212
|
},
|
|
209
213
|
|
|
210
214
|
methods: {
|
|
@@ -218,10 +222,10 @@ module.exports = require("stampit")({
|
|
|
218
222
|
try {
|
|
219
223
|
// This is supposed to be executed only once (per uri) unless it throws.
|
|
220
224
|
// There are only 3 situations when this throws:
|
|
221
|
-
// * the "introspect" method not found on server,
|
|
222
|
-
// * the network request is malformed,
|
|
225
|
+
// * the "introspect" method not found on server, (GRPC)
|
|
226
|
+
// * the network request is malformed, (HTTP-like)
|
|
223
227
|
// * couldn't connect to the remote host.
|
|
224
|
-
ctx.result = await
|
|
228
|
+
ctx.result = await this._callTransport(ctx);
|
|
225
229
|
} catch (err) {
|
|
226
230
|
ctx.result = {
|
|
227
231
|
success: false,
|
|
@@ -281,19 +285,41 @@ module.exports = require("stampit")({
|
|
|
281
285
|
return await runMiddlewares(middlewares);
|
|
282
286
|
},
|
|
283
287
|
|
|
288
|
+
_callTransport(ctx) {
|
|
289
|
+
const transportMethod = ctx.isIntrospection ? "introspect" : "call";
|
|
290
|
+
// In JavaScript if the `timeout` is null or undefined or some other object this condition will return `false`
|
|
291
|
+
if (this[p].timeout > 0) {
|
|
292
|
+
return Promise.race([
|
|
293
|
+
this[p].transport[transportMethod](ctx),
|
|
294
|
+
new Promise((resolve) =>
|
|
295
|
+
setTimeout(
|
|
296
|
+
() =>
|
|
297
|
+
resolve({
|
|
298
|
+
success: false,
|
|
299
|
+
code: "ALLSERVER_CLIENT_TIMEOUT",
|
|
300
|
+
message: `The remote procedure ${ctx.procedureName} timed out in ${this[p].timeout} ms`,
|
|
301
|
+
}),
|
|
302
|
+
this[p].timeout
|
|
303
|
+
)
|
|
304
|
+
),
|
|
305
|
+
]);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return this[p].transport[transportMethod](ctx);
|
|
309
|
+
},
|
|
310
|
+
|
|
284
311
|
async call(procedureName, arg) {
|
|
285
312
|
if (!arg) arg = {};
|
|
286
313
|
if (!arg._) arg._ = {};
|
|
287
314
|
arg._.procedureName = procedureName;
|
|
288
315
|
|
|
289
|
-
const transport = this[p].transport;
|
|
290
316
|
const defaultCtx = { procedureName, arg, client: this };
|
|
291
|
-
const ctx = transport.createCallContext(defaultCtx);
|
|
317
|
+
const ctx = this[p].transport.createCallContext(defaultCtx);
|
|
292
318
|
|
|
293
319
|
await this._callMiddlewares(ctx, "before", async () => {
|
|
294
320
|
if (!ctx.result) {
|
|
295
321
|
try {
|
|
296
|
-
ctx.result = await
|
|
322
|
+
ctx.result = await this._callTransport(ctx);
|
|
297
323
|
} catch (err) {
|
|
298
324
|
if (!this[p].neverThrow) throw err;
|
|
299
325
|
|
|
@@ -335,8 +361,9 @@ module.exports = require("stampit")({
|
|
|
335
361
|
before,
|
|
336
362
|
after,
|
|
337
363
|
} = {}) {
|
|
338
|
-
if (before) before = [].
|
|
339
|
-
if (after) after = [].
|
|
364
|
+
if (before != null) before = (Array.isArray(before) ? before : [before]).filter(isFunction);
|
|
365
|
+
if (after != null) after = (Array.isArray(after) ? after : [after]).filter(isFunction);
|
|
366
|
+
|
|
340
367
|
return this.deepProps({
|
|
341
368
|
[p]: {
|
|
342
369
|
transport,
|
package/src/server/Allserver.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
const assert = require("assert");
|
|
2
2
|
|
|
3
|
-
const { isObject, isBoolean, isFunction } = require("../util");
|
|
3
|
+
const { isObject, isBoolean, isFunction, uniq } = require("../util");
|
|
4
4
|
|
|
5
5
|
module.exports = require("stampit")({
|
|
6
6
|
name: "Allserver",
|
|
7
7
|
|
|
8
|
+
deepProps: {
|
|
9
|
+
before: null,
|
|
10
|
+
after: null,
|
|
11
|
+
},
|
|
12
|
+
|
|
8
13
|
props: {
|
|
9
14
|
procedures: {},
|
|
10
15
|
transport: null,
|
|
11
16
|
logger: console,
|
|
12
17
|
introspection: true,
|
|
13
|
-
before: null,
|
|
14
|
-
after: null,
|
|
15
18
|
|
|
16
19
|
callsCount: 0,
|
|
17
20
|
},
|
|
@@ -21,8 +24,8 @@ module.exports = require("stampit")({
|
|
|
21
24
|
this.transport = transport || this.transport || require("./HttpTransport")();
|
|
22
25
|
this.logger = logger || this.logger;
|
|
23
26
|
this.introspection = introspection != null ? introspection : this.introspection;
|
|
24
|
-
this.before =
|
|
25
|
-
this.after =
|
|
27
|
+
if (before) this.before = uniq([].concat(this.before).concat(before).filter(isFunction));
|
|
28
|
+
if (after) this.after = uniq([].concat(this.after).concat(after).filter(isFunction));
|
|
26
29
|
|
|
27
30
|
this._validateProcedures();
|
|
28
31
|
},
|
|
@@ -178,7 +181,13 @@ module.exports = require("stampit")({
|
|
|
178
181
|
|
|
179
182
|
statics: {
|
|
180
183
|
defaults({ procedures, transport, logger, introspection, before, after } = {}) {
|
|
181
|
-
|
|
184
|
+
if (before != null) before = (Array.isArray(before) ? before : [before]).filter(isFunction);
|
|
185
|
+
if (after != null) after = (Array.isArray(after) ? after : [after]).filter(isFunction);
|
|
186
|
+
|
|
187
|
+
return this.compose({
|
|
188
|
+
props: { procedures, transport, logger, introspection },
|
|
189
|
+
deepProps: { before, after },
|
|
190
|
+
});
|
|
182
191
|
},
|
|
183
192
|
},
|
|
184
193
|
});
|
|
@@ -60,6 +60,7 @@ module.exports = require("./Transport").compose({
|
|
|
60
60
|
return new Promise((r) => {
|
|
61
61
|
if (this.server.closeIdleConnections) this.server.closeIdleConnections();
|
|
62
62
|
this.server.close(r);
|
|
63
|
+
if (this.server.closeAllConnections) this.server.closeAllConnections();
|
|
63
64
|
});
|
|
64
65
|
},
|
|
65
66
|
|