@replit/river 0.17.3 → 0.18.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.
Files changed (45) hide show
  1. package/README.md +4 -3
  2. package/dist/{chunk-7WY3Z5ZN.js → chunk-CLY7AQ25.js} +169 -95
  3. package/dist/{chunk-4C2OXQJB.js → chunk-TIFNW5GQ.js} +62 -65
  4. package/dist/{chunk-F3LFO3GU.js → chunk-UEKU6XRG.js} +1 -1
  5. package/dist/chunk-YITXOAPA.js +72 -0
  6. package/dist/{chunk-Q7OSVPZ5.js → chunk-ZPPKYJI7.js} +1 -1
  7. package/dist/{connection-713c8c66.d.ts → connection-32bf6608.d.ts} +1 -1
  8. package/dist/{connection-b79329de.d.ts → connection-df5f32ee.d.ts} +1 -1
  9. package/dist/{index-80f87385.d.ts → index-314e676a.d.ts} +4 -86
  10. package/dist/index-6118cd48.d.ts +117 -0
  11. package/dist/logging/index.cjs +63 -27
  12. package/dist/logging/index.d.cts +2 -34
  13. package/dist/logging/index.d.ts +2 -34
  14. package/dist/logging/index.js +7 -7
  15. package/dist/{procedures-79a5f07e.d.ts → procedures-74a10937.d.ts} +4 -3
  16. package/dist/router/index.cjs +63 -66
  17. package/dist/router/index.d.cts +43 -42
  18. package/dist/router/index.d.ts +43 -42
  19. package/dist/router/index.js +2 -2
  20. package/dist/transport/impls/uds/client.cjs +152 -84
  21. package/dist/transport/impls/uds/client.d.cts +3 -2
  22. package/dist/transport/impls/uds/client.d.ts +3 -2
  23. package/dist/transport/impls/uds/client.js +7 -4
  24. package/dist/transport/impls/uds/server.cjs +116 -65
  25. package/dist/transport/impls/uds/server.d.cts +3 -2
  26. package/dist/transport/impls/uds/server.d.ts +3 -2
  27. package/dist/transport/impls/uds/server.js +3 -3
  28. package/dist/transport/impls/ws/client.cjs +156 -87
  29. package/dist/transport/impls/ws/client.d.cts +3 -2
  30. package/dist/transport/impls/ws/client.d.ts +3 -2
  31. package/dist/transport/impls/ws/client.js +11 -7
  32. package/dist/transport/impls/ws/server.cjs +116 -65
  33. package/dist/transport/impls/ws/server.d.cts +4 -3
  34. package/dist/transport/impls/ws/server.d.ts +4 -3
  35. package/dist/transport/impls/ws/server.js +3 -3
  36. package/dist/transport/index.cjs +170 -96
  37. package/dist/transport/index.d.cts +2 -1
  38. package/dist/transport/index.d.ts +2 -1
  39. package/dist/transport/index.js +2 -2
  40. package/dist/util/testHelpers.cjs +65 -32
  41. package/dist/util/testHelpers.d.cts +8 -7
  42. package/dist/util/testHelpers.d.ts +8 -7
  43. package/dist/util/testHelpers.js +20 -18
  44. package/package.json +1 -1
  45. package/dist/chunk-H4BYJELI.js +0 -37
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-VH3NGOXQ.js";
7
7
  import {
8
8
  log
9
- } from "./chunk-H4BYJELI.js";
9
+ } from "./chunk-YITXOAPA.js";
10
10
 
11
11
  // router/services.ts
12
12
  import { Type } from "@sinclair/typebox";
@@ -637,46 +637,25 @@ var createClient = (transport, serverId, providedClientOptions = {}) => {
637
637
  );
638
638
  }
639
639
  const [input] = opts.args;
640
- log?.info(
641
- `${transport.clientId} -- invoked ${procType}: ${serviceName}.${procName} with args: ${JSON.stringify(
642
- input
643
- )}`
644
- );
640
+ log?.info(`invoked ${procType} ${serviceName}.${procName}`, {
641
+ clientId: transport.clientId,
642
+ partialTransportMessage: {
643
+ procedureName: procName,
644
+ serviceName,
645
+ payload: input
646
+ }
647
+ });
645
648
  if (options.connectOnInvoke && !transport.connections.has(serverId)) {
646
649
  void transport.connect(serverId);
647
650
  }
