pure-effect 0.5.0 → 0.7.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.
package/index.d.ts CHANGED
@@ -10,102 +10,202 @@ export type FailureState<E = unknown> = {
10
10
  initialInput?: unknown;
11
11
  };
12
12
 
13
- export type CommandState<R, T, E = unknown> = {
13
+ export type CommandState<R, T, E = unknown, Ctx = unknown> = {
14
14
  type: 'Command';
15
15
  cmd: () => Promise<R> | R;
16
- next: (result: R) => Effect<T, E>;
16
+ next: (result: R) => Effect<T, E, Ctx>;
17
17
  meta?: unknown;
18
18
  initialInput?: unknown;
19
19
  };
20
20
 
21
- export type Effect<T, E = unknown> =
21
+ export type AskState<T, E = unknown, Ctx = unknown> = {
22
+ type: 'Ask';
23
+ next: (context: Ctx) => Effect<T, E, Ctx>;
24
+ initialInput?: unknown;
25
+ };
26
+
27
+ export type RetryOptions = {
28
+ attempts?: number;
29
+ delay?: number;
30
+ backoff?: number;
31
+ };
32
+
33
+ export type RetryState<T, E = unknown, Ctx = unknown> = {
34
+ type: 'Retry';
35
+ effect: Effect<T, E, Ctx>;
36
+ options: RetryOptions;
37
+ next: (value: T) => Effect<T, E, Ctx>;
38
+ initialInput?: unknown;
39
+ };
40
+
41
+ export type RetryExhaustedError<E = unknown> = {
42
+ retryExhausted: true;
43
+ lastError: E;
44
+ attempts: number;
45
+ };
46
+
47
+ export type Effect<T, E = unknown, Ctx = unknown> =
22
48
  | SuccessState<T>
23
49
  | FailureState<E>
24
- | CommandState<any, T, E>;
50
+ | CommandState<any, T, E, Ctx>
51
+ | AskState<T, E, Ctx>
52
+ | RetryState<T, E, Ctx>;
25
53
 
26
54
  export declare function Success<T>(value: T): SuccessState<T>;
27
55
 
28
- export declare function Failure<E = unknown>(
29
- error: E,
30
- initialInput?: unknown
31
- ): FailureState<E>;
56
+ export declare function Failure<E = unknown>(error: E, initialInput?: unknown): FailureState<E>;
32
57
 
33
- export declare function Command<R, T, E = unknown>(
58
+ export declare function Command<R, T, E = unknown, Ctx = unknown>(
34
59
  cmd: () => Promise<R> | R,
35
- next: (result: R) => Effect<T, E>,
60
+ next: (result: R) => Effect<T, E, Ctx>,
36
61
  meta?: unknown
37
- ): CommandState<R, T, E>;
38
-
39
- export declare function effectPipe<A, B, E = unknown>(
40
- f1: (a: A) => Effect<B, E>
41
- ): (start: A) => Effect<B, E>;
42
-
43
- export declare function effectPipe<A, B, C, E = unknown>(
44
- f1: (a: A) => Effect<B, E>,
45
- f2: (b: B) => Effect<C, E>
46
- ): (start: A) => Effect<C, E>;
47
-
48
- export declare function effectPipe<A, B, C, D, E = unknown>(
49
- f1: (a: A) => Effect<B, E>,
50
- f2: (b: B) => Effect<C, E>,
51
- f3: (c: C) => Effect<D, E>
52
- ): (start: A) => Effect<D, E>;
53
-
54
- export declare function effectPipe<A, B, C, D, F, E = unknown>(
55
- f1: (a: A) => Effect<B, E>,
56
- f2: (b: B) => Effect<C, E>,
57
- f3: (c: C) => Effect<D, E>,
58
- f4: (d: D) => Effect<F, E>
59
- ): (start: A) => Effect<F, E>;
60
-
61
- export declare function effectPipe<A, B, C, D, F, G, E = unknown>(
62
- f1: (a: A) => Effect<B, E>,
63
- f2: (b: B) => Effect<C, E>,
64
- f3: (c: C) => Effect<D, E>,
65
- f4: (d: D) => Effect<F, E>,
66
- f5: (f: F) => Effect<G, E>
67
- ): (start: A) => Effect<G, E>;
68
-
69
- export declare function effectPipe<A, B, C, D, F, G, H, E = unknown>(
70
- f1: (a: A) => Effect<B, E>,
71
- f2: (b: B) => Effect<C, E>,
72
- f3: (c: C) => Effect<D, E>,
73
- f4: (d: D) => Effect<F, E>,
74
- f5: (f: F) => Effect<G, E>,
75
- f6: (g: G) => Effect<H, E>
76
- ): (start: A) => Effect<H, E>;
77
-
78
- export declare function effectPipe<A, B, C, D, F, G, H, I, E = unknown>(
79
- f1: (a: A) => Effect<B, E>,
80
- f2: (b: B) => Effect<C, E>,
81
- f3: (c: C) => Effect<D, E>,
82
- f4: (d: D) => Effect<F, E>,
83
- f5: (f: F) => Effect<G, E>,
84
- f6: (g: G) => Effect<H, E>,
85
- f7: (h: H) => Effect<I, E>
86
- ): (start: A) => Effect<I, E>;
87
-
88
- export declare function effectPipe<A, B, C, D, F, G, H, I, J, E = unknown>(
89
- f1: (a: A) => Effect<B, E>,
90
- f2: (b: B) => Effect<C, E>,
91
- f3: (c: C) => Effect<D, E>,
92
- f4: (d: D) => Effect<F, E>,
93
- f5: (f: F) => Effect<G, E>,
94
- f6: (g: G) => Effect<H, E>,
95
- f7: (h: H) => Effect<I, E>,
96
- f8: (i: I) => Effect<J, E>
97
- ): (start: A) => Effect<J, E>;
98
-
99
- export declare function runEffect<T, E = unknown>(
100
- effect: Effect<T, E>,
101
- context?: unknown
102
- ): Promise<SuccessState<T> | FailureState<E>>;
103
-
104
- export type StepRunner = (
105
- name: string,
106
- type: string,
107
- op: () => Promise<unknown>
108
- ) => Promise<unknown>;
62
+ ): CommandState<R, T, E, Ctx>;
63
+
64
+ export declare function Ask<T, E = unknown, Ctx = unknown>(
65
+ next: (context: Ctx) => Effect<T, E, Ctx>
66
+ ): AskState<T, E, Ctx>;
67
+
68
+ export declare function Retry<T, E = unknown, Ctx = unknown>(
69
+ effect: Effect<T, E, Ctx>,
70
+ options?: RetryOptions
71
+ ): RetryState<T, E, Ctx>;
72
+
73
+ export declare function effectPipe<A, B, E1 = unknown, Ctx = unknown>(
74
+ f1: (a: A) => Effect<B, E1, Ctx>
75
+ ): (start: A) => Effect<B, E1, Ctx>;
76
+
77
+ export declare function effectPipe<A, B, C, E1 = unknown, E2 = unknown, Ctx = unknown>(
78
+ f1: (a: A) => Effect<B, E1, Ctx>,
79
+ f2: (b: B) => Effect<C, E2, Ctx>
80
+ ): (start: A) => Effect<C, E1 | E2, Ctx>;
81
+
82
+ export declare function effectPipe<A, B, C, D, E1 = unknown, E2 = unknown, E3 = unknown, Ctx = unknown>(
83
+ f1: (a: A) => Effect<B, E1, Ctx>,
84
+ f2: (b: B) => Effect<C, E2, Ctx>,
85
+ f3: (c: C) => Effect<D, E3, Ctx>
86
+ ): (start: A) => Effect<D, E1 | E2 | E3, Ctx>;
87
+
88
+ export declare function effectPipe<
89
+ A,
90
+ B,
91
+ C,
92
+ D,
93
+ F,
94
+ E1 = unknown,
95
+ E2 = unknown,
96
+ E3 = unknown,
97
+ E4 = unknown,
98
+ Ctx = unknown
99
+ >(
100
+ f1: (a: A) => Effect<B, E1, Ctx>,
101
+ f2: (b: B) => Effect<C, E2, Ctx>,
102
+ f3: (c: C) => Effect<D, E3, Ctx>,
103
+ f4: (d: D) => Effect<F, E4, Ctx>
104
+ ): (start: A) => Effect<F, E1 | E2 | E3 | E4, Ctx>;
105
+
106
+ export declare function effectPipe<
107
+ A,
108
+ B,
109
+ C,
110
+ D,
111
+ F,
112
+ G,
113
+ E1 = unknown,
114
+ E2 = unknown,
115
+ E3 = unknown,
116
+ E4 = unknown,
117
+ E5 = unknown,
118
+ Ctx = unknown
119
+ >(
120
+ f1: (a: A) => Effect<B, E1, Ctx>,
121
+ f2: (b: B) => Effect<C, E2, Ctx>,
122
+ f3: (c: C) => Effect<D, E3, Ctx>,
123
+ f4: (d: D) => Effect<F, E4, Ctx>,
124
+ f5: (f: F) => Effect<G, E5, Ctx>
125
+ ): (start: A) => Effect<G, E1 | E2 | E3 | E4 | E5, Ctx>;
126
+
127
+ export declare function effectPipe<
128
+ A,
129
+ B,
130
+ C,
131
+ D,
132
+ F,
133
+ G,
134
+ H,
135
+ E1 = unknown,
136
+ E2 = unknown,
137
+ E3 = unknown,
138
+ E4 = unknown,
139
+ E5 = unknown,
140
+ E6 = unknown,
141
+ Ctx = unknown
142
+ >(
143
+ f1: (a: A) => Effect<B, E1, Ctx>,
144
+ f2: (b: B) => Effect<C, E2, Ctx>,
145
+ f3: (c: C) => Effect<D, E3, Ctx>,
146
+ f4: (d: D) => Effect<F, E4, Ctx>,
147
+ f5: (f: F) => Effect<G, E5, Ctx>,
148
+ f6: (g: G) => Effect<H, E6, Ctx>
149
+ ): (start: A) => Effect<H, E1 | E2 | E3 | E4 | E5 | E6, Ctx>;
150
+
151
+ export declare function effectPipe<
152
+ A,
153
+ B,
154
+ C,
155
+ D,
156
+ F,
157
+ G,
158
+ H,
159
+ I,
160
+ E1 = unknown,
161
+ E2 = unknown,
162
+ E3 = unknown,
163
+ E4 = unknown,
164
+ E5 = unknown,
165
+ E6 = unknown,
166
+ E7 = unknown,
167
+ Ctx = unknown
168
+ >(
169
+ f1: (a: A) => Effect<B, E1, Ctx>,
170
+ f2: (b: B) => Effect<C, E2, Ctx>,
171
+ f3: (c: C) => Effect<D, E3, Ctx>,
172
+ f4: (d: D) => Effect<F, E4, Ctx>,
173
+ f5: (f: F) => Effect<G, E5, Ctx>,
174
+ f6: (g: G) => Effect<H, E6, Ctx>,
175
+ f7: (h: H) => Effect<I, E7, Ctx>
176
+ ): (start: A) => Effect<I, E1 | E2 | E3 | E4 | E5 | E6 | E7, Ctx>;
177
+
178
+ export declare function effectPipe<
179
+ A,
180
+ B,
181
+ C,
182
+ D,
183
+ F,
184
+ G,
185
+ H,
186
+ I,
187
+ J,
188
+ E1 = unknown,
189
+ E2 = unknown,
190
+ E3 = unknown,
191
+ E4 = unknown,
192
+ E5 = unknown,
193
+ E6 = unknown,
194
+ E7 = unknown,
195
+ E8 = unknown,
196
+ Ctx = unknown
197
+ >(
198
+ f1: (a: A) => Effect<B, E1, Ctx>,
199
+ f2: (b: B) => Effect<C, E2, Ctx>,
200
+ f3: (c: C) => Effect<D, E3, Ctx>,
201
+ f4: (d: D) => Effect<F, E4, Ctx>,
202
+ f5: (f: F) => Effect<G, E5, Ctx>,
203
+ f6: (g: G) => Effect<H, E6, Ctx>,
204
+ f7: (h: H) => Effect<I, E7, Ctx>,
205
+ f8: (i: I) => Effect<J, E8, Ctx>
206
+ ): (start: A) => Effect<J, E1 | E2 | E3 | E4 | E5 | E6 | E7 | E8, Ctx>;
207
+
208
+ export type StepRunner = (name: string, type: string, op: () => Promise<unknown>) => Promise<unknown>;
109
209
 
110
210
  export type RunWrapper = (
111
211
  effect: Effect<unknown>,
@@ -113,15 +213,19 @@ export type RunWrapper = (
113
213
  flowName?: string
114
214
  ) => Promise<SuccessState<unknown> | FailureState<unknown>>;
115
215
 
116
- export type CommandInterceptor = (
117
- command: CommandState<unknown, unknown>,
118
- context?: any
119
- ) => Promise<void>;
216
+ export type CommandInterceptor = (command: CommandState<unknown, unknown>, context?: any) => Promise<void>;
120
217
 
121
218
  export interface EffectConfiguration {
122
219
  onStep?: StepRunner;
123
220
  onRun?: RunWrapper;
124
221
  onBeforeCommand?: CommandInterceptor;
222
+ retry?: RetryOptions;
125
223
  }
126
224
 
127
225
  export declare function configureEffect(options: EffectConfiguration): void;
226
+
227
+ export declare function runEffect<T, E = unknown, Ctx = unknown>(
228
+ effect: Effect<T, E, Ctx>,
229
+ context?: Ctx,
230
+ callConfig?: EffectConfiguration
231
+ ): Promise<SuccessState<T> | FailureState<E>>;
package/index.js CHANGED
@@ -11,10 +11,27 @@
11
11
  * initialInput?: any
12
12
  * }} CommandState
