@rivetkit/effect 0.0.0-06-09-refactor-rivetkit-split-workflow-context-into-workflowcontext-workflowstepcontext.e0c9540

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 (89) hide show
  1. package/dist/Action.d.ts +104 -0
  2. package/dist/Action.d.ts.map +1 -0
  3. package/dist/Action.js +50 -0
  4. package/dist/Action.js.map +1 -0
  5. package/dist/Actor.d.ts +133 -0
  6. package/dist/Actor.d.ts.map +1 -0
  7. package/dist/Actor.js +104 -0
  8. package/dist/Actor.js.map +1 -0
  9. package/dist/Client.d.ts +31 -0
  10. package/dist/Client.d.ts.map +1 -0
  11. package/dist/Client.js +98 -0
  12. package/dist/Client.js.map +1 -0
  13. package/dist/Logger.d.ts +29 -0
  14. package/dist/Logger.d.ts.map +1 -0
  15. package/dist/Logger.js +31 -0
  16. package/dist/Logger.js.map +1 -0
  17. package/dist/Registry.d.ts +72 -0
  18. package/dist/Registry.d.ts.map +1 -0
  19. package/dist/Registry.js +125 -0
  20. package/dist/Registry.js.map +1 -0
  21. package/dist/RivetError.d.ts +438 -0
  22. package/dist/RivetError.d.ts.map +1 -0
  23. package/dist/RivetError.js +873 -0
  24. package/dist/RivetError.js.map +1 -0
  25. package/dist/State.d.ts +123 -0
  26. package/dist/State.d.ts.map +1 -0
  27. package/dist/State.js +104 -0
  28. package/dist/State.js.map +1 -0
  29. package/dist/internal/ActionDispatcher.d.ts +14 -0
  30. package/dist/internal/ActionDispatcher.d.ts.map +1 -0
  31. package/dist/internal/ActionDispatcher.js +100 -0
  32. package/dist/internal/ActionDispatcher.js.map +1 -0
  33. package/dist/internal/ActionErrorEnvelope.d.ts +11 -0
  34. package/dist/internal/ActionErrorEnvelope.d.ts.map +1 -0
  35. package/dist/internal/ActionErrorEnvelope.js +14 -0
  36. package/dist/internal/ActionErrorEnvelope.js.map +1 -0
  37. package/dist/internal/ActorInstanceManager.d.ts +28 -0
  38. package/dist/internal/ActorInstanceManager.d.ts.map +1 -0
  39. package/dist/internal/ActorInstanceManager.js +51 -0
  40. package/dist/internal/ActorInstanceManager.js.map +1 -0
  41. package/dist/internal/ActorStateAdapter.d.ts +18 -0
  42. package/dist/internal/ActorStateAdapter.d.ts.map +1 -0
  43. package/dist/internal/ActorStateAdapter.js +29 -0
  44. package/dist/internal/ActorStateAdapter.js.map +1 -0
  45. package/dist/internal/StateOptions.d.ts +12 -0
  46. package/dist/internal/StateOptions.d.ts.map +1 -0
  47. package/dist/internal/StateOptions.js +2 -0
  48. package/dist/internal/StateOptions.js.map +1 -0
  49. package/dist/internal/logging.d.ts +23 -0
  50. package/dist/internal/logging.d.ts.map +1 -0
  51. package/dist/internal/logging.js +162 -0
  52. package/dist/internal/logging.js.map +1 -0
  53. package/dist/internal/tracing.d.ts +23 -0
  54. package/dist/internal/tracing.d.ts.map +1 -0
  55. package/dist/internal/tracing.js +30 -0
  56. package/dist/internal/tracing.js.map +1 -0
  57. package/dist/internal/utils.d.ts +7 -0
  58. package/dist/internal/utils.d.ts.map +1 -0
  59. package/dist/internal/utils.js +7 -0
  60. package/dist/internal/utils.js.map +1 -0
  61. package/dist/mod.d.ts +8 -0
  62. package/dist/mod.d.ts.map +1 -0
  63. package/dist/mod.js +8 -0
  64. package/dist/mod.js.map +1 -0
  65. package/package.json +46 -0
  66. package/src/Action.ts +231 -0
  67. package/src/Actor.test-d.ts +603 -0
  68. package/src/Actor.test.ts +206 -0
  69. package/src/Actor.ts +550 -0
  70. package/src/Client.test.ts +210 -0
  71. package/src/Client.ts +216 -0
  72. package/src/Logger.ts +43 -0
  73. package/src/Registry.test-d.ts +126 -0
  74. package/src/Registry.test.ts +411 -0
  75. package/src/Registry.ts +243 -0
  76. package/src/RivetError.test.ts +188 -0
  77. package/src/RivetError.ts +1044 -0
  78. package/src/State.test.ts +181 -0
  79. package/src/State.ts +224 -0
  80. package/src/internal/ActionDispatcher.ts +192 -0
  81. package/src/internal/ActionErrorEnvelope.ts +19 -0
  82. package/src/internal/ActorInstanceManager.ts +143 -0
  83. package/src/internal/ActorStateAdapter.ts +88 -0
  84. package/src/internal/StateOptions.ts +17 -0
  85. package/src/internal/logging.test.ts +288 -0
  86. package/src/internal/logging.ts +237 -0
  87. package/src/internal/tracing.ts +42 -0
  88. package/src/internal/utils.ts +12 -0
  89. package/src/mod.ts +7 -0