648
651
  if (procType === "rpc") {
649
- return handleRpc(
650
- transport,
651
- serverId,
652
- input,
653
- serviceName,
654
- procName
655
- );
652
+ return handleRpc(transport, serverId, input, serviceName, procName);
656
653
  } else if (procType === "stream") {
657
- return handleStream(
658
- transport,
659
- serverId,
660
- input,
661
- serviceName,
662
- procName
663
- );
654
+ return handleStream(transport, serverId, input, serviceName, procName);
664
655
  } else if (procType === "subscribe") {
665
- return handleSubscribe(
666
- transport,
667
- serverId,
668
- input,
669
- serviceName,
670
- procName
671
- );
656
+ return handleSubscribe(transport, serverId, input, serviceName, procName);
672
657
  } else if (procType === "upload") {
673
- return handleUpload(
674
- transport,
675
- serverId,
676
- input,
677
- serviceName,
678
- procName
679
- );
658
+ return handleUpload(transport, serverId, input, serviceName, procName);
680
659
  } else {
681
660
  throw new Error(`invalid river call, unknown procedure type ${procType}`);
682
661
  }
@@ -950,9 +929,10 @@ var RiverServer = class {
950
929
  }
951
930
  onMessage = async (message) => {
952
931
  if (message.to !== this.transport.clientId) {
953
- log?.info(
954
- `${this.transport.clientId} -- got msg with destination that isn't the server, ignoring`
955
- );
932
+ log?.info(`got msg with destination that isn't this server, ignoring`, {
933
+ clientId: this.transport.clientId,
934
+ fullTransportMessage: message
935
+ });
956
936
  return;
957
937
  }
958
938
  let procStream = this.streamMap.get(message.streamId);
@@ -969,7 +949,8 @@ var RiverServer = class {
969
949
  return;
970
950
  const disconnectedClientId = evt.session.to;
971
951
  log?.info(
972
- `${this.transport.clientId} -- got session disconnect from ${disconnectedClientId}, cleaning up streams`
952
+ `got session disconnect from ${disconnectedClientId}, cleaning up streams`,
953
+ evt.session.loggingMetadata
973
954
  );
974
955
  const streamsFromThisClient = this.clientStreams.get(disconnectedClientId);
975
956
  if (!streamsFromThisClient)
@@ -989,37 +970,43 @@ var RiverServer = class {
989
970
  createNewProcStream(message) {
990
971
  if (!isStreamOpen(message.controlFlags)) {
991
972
  log?.error(
992
- `${this.transport.clientId} -- can't create a new procedure stream from a message that doesn't have the stream open bit set`
973
+ `can't create a new procedure stream from a message that doesn't have the stream open bit set`,
974
+ { clientId: this.transport.clientId, fullTransportMessage: message }
993
975
  );
994
- log?.debug(` -> ${JSON.stringify(message)}`);
995
976
  return;
996
977
  }
997
978
  if (!message.procedureName || !message.serviceName) {
998
- log?.warn(
999
- `${this.transport.clientId} -- missing procedure or service name in stream open message`
1000
- );
1001
- log?.debug(` -> ${JSON.stringify(message)}`);
979
+ log?.warn(`missing procedure or service name in stream open message`, {
980
+ clientId: this.transport.clientId,
981
+ fullTransportMessage: message
982
+ });
1002
983
  return;
1003
984
  }
1004
985
  if (!(message.serviceName in this.services)) {
1005
- log?.warn(
1006
- `${this.transport.clientId} -- couldn't find service ${message.serviceName}`
1007
- );
986
+ log?.warn(`couldn't find service ${message.serviceName}`, {
987
+ clientId: this.transport.clientId,
988
+ fullTransportMessage: message
989
+ });
1008
990
  return;
1009
991
  }
1010
992
  const service = this.services[message.serviceName];
1011
993
  const serviceContext = this.getContext(service, message.serviceName);
1012
994
  if (!(message.procedureName in service.procedures)) {
1013
995
  log?.warn(
1014
- `${this.transport.clientId} -- couldn't find a matching procedure for ${message.serviceName}.${message.procedureName}`
996
+ `couldn't find a matching procedure for ${message.serviceName}.${message.procedureName}`,
997
+ {
998
+ clientId: this.transport.clientId,
999
+ fullTransportMessage: message
1000
+ }
1015
1001
  );
1016
1002
  return;
1017
1003
  }
1018
1004
  const session = this.transport.sessions.get(message.from);
1019
1005
  if (!session) {
1020
- log?.warn(
1021
- `${this.transport.clientId} -- couldn't find session for ${message.from}`
1022
- );
1006
+ log?.warn(`couldn't find session for ${message.from}`, {
1007
+ clientId: this.transport.clientId,
1008
+ fullTransportMessage: message
1009
+ });
1023
1010
  return;
1024
1011
  }
1025
1012
  const procedure = service.procedures[message.procedureName];
@@ -1062,7 +1049,8 @@ var RiverServer = class {
1062
1049
  const errorHandler = (err) => {
1063
1050
  const errorMsg = coerceErrorString(err);
1064
1051
  log?.error(
1065
- `${this.transport.clientId} -- procedure ${message.serviceName}.${message.procedureName}:${message.streamId} threw an uncaught error: ${errorMsg}`
1052
+ `procedure ${message.serviceName}.${message.procedureName} threw an uncaught error: ${errorMsg}`,
1053
+ session.loggingMetadata
1066
1054
  );
1067
1055
  outgoing.push(
1068
1056
  Err({
@@ -1105,12 +1093,19 @@ var RiverServer = class {
1105
1093
  if (initMessage.done) {
1106
1094
  return;
1107
1095
  }
1108
- return procedure.handler(
1109
- serviceContextWithTransportInfo,
1110
- initMessage.value,
1111
- incoming,
1112
- outgoing
1113
- ).catch(errorHandler);
1096
+ try {
1097
+ const dispose = await procedure.handler(
1098
+ serviceContextWithTransportInfo,
1099
+ initMessage.value,
1100
+ incoming,
1101
+ outgoing
1102
+ );
1103
+ if (dispose) {
1104
+ disposables.push(dispose);
1105
+ }
1106
+ } catch (err) {
1107
+ errorHandler(err);
1108
+ }
1114
1109
  })();
1115
1110
  } else {
1116
1111
  inputHandler = procedure.handler(serviceContextWithTransportInfo, incoming, outgoing).catch(errorHandler);
@@ -1174,7 +1169,8 @@ var RiverServer = class {
1174
1169
  break;
1175
1170
  default:
1176
1171
  log?.warn(
1177
- `${this.transport.clientId} -- got request for invalid procedure type ${procedure.type} at ${message.serviceName}.${message.procedureName}`
1172
+ `got request for invalid procedure type ${procedure.type} at ${message.serviceName}.${message.procedureName}`,
1173
+ { ...session.loggingMetadata, fullTransportMessage: message }
1178
1174
  );
1179
1175
  return;
1180
1176
  }
@@ -1202,9 +1198,8 @@ var RiverServer = class {
1202
1198
  procStream.incoming.push(message.payload);
1203
1199
  } else if (!Value.Check(ControlMessagePayloadSchema, message.payload)) {
1204
1200
  log?.error(
1205
- `${this.transport.clientId} -- procedure ${serviceName}.${procedureName} received invalid payload: ${JSON.stringify(
1206
- message.payload
1207
- )}`
1201
+ `procedure ${serviceName}.${procedureName} received invalid payload`,
1202
+ { clientId: this.transport.clientId, fullTransportMessage: message }
1208
1203
  );
1209
1204
  }
1210
1205
  if (isStreamClose(message.controlFlags)) {
@@ -1218,11 +1213,13 @@ var RiverServer = class {
1218
1213
  }
1219
1214
  }
1220
1215
  }
1221
- getContext(service, name) {
1216
+ getContext(service, serviceName) {
1222
1217
  const context = this.contextMap.get(service);
1223
1218
  if (!context) {
1224
- const err = `${this.transport.clientId} -- no context found for ${name}`;
1225
- log?.error(err);
1219
+ const err = `no context found for ${serviceName}`;
1220
+ log?.error(err, {
1221
+ clientId: this.transport.clientId
1222
+ });
1226
1223
  throw new Error(err);
1227
1224
  }
1228
1225
  return context;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Connection
3
- } from "./chunk-7WY3Z5ZN.js";
3
+ } from "./chunk-CLY7AQ25.js";
4
4
 
5
5
  // transport/impls/ws/connection.ts
6
6
  var WebSocketConnection = class extends Connection {
@@ -0,0 +1,72 @@
1
+ // logging/log.ts
2
+ var LoggingLevels = {
3
+ debug: -1,
4
+ info: 0,
5
+ warn: 1,
6
+ error: 2
7
+ };
8
+ var BaseLogger = class {
9
+ minLevel;
10
+ output;
11
+ constructor(output, minLevel = "info") {
12
+ this.minLevel = minLevel;
13
+ this.output = output;
14
+ }
15
+ debug(msg, metadata) {
16
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.debug) {
17
+ this.output(msg, metadata ?? {}, "debug");
18
+ }
19
+ }
20
+ info(msg, metadata) {
21
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.info) {
22
+ this.output(msg, metadata ?? {}, "info");
23
+ }
24
+ }
25
+ warn(msg, metadata) {
26
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.warn) {
27
+ this.output(msg, metadata ?? {}, "warn");
28
+ }
29
+ }
30
+ error(msg, metadata) {
31
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.error) {
32
+ this.output(msg, metadata ?? {}, "error");
33
+ }
34
+ }
35
+ };
36
+ var stringLogger = (msg, _ctx, level) => {
37
+ console.log(`[river:${level}] ${msg}`);
38
+ };
39
+ var colorMap = {
40
+ debug: "\x1B[34m",
41
+ info: "\x1B[32m",
42
+ warn: "\x1B[33m",
43
+ error: "\x1B[31m"
44
+ };
45
+ var coloredStringLogger = (msg, _ctx, level) => {
46
+ const color = colorMap[level];
47
+ console.log(`[river:${color}${level}\x1B[0m] ${msg}`);
48
+ };
49
+ var jsonLogger = (msg, ctx, level) => {
50
+ console.log(JSON.stringify({ msg, ctx, level }));
51
+ };
52
+ var log = void 0;
53
+ function bindLogger(fn, level) {
54
+ if (!fn) {
55
+ log = void 0;
56
+ return;
57
+ }
58
+ if (fn instanceof BaseLogger) {
59
+ log = fn;
60
+ return fn;
61
+ }
62
+ log = new BaseLogger(fn, level);
63
+ return log;
64
+ }
65
+
66
+ export {
67
+ stringLogger,
68
+ coloredStringLogger,
69
+ jsonLogger,
70
+ log,
71
+ bindLogger
72
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Connection
3
- } from "./chunk-7WY3Z5ZN.js";
3
+ } from "./chunk-CLY7AQ25.js";
4
4
 
5
5
  // transport/transforms/messageFraming.ts
6
6
  import { Transform } from "node:stream";
@@ -1,4 +1,4 @@
1
- import { C as Connection } from './index-80f87385.js';
1
+ import { C as Connection } from './index-314e676a.js';
2
2
  import { Socket } from 'node:net';
3
3
  import stream, { Transform, TransformCallback, TransformOptions } from 'node:stream';
4
4
 
@@ -1,5 +1,5 @@
1
1
  import WebSocket from 'isomorphic-ws';
2
- import { C as Connection } from './index-80f87385.js';
2
+ import { C as Connection } from './index-314e676a.js';
3
3
 
4
4
  declare class WebSocketConnection extends Connection {
5
5
  ws: WebSocket;
@@ -1,88 +1,5 @@
1
1
  import { C as Codec } from './types-3e5768ec.js';
2
- import * as _sinclair_typebox from '@sinclair/typebox';
3
- import { TSchema } from '@sinclair/typebox';
4
-
5
- /**
6
- * Generic Typebox schema for a transport message.
7
- * @template T The type of the payload.
8
- * @param {T} t The payload schema.
9
- * @returns The transport message schema.
10
- */
11
- declare const TransportMessageSchema: <T extends TSchema>(t: T) => _sinclair_typebox.TObject<{
12
- id: _sinclair_typebox.TString;
13
- from: _sinclair_typebox.TString;
14
- to: _sinclair_typebox.TString;
15
- seq: _sinclair_typebox.TInteger;
16
- ack: _sinclair_typebox.TInteger;
17
- serviceName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
18
- procedureName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
19
- streamId: _sinclair_typebox.TString;
20
- controlFlags: _sinclair_typebox.TInteger;
21
- payload: T;
22
- }>;
23
- /**
24
- * Defines the schema for an opaque transport message that is agnostic to any
25
- * procedure/service.
26
- * @returns The transport message schema.
27
- */
28
- declare const OpaqueTransportMessageSchema: _sinclair_typebox.TObject<{
29
- id: _sinclair_typebox.TString;
30
- from: _sinclair_typebox.TString;
31
- to: _sinclair_typebox.TString;
32
- seq: _sinclair_typebox.TInteger;
33
- ack: _sinclair_typebox.TInteger;
34
- serviceName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
35
- procedureName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
36
- streamId: _sinclair_typebox.TString;
37
- controlFlags: _sinclair_typebox.TInteger;
38
- payload: _sinclair_typebox.TUnknown;
39
- }>;
40
- /**
41
- * Represents a transport message. This is the same type as {@link TransportMessageSchema} but
42
- * we can't statically infer generics from generic Typebox schemas so we have to define it again here.
43
- *
44
- * TypeScript can't enforce types when a bitmask is involved, so these are the semantics of
45
- * `controlFlags`:
46
- * * If `controlFlags & StreamOpenBit == StreamOpenBit`, `streamId` must be set to a unique value
47
- * (suggestion: use `nanoid`).
48
- * * If `controlFlags & StreamOpenBit == StreamOpenBit`, `serviceName` and `procedureName` must be set.
49
- * * If `controlFlags & StreamClosedBit == StreamClosedBit` and the kind is `stream` or `subscription`,
50
- * `payload` should be discarded (usually contains a control message).
51
- * * If `controlFlags & AckBit == AckBit`, the message is an explicit acknowledgement message and doesn't
52
- * contain any payload that is relevant to the application so should not be delivered.
53
- * @template Payload The type of the payload.
54
- */
55
- interface TransportMessage<Payload = Record<string, unknown>> {
56
- id: string;
57
- from: string;
58
- to: string;
59
- seq: number;
60
- ack: number;
61
- serviceName?: string;
62
- procedureName?: string;
63
- streamId: string;
64
- controlFlags: number;
65
- payload: Payload;
66
- }
67
- type PartialTransportMessage<Payload extends Record<string, unknown> = Record<string, unknown>> = Omit<TransportMessage<Payload>, 'id' | 'from' | 'to' | 'seq' | 'ack'>;
68
- /**
69
- * A type alias for a transport message with an opaque payload.
70
- * @template T - The type of the opaque payload.
71
- */
72
- type OpaqueTransportMessage = TransportMessage<unknown>;
73
- type TransportClientId = string;
74
- /**
75
- * Checks if the given control flag (usually found in msg.controlFlag) is a stream open message.
76
- * @param controlFlag - The control flag to check.
77
- * @returns True if the control flag contains the StreamOpenBit, false otherwise.
78
- */
79
- declare function isStreamOpen(controlFlag: number): boolean;
80
- /**
81
- * Checks if the given control flag (usually found in msg.controlFlag) is a stream close message.
82
- * @param controlFlag - The control flag to check.
83
- * @returns True if the control flag contains the StreamCloseBit, false otherwise.
84
- */
85
- declare function isStreamClose(controlFlag: number): boolean;
2
+ import { T as TransportClientId, M as MessageMetadata, P as PartialTransportMessage, a as TransportMessage, O as OpaqueTransportMessage } from './index-6118cd48.js';
86
3
 
87
4
  /**
88
5
  * A connection is the actual raw underlying transport connection.
@@ -198,6 +115,7 @@ declare class Session<ConnType extends Connection> {
198
115
  */
199
116
  private heartbeat;
200
117
  constructor(conn: ConnType | undefined, from: TransportClientId, to: TransportClientId, options: SessionOptions);
118
+ get loggingMetadata(): Omit<MessageMetadata, 'parsedMsg'>;
201
119
  /**
202
120
  * Sends a message over the session's connection.
203
121
  * If the connection is not ready or the message fails to send, the message can be buffered for retry unless skipped.
@@ -218,7 +136,7 @@ declare class Session<ConnType extends Connection> {
218
136
  close(): void;
219
137
  get connected(): boolean;
220
138
  get nextExpectedSeq(): number;
221
- constructMsg<Payload extends Record<string, unknown>>(partialMsg: PartialTransportMessage<Payload>): TransportMessage<Payload>;
139
+ constructMsg<Payload>(partialMsg: PartialTransportMessage<Payload>): TransportMessage<Payload>;
222
140
  inspectSendBuffer(): ReadonlyArray<OpaqueTransportMessage>;
223
141
  }
224
142
 
@@ -499,4 +417,4 @@ declare abstract class ServerTransport<ConnType extends Connection> extends Tran
499
417
  receiveHandshakeRequestMessage(data: Uint8Array, conn: ConnType): Session<ConnType> | false;
500
418
  }
501
419
 
502
- export { Connection as C, EventMap as E, OpaqueTransportMessage as O, PartialTransportMessage as P, SessionOptions as S, Transport as T, ClientTransport as a, TransportClientId as b, ProvidedClientTransportOptions as c, ServerTransport as d, ProvidedTransportOptions as e, Session as f, TransportStatus as g, TransportMessageSchema as h, OpaqueTransportMessageSchema as i, TransportMessage as j, isStreamOpen as k, isStreamClose as l, EventTypes as m, EventHandler as n, ProtocolError as o, ProtocolErrorType as p };
420
+ export { Connection as C, EventMap as E, ProvidedClientTransportOptions as P, SessionOptions as S, Transport as T, Session as a, ClientTransport as b, ServerTransport as c, ProvidedTransportOptions as d, TransportStatus as e, EventTypes as f, EventHandler as g, ProtocolError as h, ProtocolErrorType as i };
@@ -0,0 +1,117 @@
1
+ import * as _sinclair_typebox from '@sinclair/typebox';
2
+ import { TSchema } from '@sinclair/typebox';
3
+
4
+ /**
5
+ * Generic Typebox schema for a transport message.
6
+ * @template T The type of the payload.
7
+ * @param {T} t The payload schema.
8
+ * @returns The transport message schema.
9
+ */
10
+ declare const TransportMessageSchema: <T extends TSchema>(t: T) => _sinclair_typebox.TObject<{
11
+ id: _sinclair_typebox.TString;
12
+ from: _sinclair_typebox.TString;
13
+ to: _sinclair_typebox.TString;
14
+ seq: _sinclair_typebox.TInteger;
15
+ ack: _sinclair_typebox.TInteger;
16
+ serviceName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
17
+ procedureName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
18
+ streamId: _sinclair_typebox.TString;
19
+ controlFlags: _sinclair_typebox.TInteger;
20
+ payload: T;
21
+ }>;
22
+ /**
23
+ * Defines the schema for an opaque transport message that is agnostic to any
24
+ * procedure/service.
25
+ * @returns The transport message schema.
26
+ */
27
+ declare const OpaqueTransportMessageSchema: _sinclair_typebox.TObject<{
28
+ id: _sinclair_typebox.TString;
29
+ from: _sinclair_typebox.TString;
30
+ to: _sinclair_typebox.TString;
31
+ seq: _sinclair_typebox.TInteger;
32
+ ack: _sinclair_typebox.TInteger;
33
+ serviceName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
34
+ procedureName: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
35
+ streamId: _sinclair_typebox.TString;
36
+ controlFlags: _sinclair_typebox.TInteger;
37
+ payload: _sinclair_typebox.TUnknown;
38
+ }>;
39
+ /**
40
+ * Represents a transport message. This is the same type as {@link TransportMessageSchema} but
41
+ * we can't statically infer generics from generic Typebox schemas so we have to define it again here.
42
+ *
43
+ * TypeScript can't enforce types when a bitmask is involved, so these are the semantics of
44
+ * `controlFlags`:
45
+ * * If `controlFlags & StreamOpenBit == StreamOpenBit`, `streamId` must be set to a unique value
46
+ * (suggestion: use `nanoid`).
47
+ * * If `controlFlags & StreamOpenBit == StreamOpenBit`, `serviceName` and `procedureName` must be set.
48
+ * * If `controlFlags & StreamClosedBit == StreamClosedBit` and the kind is `stream` or `subscription`,
49
+ * `payload` should be discarded (usually contains a control message).
50
+ * * If `controlFlags & AckBit == AckBit`, the message is an explicit acknowledgement message and doesn't
51
+ * contain any payload that is relevant to the application so should not be delivered.
52
+ * @template Payload The type of the payload.
53
+ */
54
+ interface TransportMessage<Payload = unknown> {
55
+ id: string;
56
+ from: string;
57
+ to: string;
58
+ seq: number;
59
+ ack: number;
60
+ serviceName?: string;
61
+ procedureName?: string;
62
+ streamId: string;
63
+ controlFlags: number;
64
+ payload: Payload;
65
+ }
66
+ type PartialTransportMessage<Payload = unknown> = Omit<TransportMessage<Payload>, 'id' | 'from' | 'to' | 'seq' | 'ack'>;
67
+ /**
68
+ * A type alias for a transport message with an opaque payload.
69
+ * @template T - The type of the opaque payload.
70
+ */
71
+ type OpaqueTransportMessage = TransportMessage;
72
+ type TransportClientId = string;
73
+ /**
74
+ * Checks if the given control flag (usually found in msg.controlFlag) is a stream open message.
75
+ * @param controlFlag - The control flag to check.
76
+ * @returns True if the control flag contains the StreamOpenBit, false otherwise.
77
+ */
78
+ declare function isStreamOpen(controlFlag: number): boolean;
79
+ /**
80
+ * Checks if the given control flag (usually found in msg.controlFlag) is a stream close message.
81
+ * @param controlFlag - The control flag to check.
82
+ * @returns True if the control flag contains the StreamCloseBit, false otherwise.
83
+ */
84
+ declare function isStreamClose(controlFlag: number): boolean;
85
+
86
+ declare const LoggingLevels: {
87
+ readonly debug: -1;
88
+ readonly info: 0;
89
+ readonly warn: 1;
90
+ readonly error: 2;
91
+ };
92
+ type LoggingLevel = keyof typeof LoggingLevels;
93
+ type LogFn = (msg: string, ctx: MessageMetadata, level: LoggingLevel) => void;
94
+ type MessageMetadata = Record<string, unknown> & Partial<{
95
+ protocolVersion: string;
96
+ clientId: string;
97
+ connectedTo: string;
98
+ sessionId: string;
99
+ connId: string;
100
+ fullTransportMessage: OpaqueTransportMessage;
101
+ partialTransportMessage: Partial<PartialTransportMessage>;
102
+ }>;
103
+ declare class BaseLogger {
104
+ minLevel: LoggingLevel;
105
+ private output;
106
+ constructor(output: LogFn, minLevel?: LoggingLevel);
107
+ debug(msg: string, metadata?: MessageMetadata): void;
108
+ info(msg: string, metadata?: MessageMetadata): void;
109
+ warn(msg: string, metadata?: MessageMetadata): void;
110
+ error(msg: string, metadata?: MessageMetadata): void;
111
+ }
112
+ declare const stringLogger: LogFn;
113
+ declare const coloredStringLogger: LogFn;
114
+ declare const jsonLogger: LogFn;
115
+ declare function bindLogger(fn: LogFn | BaseLogger | undefined, level?: LoggingLevel): BaseLogger | undefined;
116
+
117
+ export { LogFn as L, MessageMetadata as M, OpaqueTransportMessage as O, PartialTransportMessage as P, TransportClientId as T, TransportMessage as a, TransportMessageSchema as b, OpaqueTransportMessageSchema as c, isStreamClose as d, coloredStringLogger as e, bindLogger as f, isStreamOpen as i, jsonLogger as j, stringLogger as s };
@@ -21,44 +21,80 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var logging_exports = {};
22
22
  __export(logging_exports, {
23
23
  bindLogger: () => bindLogger,
24
- log: () => log,
25
- setLevel: () => setLevel,
26
- unbindLogger: () => unbindLogger
24
+ coloredStringLogger: () => coloredStringLogger,
25
+ jsonLogger: () => jsonLogger,
26
+ stringLogger: () => stringLogger
27
27
  });
28
28
  module.exports = __toCommonJS(logging_exports);
29
+
30
+ // logging/log.ts
29
31
  var LoggingLevels = {
30
32
  debug: -1,
31
33
  info: 0,
32
34
  warn: 1,
33
35
  error: 2
34
36
  };
35
- var log;
36
- var defaultLoggingLevel = "info";
37
- function bindLogger(write, color) {
38
- const debug = color ? "\x1B[37mdebug\x1B[0m" : "debug";
39
- const info = color ? "\x1B[37minfo\x1B[0m" : "info";
40
- const warn = color ? "\x1B[33mwarn\x1B[0m" : "warn";
41
- const error = color ? "\x1B[31merr\x1B[0m" : "err";
42
- log = {
43
- debug: (msg) => log && LoggingLevels[log.minLevel] <= -1 && write(`[river:${debug}] ${msg}`),
44
- info: (msg) => log && LoggingLevels[log.minLevel] <= 0 && write(`[river:${info}] ${msg}`),
45
- warn: (msg) => log && LoggingLevels[log.minLevel] <= 1 && write(`[river:${warn}] ${msg}`),
46
- error: (msg) => log && LoggingLevels[log.minLevel] <= 2 && write(`[river:${error}] ${msg}`),
47
- minLevel: log?.minLevel ?? defaultLoggingLevel
48
- };
49
- }
50
- function unbindLogger() {
51
- log = void 0;
52
- }
53
- function setLevel(level) {
54
- if (log) {
55
- log.minLevel = level;
37
+ var BaseLogger = class {
38
+ minLevel;
39
+ output;
40
+ constructor(output, minLevel = "info") {
41
+ this.minLevel = minLevel;
42
+ this.output = output;
43
+ }
44
+ debug(msg, metadata) {
45
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.debug) {
46
+ this.output(msg, metadata ?? {}, "debug");
47
+ }
48
+ }
49
+ info(msg, metadata) {
50
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.info) {
51
+ this.output(msg, metadata ?? {}, "info");
52
+ }
53
+ }
54
+ warn(msg, metadata) {
55
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.warn) {
56
+ this.output(msg, metadata ?? {}, "warn");
57
+ }
58
+ }
59
+ error(msg, metadata) {
60
+ if (LoggingLevels[this.minLevel] <= LoggingLevels.error) {
61
+ this.output(msg, metadata ?? {}, "error");
62
+ }
63
+ }
64
+ };
65
+ var stringLogger = (msg, _ctx, level) => {
66
+ console.log(`[river:${level}] ${msg}`);
67
+ };
68
+ var colorMap = {
69
+ debug: "\x1B[34m",
70
+ info: "\x1B[32m",
71
+ warn: "\x1B[33m",
72
+ error: "\x1B[31m"
73
+ };
74
+ var coloredStringLogger = (msg, _ctx, level) => {
75
+ const color = colorMap[level];
76
+ console.log(`[river:${color}${level}\x1B[0m] ${msg}`);
77
+ };
78
+ var jsonLogger = (msg, ctx, level) => {
79
+ console.log(JSON.stringify({ msg, ctx, level }));
80
+ };
81
+ var log = void 0;
82
+ function bindLogger(fn, level) {
83
+ if (!fn) {
84
+ log = void 0;
85
+ return;
86
+ }
87
+ if (fn instanceof BaseLogger) {
88
+ log = fn;
89
+ return fn;
56
90
  }
91
+ log = new BaseLogger(fn, level);
92
+ return log;
57
93
  }
58
94
  // Annotate the CommonJS export names for ESM import in node:
59
95
  0 && (module.exports = {
60
96
  bindLogger,
61
- log,
62
- setLevel,
63
- unbindLogger
97
+ coloredStringLogger,
98
+ jsonLogger,
99
+ stringLogger
64
100
  });