13
13
  */
14
+ /**
15
+ * @typedef {{
16
+ * type: 'Ask',
17
+ * next: (context: any) => Effect,
18
+ * initialInput?: any
19
+ * }} AskState
20
+ */
21
+
22
+ /**
23
+ * @typedef {{
24
+ * type: 'Retry',
25
+ * effect: Effect,
26
+ * options: { attempts?: number, delay?: number, backoff?: number },
27
+ * next: (value: any) => Effect,
28
+ * initialInput?: any
29
+ * }} RetryState
30
+ */
14
31
 
15
32
  /**
16
33
  * The Union type for all possible states
17
- * @typedef {SuccessState | FailureState | CommandState} Effect
34
+ * @typedef {SuccessState | FailureState | CommandState | AskState | RetryState} Effect
18
35
  */
19
36
 
20
37
  /**
@@ -30,7 +47,11 @@ const Success = (value) => ({ type: 'Success', value });
30
47
  * @param {any} [initialInput] - initial input passed to the flow (optional)
31
48
  * @returns {FailureState}
32
49
  */
33
- const Failure = (error, initialInput) => ({ type: 'Failure', error, initialInput });
50
+ const Failure = (error, initialInput) => ({
51
+ type: 'Failure',
52
+ error,
53
+ initialInput
54
+ });
34
55
 