@@ -0,0 +1,237 @@
1
+ import {
2
+ Cause,
3
+ Config,
4
+ Context,
5
+ Effect,
6
+ Logger as EffectLogger,
7
+ type LogLevel,
8
+ References,
9
+ } from "effect";
10
+ 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";
17
+
18
+ const EMPTY_KEY = "/";
19
+ const KEY_SEPARATOR = "/";
20
+
21
+ type ActorLogContext = {
22
+ readonly name: string;
23
+ readonly key: Rivetkit.ActorKey;
24
+ readonly actorId: string;
25
+ };
26
+
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
+ };
41
+
42
+ export const toPinoLevel = (logLevel: LogLevel.LogLevel): PinoLogLevel =>
43
+ PinoLevelByEffectLevel[logLevel];
44
+
45
+ const EffectLevelByPinoLevel: Record<PinoLogLevel, LogLevel.LogLevel> = {
46
+ trace: "Trace",
47
+ debug: "Debug",
48
+ info: "Info",
49
+ warn: "Warn",
50
+ error: "Error",
51
+ fatal: "Fatal",
52
+ silent: "None",
53
+ };
54
+
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
+ }
61
+
62
+ return "Info";
63
+ }),
64
+ );
65
+
66
+ const logLevelFromEnv = Config.logLevel("RIVET_LOG_LEVEL").pipe(
67
+ Config.orElse(() => pinoLogLevelFromEnv),
68
+ Effect.option,
69
+ );
70
+
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,
77
+ );
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
+ );
92
+
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;
98
+ }
99
+
100
+ return yield* makeDefaultBaseLogger;
101
+ },
102
+ );
103
+
104
+ export function makeActorLogAnnotations(context: ActorLogContext): {
105
+ readonly actor: string;
106
+ readonly key: string;
107
+ readonly actorId: string;
108
+ } {
109
+ return {
110
+ actor: context.name,
111
+ key: serializeActorKey(context.key),
112
+ actorId: context.actorId,
113
+ };
114
+ }
115
+
116
+ export function serializeActorKey(key: Rivetkit.ActorKey): string {
117
+ if (key.length === 0) {
118
+ return EMPTY_KEY;
119
+ }
120
+
121
+ return key
122
+ .map((part) => {
123
+ if (part === "") {
124
+ return "\\0";
125
+ }
126
+
127
+ return part
128
+ .replace(/\\/g, "\\\\")
129
+ .replace(/\//g, `\\${KEY_SEPARATOR}`);
130
+ })
131
+ .join(KEY_SEPARATOR);
132
+ }
133
+
134
+ function structuredValue(value: unknown): unknown {
135
+ if (value instanceof Error) {
136
+ return value;
137
+ }
138
+
139
+ return value;
140
+ }
141
+
142
+ function extractMessageAndFields(message: unknown): {
143
+ readonly msg: string | undefined;
144
+ readonly fields: Record<string, unknown>;
145
+ } {
146
+ 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
+ const fields: Record<string, unknown> = {};
153
+ let msg: string | undefined;
154
+
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) {
176
+ 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);
186
+ }
187
+ } else {
188
+ args.push(value);
189
+ }
190
+ }
191
+
192
+ if (args.length > 0) {
193
+ fields.args = args;
194
+ }
195
+
196
+ return { msg, fields };
197
+ }
198
+
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
+ });
237
+ }
@@ -0,0 +1,42 @@
1
+ import { Predicate } from "effect";
2
+
3
+ /**
4
+ * Identifies the SDK as the RPC system on action spans. Stamped onto
5
+ * the `rpc.system.name` OTel attribute.
6
+ */
7
+ export const rpcSystem = "rivet.actors";
8
+
9
+ /**
10
+ * Cross-wire trace metadata. Carries just enough of an `Effect.Tracer`
11
+ * span to reconstitute it on the server as a `Tracer.externalSpan`
12
+ * parent for the handler's span.
13
+ */
14
+ export interface TraceMeta {
15
+ readonly traceId: string;
16
+ readonly spanId: string;
17
+ readonly sampled: boolean;
18
+ }
19
+
20
+ /**
21
+ * Pull a valid `TraceMeta` out of the wire `ActionMeta` envelope, or
22
+ * `undefined` if the caller didn't ship one (or shipped something
23
+ * malformed). Kept lenient because the meta envelope is forward-
24
+ * extensible — future fields shouldn't break trace extraction.
25
+ */
26
+ export const readTraceMeta = (meta: unknown): TraceMeta | undefined => {
27
+ if (!Predicate.isObject(meta)) return undefined;
28
+ const trace = meta.trace;
29
+ if (!Predicate.isObject(trace)) return undefined;
30
+ if (
31
+ !Predicate.isString(trace.traceId) ||
32
+ !Predicate.isString(trace.spanId) ||
33
+ !Predicate.isBoolean(trace.sampled)
34
+ ) {
35
+ return undefined;
36
+ }
37
+ return {
38
+ traceId: trace.traceId,
39
+ spanId: trace.spanId,
40
+ sampled: trace.sampled,
41
+ };
42
+ };
@@ -0,0 +1,12 @@
1
+ import { Predicate } from "effect";
2
+
3
+ /**
4
+ * Refinement that narrows `unknown` to an object with `key` set to a
5
+ * `string`.
6
+ */
7
+ export const hasStringProperty =
8
+ <K extends PropertyKey>(
9
+ key: K,
10
+ ): Predicate.Refinement<unknown, { readonly [P in K]: string }> =>
11
+ (u): u is { readonly [P in K]: string } =>
12
+ Predicate.hasProperty(u, key) && Predicate.isString(u[key]);
package/src/mod.ts ADDED
@@ -0,0 +1,7 @@
1
+ export * as Action from "./Action.ts";
2
+ export * as Actor from "./Actor.ts";
3
+ export * as Client from "./Client.ts";
4
+ export * as Logger from "./Logger.ts";
5
+ export * as Registry from "./Registry.ts";
6
+ export * as RivetError from "./RivetError.ts";
7
+ export * as State from "./State.ts";