@aztec/foundation 0.0.1-commit.f504929 → 0.0.1-commit.f5a9928
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/dest/bigint-buffer/index.d.ts +1 -1
- package/dest/bigint-buffer/index.d.ts.map +1 -1
- package/dest/bigint-buffer/index.js +6 -1
- package/dest/branded-types/block_number.d.ts +3 -3
- package/dest/branded-types/block_number.d.ts.map +1 -1
- package/dest/branded-types/block_number.js +15 -4
- package/dest/branded-types/buffer32_hash.d.ts +27 -0
- package/dest/branded-types/buffer32_hash.d.ts.map +1 -0
- package/dest/branded-types/buffer32_hash.js +12 -0
- package/dest/branded-types/checkpoint_number.d.ts +9 -3
- package/dest/branded-types/checkpoint_number.d.ts.map +1 -1
- package/dest/branded-types/checkpoint_number.js +11 -0
- package/dest/branded-types/epoch.d.ts +2 -2
- package/dest/branded-types/epoch.d.ts.map +1 -1
- package/dest/branded-types/index.d.ts +2 -1
- package/dest/branded-types/index.d.ts.map +1 -1
- package/dest/branded-types/index.js +1 -0
- package/dest/branded-types/index_within_checkpoint.d.ts +2 -2
- package/dest/branded-types/index_within_checkpoint.d.ts.map +1 -1
- package/dest/branded-types/slot.d.ts +5 -2
- package/dest/branded-types/slot.d.ts.map +1 -1
- package/dest/branded-types/slot.js +3 -0
- package/dest/buffer/buffer16.d.ts +3 -1
- package/dest/buffer/buffer16.d.ts.map +1 -1
- package/dest/buffer/buffer32.d.ts +28 -61
- package/dest/buffer/buffer32.d.ts.map +1 -1
- package/dest/buffer/buffer32.js +29 -63
- package/dest/buffer/index.d.ts +2 -1
- package/dest/buffer/index.d.ts.map +1 -1
- package/dest/buffer/index.js +1 -0
- package/dest/buffer/utils.d.ts +3 -0
- package/dest/buffer/utils.d.ts.map +1 -0
- package/dest/buffer/utils.js +7 -0
- package/dest/collection/array.d.ts +11 -1
- package/dest/collection/array.d.ts.map +1 -1
- package/dest/collection/array.js +33 -0
- package/dest/collection/index.d.ts +3 -1
- package/dest/collection/index.d.ts.map +1 -1
- package/dest/collection/index.js +2 -0
- package/dest/collection/lru_map.d.ts +41 -0
- package/dest/collection/lru_map.d.ts.map +1 -0
- package/dest/collection/lru_map.js +119 -0
- package/dest/collection/lru_set.d.ts +35 -0
- package/dest/collection/lru_set.d.ts.map +1 -0
- package/dest/collection/lru_set.js +95 -0
- package/dest/committable/committable.js +1 -1
- package/dest/config/env_var.d.ts +2 -2
- package/dest/config/env_var.d.ts.map +1 -1
- package/dest/config/index.d.ts +67 -37
- package/dest/config/index.d.ts.map +1 -1
- package/dest/config/index.js +72 -71
- package/dest/config/network_config.d.ts +13 -45
- package/dest/config/network_config.d.ts.map +1 -1
- package/dest/config/network_config.js +3 -1
- package/dest/config/network_name.d.ts +2 -2
- package/dest/config/network_name.d.ts.map +1 -1
- package/dest/config/network_name.js +1 -3
- package/dest/config/secret_value.d.ts +2 -2
- package/dest/config/secret_value.d.ts.map +1 -1
- package/dest/crypto/aes128/index.d.ts +2 -1
- package/dest/crypto/aes128/index.d.ts.map +1 -1
- package/dest/crypto/aes128/index.js +11 -2
- package/dest/crypto/bls/bn254_keystore.d.ts +10 -177
- package/dest/crypto/bls/bn254_keystore.d.ts.map +1 -1
- package/dest/crypto/bls/bn254_keystore.js +22 -34
- package/dest/crypto/poseidon/index.d.ts +1 -1
- package/dest/crypto/poseidon/index.d.ts.map +1 -1
- package/dest/crypto/poseidon/index.js +40 -33
- package/dest/crypto/schnorr/index.d.ts +8 -7
- package/dest/crypto/schnorr/index.d.ts.map +1 -1
- package/dest/crypto/schnorr/index.js +6 -6
- package/dest/crypto/schnorr/signature.d.ts +9 -29
- package/dest/crypto/schnorr/signature.d.ts.map +1 -1
- package/dest/crypto/schnorr/signature.js +20 -36
- package/dest/curves/bls12/field.d.ts +3 -3
- package/dest/curves/bls12/field.d.ts.map +1 -1
- package/dest/curves/bls12/field.js +0 -5
- package/dest/curves/bls12/point.d.ts +2 -2
- package/dest/curves/bls12/point.d.ts.map +1 -1
- package/dest/curves/bn254/field.d.ts +23 -19
- package/dest/curves/bn254/field.d.ts.map +1 -1
- package/dest/curves/bn254/field.js +23 -17
- package/dest/curves/grumpkin/point.d.ts +14 -28
- package/dest/curves/grumpkin/point.d.ts.map +1 -1
- package/dest/curves/grumpkin/point.js +29 -43
- package/dest/eth-address/index.d.ts +2 -2
- package/dest/eth-address/index.d.ts.map +1 -1
- package/dest/eth-address/index.js +0 -3
- package/dest/eth-signature/eth_signature.d.ts +2 -2
- package/dest/eth-signature/eth_signature.d.ts.map +1 -1
- package/dest/fifo/fifo_frame_reader.d.ts +41 -0
- package/dest/fifo/fifo_frame_reader.d.ts.map +1 -0
- package/dest/fifo/fifo_frame_reader.js +74 -0
- package/dest/fifo/index.d.ts +2 -0
- package/dest/fifo/index.d.ts.map +1 -0
- package/dest/fifo/index.js +1 -0
- package/dest/fifo_set/fifo_set.d.ts +15 -0
- package/dest/fifo_set/fifo_set.d.ts.map +1 -0
- package/dest/fifo_set/fifo_set.js +39 -0
- package/dest/fifo_set/index.d.ts +2 -0
- package/dest/fifo_set/index.d.ts.map +1 -0
- package/dest/fifo_set/index.js +1 -0
- package/dest/iterable/first.d.ts +8 -0
- package/dest/iterable/first.d.ts.map +1 -0
- package/dest/iterable/first.js +11 -0
- package/dest/iterable/index.d.ts +2 -1
- package/dest/iterable/index.d.ts.map +1 -1
- package/dest/iterable/index.js +1 -0
- package/dest/json-rpc/client/fetch.d.ts +8 -3
- package/dest/json-rpc/client/fetch.d.ts.map +1 -1
- package/dest/json-rpc/client/fetch.js +11 -7
- package/dest/json-rpc/client/safe_json_rpc_client.d.ts +1 -1
- package/dest/json-rpc/client/safe_json_rpc_client.d.ts.map +1 -1
- package/dest/json-rpc/client/safe_json_rpc_client.js +2 -2
- package/dest/json-rpc/client/undici.d.ts +14 -3
- package/dest/json-rpc/client/undici.d.ts.map +1 -1
- package/dest/json-rpc/client/undici.js +47 -14
- package/dest/json-rpc/fixtures/test_state.d.ts +4 -8
- package/dest/json-rpc/fixtures/test_state.d.ts.map +1 -1
- package/dest/json-rpc/fixtures/test_state.js +57 -17
- package/dest/json-rpc/server/safe_json_rpc_server.d.ts +49 -11
- package/dest/json-rpc/server/safe_json_rpc_server.d.ts.map +1 -1
- package/dest/json-rpc/server/safe_json_rpc_server.js +159 -40
- package/dest/log/aws-logger-config.d.ts +8 -0
- package/dest/log/aws-logger-config.d.ts.map +1 -0
- package/dest/log/aws-logger-config.js +55 -0
- package/dest/log/pino-logger.d.ts +1 -1
- package/dest/log/pino-logger.d.ts.map +1 -1
- package/dest/log/pino-logger.js +29 -8
- package/dest/noir/noir_package_config.d.ts +19 -104
- package/dest/noir/noir_package_config.d.ts.map +1 -1
- package/dest/noir/noir_package_config.js +1 -1
- package/dest/promise/running-promise.d.ts +8 -2
- package/dest/promise/running-promise.d.ts.map +1 -1
- package/dest/promise/running-promise.js +17 -5
- package/dest/promise/utils.d.ts +14 -1
- package/dest/promise/utils.d.ts.map +1 -1
- package/dest/promise/utils.js +20 -0
- package/dest/queue/batch_queue.d.ts +1 -1
- package/dest/queue/batch_queue.d.ts.map +1 -1
- package/dest/queue/batch_queue.js +1 -0
- package/dest/retry/index.d.ts +31 -3
- package/dest/retry/index.d.ts.map +1 -1
- package/dest/retry/index.js +44 -2
- package/dest/schemas/api.d.ts +12 -10
- package/dest/schemas/api.d.ts.map +1 -1
- package/dest/schemas/api.js +7 -1
- package/dest/schemas/parse.d.ts +4 -4
- package/dest/schemas/parse.d.ts.map +1 -1
- package/dest/schemas/parse.js +6 -5
- package/dest/schemas/schemas.d.ts +15 -15
- package/dest/schemas/types.d.ts +3 -3
- package/dest/schemas/types.d.ts.map +1 -1
- package/dest/schemas/utils.d.ts +7 -11
- package/dest/schemas/utils.d.ts.map +1 -1
- package/dest/schemas/utils.js +2 -18
- package/dest/serialize/buffer_reader.d.ts +1 -1
- package/dest/serialize/buffer_reader.d.ts.map +1 -1
- package/dest/serialize/buffer_reader.js +5 -0
- package/dest/serialize/buffer_sink.d.ts +134 -0
- package/dest/serialize/buffer_sink.d.ts.map +1 -0
- package/dest/serialize/buffer_sink.js +297 -0
- package/dest/serialize/index.d.ts +2 -1
- package/dest/serialize/index.d.ts.map +1 -1
- package/dest/serialize/index.js +1 -0
- package/dest/serialize/serialize.d.ts +1 -32
- package/dest/serialize/serialize.d.ts.map +1 -1
- package/dest/serialize/serialize.js +0 -21
- package/dest/string/index.js +1 -1
- package/dest/testing/files/index.d.ts +2 -3
- package/dest/testing/files/index.d.ts.map +1 -1
- package/dest/testing/files/index.js +1 -2
- package/dest/timer/index.d.ts +2 -2
- package/dest/timer/index.d.ts.map +1 -1
- package/dest/timer/index.js +1 -1
- package/dest/timer/timeout.d.ts +3 -1
- package/dest/timer/timeout.d.ts.map +1 -1
- package/dest/timer/timeout.js +26 -0
- package/dest/transport/dispatch/create_dispatch_proxy.d.ts +11 -2
- package/dest/transport/dispatch/create_dispatch_proxy.d.ts.map +1 -1
- package/dest/transport/index.d.ts +1 -2
- package/dest/transport/index.d.ts.map +1 -1
- package/dest/transport/index.js +0 -1
- package/dest/trees/balanced_merkle_tree_root.d.ts +2 -3
- package/dest/trees/balanced_merkle_tree_root.d.ts.map +1 -1
- package/dest/trees/balanced_merkle_tree_root.js +2 -3
- package/dest/trees/hasher.d.ts +3 -2
- package/dest/trees/hasher.d.ts.map +1 -1
- package/dest/trees/hasher.js +5 -5
- package/dest/trees/indexed_merkle_tree_calculator.d.ts +1 -1
- package/dest/trees/indexed_merkle_tree_calculator.d.ts.map +1 -1
- package/dest/trees/indexed_merkle_tree_calculator.js +5 -1
- package/dest/trees/membership_witness.d.ts +2 -6
- package/dest/trees/membership_witness.d.ts.map +1 -1
- package/dest/trees/membership_witness.js +0 -9
- package/dest/trees/merkle_tree_calculator.d.ts +4 -2
- package/dest/trees/merkle_tree_calculator.d.ts.map +1 -1
- package/dest/trees/merkle_tree_calculator.js +1 -5
- package/dest/trees/sibling_path.d.ts +13 -14
- package/dest/trees/sibling_path.d.ts.map +1 -1
- package/dest/trees/sibling_path.js +23 -28
- package/dest/trees/unbalanced_merkle_tree_root.d.ts +2 -3
- package/dest/trees/unbalanced_merkle_tree_root.d.ts.map +1 -1
- package/dest/trees/unbalanced_merkle_tree_root.js +2 -3
- package/dest/types/index.d.ts +23 -1
- package/dest/types/index.d.ts.map +1 -1
- package/dest/types/index.js +15 -0
- package/package.json +6 -4
- package/src/bigint-buffer/index.ts +6 -1
- package/src/branded-types/block_number.ts +20 -2
- package/src/branded-types/buffer32_hash.ts +38 -0
- package/src/branded-types/checkpoint_number.ts +16 -1
- package/src/branded-types/epoch.ts +1 -1
- package/src/branded-types/index.ts +1 -0
- package/src/branded-types/index_within_checkpoint.ts +1 -1
- package/src/branded-types/slot.ts +6 -1
- package/src/buffer/buffer16.ts +3 -0
- package/src/buffer/buffer32.ts +39 -68
- package/src/buffer/index.ts +1 -0
- package/src/buffer/utils.ts +8 -0
- package/src/collection/array.ts +34 -0
- package/src/collection/index.ts +2 -0
- package/src/collection/lru_map.ts +143 -0
- package/src/collection/lru_set.ts +115 -0
- package/src/committable/committable.ts +1 -1
- package/src/config/env_var.ts +65 -25
- package/src/config/index.ts +143 -122
- package/src/config/network_config.ts +2 -0
- package/src/config/network_name.ts +2 -5
- package/src/config/secret_value.ts +1 -1
- package/src/crypto/aes128/index.ts +11 -2
- package/src/crypto/bls/bn254_keystore.ts +33 -43
- package/src/crypto/poseidon/index.ts +42 -34
- package/src/crypto/schnorr/index.ts +9 -8
- package/src/crypto/schnorr/signature.ts +17 -46
- package/src/curves/bls12/field.ts +0 -7
- package/src/curves/bn254/field.ts +35 -34
- package/src/curves/grumpkin/point.ts +23 -40
- package/src/eth-address/index.ts +0 -4
- package/src/fifo/fifo_frame_reader.ts +98 -0
- package/src/fifo/index.ts +1 -0
- package/src/fifo_set/fifo_set.ts +52 -0
- package/src/fifo_set/index.ts +1 -0
- package/src/iterable/first.ts +14 -0
- package/src/iterable/index.ts +1 -0
- package/src/json-rpc/client/fetch.ts +19 -5
- package/src/json-rpc/client/safe_json_rpc_client.ts +2 -2
- package/src/json-rpc/client/undici.ts +54 -12
- package/src/json-rpc/fixtures/test_state.ts +10 -10
- package/src/json-rpc/server/safe_json_rpc_server.ts +204 -47
- package/src/log/aws-logger-config.ts +32 -0
- package/src/log/pino-logger.ts +33 -6
- package/src/noir/noir_package_config.ts +32 -20
- package/src/promise/running-promise.ts +20 -7
- package/src/promise/utils.ts +31 -0
- package/src/queue/batch_queue.ts +1 -0
- package/src/retry/index.ts +66 -4
- package/src/schemas/api.ts +25 -25
- package/src/schemas/parse.ts +9 -6
- package/src/schemas/schemas.ts +4 -4
- package/src/schemas/types.ts +2 -2
- package/src/schemas/utils.ts +4 -38
- package/src/serialize/buffer_reader.ts +5 -0
- package/src/serialize/buffer_sink.ts +350 -0
- package/src/serialize/index.ts +1 -0
- package/src/serialize/serialize.ts +0 -50
- package/src/string/index.ts +1 -1
- package/src/testing/files/index.ts +1 -2
- package/src/timer/index.ts +1 -1
- package/src/timer/timeout.ts +31 -0
- package/src/transport/dispatch/create_dispatch_proxy.ts +11 -1
- package/src/transport/index.ts +0 -1
- package/src/trees/balanced_merkle_tree_root.ts +2 -5
- package/src/trees/hasher.ts +6 -3
- package/src/trees/indexed_merkle_tree_calculator.ts +5 -1
- package/src/trees/membership_witness.ts +0 -8
- package/src/trees/merkle_tree_calculator.ts +4 -10
- package/src/trees/sibling_path.ts +24 -30
- package/src/trees/unbalanced_merkle_tree_root.ts +2 -5
- package/src/types/index.ts +47 -0
- package/dest/crypto/serialize.d.ts +0 -51
- package/dest/crypto/serialize.d.ts.map +0 -1
- package/dest/crypto/serialize.js +0 -68
- package/dest/transport/dispatch/create_dispatch_fn.d.ts +0 -25
- package/dest/transport/dispatch/create_dispatch_fn.d.ts.map +0 -1
- package/dest/transport/dispatch/create_dispatch_fn.js +0 -17
- package/src/crypto/serialize.ts +0 -85
- package/src/transport/dispatch/create_dispatch_fn.ts +0 -35
|
@@ -10,7 +10,14 @@ import { ZodError } from 'zod';
|
|
|
10
10
|
|
|
11
11
|
import { type Logger, createLogger } from '../../log/index.js';
|
|
12
12
|
import { promiseWithResolvers } from '../../promise/utils.js';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
type ApiSchema,
|
|
15
|
+
type ApiSchemaFor,
|
|
16
|
+
getSchemaParameters,
|
|
17
|
+
parseWithOptionals,
|
|
18
|
+
schemaHasMethod,
|
|
19
|
+
} from '../../schemas/index.js';
|
|
20
|
+
import { Timer } from '../../timer/index.js';
|
|
14
21
|
import { jsonStringify } from '../convert.js';
|
|
15
22
|
import { assert } from '../js_utils.js';
|
|
16
23
|
|
|
@@ -19,6 +26,8 @@ export type DiagnosticsData = {
|
|
|
19
26
|
method: string;
|
|
20
27
|
params: any[];
|
|
21
28
|
headers: http.IncomingHttpHeaders;
|
|
29
|
+
requestValidationDurationMs?: number;
|
|
30
|
+
requestValidationSucceeded?: boolean;
|
|
22
31
|
};
|
|
23
32
|
|
|
24
33
|
export type DiagnosticsMiddleware = (ctx: DiagnosticsData, next: () => Promise<void>) => Promise<void>;
|
|
@@ -30,14 +39,41 @@ export type SafeJsonRpcServerConfig = {
|
|
|
30
39
|
http200OnError: boolean;
|
|
31
40
|
/** The maximum body size the server will accept */
|
|
32
41
|
maxBodySizeBytes: string;
|
|
42
|
+
/** Origins allowed to make credentialed cross-origin requests. An empty list preserves wildcard CORS. */
|
|
43
|
+
corsAllowedOrigins?: string[];
|
|
44
|
+
/** Headers allowed in cross-origin requests. An empty list reflects the requested headers. */
|
|
45
|
+
corsAllowedHeaders?: string[];
|
|
33
46
|
};
|
|
34
47
|
|
|
35
|
-
|
|
48
|
+
type ResolvedSafeJsonRpcServerConfig = Omit<SafeJsonRpcServerConfig, 'corsAllowedOrigins' | 'corsAllowedHeaders'> & {
|
|
49
|
+
corsAllowedOrigins: string[];
|
|
50
|
+
corsAllowedHeaders: string[];
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const defaultServerConfig: ResolvedSafeJsonRpcServerConfig = {
|
|
36
54
|
http200OnError: false,
|
|
37
55
|
maxBatchSize: 100,
|
|
38
56
|
maxBodySizeBytes: '1mb',
|
|
57
|
+
corsAllowedOrigins: [],
|
|
58
|
+
corsAllowedHeaders: [],
|
|
39
59
|
};
|
|
40
60
|
|
|
61
|
+
function normalizeCorsOrigin(origin: string): string {
|
|
62
|
+
if (origin === '*') {
|
|
63
|
+
return origin;
|
|
64
|
+
}
|
|
65
|
+
const url = new URL(origin);
|
|
66
|
+
if (!['http:', 'https:'].includes(url.protocol)) {
|
|
67
|
+
throw new Error(`Invalid CORS origin protocol: ${origin}`);
|
|
68
|
+
}
|
|
69
|
+
if (url.username || url.password || (url.pathname !== '' && url.pathname !== '/') || url.search || url.hash) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`CORS allowed origin must not include credentials, a path, query parameters, or a fragment: ${origin}`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return url.origin;
|
|
75
|
+
}
|
|
76
|
+
|
|
41
77
|
export class SafeJsonRpcServer {
|
|
42
78
|
/**
|
|
43
79
|
* The HTTP server accepting remote requests.
|
|
@@ -45,7 +81,7 @@ export class SafeJsonRpcServer {
|
|
|
45
81
|
*/
|
|
46
82
|
private httpServer?: http.Server;
|
|
47
83
|
|
|
48
|
-
private config:
|
|
84
|
+
private config: ResolvedSafeJsonRpcServerConfig;
|
|
49
85
|
|
|
50
86
|
constructor(
|
|
51
87
|
/** The proxy object to delegate requests to */
|
|
@@ -53,12 +89,15 @@ export class SafeJsonRpcServer {
|
|
|
53
89
|
config: Partial<SafeJsonRpcServerConfig> = {},
|
|
54
90
|
/** Health check function */
|
|
55
91
|
private readonly healthCheck: StatusCheckFn = () => true,
|
|
56
|
-
/** Additional middlewares */
|
|
92
|
+
/** Additional Koa middlewares */
|
|
57
93
|
private extraMiddlewares: Application.Middleware[] = [],
|
|
94
|
+
/** Additional per-request diagnostics middlewares */
|
|
95
|
+
private diagnosticsMiddleware?: DiagnosticsMiddleware,
|
|
58
96
|
/** Logger */
|
|
59
97
|
private log = createLogger('json-rpc:server'),
|
|
60
98
|
) {
|
|
61
99
|
this.config = { ...defaultServerConfig, ...config };
|
|
100
|
+
this.config.corsAllowedOrigins = this.config.corsAllowedOrigins.map(normalizeCorsOrigin);
|
|
62
101
|
|
|
63
102
|
// handle empty string
|
|
64
103
|
if (!this.config.maxBodySizeBytes) {
|
|
@@ -66,8 +105,16 @@ export class SafeJsonRpcServer {
|
|
|
66
105
|
}
|
|
67
106
|
}
|
|
68
107
|
|
|
108
|
+
/** Returns the status of this server, including per-component health when the health check reports it. */
|
|
109
|
+
public getStatus(): Promise<ServerStatus> {
|
|
110
|
+
return Promise.resolve(this.healthCheck()).then(result => {
|
|
111
|
+
const { healthy, details } = normalizeStatusCheckResult(result);
|
|
112
|
+
return { ok: healthy, ...details };
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
69
116
|
public isHealthy(): boolean | Promise<boolean> {
|
|
70
|
-
return this.
|
|
117
|
+
return this.getStatus().then(status => status.ok);
|
|
71
118
|
}
|
|
72
119
|
|
|
73
120
|
/**
|
|
@@ -92,7 +139,7 @@ export class SafeJsonRpcServer {
|
|
|
92
139
|
ctx.body = { jsonrpc: '2.0', id: null, error: { code: -32700, message: `Parse error: ${err.message}` } };
|
|
93
140
|
} else {
|
|
94
141
|
ctx.status = 500;
|
|
95
|
-
ctx.body = { jsonrpc: '2.0', id: null, error: { code: -
|
|
142
|
+
ctx.body = { jsonrpc: '2.0', id: null, error: { code: -32603, message: err.message ?? 'Internal error' } };
|
|
96
143
|
}
|
|
97
144
|
}
|
|
98
145
|
};
|
|
@@ -116,6 +163,36 @@ export class SafeJsonRpcServer {
|
|
|
116
163
|
|
|
117
164
|
app.use(compress({ br: false }));
|
|
118
165
|
app.use(jsonResponse);
|
|
166
|
+
const corsAllowedHeaders =
|
|
167
|
+
this.config.corsAllowedHeaders.length > 0 ? { allowHeaders: this.config.corsAllowedHeaders } : {};
|
|
168
|
+
if (this.config.corsAllowedOrigins.length === 0) {
|
|
169
|
+
app.use(cors(corsAllowedHeaders));
|
|
170
|
+
} else {
|
|
171
|
+
const allowedOrigins = new Set(this.config.corsAllowedOrigins);
|
|
172
|
+
const allowAnyOrigin = allowedOrigins.has('*');
|
|
173
|
+
app.use(
|
|
174
|
+
cors({
|
|
175
|
+
origin: ctx => {
|
|
176
|
+
const origin = ctx.get('Origin');
|
|
177
|
+
if (!origin) {
|
|
178
|
+
return '';
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (allowAnyOrigin) {
|
|
182
|
+
return origin;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (allowedOrigins.has(origin)) {
|
|
186
|
+
return origin;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return '';
|
|
190
|
+
},
|
|
191
|
+
credentials: true,
|
|
192
|
+
...corsAllowedHeaders,
|
|
193
|
+
}),
|
|
194
|
+
);
|
|
195
|
+
}
|
|
119
196
|
for (const middleware of this.extraMiddlewares) {
|
|
120
197
|
app.use(middleware);
|
|
121
198
|
}
|
|
@@ -126,7 +203,6 @@ export class SafeJsonRpcServer {
|
|
|
126
203
|
enableTypes: ['json'],
|
|
127
204
|
}),
|
|
128
205
|
);
|
|
129
|
-
app.use(cors());
|
|
130
206
|
app.use(router.routes());
|
|
131
207
|
app.use(router.allowedMethods());
|
|
132
208
|
|
|
@@ -155,7 +231,7 @@ export class SafeJsonRpcServer {
|
|
|
155
231
|
};
|
|
156
232
|
return;
|
|
157
233
|
}
|
|
158
|
-
const resp = await this.processBatch(ctx.request.body);
|
|
234
|
+
const resp = await this.processBatch(ctx.request.body, ctx.request.headers);
|
|
159
235
|
if (Array.isArray(resp)) {
|
|
160
236
|
ctx.status = 200;
|
|
161
237
|
ctx.body = resp;
|
|
@@ -164,7 +240,7 @@ export class SafeJsonRpcServer {
|
|
|
164
240
|
ctx.body = resp;
|
|
165
241
|
}
|
|
166
242
|
} else {
|
|
167
|
-
const resp = await this.processRequest(ctx.request.body);
|
|
243
|
+
const resp = await this.processRequest(ctx.request.body, ctx.request.headers);
|
|
168
244
|
if ('error' in resp) {
|
|
169
245
|
ctx.status = this.config.http200OnError ? 200 : 400;
|
|
170
246
|
}
|
|
@@ -176,22 +252,22 @@ export class SafeJsonRpcServer {
|
|
|
176
252
|
return router;
|
|
177
253
|
}
|
|
178
254
|
|
|
179
|
-
private async processBatch(requests: any[]) {
|
|
255
|
+
private async processBatch(requests: any[], headers: http.IncomingHttpHeaders = {}) {
|
|
180
256
|
if (requests.length === 0) {
|
|
181
257
|
return { jsonrpc: '2.0', error: { code: -32600, message: 'Invalid Request' }, id: null };
|
|
182
258
|
}
|
|
183
|
-
const results = await Promise.allSettled(requests.map(req => this.processRequest(req)));
|
|
259
|
+
const results = await Promise.allSettled(requests.map(req => this.processRequest(req, headers)));
|
|
184
260
|
return results.map(res => {
|
|
185
261
|
if (res.status === 'fulfilled') {
|
|
186
262
|
return res.value;
|
|
187
263
|
}
|
|
188
264
|
|
|
189
265
|
this.log.warn(`Uncaught error executing request in batch: ${res.reason}.`);
|
|
190
|
-
return { jsonrpc: '2.0', error: { code: -
|
|
266
|
+
return { jsonrpc: '2.0', error: { code: -32603, message: 'Internal error' }, id: null };
|
|
191
267
|
});
|
|
192
268
|
}
|
|
193
269
|
|
|
194
|
-
private async processRequest(request: any) {
|
|
270
|
+
private async processRequest(request: any, headers: http.IncomingHttpHeaders = {}) {
|
|
195
271
|
if (!request || typeof request !== 'object') {
|
|
196
272
|
return { jsonrpc: '2.0', error: { code: -32600, message: 'Invalid Request' }, id: null };
|
|
197
273
|
}
|
|
@@ -206,8 +282,25 @@ export class SafeJsonRpcServer {
|
|
|
206
282
|
return { jsonrpc, id, error: { code: -32601, message: `Method not found: ${method}` } };
|
|
207
283
|
} else {
|
|
208
284
|
try {
|
|
209
|
-
|
|
210
|
-
|
|
285
|
+
let result: any;
|
|
286
|
+
|
|
287
|
+
if (this.diagnosticsMiddleware) {
|
|
288
|
+
const diagnosticsData: DiagnosticsData = { id: id ?? null, method, params, headers };
|
|
289
|
+
await this.diagnosticsMiddleware(diagnosticsData, async () => {
|
|
290
|
+
result = await this.proxy.call(method, params, (durationMs, succeeded) => {
|
|
291
|
+
diagnosticsData.requestValidationDurationMs = durationMs;
|
|
292
|
+
diagnosticsData.requestValidationSucceeded = succeeded;
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
} else {
|
|
296
|
+
result = await this.proxy.call(method, params);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Coerce an undefined return value to null so the response always carries a `result` key.
|
|
300
|
+
// JSON.stringify drops undefined-valued keys, which would otherwise produce a JSON-RPC
|
|
301
|
+
// response with neither `result` nor `error` — a spec violation that leaves callers unable
|
|
302
|
+
// to distinguish "not found" from a malformed response.
|
|
303
|
+
return { jsonrpc, id, result: result ?? null };
|
|
211
304
|
} catch (err: any) {
|
|
212
305
|
if (err && err instanceof ZodError) {
|
|
213
306
|
const message = err.issues.map(e => `${e.message} (${e.path.join('.')})`).join('. ') || 'Validation error';
|
|
@@ -274,11 +367,42 @@ export class SafeJsonRpcServer {
|
|
|
274
367
|
}
|
|
275
368
|
}
|
|
276
369
|
|
|
277
|
-
|
|
370
|
+
/** Health of a single component, along with any details worth surfacing to whoever queries the status endpoint. */
|
|
371
|
+
export type StatusCheckResult = {
|
|
372
|
+
/** Whether the component is healthy. */
|
|
373
|
+
healthy: boolean;
|
|
374
|
+
/** Component-specific information, reported next to the healthy flag. */
|
|
375
|
+
details?: object;
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
/** Health check for a component. Returning a plain boolean is shorthand for `{ healthy: <boolean> }`. */
|
|
379
|
+
export type StatusCheckFn = () => boolean | StatusCheckResult | Promise<boolean | StatusCheckResult>;
|
|
380
|
+
|
|
381
|
+
/** Health of a component as reported on the status endpoint: its healthy flag flattened with its details. */
|
|
382
|
+
export type ComponentStatus = { healthy: boolean } & Record<string, unknown>;
|
|
383
|
+
|
|
384
|
+
/** Status of a server as reported on the status endpoint. */
|
|
385
|
+
export type ServerStatus = {
|
|
386
|
+
/** Whether every checked component reported healthy. */
|
|
387
|
+
ok: boolean;
|
|
388
|
+
/** Health of each component keyed by namespace, when the server has component-level health checks. */
|
|
389
|
+
components?: Record<string, ComponentStatus>;
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
/** Returns the status of a server. */
|
|
393
|
+
export type ServerStatusFn = () => ServerStatus | Promise<ServerStatus>;
|
|
394
|
+
|
|
395
|
+
function normalizeStatusCheckResult(result: boolean | StatusCheckResult): StatusCheckResult {
|
|
396
|
+
return typeof result === 'boolean' ? { healthy: result } : result;
|
|
397
|
+
}
|
|
278
398
|
|
|
279
399
|
interface Proxy {
|
|
280
400
|
hasMethod(methodName: string): boolean;
|
|
281
|
-
call(
|
|
401
|
+
call(
|
|
402
|
+
methodName: string,
|
|
403
|
+
jsonParams?: any[],
|
|
404
|
+
onRequestValidated?: (durationMs: number, succeeded: boolean) => void,
|
|
405
|
+
): Promise<any>;
|
|
282
406
|
}
|
|
283
407
|
|
|
284
408
|
/**
|
|
@@ -302,14 +426,26 @@ export class SafeJsonProxy<T extends object = any> implements Proxy {
|
|
|
302
426
|
* @param jsonParams - The RPC parameters.
|
|
303
427
|
* @returns The remote result.
|
|
304
428
|
*/
|
|
305
|
-
public async call(
|
|
429
|
+
public async call(
|
|
430
|
+
methodName: string,
|
|
431
|
+
jsonParams: any[] = [],
|
|
432
|
+
onRequestValidated?: (durationMs: number, succeeded: boolean) => void,
|
|
433
|
+
) {
|
|
306
434
|
this.log.debug(format(`request`, methodName, jsonParams));
|
|
307
435
|
|
|
308
|
-
assert(Array.isArray(jsonParams), `Params to ${methodName} is not an array: ${jsonParams}`);
|
|
309
436
|
assert(schemaHasMethod(this.schema, methodName), `Method ${methodName} not found in schema`);
|
|
310
437
|
const method = this.handler[methodName as keyof T];
|
|
311
438
|
assert(typeof method === 'function', `Method ${methodName} is not a function`);
|
|
312
|
-
const
|
|
439
|
+
const validationTimer = new Timer();
|
|
440
|
+
let args: any[];
|
|
441
|
+
try {
|
|
442
|
+
assert(Array.isArray(jsonParams), `Params to ${methodName} is not an array: ${jsonParams}`);
|
|
443
|
+
args = await parseWithOptionals(jsonParams, getSchemaParameters(this.schema[methodName]));
|
|
444
|
+
onRequestValidated?.(validationTimer.ms(), true);
|
|
445
|
+
} catch (error) {
|
|
446
|
+
onRequestValidated?.(validationTimer.ms(), false);
|
|
447
|
+
throw error;
|
|
448
|
+
}
|
|
313
449
|
const ret = await method.apply(this.handler, args);
|
|
314
450
|
this.log.debug(format('response', methodName, ret));
|
|
315
451
|
return ret;
|
|
@@ -329,12 +465,16 @@ class NamespacedSafeJsonProxy implements Proxy {
|
|
|
329
465
|
}
|
|
330
466
|
}
|
|
331
467
|
|
|
332
|
-
public call(
|
|
468
|
+
public call(
|
|
469
|
+
namespacedMethodName: string,
|
|
470
|
+
jsonParams: any[] = [],
|
|
471
|
+
onRequestValidated?: (durationMs: number, succeeded: boolean) => void,
|
|
472
|
+
) {
|
|
333
473
|
const [namespace, methodName] = namespacedMethodName.split('_', 2);
|
|
334
474
|
assert(namespace && methodName, `Invalid namespaced method name: ${namespacedMethodName}`);
|
|
335
475
|
const handler = this.proxies[namespace];
|
|
336
476
|
assert(handler, `Namespace not found: ${namespace}`);
|
|
337
|
-
return handler.call(methodName, jsonParams);
|
|
477
|
+
return handler.call(methodName, jsonParams, onRequestValidated);
|
|
338
478
|
}
|
|
339
479
|
|
|
340
480
|
public hasMethod(namespacedMethodName: string): boolean {
|
|
@@ -353,23 +493,23 @@ export function makeHandler<T extends object>(handler: T, schema: ApiSchemaFor<T
|
|
|
353
493
|
}
|
|
354
494
|
|
|
355
495
|
function makeAggregateHealthcheck(namedHandlers: NamespacedApiHandlers, log?: Logger): StatusCheckFn {
|
|
356
|
-
return async () => {
|
|
496
|
+
return async (): Promise<StatusCheckResult> => {
|
|
357
497
|
try {
|
|
358
|
-
const
|
|
359
|
-
Object.entries(namedHandlers).map(async ([name, [, , healthCheck]]) =>
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
498
|
+
const entries = await Promise.all(
|
|
499
|
+
Object.entries(namedHandlers).map(async ([name, [, , healthCheck]]): Promise<[string, ComponentStatus]> => {
|
|
500
|
+
const { healthy, details } = normalizeStatusCheckResult(healthCheck ? await healthCheck() : true);
|
|
501
|
+
return [name, { healthy, ...details }];
|
|
502
|
+
}),
|
|
363
503
|
);
|
|
364
|
-
const
|
|
504
|
+
const components = Object.fromEntries(entries);
|
|
505
|
+
const failed = entries.filter(([, status]) => !status.healthy).map(([name]) => name);
|
|
365
506
|
if (failed.length > 0) {
|
|
366
|
-
log?.warn(`Health check failed for ${failed.
|
|
367
|
-
return false;
|
|
507
|
+
log?.warn(`Health check failed for ${failed.join(', ')}`, { components });
|
|
368
508
|
}
|
|
369
|
-
return
|
|
509
|
+
return { healthy: failed.length === 0, details: { components } };
|
|
370
510
|
} catch (err) {
|
|
371
511
|
log?.error(`Error during health check`, err);
|
|
372
|
-
return false;
|
|
512
|
+
return { healthy: false };
|
|
373
513
|
}
|
|
374
514
|
};
|
|
375
515
|
}
|
|
@@ -377,6 +517,7 @@ function makeAggregateHealthcheck(namedHandlers: NamespacedApiHandlers, log?: Lo
|
|
|
377
517
|
export type SafeJsonRpcServerOptions = Partial<
|
|
378
518
|
SafeJsonRpcServerConfig & {
|
|
379
519
|
healthCheck: StatusCheckFn;
|
|
520
|
+
diagnostic: DiagnosticsMiddleware;
|
|
380
521
|
log: Logger;
|
|
381
522
|
middlewares: Application.Middleware[];
|
|
382
523
|
}
|
|
@@ -391,10 +532,10 @@ export function createNamespacedSafeJsonRpcServer(
|
|
|
391
532
|
handlers: NamespacedApiHandlers,
|
|
392
533
|
options: Omit<SafeJsonRpcServerOptions, 'healthcheck'> = {},
|
|
393
534
|
): SafeJsonRpcServer {
|
|
394
|
-
const { middlewares, log } = options;
|
|
535
|
+
const { diagnostic, middlewares, log } = options;
|
|
395
536
|
const proxy = new NamespacedSafeJsonProxy(handlers);
|
|
396
537
|
const healthCheck = makeAggregateHealthcheck(handlers, log);
|
|
397
|
-
return new SafeJsonRpcServer(proxy, options, healthCheck, middlewares, log);
|
|
538
|
+
return new SafeJsonRpcServer(proxy, options, healthCheck, middlewares, diagnostic, log);
|
|
398
539
|
}
|
|
399
540
|
|
|
400
541
|
export function createSafeJsonRpcServer<T extends object = any>(
|
|
@@ -402,51 +543,61 @@ export function createSafeJsonRpcServer<T extends object = any>(
|
|
|
402
543
|
schema: ApiSchemaFor<T>,
|
|
403
544
|
options: SafeJsonRpcServerOptions = {},
|
|
404
545
|
) {
|
|
405
|
-
const { log, healthCheck, middlewares: extraMiddlewares } = options;
|
|
546
|
+
const { diagnostic, log, healthCheck, middlewares: extraMiddlewares } = options;
|
|
406
547
|
const proxy = new SafeJsonProxy(handler, schema);
|
|
407
|
-
return new SafeJsonRpcServer(proxy, options, healthCheck, extraMiddlewares, log);
|
|
548
|
+
return new SafeJsonRpcServer(proxy, options, healthCheck, extraMiddlewares, diagnostic, log);
|
|
408
549
|
}
|
|
409
550
|
|
|
410
551
|
/**
|
|
411
|
-
* Creates a router for handling a
|
|
412
|
-
*
|
|
552
|
+
* Creates a router for handling a status request that returns a 200 status code when healthy and a 500 otherwise,
|
|
553
|
+
* along with the reported status as a JSON body.
|
|
554
|
+
* @param getCurrentStatus - Function returning the current status of the server.
|
|
413
555
|
* @param apiPrefix - The prefix to use for all api requests
|
|
414
556
|
* @returns - The router for handling status requests.
|
|
415
557
|
*/
|
|
416
|
-
export function createStatusRouter(getCurrentStatus:
|
|
558
|
+
export function createStatusRouter(getCurrentStatus: ServerStatusFn, apiPrefix = '') {
|
|
417
559
|
const router = new Router({ prefix: `${apiPrefix}` });
|
|
418
560
|
router.get('/status', async (ctx: Koa.Context) => {
|
|
419
|
-
let
|
|
561
|
+
let status: ServerStatus;
|
|
420
562
|
try {
|
|
421
|
-
|
|
563
|
+
status = await getCurrentStatus();
|
|
422
564
|
} catch {
|
|
423
|
-
|
|
565
|
+
status = { ok: false };
|
|
424
566
|
}
|
|
425
567
|
|
|
426
|
-
ctx.status = ok ? 200 : 500;
|
|
568
|
+
ctx.status = status.ok === true ? 200 : 500;
|
|
569
|
+
ctx.type = 'application/json';
|
|
570
|
+
ctx.body = status;
|
|
427
571
|
});
|
|
428
572
|
return router;
|
|
429
573
|
}
|
|
430
574
|
|
|
431
575
|
/**
|
|
432
576
|
* Wraps a JsonRpcServer in a nodejs http server and starts it.
|
|
433
|
-
* Installs a status router that
|
|
577
|
+
* Installs a status router that reports the status of the server, using its getStatus method when available so that
|
|
578
|
+
* per-component health is included, and falling back to isHealthy otherwise.
|
|
434
579
|
* Returns once starts listening unless noWait is set.
|
|
435
580
|
* @returns A running http server.
|
|
436
581
|
*/
|
|
437
582
|
export async function startHttpRpcServer(
|
|
438
|
-
rpcServer: Pick<SafeJsonRpcServer, 'getApp' | 'isHealthy'
|
|
583
|
+
rpcServer: Pick<SafeJsonRpcServer, 'getApp' | 'isHealthy'> & Partial<Pick<SafeJsonRpcServer, 'getStatus'>>,
|
|
439
584
|
options: {
|
|
440
585
|
host?: string;
|
|
441
586
|
port?: number | string;
|
|
442
587
|
apiPrefix?: string;
|
|
443
588
|
timeoutMs?: number;
|
|
589
|
+
keepAliveTimeoutMs?: number;
|
|
590
|
+
headersTimeoutMs?: number;
|
|
444
591
|
noWait?: boolean;
|
|
445
592
|
} = {},
|
|
446
593
|
): Promise<http.Server & { port: number }> {
|
|
447
594
|
const app = rpcServer.getApp(options.apiPrefix);
|
|
448
595
|
|
|
449
|
-
const
|
|
596
|
+
const getStatus: ServerStatusFn = rpcServer.getStatus
|
|
597
|
+
? rpcServer.getStatus.bind(rpcServer)
|
|
598
|
+
: async () => ({ ok: (await rpcServer.isHealthy()) === true });
|
|
599
|
+
|
|
600
|
+
const statusRouter = createStatusRouter(getStatus, options.apiPrefix);
|
|
450
601
|
app.use(statusRouter.routes()).use(statusRouter.allowedMethods());
|
|
451
602
|
|
|
452
603
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
@@ -454,6 +605,12 @@ export async function startHttpRpcServer(
|
|
|
454
605
|
if (options.timeoutMs) {
|
|
455
606
|
httpServer.timeout = options.timeoutMs;
|
|
456
607
|
}
|
|
608
|
+
if (options.keepAliveTimeoutMs !== undefined) {
|
|
609
|
+
httpServer.keepAliveTimeout = options.keepAliveTimeoutMs;
|
|
610
|
+
}
|
|
611
|
+
if (options.headersTimeoutMs !== undefined) {
|
|
612
|
+
httpServer.headersTimeout = options.headersTimeoutMs;
|
|
613
|
+
}
|
|
457
614
|
|
|
458
615
|
const { promise, resolve } = promiseWithResolvers<void>();
|
|
459
616
|
const listenPort = options.port ? (typeof options.port === 'string' ? parseInt(options.port) : options.port) : 0;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { pino } from 'pino';
|
|
2
|
+
|
|
3
|
+
function getSeverity(label: string): { severityText: string; severityNumber: number } {
|
|
4
|
+
switch (label) {
|
|
5
|
+
case 'trace':
|
|
6
|
+
return { severityText: 'TRACE', severityNumber: 1 };
|
|
7
|
+
case 'debug':
|
|
8
|
+
return { severityText: 'DEBUG', severityNumber: 5 };
|
|
9
|
+
case 'verbose':
|
|
10
|
+
return { severityText: 'VERBOSE', severityNumber: 7 };
|
|
11
|
+
case 'info':
|
|
12
|
+
return { severityText: 'INFO', severityNumber: 9 };
|
|
13
|
+
case 'warn':
|
|
14
|
+
return { severityText: 'WARN', severityNumber: 13 };
|
|
15
|
+
case 'error':
|
|
16
|
+
return { severityText: 'ERROR', severityNumber: 17 };
|
|
17
|
+
case 'fatal':
|
|
18
|
+
return { severityText: 'FATAL', severityNumber: 21 };
|
|
19
|
+
default:
|
|
20
|
+
return { severityText: 'UNSPECIFIED', severityNumber: 0 };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Pino configuration that adds OpenTelemetry severity fields understood by CloudWatch Logs. */
|
|
25
|
+
export const AWSCloudLoggerConfig = {
|
|
26
|
+
messageKey: 'msg',
|
|
27
|
+
formatters: {
|
|
28
|
+
level(label: string, level: number): object {
|
|
29
|
+
return { level, ...getSeverity(label) };
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
} satisfies pino.LoggerOptions;
|
package/src/log/pino-logger.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { inspect } from 'util';
|
|
|
7
7
|
import { compactArray } from '../collection/array.js';
|
|
8
8
|
import type { EnvVar } from '../config/index.js';
|
|
9
9
|
import { parseBooleanEnv } from '../config/parse-env.js';
|
|
10
|
+
import { AWSCloudLoggerConfig } from './aws-logger-config.js';
|
|
10
11
|
import { convertBigintsToStrings } from './bigint-utils.js';
|
|
11
12
|
import { GoogleCloudLoggerConfig } from './gcloud-logger-config.js';
|
|
12
13
|
import { getLogLevelFromFilters, parseLogLevelEnvVar } from './log-filters.js';
|
|
@@ -21,6 +22,8 @@ export type LoggerBindings = {
|
|
|
21
22
|
instanceId?: string;
|
|
22
23
|
};
|
|
23
24
|
|
|
25
|
+
const MAX_MODULE_NAME_LENGTH = 256;
|
|
26
|
+
|
|
24
27
|
// Allow global hooks for providing default bindings.
|
|
25
28
|
// Used by withLoggerBindings in pino-logger-server to propagate bindings via AsyncLocalStorage.
|
|
26
29
|
type LogBindingsHandler = () => LoggerBindings | undefined;
|
|
@@ -48,7 +51,7 @@ function getBindingsFromHandlers(): LoggerBindings | undefined {
|
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
export function createLogger(module: string, bindings?: LoggerBindings): Logger {
|
|
51
|
-
module = module.replace(/^aztec:/, '');
|
|
54
|
+
module = module.slice(0, MAX_MODULE_NAME_LENGTH).replace(/^aztec:/, '');
|
|
52
55
|
|
|
53
56
|
const resolvedBindings = { ...getBindingsFromHandlers(), ...bindings };
|
|
54
57
|
const actor = resolvedBindings?.actor;
|
|
@@ -132,8 +135,17 @@ export const [logLevel, logFilters] = parseLogLevelEnvVar(process.env.LOG_LEVEL,
|
|
|
132
135
|
// Define custom logging levels for pino.
|
|
133
136
|
const customLevels = { verbose: 25 };
|
|
134
137
|
|
|
135
|
-
// Global pino options, tweaked for
|
|
138
|
+
// Global pino options, tweaked for the active cloud logging backend.
|
|
136
139
|
const useGcloudLogging = parseBooleanEnv(process.env['USE_GCLOUD_LOGGING' satisfies EnvVar]);
|
|
140
|
+
const useAwsLogging = parseBooleanEnv(process.env['USE_AWS_LOGGING' satisfies EnvVar]);
|
|
141
|
+
const loggingConfig = useGcloudLogging
|
|
142
|
+
? GoogleCloudLoggerConfig
|
|
143
|
+
: useAwsLogging
|
|
144
|
+
? AWSCloudLoggerConfig
|
|
145
|
+
: {
|
|
146
|
+
formatters: {},
|
|
147
|
+
messageKey: 'msg',
|
|
148
|
+
};
|
|
137
149
|
|
|
138
150
|
const redactedPaths = [
|
|
139
151
|
'validatorPrivateKeys',
|
|
@@ -154,7 +166,7 @@ const redactedPaths = [
|
|
|
154
166
|
|
|
155
167
|
const pinoOpts: pino.LoggerOptions<keyof typeof customLevels> = {
|
|
156
168
|
customLevels,
|
|
157
|
-
messageKey:
|
|
169
|
+
messageKey: loggingConfig.messageKey,
|
|
158
170
|
useOnlyCustomLevels: false,
|
|
159
171
|
level: logLevel,
|
|
160
172
|
redact: {
|
|
@@ -168,8 +180,8 @@ const pinoOpts: pino.LoggerOptions<keyof typeof customLevels> = {
|
|
|
168
180
|
},
|
|
169
181
|
formatters: {
|
|
170
182
|
log: obj => convertBigintsToStrings(obj) as Record<string, unknown>,
|
|
183
|
+
...loggingConfig.formatters,
|
|
171
184
|
},
|
|
172
|
-
...(useGcloudLogging ? GoogleCloudLoggerConfig : {}),
|
|
173
185
|
};
|
|
174
186
|
|
|
175
187
|
export const levels = {
|
|
@@ -239,7 +251,7 @@ const pinoPrettyBaseOpts = {
|
|
|
239
251
|
destination: 2,
|
|
240
252
|
sync: true,
|
|
241
253
|
colorize: useColor,
|
|
242
|
-
ignore: 'module,actor,instanceId,pid,hostname,trace_id,span_id,trace_flags,severity',
|
|
254
|
+
ignore: 'module,actor,instanceId,pid,hostname,trace_id,span_id,trace_flags,severity,severityText,severityNumber',
|
|
243
255
|
customLevels: 'fatal:60,error:50,warn:40,info:30,verbose:25,debug:20,trace:10',
|
|
244
256
|
customColors: 'fatal:bgRed,error:red,warn:yellow,info:green,verbose:magenta,debug:blue,trace:gray',
|
|
245
257
|
minimumLevel: 'trace' as const,
|
|
@@ -375,5 +387,20 @@ export type Logger = { [K in LogLevel]: LogFn } & { /** Error log function */ er
|
|
|
375
387
|
* @returns A string with both the log message and the error message.
|
|
376
388
|
*/
|
|
377
389
|
function formatErr(msg: string, err?: unknown): string {
|
|
378
|
-
|
|
390
|
+
if (!err) {
|
|
391
|
+
return msg;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
try {
|
|
395
|
+
return `${msg}: ${inspect(err)}`;
|
|
396
|
+
} catch {
|
|
397
|
+
// inspect can crash on error objects with broken property descriptors
|
|
398
|
+
try {
|
|
399
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
400
|
+
return `${msg}: ${err instanceof Error ? `${err.name}: ${err.message}` : String(err)}`;
|
|
401
|
+
} catch {
|
|
402
|
+
// if even String(err) fails, return the original message with a note about the error
|
|
403
|
+
return `${msg}: [unserializable error]`;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
379
406
|
}
|
|
@@ -10,26 +10,6 @@ const noirLocalDependencySchema = z.object({
|
|
|
10
10
|
path: z.string(),
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
const noirPackageConfigSchema = z.object({
|
|
14
|
-
package: z.object({
|
|
15
|
-
name: z.string().default(''),
|
|
16
|
-
type: z.enum(['lib', 'contract', 'bin']).default('bin'),
|
|
17
|
-
entry: z.string().optional(),
|
|
18
|
-
description: z.string().optional(),
|
|
19
|
-
authors: z.array(z.string()).optional(),
|
|
20
|
-
// eslint-disable-next-line camelcase
|
|
21
|
-
compiler_version: z.string().optional(),
|
|
22
|
-
backend: z.string().optional(),
|
|
23
|
-
license: z.string().optional(),
|
|
24
|
-
}),
|
|
25
|
-
dependencies: z.record(z.union([noirGitDependencySchema, noirLocalDependencySchema])).default({}),
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Noir package configuration.
|
|
30
|
-
*/
|
|
31
|
-
export type NoirPackageConfig = z.infer<typeof noirPackageConfigSchema>;
|
|
32
|
-
|
|
33
13
|
/**
|
|
34
14
|
* A remote package dependency.
|
|
35
15
|
*/
|
|
@@ -45,6 +25,38 @@ export type NoirLocalDependencyConfig = z.infer<typeof noirLocalDependencySchema
|
|
|
45
25
|
*/
|
|
46
26
|
export type NoirDependencyConfig = NoirGitDependencyConfig | NoirLocalDependencyConfig;
|
|
47
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Noir package configuration.
|
|
30
|
+
*/
|
|
31
|
+
export type NoirPackageConfig = {
|
|
32
|
+
package: {
|
|
33
|
+
name: string;
|
|
34
|
+
type: 'lib' | 'contract' | 'bin';
|
|
35
|
+
entry?: string | undefined;
|
|
36
|
+
description?: string | undefined;
|
|
37
|
+
authors?: string[] | undefined;
|
|
38
|
+
compiler_version?: string | undefined;
|
|
39
|
+
backend?: string | undefined;
|
|
40
|
+
license?: string | undefined;
|
|
41
|
+
};
|
|
42
|
+
dependencies: Record<string, NoirDependencyConfig>;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const noirPackageConfigSchema: z.ZodType<NoirPackageConfig> = z.object({
|
|
46
|
+
package: z.object({
|
|
47
|
+
name: z.string().default(''),
|
|
48
|
+
type: z.enum(['lib', 'contract', 'bin']).default('bin'),
|
|
49
|
+
entry: z.string().optional(),
|
|
50
|
+
description: z.string().optional(),
|
|
51
|
+
authors: z.array(z.string()).optional(),
|
|
52
|
+
// eslint-disable-next-line camelcase
|
|
53
|
+
compiler_version: z.string().optional(),
|
|
54
|
+
backend: z.string().optional(),
|
|
55
|
+
license: z.string().optional(),
|
|
56
|
+
}),
|
|
57
|
+
dependencies: z.record(z.string(), z.union([noirGitDependencySchema, noirLocalDependencySchema])).default({}),
|
|
58
|
+
});
|
|
59
|
+
|
|
48
60
|
/**
|
|
49
61
|
* Checks that an object is a package configuration.
|
|
50
62
|
* @param config - Config to check
|