35
56
  /**
36
57
  * Represents a side effect to be executed later
@@ -41,23 +62,64 @@ const Failure = (error, initialInput) => ({ type: 'Failure', error, initialInput
41
62
  */
42
63
  const Command = (cmd, next, meta) => ({ type: 'Command', cmd, next, meta });
43
64
 
65
+ /**
66
+ * Reads the context object from the current `runEffect` call.
67
+ * @param {(context: any) => Effect} next - Receives the context and returns the next Effect
68
+ * @returns {AskState}
69
+ */
70
+ const Ask = (next) => ({ type: 'Ask', next });
71
+
72
+ /**
73
+ * Wraps an Effect tree with retry-on-failure semantics.
74
+ * @param {Effect} effect - The inner Effect tree to retry
75
+ * @param {Object} [options] - Per-use retry options; merged over global defaults at runtime
76
+ * @param {number} [options.attempts] - Max retries (not counting first try)
77
+ * @param {number} [options.delay] - Ms before first retry
78
+ * @param {number} [options.backoff] - Multiplier applied to delay on each subsequent retry
79
+ * @returns {RetryState}
80
+ */
81
+ const Retry = (effect, options = {}) => ({
82
+ type: 'Retry',
83
+ effect,
84
+ options,
85
+ next: (value) => Success(value)
86
+ });
87
+
44
88
  /**
45
89
  * Connects an Effect to the next function in the pipeline.
46
- * Handles the branching logic for Success, Failure, and Command.
90
+ * Handles the branching logic for Success, Failure, Command, Ask, and Retry.
47
91
  *
48
92
  * @param {Effect} effect - The current Effect object
49
93
  * @param {(value: any) => Effect} fn - The next function to run if the current effect is a Success
50
94
  * @returns {Effect} The composed Effect
51
95
  */
