@rivetkit/effect 0.0.0-main.879b6a2 → 0.0.0-sqlite-uds.4e59a38

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 (67) hide show
  1. package/dist/Actor.d.ts +2 -3
  2. package/dist/Actor.d.ts.map +1 -1
  3. package/dist/Actor.js +2 -2
  4. package/dist/Actor.js.map +1 -1
  5. package/dist/Client.d.ts.map +1 -1
  6. package/dist/Client.js +6 -4
  7. package/dist/Client.js.map +1 -1
  8. package/dist/Registry.d.ts +69 -7
  9. package/dist/Registry.d.ts.map +1 -1
  10. package/dist/Registry.js +93 -40
  11. package/dist/Registry.js.map +1 -1
  12. package/dist/RivetError.d.ts +18 -3
  13. package/dist/RivetError.d.ts.map +1 -1
  14. package/dist/RivetError.js +31 -0
  15. package/dist/RivetError.js.map +1 -1
  16. package/dist/RivetLogger.d.ts +41 -0
  17. package/dist/RivetLogger.d.ts.map +1 -0
  18. package/dist/RivetLogger.js +41 -0
  19. package/dist/RivetLogger.js.map +1 -0
  20. package/dist/State.d.ts +92 -56
  21. package/dist/State.d.ts.map +1 -1
  22. package/dist/State.js +51 -57
  23. package/dist/State.js.map +1 -1
  24. package/dist/internal/ActionDispatcher.d.ts.map +1 -1
  25. package/dist/internal/ActionDispatcher.js.map +1 -1
  26. package/dist/internal/ActorInstanceManager.d.ts.map +1 -1
  27. package/dist/internal/ActorInstanceManager.js +4 -4
  28. package/dist/internal/ActorInstanceManager.js.map +1 -1
  29. package/dist/internal/ActorStateAdapter.d.ts +1 -1
  30. package/dist/internal/ActorStateAdapter.d.ts.map +1 -1
  31. package/dist/internal/ActorStateAdapter.js +2 -7
  32. package/dist/internal/ActorStateAdapter.js.map +1 -1
  33. package/dist/internal/StateOptions.d.ts +1 -0
  34. package/dist/internal/StateOptions.d.ts.map +1 -1
  35. package/dist/internal/logging.d.ts +6 -7
  36. package/dist/internal/logging.d.ts.map +1 -1
  37. package/dist/internal/logging.js +78 -102
  38. package/dist/internal/logging.js.map +1 -1
  39. package/dist/mod.d.ts +1 -1
  40. package/dist/mod.d.ts.map +1 -1
  41. package/dist/mod.js +1 -1
  42. package/dist/mod.js.map +1 -1
  43. package/package.json +3 -2
  44. package/src/Actor.test-d.ts +32 -0
  45. package/src/Actor.test.ts +4 -1
  46. package/src/Actor.ts +29 -4
  47. package/src/Client.test.ts +22 -26
  48. package/src/Client.ts +6 -4
  49. package/src/Registry.test.ts +12 -23
  50. package/src/Registry.ts +131 -70
  51. package/src/RivetError.test.ts +11 -0
  52. package/src/RivetError.ts +37 -0
  53. package/src/RivetLogger.ts +60 -0
  54. package/src/State.test.ts +163 -4
  55. package/src/State.ts +293 -97
  56. package/src/internal/ActionDispatcher.ts +8 -11
  57. package/src/internal/ActorInstanceManager.ts +32 -38
  58. package/src/internal/ActorStateAdapter.ts +5 -11
  59. package/src/internal/StateOptions.ts +4 -0
  60. package/src/internal/logging.test.ts +107 -121
  61. package/src/internal/logging.ts +103 -143
  62. package/src/mod.ts +1 -1
  63. package/dist/Logger.d.ts +0 -29
  64. package/dist/Logger.d.ts.map +0 -1
  65. package/dist/Logger.js +0 -31
  66. package/dist/Logger.js.map +0 -1
  67. package/src/Logger.ts +0 -43
