@flux-control/effect-modbus-rs 0.3.1 → 0.4.1

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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  For the complete API reference, see the [GitHub Pages documentation](https://flux-control-solutions.github.io/Effect-modbus-rs/).
6
6
 
7
- Provides scoped [`Effect.Service`](https://effect.website) constructors for RTU (serial), TCP, and ASCII Modbus transports. Clients expose a typed `Effect`-based API for all standard Modbus function codes.
7
+ Provides scoped [`Context.Service`](https://effect.website) constructors for RTU (serial), TCP, and ASCII Modbus transports. Clients expose a typed `Effect`-based API for all standard Modbus function codes.
8
8
 
9
9
  > This project is under active development. Its API may change before the 1.0 release.
10
10
 
@@ -44,7 +44,7 @@ program.pipe(
44
44
  ModbusInvalidArgumentError: (err) => Console.log(`Invalid argument: ${err.message}`),
45
45
  }),
46
46
  Effect.catchAll((err) => Console.log(`Unhandled error: ${err.message}`)),
47
- Effect.provide(RtuTransportService.Default({ portPath: '/dev/ttyUSB0', baudRate: 9600 })),
47
+ Effect.provide(RtuTransportService.make({ portPath: '/dev/ttyUSB0', baudRate: 9600 })),
48
48
  Effect.scoped,
49
49
  Effect.runPromise,
50
50
  );
@@ -64,7 +64,7 @@ const program = Effect.gen(function* () {
64
64
  });
65
65
 
66
66
  program.pipe(
67
- Effect.provide(TcpTransportService.Default({ host: '192.168.1.100', port: 502 })),
67
+ Effect.provide(TcpTransportService.make({ host: '192.168.1.100', port: 502 })),
68
68
  Effect.scoped,
69
69
  Effect.runPromise,
70
70
  );
@@ -87,7 +87,7 @@ const program = Effect.gen(function* () {
87
87
  });
88
88
 
89
89
  program.pipe(
90
- Effect.provide(AsciiTransportService.Default({ portPath: '/dev/ttyUSB0', baudRate: 9600 })),
90
+ Effect.provide(AsciiTransportService.make({ portPath: '/dev/ttyUSB0', baudRate: 9600 })),
91
91
  Effect.scoped,
92
92
  Effect.runPromise,
93
93
  );
@@ -112,7 +112,7 @@ const program = Effect.gen(function* () {
112
112
  });
113
113
 
114
114
  program.pipe(
115
- Effect.provide(WasmWsTransportService.Default({ wsUrl: 'ws://localhost:8080' })),
115
+ Effect.provide(WasmWsTransportService.make({ wsUrl: 'ws://localhost:8080' })),
116
116
  Effect.scoped,
117
117
  Effect.runPromise,
118
118
  );
@@ -129,7 +129,7 @@ connectButton.addEventListener('click', () => {
129
129
  Effect.gen(function* () {
130
130
  const port = yield* requestSerialPort();
131
131
  yield* program.pipe(
132
- Effect.provide(WasmRtuTransportService.Default({ port, baudRate: 19200 })),
132
+ Effect.provide(WasmRtuTransportService.make({ port, baudRate: 19200 })),
133
133
  Effect.scoped,
134
134
  );
135
135
  }),
@@ -150,7 +150,7 @@ Not demonstrated in `examples/wasm/` (see that app's README) — the same `impor
150
150
 
151
151
  ## Transports
152
152
 
153
- Each transport is a scoped `Effect.Service`. You provide it with `Effect.provide`, and the connection is opened on service access and closed when the scope ends.
153
+ Each transport is a scoped `Context.Service`. You provide it with `Effect.provide`, and the connection is opened on service access and closed when the scope ends.
154
154
 
155
155
  | Service | Options | Connection |
156
156
  | ------------------------------------- | ------------------------------ | ----------------------------- |
@@ -279,7 +279,7 @@ Handle with `Effect.catchTags`. The `ModbusError` union type covers all seven va
279
279
  Resilience belongs to the **transport**, not to call sites. Attach a policy where the transport is created and every client derived from it carries it:
280
280
 
281
281
  ```ts
282
- const layer = TcpTransportService.Default({
282
+ const layer = TcpTransportService.make({
283
283
  host: '192.168.1.50',
284
284
  port: 502,
285
285
  retry: RetryPolicies.tcp(), // applied to every operation
@@ -393,7 +393,7 @@ So `RetryPolicies.tcp()` waits roughly 80–120 ms before its first retry, not e
393
393
  Passing `reconnect` hands reconnection to a supervisor fiber owned by the transport — **one reconnect for the whole application**, however many fibers were in flight when the link dropped:
394
394
 
395
395
  ```ts
396
- TcpTransportService.Default({
396
+ TcpTransportService.make({
397
397
  host,
398
398
  port,
399
399
  reconnect: {
@@ -445,7 +445,7 @@ See `examples/retry-policies.ts` for a runnable walkthrough.
445
445
  `modbus-rs` exposes `retryAttempts`, `retryDelayMs`, and `retryBackoffStrategy` on its transport options. This package removes all three from every transport constructor, so setting one is a compile error rather than a documented hazard:
446
446
 
447
447
  ```ts
448
- TcpTransportService.Default({ host, port, retryAttempts: 3 });
448
+ TcpTransportService.make({ host, port, retryAttempts: 3 });
449
449
  // ^^^^^^^^^^^^^ Object literal may only specify
450
450
  // known properties, and 'retryAttempts' does not
451
451
  // exist in type 'TcpTransportOpenOptions & …'
@@ -568,17 +568,17 @@ src/
568
568
  connection.ts — Connection state machine, reconnect supervisor, circuit breaker
569
569
  retry.ts — Opt-in retry policies (backoff, jitter, per-error rules)
570
570
  shared-transport.ts — Generic scoped transport lifecycle management, WithoutUpstreamRetry
571
- RtuTransportService.ts — Scoped Effect.Service wrapping AsyncRtuTransport
572
- TcpTransportService.ts — Scoped Effect.Service wrapping AsyncTcpTransport
573
- AsciiTransportService.ts — Scoped Effect.Service wrapping AsyncAsciiTransport
571
+ RtuTransportService.ts — Scoped Context.Service wrapping AsyncRtuTransport
572
+ TcpTransportService.ts — Scoped Context.Service wrapping AsyncTcpTransport
573
+ AsciiTransportService.ts — Scoped Context.Service wrapping AsyncAsciiTransport
574
574
  SerialTransportService.ts — Abstract serial transport (RTU/ASCII) tag
575
575
  TcpModbusServerService.ts — tcpServerLayer
576
576
  SerialModbusServerService.ts — serialRtuServerLayer / serialAsciiServerLayer
577
577
  TcpGatewayService.ts — tcpGatewayLayer
578
578
  WasmSerialPort.ts — requestSerialPort() Effect helper (browser, user-gesture gated)
579
- WasmWsTransportService.ts — Scoped Effect.Service wrapping WasmWsTransport (browser, WS gateway)
580
- WasmRtuTransportService.ts — Scoped Effect.Service wrapping WasmRtuTransport (browser, Web Serial RTU)
581
- WasmAsciiTransportService.ts — Scoped Effect.Service wrapping WasmAsciiTransport (browser, Web Serial ASCII)
579
+ WasmWsTransportService.ts — Scoped Context.Service wrapping WasmWsTransport (browser, WS gateway)
580
+ WasmRtuTransportService.ts — Scoped Context.Service wrapping WasmRtuTransport (browser, Web Serial RTU)
581
+ WasmAsciiTransportService.ts — Scoped Context.Service wrapping WasmAsciiTransport (browser, Web Serial ASCII)
582
582
  WasmSerialTransportService.ts — Abstract browser serial transport (RTU/ASCII) tag
583
583
  WasmTcpServerService.ts — wasmWsServerLayer (experimental)
584
584
  WasmSerialModbusServerService.ts — wasmSerialRtuServerLayer / wasmSerialAsciiServerLayer (experimental)
package/dist/index.d.ts CHANGED
@@ -54,7 +54,7 @@
54
54
  * every client derived from it:
55
55
  *
56
56
  * ```ts
57
- * TcpTransportService.Default({
57
+ * TcpTransportService.make({
58
58
  * host, port,
59
59
  * retry: RetryPolicies.tcp(), // applied to every operation
60
60
  * reconnect: {}, // supervised reconnect + circuit breaker
package/dist/index.js CHANGED
@@ -55,7 +55,7 @@ var toModbusError = (cause) => {
55
55
  }
56
56
  };
57
57
  // src/retry.ts
58
- import { Duration, Effect, Schedule } from "effect";
58
+ import { Duration, Effect, Random, Schedule } from "effect";
59
59
  var retryableExceptionCodes = [5, 6, 10, 11];
60
60
  var defaultRetryableTags = {
61
61
  ModbusTimeoutError: true,
@@ -68,7 +68,7 @@ var defaultRetryableTags = {
68
68
  ModbusInternalError: false
69
69
  };
70
70
  var allTags = Object.keys(defaultRetryableTags);
71
- var toMillis = (input) => Duration.toMillis(Duration.decode(input));
71
+ var toMillis = (input) => Duration.toMillis(Duration.fromInputUnsafe(input));
72
72
  var resolveRetryableTags = (options) => {
73
73
  const retryable = {};
74
74
  for (const tag of allTags) {
@@ -112,10 +112,14 @@ var makeRetryPolicy = (options = {}) => {
112
112
  const { baseMs, factor, maxMs } = delays[error._tag];
113
113
  return Duration.millis(Math.min(maxMs, baseMs * factor ** retryIndex));
114
114
  };
115
- const base = Schedule.recurs(options.maxRetries ?? 3).pipe(Schedule.intersect(Schedule.identity()), Schedule.modifyDelay(([retryIndex, error]) => delayFor(error, retryIndex)), Schedule.whileInput(isRetryable));
115
+ const base = Schedule.recurs(options.maxRetries ?? 3).pipe(Schedule.setInputType(), Schedule.modifyDelay((metadata) => Effect.succeed(delayFor(metadata.input, metadata.attempt - 1))), Schedule.while((metadata) => Effect.succeed(isRetryable(metadata.input))));
116
116
  const jitter = options.jitter ?? true;
117
- const jittered = jitter === false ? base : Schedule.jitteredWith(base, jitter === true ? {} : jitter);
118
- const schedule = options.maxElapsed === undefined ? jittered : Schedule.upTo(jittered, options.maxElapsed);
117
+ const jittered = jitter === false ? base : jitter === true ? Schedule.jittered(base) : Schedule.modifyDelay(base, (metadata) => Effect.map(Random.next, (r) => {
118
+ const min = jitter.min ?? 0.8;
119
+ const max = jitter.max ?? 1.2;
120
+ return Duration.millis(Duration.toMillis(metadata.duration) * (min + r * (max - min)));
121
+ }));
122
+ const schedule = options.maxElapsed === undefined ? jittered : Schedule.upTo(jittered, { duration: options.maxElapsed });
119
123
  return { schedule, isRetryable };
120
124
  };
121
125
  var RetryPolicies = {
@@ -146,7 +150,7 @@ var RetryPolicies = {
146
150
  };
147
151
  var retryModbus = (policy) => (self) => Effect.retry(self, policy.schedule);
148
152
  // src/connection.ts
149
- import { Data as Data2, Duration as Duration2, Effect as Effect2, Either, SubscriptionRef } from "effect";
153
+ import { Data as Data2, Duration as Duration2, Effect as Effect2, Result, SubscriptionRef } from "effect";
150
154
  var ConnectionState = Data2.taggedEnum();
151
155
  var defaultReconnectPolicy = makeRetryPolicy({
152
156
  maxRetries: 5,
@@ -162,7 +166,7 @@ var resolveReconnect = (options) => {
162
166
  const triggerTags = options.triggerOn ?? defaultTriggers;
163
167
  return {
164
168
  policy: options.policy ?? defaultReconnectPolicy,
165
- resetAfter: Duration2.decode(options.resetAfter ?? "30 seconds"),
169
+ resetAfter: Duration2.fromInputUnsafe(options.resetAfter ?? "30 seconds"),
166
170
  triggers: (error) => triggerTags.includes(error._tag)
167
171
  };
168
172
  };
@@ -181,21 +185,29 @@ var guardCircuit = (state) => Effect2.flatMap(SubscriptionRef.get(state), (curre
181
185
  var superviseReconnect = (reconnect, state, resolved) => Effect2.gen(function* () {
182
186
  while (true) {
183
187
  const attempt = reconnect.pipe(Effect2.tapError(() => SubscriptionRef.update(state, (current) => ConnectionState.$is("Reconnecting")(current) ? ConnectionState.Reconnecting({ attempt: current.attempt + 1 }) : current)), retryModbus(resolved.policy));
184
- const result = yield* Effect2.either(attempt);
185
- if (Either.isRight(result)) {
188
+ const result = yield* Effect2.result(attempt);
189
+ if (Result.isSuccess(result)) {
186
190
  yield* SubscriptionRef.set(state, ConnectionState.Connected());
187
191
  return;
188
192
  }
189
- yield* Effect2.logDebug(`Reconnect attempts exhausted: ${result.left.message}`);
190
- yield* SubscriptionRef.set(state, ConnectionState.Down({ cause: result.left }));
193
+ yield* Effect2.logDebug(`Reconnect attempts exhausted: ${result.failure.message}`);
194
+ yield* SubscriptionRef.set(state, ConnectionState.Down({ cause: result.failure }));
191
195
  yield* Effect2.sleep(resolved.resetAfter);
192
196
  const probe = yield* SubscriptionRef.modify(state, (current) => ConnectionState.$is("Down")(current) ? [true, ConnectionState.Reconnecting({ attempt: 0 })] : [false, current]);
193
197
  if (!probe)
194
198
  return;
195
199
  }
196
200
  });
201
+ var claimReconnect = (reconnect, state, resolved, scope, onClaim) => Effect2.gen(function* () {
202
+ const claimed = yield* SubscriptionRef.modify(state, (current) => ConnectionState.$is("Connected")(current) ? [true, ConnectionState.Reconnecting({ attempt: 0 })] : [false, current]);
203
+ if (!claimed)
204
+ return;
205
+ if (onClaim)
206
+ yield* onClaim;
207
+ yield* Effect2.forkIn(superviseReconnect(reconnect, state, resolved), scope);
208
+ });
197
209
  // src/AsciiTransportService.ts
198
- import { Effect as Effect6, Layer } from "effect";
210
+ import { Context, Layer } from "effect";
199
211
 
200
212
  // src/mocks.ts
201
213
  import { Effect as Effect4, Schema, SubscriptionRef as SubscriptionRef2 } from "effect";
@@ -228,7 +240,7 @@ var makeEffectModbusClient = (client) => ({
228
240
  });
229
241
  var withResilience = (operations, resilience) => {
230
242
  const run = (operation) => {
231
- const attempt = Effect3.zipRight(resilience.guard, Effect3.suspend(operation)).pipe(Effect3.tapError((error) => resilience.report(error)));
243
+ const attempt = Effect3.andThen(resilience.guard, Effect3.suspend(operation)).pipe(Effect3.tapError((error) => resilience.report(error)));
232
244
  return resilience.policy ? retryModbus(resilience.policy)(attempt) : attempt;
233
245
  };
234
246
  return {
@@ -266,18 +278,10 @@ var RegisterDefinition = Schema.Struct({
266
278
  });
267
279
  var SlaveDeviceDefinition = Schema.Struct({
268
280
  unitId: Schema.Number,
269
- coils: Schema.optionalWith(Schema.Array(CoilDefinition), {
270
- default: () => []
271
- }),
272
- discreteInputs: Schema.optionalWith(Schema.Array(DiscreteInputDefinition), {
273
- default: () => []
274
- }),
275
- holdingRegisters: Schema.optionalWith(Schema.Array(RegisterDefinition), {
276
- default: () => []
277
- }),
278
- inputRegisters: Schema.optionalWith(Schema.Array(RegisterDefinition), {
279
- default: () => []
280
- })
281
+ coils: Schema.Array(CoilDefinition).pipe(Schema.withDecodingDefaultType(Effect4.succeed([]))),
282
+ discreteInputs: Schema.Array(DiscreteInputDefinition).pipe(Schema.withDecodingDefaultType(Effect4.succeed([]))),
283
+ holdingRegisters: Schema.Array(RegisterDefinition).pipe(Schema.withDecodingDefaultType(Effect4.succeed([]))),
284
+ inputRegisters: Schema.Array(RegisterDefinition).pipe(Schema.withDecodingDefaultType(Effect4.succeed([])))
281
285
  });
282
286
  var SlaveDeviceDefinitions = Schema.Array(SlaveDeviceDefinition);
283
287
  var buildCoils = (defs) => {
@@ -458,21 +462,16 @@ var makeMockTransport = (devices) => {
458
462
  const connectionState = yield* SubscriptionRef2.make(ConnectionState.Connected());
459
463
  const supervised = options.reconnect ? resolveReconnect(options.reconnect) : null;
460
464
  const serviceScope = yield* Effect4.scope;
461
- const reconnectOnce = Effect4.zipRight(Effect4.logDebug("Mock: reconnecting"), Effect4.suspend(() => {
465
+ const reconnectOnce = Effect4.andThen(Effect4.logDebug("Mock: reconnecting"), Effect4.suspend(() => {
462
466
  const injected = options.reconnectFault?.();
463
467
  return injected ? Effect4.fail(injected) : Effect4.void;
464
468
  }));
465
469
  const report = (error) => {
466
470
  if (!supervised || !supervised.triggers(error))
467
471
  return Effect4.void;
468
- return Effect4.gen(function* () {
469
- const claimed = yield* SubscriptionRef2.modify(connectionState, (current) => ConnectionState.$is("Connected")(current) ? [true, ConnectionState.Reconnecting({ attempt: 0 })] : [false, current]);
470
- if (!claimed)
471
- return;
472
- yield* Effect4.forkIn(superviseReconnect(reconnectOnce, connectionState, supervised), serviceScope);
473
- });
472
+ return claimReconnect(reconnectOnce, connectionState, supervised, serviceScope);
474
473
  };
475
- const guard = Effect4.zipRight(supervised ? guardCircuit(connectionState) : Effect4.void, Effect4.suspend(() => {
474
+ const guard = Effect4.andThen(supervised ? guardCircuit(connectionState) : Effect4.void, Effect4.suspend(() => {
476
475
  const injected = options.fault?.();
477
476
  return injected ? Effect4.fail(injected) : Effect4.void;
478
477
  }));
@@ -494,8 +493,8 @@ var makeMockTransport = (devices) => {
494
493
  }),
495
494
  setRequestTimeout: (_timeoutMs) => Effect4.void,
496
495
  clearRequestTimeout: () => Effect4.void,
497
- reconnect: () => Effect4.zipRight(reconnectOnce, SubscriptionRef2.set(connectionState, ConnectionState.Connected())),
498
- close: () => Effect4.zipRight(Effect4.logDebug("Mock: closing transport"), SubscriptionRef2.set(connectionState, ConnectionState.Disconnected())),
496
+ reconnect: () => Effect4.andThen(reconnectOnce, SubscriptionRef2.set(connectionState, ConnectionState.Connected())),
497
+ close: () => Effect4.andThen(Effect4.logDebug("Mock: closing transport"), SubscriptionRef2.set(connectionState, ConnectionState.Disconnected())),
499
498
  hasPendingRequests: () => false
500
499
  };
501
500
  });
@@ -511,7 +510,7 @@ var singleFlight = (inFlight, work) => Effect5.uninterruptibleMask((restore) =>
511
510
  onNone: () => [[fresh, true], Option.some(fresh)]
512
511
  }));
513
512
  if (isLeader) {
514
- yield* Effect5.forkDaemon(Effect5.interruptible(work).pipe(Effect5.onExit((exit) => Effect5.zipRight(Ref.set(inFlight, Option.none()), Deferred.done(deferred, exit)))));
513
+ yield* Effect5.forkDetach(Effect5.interruptible(work).pipe(Effect5.onExit((exit) => Effect5.andThen(Ref.set(inFlight, Option.none()), Deferred.done(deferred, exit)))));
515
514
  }
516
515
  return yield* restore(Deferred.await(deferred));
517
516
  }));
@@ -533,11 +532,11 @@ function makeTransportScoped(transportKey, openMethod, serviceName, config) {
533
532
  cause: new Error("Transport has been closed"),
534
533
  message: "Transport has been closed"
535
534
  });
536
- const closeOrphan = (t) => Effect5.forkDaemon(Effect5.ignore(Effect5.tryPromise(() => t.close())));
535
+ const closeOrphan = (t) => Effect5.forkDetach(Effect5.ignore(Effect5.tryPromise(() => t.close())));
537
536
  const openTransport = Effect5.tryPromise({
538
537
  try: () => openMethod(TC, openOptions),
539
538
  catch: (error) => toModbusError(error)
540
- }).pipe(Effect5.tap((t) => closed ? closeOrphan(t) : Effect5.zipRight(Effect5.sync(() => {
539
+ }).pipe(Effect5.tap((t) => closed ? closeOrphan(t) : Effect5.andThen(Effect5.sync(() => {
541
540
  transport = t;
542
541
  }), SubscriptionRef3.set(connectionState, ConnectionState.Connected()))));
543
542
  const ensureOpen = Effect5.fnUntraced(function* () {
@@ -557,7 +556,7 @@ function makeTransportScoped(transportKey, openMethod, serviceName, config) {
557
556
  const t = transport;
558
557
  if (!t)
559
558
  return SubscriptionRef3.set(connectionState, ConnectionState.Disconnected());
560
- return Effect5.andThen(Effect5.logDebug(`Closing ${serviceName}`), Effect5.zipRight(Effect5.promise(() => t.close()), SubscriptionRef3.set(connectionState, ConnectionState.Disconnected())));
559
+ return Effect5.andThen(Effect5.logDebug(`Closing ${serviceName}`), Effect5.andThen(Effect5.promise(() => t.close()), SubscriptionRef3.set(connectionState, ConnectionState.Disconnected())));
561
560
  });
562
561
  const notConnectedMsg = "Transport is not connected. Call withClient() first.";
563
562
  const reconnectOnce = Effect5.suspend(() => {
@@ -572,13 +571,7 @@ function makeTransportScoped(transportKey, openMethod, serviceName, config) {
572
571
  const report = (error) => {
573
572
  if (!supervised || closed || !supervised.triggers(error))
574
573
  return Effect5.void;
575
- return Effect5.gen(function* () {
576
- const claimed = yield* SubscriptionRef3.modify(connectionState, (current) => ConnectionState.$is("Connected")(current) ? [true, ConnectionState.Reconnecting({ attempt: 0 })] : [false, current]);
577
- if (!claimed)
578
- return;
579
- yield* Effect5.logDebug(`${serviceName}: reconnecting after ${error.message}`);
580
- yield* Effect5.forkIn(superviseReconnect(reconnectOnce, connectionState, supervised), serviceScope);
581
- });
574
+ return claimReconnect(reconnectOnce, connectionState, supervised, serviceScope, Effect5.logDebug(`${serviceName}: reconnecting after ${error.message}`));
582
575
  };
583
576
  const resilience = {
584
577
  guard: supervised ? guardCircuit(connectionState) : Effect5.void,
@@ -665,54 +658,54 @@ function makeTransportScoped(transportKey, openMethod, serviceName, config) {
665
658
  }
666
659
 
667
660
  // src/AsciiTransportService.ts
668
- class AsciiTransportService extends Effect6.Service()("AsciiTransportService", {
669
- scoped: makeTransportScoped("AsyncAsciiTransport", (TC, options) => TC.open(options), "AsciiTransportService")
670
- }) {
661
+ class AsciiTransportService extends Context.Service()("AsciiTransportService") {
662
+ static makeScoped = makeTransportScoped("AsyncAsciiTransport", (TC, options) => TC.open(options), "AsciiTransportService");
663
+ static make = (options) => Layer.effect(AsciiTransportService, AsciiTransportService.makeScoped(options));
671
664
  static makeMockTransport = (devices) => {
672
665
  const factory = makeMockTransport(devices);
673
- return (options) => Layer.scoped(AsciiTransportService, factory(options));
666
+ return (options) => Layer.effect(AsciiTransportService, factory(options));
674
667
  };
675
668
  }
676
669
  // src/SerialTransportService.ts
677
- import { Context, Layer as Layer3 } from "effect";
670
+ import { Context as Context3, Layer as Layer3 } from "effect";
678
671
 
679
672
  // src/RtuTransportService.ts
680
- import { Effect as Effect7, Layer as Layer2 } from "effect";
681
- class RtuTransportService extends Effect7.Service()("RtuTransportService", {
682
- scoped: makeTransportScoped("AsyncRtuTransport", (TC, options) => TC.open(options), "RtuTransportService")
683
- }) {
673
+ import { Context as Context2, Layer as Layer2 } from "effect";
674
+ class RtuTransportService extends Context2.Service()("RtuTransportService") {
675
+ static makeScoped = makeTransportScoped("AsyncRtuTransport", (TC, options) => TC.open(options), "RtuTransportService");
676
+ static make = (options) => Layer2.effect(RtuTransportService, RtuTransportService.makeScoped(options));
684
677
  static makeMockTransport = (devices) => {
685
678
  const factory = makeMockTransport(devices);
686
- return (options) => Layer2.scoped(RtuTransportService, factory(options));
679
+ return (options) => Layer2.effect(RtuTransportService, factory(options));
687
680
  };
688
681
  }
689
682
 
690
683
  // src/SerialTransportService.ts
691
- class SerialTransportService extends Context.Tag("SerialTransportService")() {
684
+ class SerialTransportService extends Context3.Service()("SerialTransportService") {
692
685
  static fromAscii(options) {
693
- return Layer3.project(AsciiTransportService, SerialTransportService, (ascii) => ascii)(AsciiTransportService.Default(options));
686
+ return Layer3.flatMap(AsciiTransportService.make(options), (context) => Layer3.succeed(SerialTransportService, Context3.get(context, AsciiTransportService)));
694
687
  }
695
688
  static fromRtu(options) {
696
- return Layer3.project(RtuTransportService, SerialTransportService, (rtu) => rtu)(RtuTransportService.Default(options));
689
+ return Layer3.flatMap(RtuTransportService.make(options), (context) => Layer3.succeed(SerialTransportService, Context3.get(context, RtuTransportService)));
697
690
  }
698
691
  static makeMockTransport = (devices) => {
699
692
  const factory = makeMockTransport(devices);
700
- return (options) => Layer3.scoped(SerialTransportService, factory(options));
693
+ return (options) => Layer3.effect(SerialTransportService, factory(options));
701
694
  };
702
695
  }
703
696
  // src/TcpTransportService.ts
704
- import { Effect as Effect8, Layer as Layer4 } from "effect";
705
- class TcpTransportService extends Effect8.Service()("TcpTransportService", {
706
- scoped: makeTransportScoped("AsyncTcpTransport", (TC, options) => TC.connect(options), "TcpTransportService")
707
- }) {
697
+ import { Context as Context4, Layer as Layer4 } from "effect";
698
+ class TcpTransportService extends Context4.Service()("TcpTransportService") {
699
+ static makeScoped = makeTransportScoped("AsyncTcpTransport", (TC, options) => TC.connect(options), "TcpTransportService");
700
+ static make = (options) => Layer4.effect(TcpTransportService, TcpTransportService.makeScoped(options));
708
701
  static makeMockTransport = (devices) => {
709
702
  const factory = makeMockTransport(devices);
710
- return (options) => Layer4.scoped(TcpTransportService, factory(options));
703
+ return (options) => Layer4.effect(TcpTransportService, factory(options));
711
704
  };
712
705
  }
713
706
  // src/SerialModbusServerService.ts
714
707
  import { Effect as Effect9, Layer as Layer5 } from "effect";
715
- var serialRtuServerLayer = (options, handlers) => Layer5.scopedDiscard(Effect9.gen(function* () {
708
+ var serialRtuServerLayer = (options, handlers) => Layer5.effectDiscard(Effect9.gen(function* () {
716
709
  const { AsyncSerialModbusServer } = yield* Effect9.promise(() => import("modbus-rs"));
717
710
  const server = yield* Effect9.tryPromise({
718
711
  try: () => AsyncSerialModbusServer.bindRtu(options, handlers),
@@ -722,9 +715,9 @@ var serialRtuServerLayer = (options, handlers) => Layer5.scopedDiscard(Effect9.g
722
715
  yield* Effect9.addFinalizer(() => Effect9.logDebug("Serial RTU server shutting down").pipe(Effect9.andThen(Effect9.tryPromise({
723
716
  try: () => server.shutdown(),
724
717
  catch: (error) => toModbusError(error)
725
- })), Effect9.catchAll(() => Effect9.void)));
718
+ })), Effect9.catch(() => Effect9.void)));
726
719
  }));
727
- var serialAsciiServerLayer = (options, handlers) => Layer5.scopedDiscard(Effect9.gen(function* () {
720
+ var serialAsciiServerLayer = (options, handlers) => Layer5.effectDiscard(Effect9.gen(function* () {
728
721
  const { AsyncSerialModbusServer } = yield* Effect9.promise(() => import("modbus-rs"));
729
722
  const server = yield* Effect9.tryPromise({
730
723
  try: () => AsyncSerialModbusServer.bindAscii(options, handlers),
@@ -734,11 +727,11 @@ var serialAsciiServerLayer = (options, handlers) => Layer5.scopedDiscard(Effect9
734
727
  yield* Effect9.addFinalizer(() => Effect9.logDebug("Serial ASCII server shutting down").pipe(Effect9.andThen(Effect9.tryPromise({
735
728
  try: () => server.shutdown(),
736
729
  catch: (error) => toModbusError(error)
737
- })), Effect9.catchAll(() => Effect9.void)));
730
+ })), Effect9.catch(() => Effect9.void)));
738
731
  }));
739
732
  // src/TcpModbusServerService.ts
740
733
  import { Effect as Effect10, Layer as Layer6 } from "effect";
741
- var tcpServerLayer = (options, handlers) => Layer6.scopedDiscard(Effect10.gen(function* () {
734
+ var tcpServerLayer = (options, handlers) => Layer6.effectDiscard(Effect10.gen(function* () {
742
735
  const { AsyncTcpModbusServer } = yield* Effect10.promise(() => import("modbus-rs"));
743
736
  const server = yield* Effect10.tryPromise({
744
737
  try: () => AsyncTcpModbusServer.bind(options, handlers),
@@ -748,11 +741,11 @@ var tcpServerLayer = (options, handlers) => Layer6.scopedDiscard(Effect10.gen(fu
748
741
  yield* Effect10.addFinalizer(() => Effect10.logDebug("TCP server shutting down").pipe(Effect10.andThen(Effect10.tryPromise({
749
742
  try: () => server.shutdown(),
750
743
  catch: (error) => toModbusError(error)
751
- })), Effect10.catchAll(() => Effect10.void)));
744
+ })), Effect10.catch(() => Effect10.void)));
752
745
  }));
753
746
  // src/TcpGatewayService.ts
754
747
  import { Effect as Effect11, Layer as Layer7 } from "effect";
755
- var tcpGatewayLayer = (options, gatewayConfig) => Layer7.scopedDiscard(Effect11.gen(function* () {
748
+ var tcpGatewayLayer = (options, gatewayConfig) => Layer7.effectDiscard(Effect11.gen(function* () {
756
749
  const { AsyncTcpGateway } = yield* Effect11.promise(() => import("modbus-rs"));
757
750
  const gateway = yield* Effect11.tryPromise({
758
751
  try: () => AsyncTcpGateway.bind(options, gatewayConfig),
@@ -762,50 +755,50 @@ var tcpGatewayLayer = (options, gatewayConfig) => Layer7.scopedDiscard(Effect11.
762
755
  yield* Effect11.addFinalizer(() => Effect11.logDebug("TCP gateway shutting down").pipe(Effect11.andThen(Effect11.tryPromise({
763
756
  try: () => gateway.shutdown(),
764
757
  catch: (error) => toModbusError(error)
765
- })), Effect11.catchAll(() => Effect11.void)));
758
+ })), Effect11.catch(() => Effect11.void)));
766
759
  }));
767
760
  // src/WasmWsTransportService.ts
768
- import { Effect as Effect12, Layer as Layer8 } from "effect";
769
- class WasmWsTransportService extends Effect12.Service()("WasmWsTransportService", {
770
- scoped: makeTransportScoped("WasmWsTransport", (TC, options) => TC.connect(options), "WasmWsTransportService", { moduleSpecifier: "modbus-rs/web" })
771
- }) {
761
+ import { Context as Context5, Layer as Layer8 } from "effect";
762
+ class WasmWsTransportService extends Context5.Service()("WasmWsTransportService") {
763
+ static makeScoped = makeTransportScoped("WasmWsTransport", (TC, options) => TC.connect(options), "WasmWsTransportService", { moduleSpecifier: "modbus-rs/web" });
764
+ static make = (options) => Layer8.effect(WasmWsTransportService, WasmWsTransportService.makeScoped(options));
772
765
  static makeMockTransport = (devices) => {
773
766
  const factory = makeMockTransport(devices);
774
- return (options) => Layer8.scoped(WasmWsTransportService, factory(options));
767
+ return (options) => Layer8.effect(WasmWsTransportService, factory(options));
775
768
  };
776
769
  }
777
770
  // src/WasmRtuTransportService.ts
778
- import { Effect as Effect13, Layer as Layer9 } from "effect";
779
- class WasmRtuTransportService extends Effect13.Service()("WasmRtuTransportService", {
780
- scoped: makeTransportScoped("WasmRtuTransport", (TC, { port, ...rest }) => TC.open(port, rest), "WasmRtuTransportService", { moduleSpecifier: "modbus-rs/web" })
781
- }) {
771
+ import { Context as Context6, Layer as Layer9 } from "effect";
772
+ class WasmRtuTransportService extends Context6.Service()("WasmRtuTransportService") {
773
+ static makeScoped = makeTransportScoped("WasmRtuTransport", (TC, { port, ...rest }) => TC.open(port, rest), "WasmRtuTransportService", { moduleSpecifier: "modbus-rs/web" });
774
+ static make = (options) => Layer9.effect(WasmRtuTransportService, WasmRtuTransportService.makeScoped(options));
782
775
  static makeMockTransport = (devices) => {
783
776
  const factory = makeMockTransport(devices);
784
- return (options) => Layer9.scoped(WasmRtuTransportService, factory(options));
777
+ return (options) => Layer9.effect(WasmRtuTransportService, factory(options));
785
778
  };
786
779
  }
787
780
  // src/WasmAsciiTransportService.ts
788
- import { Effect as Effect14, Layer as Layer10 } from "effect";
789
- class WasmAsciiTransportService extends Effect14.Service()("WasmAsciiTransportService", {
790
- scoped: makeTransportScoped("WasmAsciiTransport", (TC, { port, ...rest }) => TC.open(port, rest), "WasmAsciiTransportService", { moduleSpecifier: "modbus-rs/web" })
791
- }) {
781
+ import { Context as Context7, Layer as Layer10 } from "effect";
782
+ class WasmAsciiTransportService extends Context7.Service()("WasmAsciiTransportService") {
783
+ static makeScoped = makeTransportScoped("WasmAsciiTransport", (TC, { port, ...rest }) => TC.open(port, rest), "WasmAsciiTransportService", { moduleSpecifier: "modbus-rs/web" });
784
+ static make = (options) => Layer10.effect(WasmAsciiTransportService, WasmAsciiTransportService.makeScoped(options));
792
785
  static makeMockTransport = (devices) => {
793
786
  const factory = makeMockTransport(devices);
794
- return (options) => Layer10.scoped(WasmAsciiTransportService, factory(options));
787
+ return (options) => Layer10.effect(WasmAsciiTransportService, factory(options));
795
788
  };
796
789
  }
797
790
  // src/WasmSerialTransportService.ts
798
- import { Context as Context2, Layer as Layer11 } from "effect";
799
- class WasmSerialTransportService extends Context2.Tag("WasmSerialTransportService")() {
791
+ import { Context as Context8, Layer as Layer11 } from "effect";
792
+ class WasmSerialTransportService extends Context8.Service()("WasmSerialTransportService") {
800
793
  static fromAscii(options) {
801
- return Layer11.project(WasmAsciiTransportService, WasmSerialTransportService, (ascii) => ascii)(WasmAsciiTransportService.Default(options));
794
+ return Layer11.flatMap(WasmAsciiTransportService.make(options), (context) => Layer11.succeed(WasmSerialTransportService, Context8.get(context, WasmAsciiTransportService)));
802
795
  }
803
796
  static fromRtu(options) {
804
- return Layer11.project(WasmRtuTransportService, WasmSerialTransportService, (rtu) => rtu)(WasmRtuTransportService.Default(options));
797
+ return Layer11.flatMap(WasmRtuTransportService.make(options), (context) => Layer11.succeed(WasmSerialTransportService, Context8.get(context, WasmRtuTransportService)));
805
798
  }
806
799
  static makeMockTransport = (devices) => {
807
800
  const factory = makeMockTransport(devices);
808
- return (options) => Layer11.scoped(WasmSerialTransportService, factory(options));
801
+ return (options) => Layer11.effect(WasmSerialTransportService, factory(options));
809
802
  };
810
803
  }
811
804
  // src/WasmSerialPort.ts
@@ -819,7 +812,7 @@ var requestSerialPort = () => Effect15.tryPromise({
819
812
  });
820
813
  // src/WasmTcpServerService.ts
821
814
  import { Effect as Effect16, Layer as Layer12 } from "effect";
822
- var wasmWsServerLayer = (options, handlers) => Layer12.scopedDiscard(Effect16.gen(function* () {
815
+ var wasmWsServerLayer = (options, handlers) => Layer12.effectDiscard(Effect16.gen(function* () {
823
816
  const { WasmWsModbusServer } = yield* Effect16.promise(() => import("modbus-rs/web"));
824
817
  const server = yield* Effect16.tryPromise({
825
818
  try: () => WasmWsModbusServer.bind(options, handlers),
@@ -829,15 +822,15 @@ var wasmWsServerLayer = (options, handlers) => Layer12.scopedDiscard(Effect16.ge
829
822
  yield* Effect16.forkScoped(Effect16.tryPromise({
830
823
  try: () => server.serve(),
831
824
  catch: (error) => toModbusError(error)
832
- }).pipe(Effect16.catchAll((error) => Effect16.logError("WASM WS server loop ended", error))));
825
+ }).pipe(Effect16.catch((error) => Effect16.logError("WASM WS server loop ended", error))));
833
826
  yield* Effect16.addFinalizer(() => Effect16.logDebug("WASM WS server shutting down").pipe(Effect16.andThen(Effect16.tryPromise({
834
827
  try: () => server.shutdown(),
835
828
  catch: (error) => toModbusError(error)
836
- })), Effect16.catchAll(() => Effect16.void)));
829
+ })), Effect16.catch(() => Effect16.void)));
837
830
  }));
838
831
  // src/WasmSerialModbusServerService.ts
839
832
  import { Effect as Effect17, Layer as Layer13 } from "effect";
840
- var wasmSerialRtuServerLayer = (options, handlers) => Layer13.scopedDiscard(Effect17.gen(function* () {
833
+ var wasmSerialRtuServerLayer = (options, handlers) => Layer13.effectDiscard(Effect17.gen(function* () {
841
834
  const { WasmSerialModbusServer } = yield* Effect17.promise(() => import("modbus-rs/web"));
842
835
  const server = yield* Effect17.tryPromise({
843
836
  try: () => WasmSerialModbusServer.bindRtu(options, handlers),
@@ -847,13 +840,13 @@ var wasmSerialRtuServerLayer = (options, handlers) => Layer13.scopedDiscard(Effe
847
840
  yield* Effect17.forkScoped(Effect17.tryPromise({
848
841
  try: () => server.serve(),
849
842
  catch: (error) => toModbusError(error)
850
- }).pipe(Effect17.catchAll((error) => Effect17.logError("WASM serial RTU server loop ended", error))));
843
+ }).pipe(Effect17.catch((error) => Effect17.logError("WASM serial RTU server loop ended", error))));
851
844
  yield* Effect17.addFinalizer(() => Effect17.logDebug("WASM serial RTU server shutting down").pipe(Effect17.andThen(Effect17.tryPromise({
852
845
  try: () => server.shutdown(),
853
846
  catch: (error) => toModbusError(error)
854
- })), Effect17.catchAll(() => Effect17.void)));
847
+ })), Effect17.catch(() => Effect17.void)));
855
848
  }));
856
- var wasmSerialAsciiServerLayer = (options, handlers) => Layer13.scopedDiscard(Effect17.gen(function* () {
849
+ var wasmSerialAsciiServerLayer = (options, handlers) => Layer13.effectDiscard(Effect17.gen(function* () {
857
850
  const { WasmSerialModbusServer } = yield* Effect17.promise(() => import("modbus-rs/web"));
858
851
  const server = yield* Effect17.tryPromise({
859
852
  try: () => WasmSerialModbusServer.bindAscii(options, handlers),
@@ -863,41 +856,41 @@ var wasmSerialAsciiServerLayer = (options, handlers) => Layer13.scopedDiscard(Ef
863
856
  yield* Effect17.forkScoped(Effect17.tryPromise({
864
857
  try: () => server.serve(),
865
858
  catch: (error) => toModbusError(error)
866
- }).pipe(Effect17.catchAll((error) => Effect17.logError("WASM serial ASCII server loop ended", error))));
859
+ }).pipe(Effect17.catch((error) => Effect17.logError("WASM serial ASCII server loop ended", error))));
867
860
  yield* Effect17.addFinalizer(() => Effect17.logDebug("WASM serial ASCII server shutting down").pipe(Effect17.andThen(Effect17.tryPromise({
868
861
  try: () => server.shutdown(),
869
862
  catch: (error) => toModbusError(error)
870
- })), Effect17.catchAll(() => Effect17.void)));
863
+ })), Effect17.catch(() => Effect17.void)));
871
864
  }));
872
865
  export {
873
- wasmWsServerLayer,
874
- wasmSerialRtuServerLayer,
875
- wasmSerialAsciiServerLayer,
876
- toModbusError,
877
- tcpServerLayer,
878
- tcpGatewayLayer,
879
- serialRtuServerLayer,
880
- serialAsciiServerLayer,
881
- retryableExceptionCodes,
882
- retryModbus,
883
- requestSerialPort,
884
- makeRetryPolicy,
885
- WasmWsTransportService,
886
- WasmSerialTransportService,
887
- WasmRtuTransportService,
888
- WasmAsciiTransportService,
889
- TcpTransportService,
890
- SerialTransportService,
891
- RtuTransportService,
892
- RetryPolicies,
893
- ModbusTransportError,
894
- ModbusTimeoutError,
895
- ModbusNotConnectedError,
896
- ModbusInvalidArgumentError,
897
- ModbusInternalError,
898
- ModbusExceptionError,
899
- ModbusConnectionClosedError,
900
- ModbusCircuitOpenError,
866
+ AsciiTransportService,
901
867
  ConnectionState,
902
- AsciiTransportService
868
+ ModbusCircuitOpenError,
869
+ ModbusConnectionClosedError,
870
+ ModbusExceptionError,
871
+ ModbusInternalError,
872
+ ModbusInvalidArgumentError,
873
+ ModbusNotConnectedError,
874
+ ModbusTimeoutError,
875
+ ModbusTransportError,
876
+ RetryPolicies,
877
+ RtuTransportService,
878
+ SerialTransportService,
879
+ TcpTransportService,
880
+ WasmAsciiTransportService,
881
+ WasmRtuTransportService,
882
+ WasmSerialTransportService,
883
+ WasmWsTransportService,
884
+ makeRetryPolicy,
885
+ requestSerialPort,
886
+ retryModbus,
887
+ retryableExceptionCodes,
888
+ serialAsciiServerLayer,
889
+ serialRtuServerLayer,
890
+ tcpGatewayLayer,
891
+ tcpServerLayer,
892
+ toModbusError,
893
+ wasmSerialAsciiServerLayer,
894
+ wasmSerialRtuServerLayer,
895
+ wasmWsServerLayer
903
896
  };