52
- const chain = (effect, fn) => {
96
+ /**
97
+ * @param {Effect} effect
98
+ * @param {(value: any) => Effect} fn
99
+ * @param {any} [initialInput]
100
+ * @returns {Effect}
101
+ */
102
+ const chain = (effect, fn, initialInput) => {
103
+ const withII = (/** @type {Effect} */ e) =>
104
+ initialInput !== undefined && e.initialInput === undefined ? { ...e, initialInput } : e;
105
+
53
106
  switch (effect.type) {
54
107
  case 'Success':
55
- return fn(effect.value);
108
+ return withII(fn(effect.value));
56
109
  case 'Failure':
57
- return effect;
58
- case 'Command':
59
- const next = (/** @type {Effect} */ result) => chain(effect.next(result), fn);
60
- return Command(effect.cmd, next, effect.meta);
110
+ return withII(effect);
111
+ case 'Command': {
112
+ const next = (/** @type {any} */ result) => chain(effect.next(result), fn, initialInput);
113
+ return withII(Command(effect.cmd, next, effect.meta));
114
+ }
115
+ case 'Ask': {
116
+ const next = (/** @type {any} */ ctx) => chain(effect.next(ctx), fn, initialInput);
117
+ return withII(Ask(next));
118
+ }
119
+ case 'Retry': {
120
+ const next = (/** @type {any} */ result) => chain(effect.next(result), fn, initialInput);
121
+ return withII({ ...effect, next });
122
+ }
61
123
  }
62
124
  };
63
125
 
@@ -65,14 +127,13 @@ const chain = (effect, fn) => {
65
127
  * Composes a list of functions into a single Effect pipeline.
66
128
  * Each function receives the output of the previous one.
67
129
  *
68
- * @param {...(input: any) => Effect} fns - Functions that return Success, Failure, or Command.
130
+ * @param {...(input: any) => Effect} fns - Functions that return Success, Failure, Command, or Ask.
69
131
  * @returns {(start: any) => Effect} A function that accepts an initial input and returns the final Effect tree.
70
132
  */
71
133
  const effectPipe = (...fns) => {
72
134
  return (start) => {
73
- const effect = fns.reduce(chain, Success(start));
74
- effect.initialInput = start;
75
- return effect;
135
+ const chainWithII = (/** @type {Effect} */ eff, /** @type {(v: any) => Effect} */ fn) => chain(eff, fn, start);
136
+ return fns.reduce(chainWithII, /** @type {Effect} */ (Success(start)));
76
137
  };
77
138
  };
78
139
 
@@ -92,11 +153,15 @@ let stepRunner = defaultStepRunner;
92
153
  let runWrapper = defaultRunWrapper;
93
154
  let commandInterceptor = defaultCommandInterceptor;
94
155
 
156
+ const defaultRetryOptions = { attempts: 3, delay: 100, backoff: 1 };
157
+ let retryDefaults = { ...defaultRetryOptions };
158
+
95
159
  /**
96
160
  * @typedef {Object} EffectConfiguration
97
161
  * @property {StepRunner} [onStep] - Fires once per runEffect call. It wraps the entire workflow execution.
98
162
  * @property {RunWrapper} [onRun] - Fires every time a Command is executed.
99
163
  * @property {CommandInterceptor} [onBeforeCommand] - Intercepts a Command and any context passed to runEffect before execution.
164
+ * @property {{ attempts?: number, delay?: number, backoff?: number }} [retry] - Global Retry defaults; merged under per-use options.
100
165
  */
101
166
 
102
167
  /**
@@ -108,36 +173,78 @@ const configureEffect = (options) => {
108
173
  stepRunner = options.onStep ? options.onStep : defaultStepRunner;
109
174
  runWrapper = options.onRun ? options.onRun : defaultRunWrapper;
110
175
  commandInterceptor = options.onBeforeCommand ? options.onBeforeCommand : defaultCommandInterceptor;
176
+ retryDefaults = options.retry ? { ...defaultRetryOptions, ...options.retry } : defaultRetryOptions;
111
177
  };
112
178
 
113
179
  const runEffect =
114
180
  /**
115
181
  * The Interpreter
116
182
  * Iterates through the Effect tree, executing Commands and handling async flow.
183
+ * Ask effects are resolved synchronously with the context object.
184
+ *
185
+ * Per-call config takes precedence over global configureEffect defaults.
186
+ * onRun fires exactly once per runEffect call — Retry attempts run inside that
187
+ * single span rather than spawning their own, keeping telemetry non-duplicated.
117
188
  *
118
189
  * @param {Effect} effect - The Effect tree returned by a pipeline
119
- * @param {any} [context] - Optional context object passed to the Command Interceptor
190
+ * @param {any} [context] - Optional context object. Passed to Ask continuations and the Command Interceptor.
191
+ * @param {EffectConfiguration} [callConfig] - Per-call overrides; merged over global configureEffect defaults.
120
192
  * @returns {Promise<SuccessState | FailureState>}
121
193
  */
122
- async function runEffect(effect, context = {}) {
123
- return runWrapper(
124
- effect,
125
- async () => {
126
- while (effect.type === 'Command') {
127
- const cmdName = effect.cmd.name || 'anonymous';
128
- try {
129
- await commandInterceptor(effect, context);
130
- const result = await stepRunner(cmdName, 'Command', effect.cmd);
131
- effect = effect.next(result);
132
- } catch (e) {
133
- return Failure(e, effect.initialInput);
194
+ async function runEffect(effect, context = {}, callConfig = {}) {
195
+ const localStepRunner = callConfig.onStep ? callConfig.onStep : stepRunner;
196
+ const localRunWrapper = callConfig.onRun ? callConfig.onRun : runWrapper;
197
+ const localCommandInterceptor = callConfig.onBeforeCommand ? callConfig.onBeforeCommand : commandInterceptor;
198
+ const localRetryDefaults = callConfig.retry ? { ...retryDefaults, ...callConfig.retry } : retryDefaults;
199
+
200
+ /**
201
+ * @param {Effect} eff
202
+ * @returns {Promise<SuccessState | FailureState>}
203
+ */
204
+ async function execute(eff) {
205
+ while (eff.type === 'Command' || eff.type === 'Ask' || eff.type === 'Retry') {
206
+ if (eff.type === 'Ask') {
207
+ eff = eff.next(context);
208
+ continue;
209
+ }
210
+ if (eff.type === 'Retry') {
211
+ const opts = { ...localRetryDefaults, ...eff.options };
212
+ const { attempts } = opts;
213
+ let lastError;
214
+ let succeeded = false;
215
+
216
+ for (let attempt = 0; attempt <= attempts; attempt++) {
217
+ if (attempt > 0) {
218
+ await new Promise((r) => setTimeout(r, opts.delay * Math.pow(opts.backoff, attempt - 1)));
219
+ }
220
+ const result = await execute(eff.effect);
221
+ if (result.type === 'Success') {
222
+ eff = eff.next(result.value);
223
+ succeeded = true;
224
+ break;
225
+ }
226
+ lastError = result.error;
134
227
  }
228
+
229
+ if (!succeeded) {
230
+ return Failure({ retryExhausted: true, lastError, attempts }, eff.initialInput);
231
+ }
232
+ continue;
233
+ }
234
+ const cmdName = eff.cmd.name || 'anonymous';
235
+ const initialInput = eff.initialInput;
236
+ try {
237
+ await localCommandInterceptor(eff, context);
238
+ const result = await localStepRunner(cmdName, 'Command', eff.cmd);
239
+ eff = eff.next(result);
240
+ } catch (e) {
241
+ return Failure(e, initialInput);
135
242
  }
243
+ }
244
+ return eff;
245
+ }
136
246
 
137
- return effect;
138
- },
139
- context?.flowName || ''
140
- );
247
+ return localRunWrapper(effect, () => execute(effect), context?.flowName || '');
141
248
  };
142
249
 
143
- export { Success, Failure, Command, effectPipe, runEffect, configureEffect };
250
+ export { Success, Failure, Command, Ask, Retry, effectPipe, runEffect, configureEffect };
@@ -9,14 +9,14 @@ import { configureEffect } from './index.js';
9
9
  /** @import { RunWrapper, StepRunner } from "./index.js" */
10
10
 
11
11
  const traceExporter = new OTLPTraceExporter({
12
- url: 'http://localhost:4318/v1/traces',
12
+ url: 'http://localhost:4318/v1/traces'
13
13
  });
14
14
 
15
15
  const sdk = new NodeSDK({
16
16
  serviceName: 'pure-effect-test',
17
17
  traceExporter,
18
18
  spanProcessor: new SimpleSpanProcessor(traceExporter),
19
- instrumentations: [],
19
+ instrumentations: []
20
20
  });
21
21
 
22
22
  sdk.start();
@@ -43,7 +43,7 @@ export function enableTelemetry() {
43
43
  if (result.type === 'Failure') {
44
44
  rootSpan.setStatus({
45
45
  code: SpanStatusCode.ERROR,
46
- message: String(result.error),
46
+ message: String(result.error)
47
47
  });
48
48
  } else {
49
49
  rootSpan.setStatus({ code: SpanStatusCode.OK });
@@ -79,13 +79,13 @@ export function enableTelemetry() {
79
79
  span.recordException(err);
80
80
  span.setStatus({
81
81
  code: SpanStatusCode.ERROR,
82
- message: err.message,
82
+ message: err.message
83
83
  });
84
84
  throw err;
85
85
  } finally {
86
86
  span.end();
87
87
  }
88
88
  });
89
- },
89
+ }
90
90
  });
91
91
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pure-effect",
3
- "version": "0.5.0",
4
- "description": "A tiny, zero-dependency effect system for writing pure, testable JavaScript/TypeScript without mocks.",
3
+ "version": "0.7.0",
4
+ "description": "A TypeScript effect library where effects are plain objects you can inspect, test, and reason about. Learn the whole API in an afternoon. Tiny footprint, zero dependencies, works with plain JavaScript too.",
5
5
  "type": "module",
6
6
  "exports": "./index.js",
7
7
  "types": "./index.d.ts",