@@ -1,13 +1,6 @@
1
1
  import { assert, describe, it } from "@effect/vitest";
2
- import {
3
- Config,
4
- ConfigProvider,
5
- Effect,
6
- Layer,
7
- Logger as EffectLogger,
8
- References,
9
- } from "effect";
10
- import type { Logger as PinoLogger } from "rivetkit/log";
2
+ import { ConfigProvider, Effect, Logger, References } from "effect";
3
+ import * as RivetkitLog from "rivetkit/log";
11
4
  import * as Logging from "./logging.ts";
12
5
 
13
6
  type LogEntry = {
@@ -16,16 +9,9 @@ type LogEntry = {
16
9
  readonly msg: string | undefined;
17
10
  };
18
11
 
19
- function makeTestLogger(entries: Array<LogEntry>): PinoLogger {
12
+ function makeTestLogger(entries: Array<LogEntry>): RivetkitLog.Logger {
20
13
  const logger: Record<string, unknown> = {};
21
- for (const level of [
22
- "trace",
23
- "debug",
24
- "info",
25
- "warn",
26
- "error",
27
- "fatal",
28
- ]) {
14
+ for (const level of ["trace", "debug", "info", "warn", "error", "fatal"]) {
29
15
  logger[level] = (
30
16
  fields: Record<string, unknown>,
31
17
  msg?: string,
@@ -34,7 +20,7 @@ function makeTestLogger(entries: Array<LogEntry>): PinoLogger {
34
20
  };
35
21
  }
36
22
 
37
- return logger as unknown as PinoLogger;
23
+ return logger as unknown as RivetkitLog.Logger;
38
24
  }
39
25
 
40
26
  describe("internal/logging", () => {
@@ -72,23 +58,21 @@ describe("internal/logging", () => {
72
58
  key: "room-1",
73
59
  actorId: "actor-1",
74
60
  }),
75
- Effect.provide(
76
- EffectLogger.layer([Logging.makeEffectLogger(baseLogger)]),
77
- ),
61
+ Effect.provide(Logger.layer([Logging.makeLogger(baseLogger)])),
78
62
  );
79
63
 
80
- assert.deepStrictEqual(entries, [
81
- {
82
- level: "info",
83
- fields: {
84
- roomId: "abc",
85
- actor: "ChatRoom",
86
- key: "room-1",
87
- actorId: "actor-1",
88
- },
89
- msg: "room awake",
90
- },
91
- ]);
64
+ const entry = entries[0];
65
+ assert.ok(entry !== undefined);
66
+ assert.strictEqual(entry.level, "info");
67
+ assert.strictEqual(entry.msg, "room awake");
68
+ assert.deepStrictEqual(entry.fields, {
69
+ roomId: "abc",
70
+ actor: "ChatRoom",
71
+ key: "room-1",
72
+ actorId: "actor-1",
73
+ fiberId: entry.fields.fiberId,
74
+ });
75
+ assert.strictEqual(typeof entry.fields.fiberId, "string");
92
76
  }),
93
77
  );
94
78
 
@@ -99,9 +83,7 @@ describe("internal/logging", () => {
99
83
  const error = new Error("room failed to wake");
100
84
 
101
85
  yield* Effect.logError(error).pipe(
102
- Effect.provide(
103
- EffectLogger.layer([Logging.makeEffectLogger(baseLogger)]),
104
- ),
86
+ Effect.provide(Logger.layer([Logging.makeLogger(baseLogger)])),
105
87
  );
106
88
 
107
89
  const entry = entries[0];
@@ -122,9 +104,7 @@ describe("internal/logging", () => {
122
104
  actorId: "actor-1",
123
105
  action: "SendMessage",
124
106
  }).pipe(
125
- Effect.provide(
126
- EffectLogger.layer([Logging.makeEffectLogger(baseLogger)]),
127
- ),
107
+ Effect.provide(Logger.layer([Logging.makeLogger(baseLogger)])),
128
108
  );
129
109
 
130
110
  const entry = entries[0];
@@ -137,15 +117,7 @@ describe("internal/logging", () => {
137
117
  }),
138
118
  );
139
119
 
140
- it.effect("uses References.MinimumLogLevel when creating the base logger", () =>
141
- Effect.gen(function* () {
142
- const baseLogger = yield* Logging.makeDefaultBaseLogger;
143
-
144
- assert.strictEqual(baseLogger.level, "debug");
145
- }).pipe(Effect.provideService(References.MinimumLogLevel, "Debug")),
146
- );
147
-
148
- it.effect("accepts the shared Pino RIVET_LOG_LEVEL values", () =>
120
+ it.effect("accepts RIVET_LOG_LEVEL values", () =>
149
121
  Effect.gen(function* () {
150
122
  const baseLogger = yield* Logging.makeDefaultBaseLogger;
151
123
 
@@ -162,25 +134,24 @@ describe("internal/logging", () => {
162
134
  ),
163
135
  );
164
136
 
165
- it.effect("prefers References.MinimumLogLevel over shared env values", () =>
137
+ it.effect("accepts uppercase RIVET_LOG_LEVEL values", () =>
166
138
  Effect.gen(function* () {
167
139
  const baseLogger = yield* Logging.makeDefaultBaseLogger;
168
140
 
169
141
  assert.strictEqual(baseLogger.level, "debug");
170
142
  }).pipe(
171
- Effect.provideService(References.MinimumLogLevel, "Debug"),
172
143
  Effect.provideService(
173
144
  ConfigProvider.ConfigProvider,
174
145
  ConfigProvider.fromEnv({
175
146
  env: {
176
- RIVET_LOG_LEVEL: "silent",
147
+ RIVET_LOG_LEVEL: "DEBUG",
177
148
  },
178
149
  }),
179
150
  ),
180
151
  ),
181
152
  );
182
153
 
183
- it.effect("preserves an explicit Info minimum log level", () =>
154
+ it.effect("ignores Effect-only RIVET_LOG_LEVEL values", () =>
184
155
  Effect.gen(function* () {
185
156
  const baseLogger = yield* Logging.makeDefaultBaseLogger;
186
157
 
@@ -191,98 +162,113 @@ describe("internal/logging", () => {
191
162
  ConfigProvider.ConfigProvider,
192
163
  ConfigProvider.fromEnv({
193
164
  env: {
194
- RIVET_LOG_LEVEL: "silent",
165
+ RIVET_LOG_LEVEL: "None",
195
166
  },
196
167
  }),
197
168
  ),
198
169
  ),
199
170
  );
200
171
 
201
- it.effect("uses Config.logLevel values provided to References.MinimumLogLevel", () =>
172
+ it.effect("falls back to References.MinimumLogLevel without env", () =>
202
173
  Effect.gen(function* () {
203
174
  const baseLogger = yield* Logging.makeDefaultBaseLogger;
204
175
 
205
- assert.strictEqual(baseLogger.level, "trace");
176
+ assert.strictEqual(baseLogger.level, "debug");
206
177
  }).pipe(
207
- Effect.provide(
208
- Layer.effect(
209
- References.MinimumLogLevel,
210
- Config.logLevel("RIVET_LOG_LEVEL"),
211
- ),
212
- ),
178
+ Effect.provideService(References.MinimumLogLevel, "Debug"),
213
179
  Effect.provideService(
214
180
  ConfigProvider.ConfigProvider,
215
181
  ConfigProvider.fromEnv({
216
- env: {
217
- RIVET_LOG_LEVEL: "Trace",
218
- },
182
+ env: {},
219
183
  }),
220
184
  ),
221
185
  ),
222
186
  );
223
187
 
224
- it.effect("uses References.CurrentLogLevel for plain Effect.log calls", () =>
188
+ it.effect("RIVET_LOG_LEVEL overrides References.MinimumLogLevel", () =>
225
189
  Effect.gen(function* () {
226
- const entries: Array<LogEntry> = [];
227
- const baseLogger = makeTestLogger(entries);
228
-
229
- yield* Effect.log("plain log").pipe(
230
- Effect.provideService(References.CurrentLogLevel, "Debug"),
231
- Effect.provideService(References.MinimumLogLevel, "Debug"),
232
- Effect.provide(
233
- EffectLogger.layer([Logging.makeEffectLogger(baseLogger)]),
234
- ),
235
- );
190
+ const baseLogger = yield* Logging.makeDefaultBaseLogger;
236
191
 
237
- assert.deepStrictEqual(entries, [
238
- {
239
- level: "debug",
240
- fields: {},
241
- msg: "plain log",
242
- },
243
- ]);
244
- }),
192
+ assert.strictEqual(baseLogger.level, "silent");
193
+ }).pipe(
194
+ Effect.provideService(References.MinimumLogLevel, "Debug"),
195
+ Effect.provideService(
196
+ ConfigProvider.ConfigProvider,
197
+ ConfigProvider.fromEnv({
198
+ env: {
199
+ RIVET_LOG_LEVEL: "silent",
200
+ },
201
+ }),
202
+ ),
203
+ ),
245
204
  );
246
205
 
247
- it.effect("does not call a Pino method for the None current log level", () =>
248
- Effect.gen(function* () {
249
- const entries: Array<LogEntry> = [];
250
- const baseLogger = makeTestLogger(entries);
251
-
252
- yield* Effect.log("hidden log").pipe(
253
- Effect.provideService(References.CurrentLogLevel, "None"),
254
- Effect.provideService(References.MinimumLogLevel, "All"),
255
- Effect.provide(
256
- EffectLogger.layer([Logging.makeEffectLogger(baseLogger)]),
257
- ),
258
- );
259
-
260
- assert.deepStrictEqual(entries, []);
261
- }),
206
+ it.effect(
207
+ "uses References.CurrentLogLevel for plain Effect.log calls",
208
+ () =>
209
+ Effect.gen(function* () {
210
+ const entries: Array<LogEntry> = [];
211
+ const baseLogger = makeTestLogger(entries);
212
+
213
+ yield* Effect.log("plain log").pipe(
214
+ Effect.provideService(References.CurrentLogLevel, "Debug"),
215
+ Effect.provideService(References.MinimumLogLevel, "Debug"),
216
+ Effect.provide(
217
+ Logger.layer([Logging.makeLogger(baseLogger)]),
218
+ ),
219
+ );
220
+
221
+ const entry = entries[0];
222
+ assert.ok(entry !== undefined);
223
+ assert.strictEqual(entry.level, "debug");
224
+ assert.strictEqual(entry.msg, "plain log");
225
+ assert.deepStrictEqual(entry.fields, {
226
+ fiberId: entry.fields.fiberId,
227
+ });
228
+ assert.strictEqual(typeof entry.fields.fiberId, "string");
229
+ }),
262
230
  );
263
231
 
264
- it.effect("emits References.CurrentLogSpans as structured span durations", () =>
265
- Effect.gen(function* () {
266
- const entries: Array<LogEntry> = [];
267
- const baseLogger = makeTestLogger(entries);
268
-
269
- yield* Effect.logInfo("checkout complete").pipe(
270
- Effect.withLogSpan("checkout"),
271
- Effect.provide(
272
- EffectLogger.layer([Logging.makeEffectLogger(baseLogger)]),
273
- ),
274
- );
232
+ it.effect(
233
+ "does not call a Pino method for the None current log level",
234
+ () =>
235
+ Effect.gen(function* () {
236
+ const entries: Array<LogEntry> = [];
237
+ const baseLogger = makeTestLogger(entries);
238
+
239
+ yield* Effect.log("hidden log").pipe(
240
+ Effect.provideService(References.CurrentLogLevel, "None"),
241
+ Effect.provideService(References.MinimumLogLevel, "All"),
242
+ Effect.provide(
243
+ Logger.layer([Logging.makeLogger(baseLogger)]),
244
+ ),
245
+ );
246
+
247
+ assert.deepStrictEqual(entries, []);
248
+ }),
249
+ );
275
250
 
276
- assert.strictEqual(entries.length, 1);
277
- assert.strictEqual(entries[0]?.level, "info");
278
- assert.strictEqual(entries[0]?.msg, "checkout complete");
279
- assert.deepStrictEqual(Object.keys(entries[0]?.fields ?? {}), [
280
- "spans",
281
- ]);
282
- const spans = entries[0]?.fields.spans as
283
- | Record<string, unknown>
284
- | undefined;
285
- assert.strictEqual(typeof spans?.checkout, "number");
286
- }),
251
+ it.effect(
252
+ "emits References.CurrentLogSpans as structured span durations",
253
+ () =>
254
+ Effect.gen(function* () {
255
+ const entries: Array<LogEntry> = [];
256
+ const baseLogger = makeTestLogger(entries);
257
+
258
+ yield* Effect.logInfo("checkout complete").pipe(
259
+ Effect.withLogSpan("checkout"),
260
+ Effect.provide(
261
+ Logger.layer([Logging.makeLogger(baseLogger)]),
262
+ ),
263
+ );
264
+
265
+ assert.strictEqual(entries.length, 1);
266
+ assert.strictEqual(entries[0]?.level, "info");
267
+ assert.strictEqual(entries[0]?.msg, "checkout complete");
268
+ const spans = entries[0]?.fields.spans as
269
+ | Record<string, unknown>
270
+ | undefined;
271
+ assert.strictEqual(typeof spans?.checkout, "number");
272
+ }),
287
273
  );
288
274
  });
@@ -1,19 +1,16 @@
1
1
  import {
2
- Cause,
3
2
  Config,
4
3
  Context,
5
4
  Effect,
6
- Logger as EffectLogger,
5
+ Logger,
6
+ Option,
7
+ Predicate,
8
+ Record as EffectRecord,
7
9
  type LogLevel,
8
10
  References,
9
11
  } from "effect";
10
12
  import type * as Rivetkit from "rivetkit";
11
- import {
12
- configureDefaultLogger,
13
- getBaseLogger,
14
- type Logger as PinoLogger,
15
- type LogLevel as PinoLogLevel,
16
- } from "rivetkit/log";
13
+ import * as RivetkitLog from "rivetkit/log";
17
14
 
18
15
  const EMPTY_KEY = "/";
19
16
  const KEY_SEPARATOR = "/";
@@ -24,25 +21,14 @@ type ActorLogContext = {
24
21
  readonly actorId: string;
25
22
  };
26
23
 
27
- export class BaseLogger extends Context.Service<BaseLogger, PinoLogger>()(
28
- "@rivetkit/effect/Logger/BaseLogger",
29
- ) {}
30
-
31
- const PinoLevelByEffectLevel: Record<LogLevel.LogLevel, PinoLogLevel> = {
32
- All: "trace",
33
- Trace: "trace",
34
- Debug: "debug",
35
- Info: "info",
36
- Warn: "warn",
37
- Error: "error",
38
- Fatal: "fatal",
39
- None: "silent",
40
- };
24
+ export class BaseLogger extends Context.Service<
25
+ BaseLogger,
26
+ RivetkitLog.Logger
27
+ >()("@rivetkit/effect/RivetLogger/BaseLogger") {}
41
28
 
42
- export const toPinoLevel = (logLevel: LogLevel.LogLevel): PinoLogLevel =>
43
- PinoLevelByEffectLevel[logLevel];
29
+ const RivetkitLogLevels = RivetkitLog.LogLevelSchema.options;
44
30
 
45
- const EffectLevelByPinoLevel: Record<PinoLogLevel, LogLevel.LogLevel> = {
31
+ const EffectLevelByRivetkitLevel = {
46
32
  trace: "Trace",
47
33
  debug: "Debug",
48
34
  info: "Info",
@@ -50,56 +36,54 @@ const EffectLevelByPinoLevel: Record<PinoLogLevel, LogLevel.LogLevel> = {
50
36
  error: "Error",
51
37
  fatal: "Fatal",
52
38
  silent: "None",
53
- };
39
+ } as const satisfies Record<
40
+ RivetkitLog.LogLevel,
41
+ Exclude<LogLevel.LogLevel, "All">
42
+ >;
43
+
44
+ const RivetkitLevelByEffectLevel = {
45
+ ...Object.fromEntries(
46
+ RivetkitLogLevels.map((level) => [
47
+ EffectLevelByRivetkitLevel[level],
48
+ level,
49
+ ]),
50
+ ),
51
+ All: "trace",
52
+ } as Record<LogLevel.LogLevel, RivetkitLog.LogLevel>;
54
53
 
55
- const pinoLogLevelFromEnv = Config.string("RIVET_LOG_LEVEL").pipe(
56
- Config.map((value) => {
57
- const pinoLevel = value.toLowerCase();
58
- if (pinoLevel in EffectLevelByPinoLevel) {
59
- return EffectLevelByPinoLevel[pinoLevel as PinoLogLevel];
60
- }
54
+ const rivetLogLevelFromEnv = Config.string("RIVET_LOG_LEVEL").pipe(
55
+ Effect.option,
56
+ Effect.map((maybeRivetLogLevel) => {
57
+ if (Option.isNone(maybeRivetLogLevel)) return Option.none();
61
58
 
62
- return "Info";
59
+ const parsed = RivetkitLog.LogLevelSchema.safeParse(
60
+ maybeRivetLogLevel.value.toLowerCase(),
61
+ );
62
+ return parsed.success ? Option.some(parsed.data) : Option.none();
63
63
  }),
64
64
  );
65
65
 
66
- const logLevelFromEnv = Config.logLevel("RIVET_LOG_LEVEL").pipe(
67
- Config.orElse(() => pinoLogLevelFromEnv),
68
- Effect.option,
69
- );
66
+ export const makeDefaultBaseLogger: Effect.Effect<RivetkitLog.Logger> =
67
+ Effect.gen(function* () {
68
+ const maybeRivetLogLevel = yield* rivetLogLevelFromEnv;
69
+ const logLevel = Option.isSome(maybeRivetLogLevel)
70
+ ? maybeRivetLogLevel.value
71
+ : RivetkitLevelByEffectLevel[yield* References.MinimumLogLevel];
70
72
 
71
- export const makeDefaultBaseLogger: Effect.Effect<PinoLogger> = Effect.gen(
72
- function* () {
73
- const context = yield* Effect.context();
74
- const providedMinimumLogLevel = Context.getOrUndefined(
75
- context,
76
- References.MinimumLogLevel,
73
+ return yield* Effect.sync(() =>
74
+ RivetkitLog.makeDefaultLogger(logLevel),
77
75
  );
78
- const envLogLevel = yield* logLevelFromEnv;
79
- const logLevel =
80
- providedMinimumLogLevel !== undefined
81
- ? providedMinimumLogLevel
82
- : envLogLevel._tag === "Some"
83
- ? envLogLevel.value
84
- : yield* References.MinimumLogLevel;
85
-
86
- return yield* Effect.sync(() => {
87
- configureDefaultLogger(toPinoLevel(logLevel));
88
- return getBaseLogger();
89
- });
90
- },
91
- );
76
+ });
92
77
 
93
- export const getOrCreateBaseLogger: Effect.Effect<PinoLogger> = Effect.gen(
94
- function* () {
95
- const provided = yield* Effect.serviceOption(BaseLogger);
96
- if (provided._tag === "Some") {
97
- return provided.value;
78
+ export const getOrCreateBaseLogger: Effect.Effect<RivetkitLog.Logger> =
79
+ Effect.gen(function* () {
80
+ const maybeBaseLogger = yield* Effect.serviceOption(BaseLogger);
81
+ if (Option.isSome(maybeBaseLogger)) {
82
+ return maybeBaseLogger.value;
98
83
  }
99
84
 
100
85
  return yield* makeDefaultBaseLogger;
101
- },
102
- );
86
+ });
103
87
 
104
88
  export function makeActorLogAnnotations(context: ActorLogContext): {
105
89
  readonly actor: string;
@@ -131,59 +115,64 @@ export function serializeActorKey(key: Rivetkit.ActorKey): string {
131
115
  .join(KEY_SEPARATOR);
132
116
  }
133
117
 
134
- function structuredValue(value: unknown): unknown {
135
- if (value instanceof Error) {
136
- return value;
137
- }
118
+ export function makeLogger(
119
+ baseLogger: RivetkitLog.Logger,
120
+ ): Logger.Logger<unknown, void> {
121
+ return Logger.make((options) => {
122
+ if (options.logLevel === "None") return;
123
+ const rivetkitLevel = RivetkitLevelByEffectLevel[options.logLevel];
124
+ const structured = Logger.formatStructured.log(options);
125
+ const { msg, fields: messageFields } = extractMessage(
126
+ structured.message,
127
+ );
128
+ const fields: Record<string, unknown> = {
129
+ ...messageFields,
130
+ ...structured.annotations,
131
+ fiberId: structured.fiberId,
132
+ };
133
+
134
+ if (!EffectRecord.isEmptyRecord(structured.spans)) {
135
+ fields.spans = structured.spans;
136
+ }
137
+ if (structured.cause !== undefined) {
138
+ fields.cause = structured.cause;
139
+ }
138
140
 
139
- return value;
141
+ const logger = baseLogger[rivetkitLevel];
142
+ if (msg === undefined) {
143
+ logger.call(baseLogger, fields);
144
+ } else {
145
+ logger.call(baseLogger, fields, msg);
146
+ }
147
+ });
140
148
  }
141
149
 
142
- function extractMessageAndFields(message: unknown): {
150
+ function extractMessage(message: unknown): {
143
151
  readonly msg: string | undefined;
144
152
  readonly fields: Record<string, unknown>;
145
153
  } {
146
154
  const values = Array.isArray(message) ? message : [message];
147
- if (values.length === 0) {
148
- return { msg: undefined, fields: {} };
149
- }
150
-
151
- const [first, ...rest] = values;
152
155
  const fields: Record<string, unknown> = {};
156
+ const args: Array<unknown> = [];
153
157
  let msg: string | undefined;
154
158
 
155
- if (first instanceof Error) {
156
- fields.error = first;
157
- msg = first.message;
158
- } else if (first !== null && typeof first === "object") {
159
- const firstFields = first as Record<string, unknown>;
160
- for (const [key, value] of Object.entries(firstFields)) {
161
- if (key === "msg") {
162
- if (value !== undefined) {
163
- msg = String(value);
164
- }
165
- } else {
166
- fields[key] = structuredValue(value);
167
- }
168
- }
169
- } else if (first !== undefined) {
170
- msg = String(first);
171
- }
172
-
173
- const args: Array<unknown> = [];
174
- for (const value of rest) {
175
- if (value instanceof Error) {
159
+ for (const [index, value] of values.entries()) {
160
+ if (Predicate.isError(value)) {
161
+ fields.error = value;
162
+ if (index === 0) msg = value.message;
163
+ } else if (isStructuredError(value)) {
176
164
  fields.error = value;
177
- } else if (
178
- value !== null &&
179
- typeof value === "object" &&
180
- !Array.isArray(value)
181
- ) {
182
- for (const [key, fieldValue] of Object.entries(
183
- value as Record<string, unknown>,
184
- )) {
185
- fields[key] = structuredValue(fieldValue);
165
+ if (index === 0) msg = value.error;
166
+ } else if (Predicate.isObject(value)) {
167
+ if (index === 0) {
168
+ const { msg: valueMsg, ...rest } = value;
169
+ Object.assign(fields, rest);
170
+ if (valueMsg !== undefined) msg = String(valueMsg);
171
+ } else {
172
+ Object.assign(fields, value);
186
173
  }
174
+ } else if (index === 0) {
175
+ msg = value === undefined ? undefined : String(value);
187
176
  } else {
188
177
  args.push(value);
189
178
  }
@@ -196,42 +185,13 @@ function extractMessageAndFields(message: unknown): {
196
185
  return { msg, fields };
197
186
  }
198
187
 
199
- export function makeEffectLogger(
200
- baseLogger: PinoLogger,
201
- ): EffectLogger.Logger<unknown, void> {
202
- return EffectLogger.make(({ cause, date, fiber, logLevel, message }) => {
203
- const { msg, fields } = extractMessageAndFields(message);
204
-
205
- for (const [key, value] of Object.entries(
206
- fiber.getRef(References.CurrentLogAnnotations),
207
- )) {
208
- fields[key] = structuredValue(value);
209
- }
210
-
211
- const spans: Record<string, number> = {};
212
- for (const [label, startTime] of fiber.getRef(
213
- References.CurrentLogSpans,
214
- )) {
215
- spans[label] = date.getTime() - startTime;
216
- }
217
- if (Object.keys(spans).length > 0) {
218
- fields.spans = spans;
219
- }
220
-
221
- if (cause.reasons.length > 0) {
222
- fields.cause = Cause.pretty(cause);
223
- }
224
-
225
- const pinoLevel = toPinoLevel(logLevel);
226
- if (pinoLevel === "silent") {
227
- return;
228
- }
229
-
230
- const logger = baseLogger[pinoLevel];
231
- if (msg === undefined) {
232
- logger.call(baseLogger, fields);
233
- } else {
234
- logger.call(baseLogger, fields, msg);
235
- }
236
- });
188
+ function isStructuredError(
189
+ value: unknown,
190
+ ): value is { readonly error: string; readonly name: string } {
191
+ return (
192
+ Predicate.hasProperty(value, "error") &&
193
+ Predicate.hasProperty(value, "name") &&
194
+ Predicate.isString(value.error) &&
195
+ Predicate.isString(value.name)
196
+ );
237
197
  }
package/src/mod.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export * as Action from "./Action.ts";
2
2
  export * as Actor from "./Actor.ts";
3
3
  export * as Client from "./Client.ts";
4
- export * as Logger from "./Logger.ts";
5
4
  export * as Registry from "./Registry.ts";
5
+ export * as RivetLogger from "./RivetLogger.ts";
6
6
  export * as RivetError from "./RivetError.ts";
7
7
  export * as State from "./State.ts";
package/dist/Logger.d.ts DELETED
@@ -1,29 +0,0 @@
1
- import { Layer } from "effect";
2
- import type { Logger as PinoLogger } from "rivetkit/log";
3
- import { BaseLogger } from "./internal/logging.ts";
4
- /**
5
- * Builds a logging layer from a custom Pino-compatible logger.
6
- *
7
- * The layer installs the matching Effect logger and configures the underlying
8
- * RivetKit TypeScript SDK logs to go through the same logger.
9
- *
10
- * @example
11
- * ```ts
12
- * import { Logger } from "@rivetkit/effect"
13
- * import { pino } from "pino"
14
- *
15
- * const LoggerLive = Logger.layerPino(
16
- * pino({ transport: { target: "pino-pretty" } })
17
- * )
18
- * ```
19
- */
20
- export declare const layerPino: (baseLogger: PinoLogger) => Layer.Layer<BaseLogger, never, never>;
21
- /**
22
- * Default RivetKit Effect logging layer.
23
- *
24
- * The layer creates a base logger from `References.MinimumLogLevel` and installs
25
- * the Effect logger adapter. Applications that want custom formatting or
26
- * transports should provide {@link layerPino} instead.
27
- */
28
- export declare const layer: Layer.Layer<never>;
29
- //# sourceMappingURL=Logger.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../src/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EACN,UAAU,EAGV,MAAM,uBAAuB,CAAC;AAE/B;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,SAAS,GAAI,YAAY,UAAU,0CAO9C,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAEpC,CAAC"}