@forwardimpact/librpc 0.1.110 → 0.1.112
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 +15 -2
- package/bin/fit-unary.js +2 -2
- package/package.json +1 -1
- package/src/auth.js +8 -7
- package/src/base.js +10 -10
- package/src/client.js +46 -14
- package/src/generated/definitions/exports.js +3 -3
- package/src/generated/definitions/span.js +50 -0
- package/src/generated/services/exports.js +8 -8
- package/src/generated/services/{trace → span}/client.js +16 -16
- package/src/generated/services/{trace → span}/service.js +12 -12
- package/src/generated/types/metadata.js +90 -90
- package/src/generated/types/types.js +2127 -2127
- package/src/health.js +4 -4
- package/src/index.js +14 -14
- package/src/interceptor.js +4 -3
- package/src/server.js +13 -11
- package/src/generated/definitions/trace.js +0 -50
package/src/health.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* gRPC Health Check protocol (grpc.health.v1.Health/Check)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Messages use raw protobuf wire encoding
|
|
6
|
-
* one enum/varint field
|
|
4
|
+
* This is a manual service definition. It needs no .proto file and no
|
|
5
|
+
* proto-loader. Messages use raw protobuf wire encoding. The encoding is
|
|
6
|
+
* trivial: one string field and one enum/varint field.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
/** Serving status enum
|
|
9
|
+
/** Serving status enum that matches grpc.health.v1 */
|
|
10
10
|
export const ServingStatus = {
|
|
11
11
|
UNKNOWN: 0,
|
|
12
12
|
SERVING: 1,
|
package/src/index.js
CHANGED
|
@@ -23,30 +23,30 @@ export const clients = exports.clients || {};
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Creates a tracer instance for a service
|
|
26
|
-
*
|
|
27
|
-
* @param {string} serviceName - Name of the service
|
|
26
|
+
* Call this factory at startup in server.js files or when you create clients
|
|
27
|
+
* @param {string} serviceName - Name of the service to trace
|
|
28
28
|
* @returns {Promise<Tracer>} Configured tracer instance
|
|
29
|
-
* @throws {Error} If
|
|
29
|
+
* @throws {Error} If the factory cannot load the span service configuration
|
|
30
30
|
*/
|
|
31
31
|
export async function createTracer(serviceName) {
|
|
32
|
-
const
|
|
33
|
-
const {
|
|
34
|
-
// createTracer is a composition-root factory
|
|
35
|
-
// runtime as its DI root
|
|
36
|
-
// auth reads SERVICE_SECRET off the bag
|
|
37
|
-
//
|
|
32
|
+
const spanConfig = await createServiceConfig("span");
|
|
33
|
+
const { SpanClient } = clients;
|
|
34
|
+
// createTracer is a composition-root factory. It builds the production
|
|
35
|
+
// runtime as its DI root. It threads the runtime into the SpanClient, so the
|
|
36
|
+
// client's auth reads SERVICE_SECRET off the bag. It also threads the runtime
|
|
37
|
+
// clock into the Tracer, and so into every Span.
|
|
38
38
|
const runtime = createDefaultRuntime();
|
|
39
|
-
const
|
|
39
|
+
const spanClient = new SpanClient(spanConfig, runtime);
|
|
40
40
|
return new Tracer({
|
|
41
41
|
serviceName,
|
|
42
|
-
|
|
42
|
+
spanClient,
|
|
43
43
|
grpcMetadata: grpc.Metadata,
|
|
44
44
|
clock: runtime.clock,
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
|
-
* Factory function to create a client instance with optional
|
|
49
|
+
* Factory function to create a client instance with an optional logger and tracer
|
|
50
50
|
* @param {string} name - Service name (e.g., "memory", "llm", "tool")
|
|
51
51
|
* @param {object} [logger] - Optional logger instance
|
|
52
52
|
* @param {import("@forwardimpact/libtelemetry").Tracer} [tracer] - Optional tracer instance for distributed tracing
|
|
@@ -64,10 +64,10 @@ export async function createClient(name, logger = null, tracer = null) {
|
|
|
64
64
|
);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
// Create config for the service
|
|
67
|
+
// Create the config for the service
|
|
68
68
|
const config = await createServiceConfig(name);
|
|
69
69
|
|
|
70
|
-
// createClient is a composition-root factory
|
|
70
|
+
// createClient is a composition-root factory. Build the production runtime
|
|
71
71
|
// here and thread it so the client's auth reads SERVICE_SECRET off the bag.
|
|
72
72
|
const runtime = createDefaultRuntime();
|
|
73
73
|
|
package/src/interceptor.js
CHANGED
|
@@ -2,7 +2,8 @@ import grpc from "@grpc/grpc-js";
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* gRPC interceptor for HMAC-based service authentication
|
|
5
|
-
*
|
|
5
|
+
* Adds a token to each outgoing request automatically and validates each
|
|
6
|
+
* incoming request
|
|
6
7
|
*/
|
|
7
8
|
export class Interceptor {
|
|
8
9
|
#authenticator;
|
|
@@ -82,14 +83,14 @@ export class Interceptor {
|
|
|
82
83
|
};
|
|
83
84
|
}
|
|
84
85
|
|
|
85
|
-
// Add service ID to call context
|
|
86
|
+
// Add the service ID to the call context so handlers can use it
|
|
86
87
|
call.serviceId = verification.serviceId;
|
|
87
88
|
};
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
/**
|
|
91
92
|
* Validates an incoming gRPC call's authentication
|
|
92
|
-
* This
|
|
93
|
+
* This helper method validates the authentication manually
|
|
93
94
|
* @param {object} call - gRPC call object
|
|
94
95
|
* @returns {object} Verification result with isValid, serviceId, and error properties
|
|
95
96
|
*/
|
package/src/server.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { healthDefinition, createHealthHandlers } from "./health.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* gRPC Server class
|
|
11
|
+
* gRPC Server class that uses pre-compiled service definitions
|
|
12
12
|
* Takes a service instance and creates a gRPC server around it
|
|
13
13
|
*/
|
|
14
14
|
export class Server extends Rpc {
|
|
@@ -47,7 +47,7 @@ export class Server extends Rpc {
|
|
|
47
47
|
|
|
48
48
|
/** Starts the gRPC server */
|
|
49
49
|
async start() {
|
|
50
|
-
// Configure server with keepalive for long-running streams
|
|
50
|
+
// Configure the server with keepalive for long-running streams
|
|
51
51
|
// https://github.com/grpc/grpc-node/blob/master/doc/keepalive.md
|
|
52
52
|
this.#server = new (this.grpc().Server)({
|
|
53
53
|
"grpc.keepalive_time_ms": 30000, // Send keepalive ping every 30 seconds
|
|
@@ -57,19 +57,19 @@ export class Server extends Rpc {
|
|
|
57
57
|
"grpc.http2.max_pings_without_data": 0, // Unlimited pings without data
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
// Get pre-compiled service definition
|
|
60
|
+
// Get the pre-compiled service definition
|
|
61
61
|
const serviceName = capitalizeFirstLetter(this.config.name);
|
|
62
62
|
const definition = this.getServiceDefinition(serviceName);
|
|
63
63
|
|
|
64
|
-
// Get handlers from the service instance
|
|
64
|
+
// Get the handlers from the service instance
|
|
65
65
|
const handlers = this.#service.getHandlers();
|
|
66
66
|
|
|
67
|
-
// Wrap handlers
|
|
67
|
+
// Wrap the handlers so they authenticate and handle errors
|
|
68
68
|
const wrappedHandlers = this.#wrapHandlers(handlers, definition);
|
|
69
69
|
|
|
70
70
|
this.#server.addService(definition, wrappedHandlers);
|
|
71
71
|
|
|
72
|
-
// Register standard gRPC health check (no auth, no observer
|
|
72
|
+
// Register the standard gRPC health check (no auth, no observer wrap)
|
|
73
73
|
this.#server.addService(
|
|
74
74
|
healthDefinition,
|
|
75
75
|
createHealthHandlers(serviceName),
|
|
@@ -82,7 +82,7 @@ export class Server extends Rpc {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
|
-
* Wraps handlers
|
|
85
|
+
* Wraps the handlers so they authenticate and handle errors
|
|
86
86
|
* @param {object} handlers - Service method handlers
|
|
87
87
|
* @param {object} definition - Service definition
|
|
88
88
|
* @returns {object} Wrapped handlers
|
|
@@ -101,7 +101,8 @@ export class Server extends Rpc {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
|
-
* Wraps a streaming handler with tracing, authentication, and error
|
|
104
|
+
* Wraps a streaming handler with tracing, authentication, and error
|
|
105
|
+
* handling through Observer
|
|
105
106
|
* @param {string} methodName - Method name for tracing
|
|
106
107
|
* @param {Function} handler - Streaming handler function
|
|
107
108
|
* @returns {Function} Wrapped handler
|
|
@@ -142,7 +143,8 @@ export class Server extends Rpc {
|
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
/**
|
|
145
|
-
* Wraps a unary handler with tracing, authentication, and error handling
|
|
146
|
+
* Wraps a unary handler with tracing, authentication, and error handling
|
|
147
|
+
* through Observer
|
|
146
148
|
* @param {string} methodName - Method name for tracing
|
|
147
149
|
* @param {Function} handler - Unary handler function
|
|
148
150
|
* @returns {Function} Wrapped handler
|
|
@@ -185,7 +187,7 @@ export class Server extends Rpc {
|
|
|
185
187
|
}
|
|
186
188
|
|
|
187
189
|
/**
|
|
188
|
-
* Binds server to the specified URI
|
|
190
|
+
* Binds the server to the specified URI
|
|
189
191
|
* @param {string} uri - Server URI to bind to
|
|
190
192
|
* @returns {Promise<number>} Bound port number
|
|
191
193
|
*/
|
|
@@ -213,7 +215,7 @@ export class Server extends Rpc {
|
|
|
213
215
|
const shutdown = async () => {
|
|
214
216
|
this.observer().logger()?.info("Server", "Shutting down...");
|
|
215
217
|
|
|
216
|
-
// Call service shutdown if it exists
|
|
218
|
+
// Call the service shutdown if it exists
|
|
217
219
|
if (typeof this.#service.shutdown === "function") {
|
|
218
220
|
await this.#service.shutdown();
|
|
219
221
|
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { trace } from "@forwardimpact/libtype";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Pre-compiled gRPC service definition for Trace
|
|
5
|
-
* Generated at build time
|
|
6
|
-
*/
|
|
7
|
-
export const TraceServiceDefinition = {
|
|
8
|
-
RecordSpan: {
|
|
9
|
-
path: '/trace.Trace/RecordSpan',
|
|
10
|
-
requestStream: false,
|
|
11
|
-
responseStream: false,
|
|
12
|
-
requestSerialize: (value) => {
|
|
13
|
-
return Buffer.from(trace.Span.encode(value).finish());
|
|
14
|
-
},
|
|
15
|
-
requestDeserialize: (value) => {
|
|
16
|
-
return trace.Span.toObject(
|
|
17
|
-
trace.Span.decode(value)
|
|
18
|
-
);
|
|
19
|
-
},
|
|
20
|
-
responseSerialize: (value) => {
|
|
21
|
-
return Buffer.from(trace.RecordResponse.encode(value).finish());
|
|
22
|
-
},
|
|
23
|
-
responseDeserialize: (value) => {
|
|
24
|
-
return trace.RecordResponse.toObject(
|
|
25
|
-
trace.RecordResponse.decode(value)
|
|
26
|
-
);
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
QuerySpans: {
|
|
30
|
-
path: '/trace.Trace/QuerySpans',
|
|
31
|
-
requestStream: false,
|
|
32
|
-
responseStream: false,
|
|
33
|
-
requestSerialize: (value) => {
|
|
34
|
-
return Buffer.from(trace.QueryRequest.encode(value).finish());
|
|
35
|
-
},
|
|
36
|
-
requestDeserialize: (value) => {
|
|
37
|
-
return trace.QueryRequest.toObject(
|
|
38
|
-
trace.QueryRequest.decode(value)
|
|
39
|
-
);
|
|
40
|
-
},
|
|
41
|
-
responseSerialize: (value) => {
|
|
42
|
-
return Buffer.from(trace.QueryResponse.encode(value).finish());
|
|
43
|
-
},
|
|
44
|
-
responseDeserialize: (value) => {
|
|
45
|
-
return trace.QueryResponse.toObject(
|
|
46
|
-
trace.QueryResponse.decode(value)
|
|
47
|
-
);
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
};
|