@flux-control/effect-modbus-rs 0.1.1 → 0.3.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.
@@ -1,9 +1,30 @@
1
- import type { AsciiTransportOptions } from "modbus-rs";
2
- import { Effect, Layer } from "effect";
3
- import { SlaveDeviceDefinitions } from "./mocks";
1
+ import { Effect, Layer } from 'effect';
2
+ import type { AsciiTransportOptions } from 'modbus-rs';
3
+ import { SlaveDeviceDefinitions } from './mocks';
4
+ import type { MockFaultOptions } from './mocks';
5
+ import type { TransportResilienceOptions, WithoutUpstreamRetry } from './shared-transport';
6
+ /**
7
+ * {@link AsciiTransportOptions} minus the upstream retry knobs.
8
+ *
9
+ * @see WithoutUpstreamRetry — Why they are withheld.
10
+ */
11
+ export type AsciiTransportOpenOptions = WithoutUpstreamRetry<AsciiTransportOptions>;
4
12
  declare const AsciiTransportService_base: Effect.Service.Class<AsciiTransportService, "AsciiTransportService", {
5
- readonly scoped: (options: AsciiTransportOptions) => Effect.Effect<{
6
- withClient: (unitId: number) => Effect.Effect<import("./modbus-client").EffectModbusClient, import("./errors").ModbusError, never>;
13
+ readonly scoped: (options: AsciiTransportOpenOptions & TransportResilienceOptions) => Effect.Effect<{
14
+ connectionState: import("effect/SubscriptionRef").SubscriptionRef<{
15
+ readonly _tag: "Connected";
16
+ } | {
17
+ readonly _tag: "Disconnected";
18
+ } | {
19
+ readonly _tag: "Down";
20
+ readonly cause: import("./errors").ModbusError;
21
+ } | {
22
+ readonly _tag: "Reconnecting";
23
+ readonly attempt: number;
24
+ }>;
25
+ withClient: (unitId: number, clientOptions?: {
26
+ readonly retry?: import("./retry").ModbusRetryPolicy;
27
+ } | undefined) => Effect.Effect<import("./modbus-client").EffectModbusClient, import("./errors").ModbusError, never>;
7
28
  setRequestTimeout: (timeoutMs: number) => Effect.Effect<undefined, import("./errors").ModbusNotConnectedError, never>;
8
29
  clearRequestTimeout: () => Effect.Effect<undefined, import("./errors").ModbusNotConnectedError, never>;
9
30
  reconnect: () => Effect.Effect<undefined, import("./errors").ModbusError, never>;
@@ -24,7 +45,7 @@ declare const AsciiTransportService_base: Effect.Service.Class<AsciiTransportSer
24
45
  * requests for the same unit ID reuse the same client.
25
46
  *
26
47
  * @see AsyncAsciiTransport — Upstream `modbus-rs` ASCII transport.
27
- * @see AsciiTransportOptions — Configuration for the ASCII serial port.
48
+ * @see AsciiTransportOpenOptions — Configuration for the ASCII serial port.
28
49
  * @see makeTransportScoped — Generic lifecycle logic from shared-transport.
29
50
  */
30
51
  export declare class AsciiTransportService extends AsciiTransportService_base {
@@ -36,11 +57,11 @@ export declare class AsciiTransportService extends AsciiTransportService_base {
36
57
  * simulated Modbus slaves and their register/coil maps.
37
58
  *
38
59
  * @param devices - Slave device definitions for the mock.
39
- * @returns A function that takes {@link AsciiTransportOptions} and
60
+ * @returns A function that takes {@link AsciiTransportOpenOptions} and
40
61
  * returns a scoped {@link Layer} providing the mock service.
41
62
  *
42
63
  * @see makeMockTransport — The underlying mock factory.
43
64
  */
44
- static makeMockTransport: (devices: SlaveDeviceDefinitions) => (options: AsciiTransportOptions) => Layer.Layer<AsciiTransportService, never, never>;
65
+ static makeMockTransport: (devices: SlaveDeviceDefinitions) => (options: AsciiTransportOpenOptions & TransportResilienceOptions & MockFaultOptions) => Layer.Layer<AsciiTransportService, never, never>;
45
66
  }
46
67
  export {};
@@ -1,9 +1,30 @@
1
- import type { RtuTransportOptions } from "modbus-rs";
2
- import { Effect, Layer } from "effect";
3
- import type { SlaveDeviceDefinitions } from "./mocks";
1
+ import { Effect, Layer } from 'effect';
2
+ import type { RtuTransportOptions } from 'modbus-rs';
3
+ import type { MockFaultOptions } from './mocks';
4
+ import type { SlaveDeviceDefinitions } from './mocks';
5
+ import type { TransportResilienceOptions, WithoutUpstreamRetry } from './shared-transport';
6
+ /**
7
+ * {@link RtuTransportOptions} minus the upstream retry knobs.
8
+ *
9
+ * @see WithoutUpstreamRetry — Why they are withheld.
10
+ */
11
+ export type RtuTransportOpenOptions = WithoutUpstreamRetry<RtuTransportOptions>;
4
12
  declare const RtuTransportService_base: Effect.Service.Class<RtuTransportService, "RtuTransportService", {
5
- readonly scoped: (options: RtuTransportOptions) => Effect.Effect<{
6
- withClient: (unitId: number) => Effect.Effect<import("./modbus-client").EffectModbusClient, import("./errors").ModbusError, never>;
13
+ readonly scoped: (options: RtuTransportOpenOptions & TransportResilienceOptions) => Effect.Effect<{
14
+ connectionState: import("effect/SubscriptionRef").SubscriptionRef<{
15
+ readonly _tag: "Connected";
16
+ } | {
17
+ readonly _tag: "Disconnected";
18
+ } | {
19
+ readonly _tag: "Down";
20
+ readonly cause: import("./errors").ModbusError;
21
+ } | {
22
+ readonly _tag: "Reconnecting";
23
+ readonly attempt: number;
24
+ }>;
25
+ withClient: (unitId: number, clientOptions?: {
26
+ readonly retry?: import("./retry").ModbusRetryPolicy;
27
+ } | undefined) => Effect.Effect<import("./modbus-client").EffectModbusClient, import("./errors").ModbusError, never>;
7
28
  setRequestTimeout: (timeoutMs: number) => Effect.Effect<undefined, import("./errors").ModbusNotConnectedError, never>;
8
29
  clearRequestTimeout: () => Effect.Effect<undefined, import("./errors").ModbusNotConnectedError, never>;
9
30
  reconnect: () => Effect.Effect<undefined, import("./errors").ModbusError, never>;
@@ -24,7 +45,7 @@ declare const RtuTransportService_base: Effect.Service.Class<RtuTransportService
24
45
  * requests for the same unit ID reuse the same client.
25
46
  *
26
47
  * @see AsyncRtuTransport — Upstream `modbus-rs` RTU transport.
27
- * @see RtuTransportOptions — Configuration for the RTU serial port.
48
+ * @see RtuTransportOpenOptions — Configuration for the RTU serial port.
28
49
  * @see makeTransportScoped — Generic lifecycle logic from shared-transport.
29
50
  */
30
51
  export declare class RtuTransportService extends RtuTransportService_base {
@@ -36,11 +57,11 @@ export declare class RtuTransportService extends RtuTransportService_base {
36
57
  * simulated Modbus slaves and their register/coil maps.
37
58
  *
38
59
  * @param devices - Slave device definitions for the mock.
39
- * @returns A function that takes {@link RtuTransportOptions} and
60
+ * @returns A function that takes {@link RtuTransportOpenOptions} and
40
61
  * returns a scoped {@link Layer} providing the mock service.
41
62
  *
42
63
  * @see makeMockTransport — The underlying mock factory.
43
64
  */
44
- static makeMockTransport: (devices: SlaveDeviceDefinitions) => (options: RtuTransportOptions) => Layer.Layer<RtuTransportService, never, never>;
65
+ static makeMockTransport: (devices: SlaveDeviceDefinitions) => (options: RtuTransportOpenOptions & TransportResilienceOptions & MockFaultOptions) => Layer.Layer<RtuTransportService, never, never>;
45
66
  }
46
67
  export {};
@@ -1,6 +1,6 @@
1
- import type { SerialServerOptions, ServerHandlers } from "modbus-rs";
2
- import { Layer } from "effect";
3
- import type { ModbusError } from "./errors";
1
+ import { Layer } from 'effect';
2
+ import type { SerialServerOptions, ServerHandlers } from 'modbus-rs';
3
+ import type { ModbusError } from './errors';
4
4
  /**
5
5
  * A scoped {@link Layer} that starts a Modbus serial RTU server.
6
6
  *
@@ -11,7 +11,7 @@ import type { ModbusError } from "./errors";
11
11
  * @example
12
12
  * ```ts
13
13
  * import { Effect, Layer } from "effect";
14
- * import { serialRtuServerLayer } from "effect-modbus-rs";
14
+ * import { serialRtuServerLayer } from "@flux-control/effect-modbus-rs";
15
15
  *
16
16
  * const ServerLive = serialRtuServerLayer(
17
17
  * { portPath: "/dev/ttyUSB0", baudRate: 9600, unitId: 1 },
@@ -35,7 +35,7 @@ export declare const serialRtuServerLayer: (options: SerialServerOptions, handle
35
35
  * @example
36
36
  * ```ts
37
37
  * import { Effect, Layer } from "effect";
38
- * import { serialAsciiServerLayer } from "effect-modbus-rs";
38
+ * import { serialAsciiServerLayer } from "@flux-control/effect-modbus-rs";
39
39
  *
40
40
  * const ServerLive = serialAsciiServerLayer(
41
41
  * { portPath: "/dev/ttyUSB0", baudRate: 9600, unitId: 1 },
@@ -1,7 +1,8 @@
1
- import { Context, Layer } from "effect";
2
- import type { AsciiTransportOptions, RtuTransportOptions } from "modbus-rs";
3
- import type { TransportServiceApi } from "./shared-transport";
4
- import { type SlaveDeviceDefinitions } from "./mocks";
1
+ import { Context, Layer } from 'effect';
2
+ import { type AsciiTransportOpenOptions } from './AsciiTransportService';
3
+ import { type SlaveDeviceDefinitions } from './mocks';
4
+ import { type RtuTransportOpenOptions } from './RtuTransportService';
5
+ import type { TransportResilienceOptions, TransportServiceApi } from './shared-transport';
5
6
  declare const SerialTransportService_base: Context.TagClass<SerialTransportService, "SerialTransportService", TransportServiceApi>;
6
7
  /**
7
8
  * Abstract serial Modbus transport service tag.
@@ -27,12 +28,12 @@ export declare class SerialTransportService extends SerialTransportService_base
27
28
  * Creates a {@link Layer} providing {@link SerialTransportService}
28
29
  * backed by an ASCII transport.
29
30
  */
30
- static fromAscii(options: AsciiTransportOptions): Layer.Layer<SerialTransportService>;
31
+ static fromAscii(options: AsciiTransportOpenOptions & TransportResilienceOptions): Layer.Layer<SerialTransportService>;
31
32
  /**
32
33
  * Creates a {@link Layer} providing {@link SerialTransportService}
33
34
  * backed by an RTU transport.
34
35
  */
35
- static fromRtu(options: RtuTransportOptions): Layer.Layer<SerialTransportService>;
36
+ static fromRtu(options: RtuTransportOpenOptions & TransportResilienceOptions): Layer.Layer<SerialTransportService>;
36
37
  /**
37
38
  * Creates a mock {@link Layer} providing {@link SerialTransportService}
38
39
  * for testing or development.
@@ -40,6 +41,6 @@ export declare class SerialTransportService extends SerialTransportService_base
40
41
  * Accepts an array of {@link SlaveDeviceDefinition} describing the
41
42
  * simulated Modbus slaves and their register/coil maps.
42
43
  */
43
- static makeMockTransport: (devices: SlaveDeviceDefinitions) => (options: AsciiTransportOptions | RtuTransportOptions) => Layer.Layer<SerialTransportService>;
44
+ static makeMockTransport: (devices: SlaveDeviceDefinitions) => (options: (AsciiTransportOpenOptions | RtuTransportOpenOptions) & TransportResilienceOptions) => Layer.Layer<SerialTransportService>;
44
45
  }
45
46
  export {};
@@ -1,6 +1,6 @@
1
- import type { GatewayBindOptions, GatewayConfig } from "modbus-rs";
2
- import { Layer } from "effect";
3
- import type { ModbusError } from "./errors";
1
+ import { Layer } from 'effect';
2
+ import type { GatewayBindOptions, GatewayConfig } from 'modbus-rs';
3
+ import type { ModbusError } from './errors';
4
4
  /**
5
5
  * A scoped {@link Layer} that starts a Modbus TCP gateway.
6
6
  *
@@ -17,7 +17,7 @@ import type { ModbusError } from "./errors";
17
17
  * @example
18
18
  * ```ts
19
19
  * import { Effect, Layer } from "effect";
20
- * import { tcpGatewayLayer } from "effect-modbus-rs";
20
+ * import { tcpGatewayLayer } from "@flux-control/effect-modbus-rs";
21
21
  *
22
22
  * const GatewayLive = tcpGatewayLayer(
23
23
  * { host: "0.0.0.0", port: 8502 },
@@ -1,6 +1,6 @@
1
- import type { ServerHandlers, TcpServerOptions } from "modbus-rs";
2
- import { Layer } from "effect";
3
- import type { ModbusError } from "./errors";
1
+ import { Layer } from 'effect';
2
+ import type { ServerHandlers, TcpServerOptions } from 'modbus-rs';
3
+ import type { ModbusError } from './errors';
4
4
  /**
5
5
  * A scoped {@link Layer} that starts a Modbus TCP server.
6
6
  *
@@ -15,7 +15,7 @@ import type { ModbusError } from "./errors";
15
15
  * @example
16
16
  * ```ts
17
17
  * import { Effect, Layer } from "effect";
18
- * import { tcpServerLayer } from "effect-modbus-rs";
18
+ * import { tcpServerLayer } from "@flux-control/effect-modbus-rs";
19
19
  *
20
20
  * const ServerLive = tcpServerLayer(
21
21
  * { host: "0.0.0.0", port: 502, unitId: 1 },
@@ -1,9 +1,30 @@
1
- import type { TcpTransportOptions } from "modbus-rs";
2
- import { Effect, Layer } from "effect";
3
- import { SlaveDeviceDefinitions } from "./mocks";
1
+ import { Effect, Layer } from 'effect';
2
+ import type { TcpTransportOptions } from 'modbus-rs';
3
+ import { SlaveDeviceDefinitions } from './mocks';
4
+ import type { MockFaultOptions } from './mocks';
5
+ import type { TransportResilienceOptions, WithoutUpstreamRetry } from './shared-transport';
6
+ /**
7
+ * {@link TcpTransportOptions} minus the upstream retry knobs.
8
+ *
9
+ * @see WithoutUpstreamRetry — Why they are withheld.
10
+ */
11
+ export type TcpTransportOpenOptions = WithoutUpstreamRetry<TcpTransportOptions>;
4
12
  declare const TcpTransportService_base: Effect.Service.Class<TcpTransportService, "TcpTransportService", {
5
- readonly scoped: (options: TcpTransportOptions) => Effect.Effect<{
6
- withClient: (unitId: number) => Effect.Effect<import("./modbus-client").EffectModbusClient, import("./errors").ModbusError, never>;
13
+ readonly scoped: (options: TcpTransportOpenOptions & TransportResilienceOptions) => Effect.Effect<{
14
+ connectionState: import("effect/SubscriptionRef").SubscriptionRef<{
15
+ readonly _tag: "Connected";
16
+ } | {
17
+ readonly _tag: "Disconnected";
18
+ } | {
19
+ readonly _tag: "Down";
20
+ readonly cause: import("./errors").ModbusError;
21
+ } | {
22
+ readonly _tag: "Reconnecting";
23
+ readonly attempt: number;
24
+ }>;
25
+ withClient: (unitId: number, clientOptions?: {
26
+ readonly retry?: import("./retry").ModbusRetryPolicy;
27
+ } | undefined) => Effect.Effect<import("./modbus-client").EffectModbusClient, import("./errors").ModbusError, never>;
7
28
  setRequestTimeout: (timeoutMs: number) => Effect.Effect<undefined, import("./errors").ModbusNotConnectedError, never>;
8
29
  clearRequestTimeout: () => Effect.Effect<undefined, import("./errors").ModbusNotConnectedError, never>;
9
30
  reconnect: () => Effect.Effect<undefined, import("./errors").ModbusError, never>;
@@ -24,7 +45,7 @@ declare const TcpTransportService_base: Effect.Service.Class<TcpTransportService
24
45
  * requests for the same unit ID reuse the same client.
25
46
  *
26
47
  * @see AsyncTcpTransport — Upstream `modbus-rs` TCP transport.
27
- * @see TcpTransportOptions — Configuration for the TCP connection.
48
+ * @see TcpTransportOpenOptions — Configuration for the TCP connection.
28
49
  * @see makeTransportScoped — Generic lifecycle logic from shared-transport.
29
50
  */
30
51
  export declare class TcpTransportService extends TcpTransportService_base {
@@ -36,11 +57,11 @@ export declare class TcpTransportService extends TcpTransportService_base {
36
57
  * simulated Modbus slaves and their register/coil maps.
37
58
  *
38
59
  * @param devices - Slave device definitions for the mock.
39
- * @returns A function that takes {@link TcpTransportOptions} and
60
+ * @returns A function that takes {@link TcpTransportOpenOptions} and
40
61
  * returns a scoped {@link Layer} providing the mock service.
41
62
  *
42
63
  * @see makeMockTransport — The underlying mock factory.
43
64
  */
44
- static makeMockTransport: (devices: SlaveDeviceDefinitions) => (options: TcpTransportOptions) => Layer.Layer<TcpTransportService, never, never>;
65
+ static makeMockTransport: (devices: SlaveDeviceDefinitions) => (options: TcpTransportOpenOptions & TransportResilienceOptions & MockFaultOptions) => Layer.Layer<TcpTransportService, never, never>;
45
66
  }
46
67
  export {};
@@ -0,0 +1,73 @@
1
+ import { Effect, Layer } from 'effect';
2
+ import type { WasmSerialPortHandle, WasmSerialTransportOptions } from 'modbus-rs/web';
3
+ import { SlaveDeviceDefinitions } from './mocks';
4
+ import type { MockFaultOptions } from './mocks';
5
+ import type { TransportResilienceOptions } from './shared-transport';
6
+ /**
7
+ * Options for {@link WasmAsciiTransportService}. `WasmAsciiTransport.open()` takes the
8
+ * serial port handle and the connection options as two separate arguments; this
9
+ * combines them into one object so it fits {@link makeTransportScoped}'s single-options
10
+ * shape, with `port` destructured back out inside the service's `openMethod`.
11
+ *
12
+ * @see requestSerialPort — Obtains the `port` handle (must be called from a user gesture).
13
+ */
14
+ export type WasmAsciiTransportOpenOptions = WasmSerialTransportOptions & {
15
+ port: WasmSerialPortHandle;
16
+ };
17
+ declare const WasmAsciiTransportService_base: Effect.Service.Class<WasmAsciiTransportService, "WasmAsciiTransportService", {
18
+ readonly scoped: (options: WasmSerialTransportOptions & {
19
+ port: WasmSerialPortHandle;
20
+ } & TransportResilienceOptions) => Effect.Effect<{
21
+ connectionState: import("effect/SubscriptionRef").SubscriptionRef<{
22
+ readonly _tag: "Connected";
23
+ } | {
24
+ readonly _tag: "Disconnected";
25
+ } | {
26
+ readonly _tag: "Down";
27
+ readonly cause: import("./errors").ModbusError;
28
+ } | {
29
+ readonly _tag: "Reconnecting";
30
+ readonly attempt: number;
31
+ }>;
32
+ withClient: (unitId: number, clientOptions?: {
33
+ readonly retry?: import("./retry").ModbusRetryPolicy;
34
+ } | undefined) => Effect.Effect<import("./modbus-client").EffectModbusClient, import("./errors").ModbusError, never>;
35
+ setRequestTimeout: (timeoutMs: number) => Effect.Effect<undefined, import("./errors").ModbusNotConnectedError, never>;
36
+ clearRequestTimeout: () => Effect.Effect<undefined, import("./errors").ModbusNotConnectedError, never>;
37
+ reconnect: () => Effect.Effect<undefined, import("./errors").ModbusError, never>;
38
+ close: () => Effect.Effect<void, import("./errors").ModbusError, import("effect/Scope").Scope>;
39
+ hasPendingRequests: () => boolean;
40
+ }, never, import("effect/Scope").Scope>;
41
+ }>;
42
+ /**
43
+ * Scoped Effect service wrapping `modbus-rs`'s browser {@link WasmAsciiTransport}
44
+ * for Modbus ASCII over the Web Serial API.
45
+ *
46
+ * The transport connection is opened lazily on the first call to
47
+ * `withClient(unitId)` and automatically closed when the consuming
48
+ * {@link Effect.Scope | Scope} finalizes.
49
+ *
50
+ * Clients are created per `unitId` via {@link WasmAsciiTransport.createClient} and
51
+ * cached, so repeated requests for the same unit ID reuse the same client.
52
+ *
53
+ * @see WasmAsciiTransport — Upstream `modbus-rs` browser Web Serial ASCII transport.
54
+ * @see requestSerialPort — Obtains the serial port handle this service's `port` option needs.
55
+ * @see makeTransportScoped — Generic lifecycle logic from shared-transport.
56
+ */
57
+ export declare class WasmAsciiTransportService extends WasmAsciiTransportService_base {
58
+ /**
59
+ * Creates a {@link Layer} providing an in-memory mock
60
+ * {@link WasmAsciiTransportService} for testing or development.
61
+ *
62
+ * Accepts an array of {@link SlaveDeviceDefinition} describing the
63
+ * simulated Modbus slaves and their register/coil maps.
64
+ *
65
+ * @param devices - Slave device definitions for the mock.
66
+ * @returns A function that takes {@link WasmAsciiTransportOpenOptions} and
67
+ * returns a scoped {@link Layer} providing the mock service.
68
+ *
69
+ * @see makeMockTransport — The underlying mock factory.
70
+ */
71
+ static makeMockTransport: (devices: SlaveDeviceDefinitions) => (options: WasmAsciiTransportOpenOptions & TransportResilienceOptions & MockFaultOptions) => Layer.Layer<WasmAsciiTransportService, never, never>;
72
+ }
73
+ export {};
@@ -0,0 +1,73 @@
1
+ import { Effect, Layer } from 'effect';
2
+ import type { WasmSerialPortHandle, WasmSerialTransportOptions } from 'modbus-rs/web';
3
+ import { SlaveDeviceDefinitions } from './mocks';
4
+ import type { MockFaultOptions } from './mocks';
5
+ import type { TransportResilienceOptions } from './shared-transport';
6
+ /**
7
+ * Options for {@link WasmRtuTransportService}. `WasmRtuTransport.open()` takes the
8
+ * serial port handle and the connection options as two separate arguments; this
9
+ * combines them into one object so it fits {@link makeTransportScoped}'s single-options
10
+ * shape, with `port` destructured back out inside the service's `openMethod`.
11
+ *
12
+ * @see requestSerialPort — Obtains the `port` handle (must be called from a user gesture).
13
+ */
14
+ export type WasmRtuTransportOpenOptions = WasmSerialTransportOptions & {
15
+ port: WasmSerialPortHandle;
16
+ };
17
+ declare const WasmRtuTransportService_base: Effect.Service.Class<WasmRtuTransportService, "WasmRtuTransportService", {
18
+ readonly scoped: (options: WasmSerialTransportOptions & {
19
+ port: WasmSerialPortHandle;
20
+ } & TransportResilienceOptions) => Effect.Effect<{
21
+ connectionState: import("effect/SubscriptionRef").SubscriptionRef<{
22
+ readonly _tag: "Connected";
23
+ } | {
24
+ readonly _tag: "Disconnected";
25
+ } | {
26
+ readonly _tag: "Down";
27
+ readonly cause: import("./errors").ModbusError;
28
+ } | {
29
+ readonly _tag: "Reconnecting";
30
+ readonly attempt: number;
31
+ }>;
32
+ withClient: (unitId: number, clientOptions?: {
33
+ readonly retry?: import("./retry").ModbusRetryPolicy;
34
+ } | undefined) => Effect.Effect<import("./modbus-client").EffectModbusClient, import("./errors").ModbusError, never>;
35
+ setRequestTimeout: (timeoutMs: number) => Effect.Effect<undefined, import("./errors").ModbusNotConnectedError, never>;
36
+ clearRequestTimeout: () => Effect.Effect<undefined, import("./errors").ModbusNotConnectedError, never>;
37
+ reconnect: () => Effect.Effect<undefined, import("./errors").ModbusError, never>;
38
+ close: () => Effect.Effect<void, import("./errors").ModbusError, import("effect/Scope").Scope>;
39
+ hasPendingRequests: () => boolean;
40
+ }, never, import("effect/Scope").Scope>;
41
+ }>;
42
+ /**
43
+ * Scoped Effect service wrapping `modbus-rs`'s browser {@link WasmRtuTransport}
44
+ * for Modbus RTU over the Web Serial API.
45
+ *
46
+ * The transport connection is opened lazily on the first call to
47
+ * `withClient(unitId)` and automatically closed when the consuming
48
+ * {@link Effect.Scope | Scope} finalizes.
49
+ *
50
+ * Clients are created per `unitId` via {@link WasmRtuTransport.createClient} and
51
+ * cached, so repeated requests for the same unit ID reuse the same client.
52
+ *
53
+ * @see WasmRtuTransport — Upstream `modbus-rs` browser Web Serial RTU transport.
54
+ * @see requestSerialPort — Obtains the serial port handle this service's `port` option needs.
55
+ * @see makeTransportScoped — Generic lifecycle logic from shared-transport.
56
+ */
57
+ export declare class WasmRtuTransportService extends WasmRtuTransportService_base {
58
+ /**
59
+ * Creates a {@link Layer} providing an in-memory mock
60
+ * {@link WasmRtuTransportService} for testing or development.
61
+ *
62
+ * Accepts an array of {@link SlaveDeviceDefinition} describing the
63
+ * simulated Modbus slaves and their register/coil maps.
64
+ *
65
+ * @param devices - Slave device definitions for the mock.
66
+ * @returns A function that takes {@link WasmRtuTransportOpenOptions} and
67
+ * returns a scoped {@link Layer} providing the mock service.
68
+ *
69
+ * @see makeMockTransport — The underlying mock factory.
70
+ */
71
+ static makeMockTransport: (devices: SlaveDeviceDefinitions) => (options: WasmRtuTransportOpenOptions & TransportResilienceOptions & MockFaultOptions) => Layer.Layer<WasmRtuTransportService, never, never>;
72
+ }
73
+ export {};
@@ -0,0 +1,54 @@
1
+ import { Layer } from 'effect';
2
+ import type { ServerHandlers } from 'modbus-rs';
3
+ import type { WasmSerialServerOptions } from 'modbus-rs/web';
4
+ import type { ModbusError } from './errors';
5
+ /**
6
+ * A scoped {@link Layer} that starts a browser Modbus RTU server over the Web
7
+ * Serial API (experimental upstream surface).
8
+ *
9
+ * `options.serialPort` is the raw `SerialPort` object obtained from the
10
+ * consumer's own app code via `navigator.serial.requestPort()` (which has the
11
+ * `dom` lib types available) — **not** this package's {@link requestSerialPort}
12
+ * helper, which returns the `WasmSerialPortHandle` wrapper used only by the
13
+ * client-side transports (`WasmRtuTransportService`/`WasmAsciiTransportService`).
14
+ *
15
+ * Like {@link wasmWsServerLayer}, the WASM server requires a continuously-awaited
16
+ * `serve()` call to drive its request loop; this layer forks that call into the
17
+ * scope automatically so the returned `Layer` "just works".
18
+ *
19
+ * @param options - Serial port, baud rate, unit ID, etc.
20
+ * @param handlers - Callback functions that handle incoming Modbus requests
21
+ * (same {@link ServerHandlers} shape as the native TCP/serial servers).
22
+ * @returns A `Layer` that fails with {@link ModbusError} on bind failure.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { Effect, Layer } from "effect";
27
+ * import { wasmSerialRtuServerLayer } from "@flux-control/effect-modbus-rs";
28
+ *
29
+ * const port = await navigator.serial.requestPort(); // user-gesture gated
30
+ * const ServerLive = wasmSerialRtuServerLayer(
31
+ * { serialPort: port, unitId: 1, baudRate: 19200 },
32
+ * { onReadCoils: (req) => [false, false] },
33
+ * );
34
+ *
35
+ * Layer.launch(ServerLive).pipe(Effect.runPromise);
36
+ * ```
37
+ *
38
+ * @see WasmSerialServerOptions — Options accepted by the upstream WASM serial server.
39
+ * @see ServerHandlers — Interface for request handler callbacks.
40
+ */
41
+ export declare const wasmSerialRtuServerLayer: (options: WasmSerialServerOptions, handlers: ServerHandlers) => Layer.Layer<never, ModbusError>;
42
+ /**
43
+ * A scoped {@link Layer} that starts a browser Modbus ASCII server over the Web
44
+ * Serial API. See {@link wasmSerialRtuServerLayer} for shared details (the
45
+ * `serialPort` source, and the `serve()`-forking behavior).
46
+ *
47
+ * @param options - Serial port, baud rate, unit ID, etc.
48
+ * @param handlers - Callback functions that handle incoming Modbus requests.
49
+ * @returns A `Layer` that fails with {@link ModbusError} on bind failure.
50
+ *
51
+ * @see WasmSerialServerOptions — Options accepted by the upstream WASM serial server.
52
+ * @see ServerHandlers — Interface for request handler callbacks.
53
+ */
54
+ export declare const wasmSerialAsciiServerLayer: (options: WasmSerialServerOptions, handlers: ServerHandlers) => Layer.Layer<never, ModbusError>;
@@ -0,0 +1,27 @@
1
+ import { Effect } from 'effect';
2
+ import type { WasmSerialPortHandle } from 'modbus-rs/web';
3
+ import type { ModbusError } from './errors';
4
+ /**
5
+ * Requests a browser serial port handle via the Web Serial API, for use with
6
+ * {@link WasmSerialTransportService.fromRtu} / `.fromAscii` (or
7
+ * `WasmRtuTransportService.Default` / `WasmAsciiTransportService.Default` directly).
8
+ *
9
+ * **Must be called synchronously from within a user-gesture event handler**
10
+ * (e.g. a `click` listener) — this is a hard Web Serial API / browser security
11
+ * constraint (`navigator.serial.requestPort()` semantics), not a library-imposed
12
+ * restriction. Calling it outside a gesture will reject.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * button.addEventListener("click", () => {
17
+ * Effect.runPromise(
18
+ * requestSerialPort().pipe(
19
+ * Effect.flatMap((port) => Effect.provide(program, WasmRtuTransportService.Default({ port, baudRate: 19200 }))),
20
+ * ),
21
+ * );
22
+ * });
23
+ * ```
24
+ *
25
+ * @see WasmSerialPortHandle — Opaque handle returned by `modbus-rs`'s WASM bindings.
26
+ */
27
+ export declare const requestSerialPort: () => Effect.Effect<WasmSerialPortHandle, ModbusError>;
@@ -0,0 +1,48 @@
1
+ import { Context, Layer } from 'effect';
2
+ import { type SlaveDeviceDefinitions } from './mocks';
3
+ import type { TransportServiceApi } from './shared-transport';
4
+ import { type WasmAsciiTransportOpenOptions } from './WasmAsciiTransportService';
5
+ import { type WasmRtuTransportOpenOptions } from './WasmRtuTransportService';
6
+ declare const WasmSerialTransportService_base: Context.TagClass<WasmSerialTransportService, "WasmSerialTransportService", TransportServiceApi>;
7
+ /**
8
+ * Abstract browser (WASM) serial Modbus transport service tag.
9
+ *
10
+ * Represents a Web Serial-based Modbus transport backed by either ASCII or RTU
11
+ * framing. Use this tag when you need a browser serial transport but don't care
12
+ * about the specific framing protocol.
13
+ *
14
+ * Consumers `yield* WasmSerialTransportService` to obtain a
15
+ * {@link TransportServiceApi} and satisfy the tag via one of the static
16
+ * provider methods:
17
+ *
18
+ * ```ts
19
+ * // Provide with ASCII framing
20
+ * Layer.provide(WasmSerialTransportService.fromAscii({ port, baudRate: 9600 }))
21
+ *
22
+ * // Provide with RTU framing
23
+ * Layer.provide(WasmSerialTransportService.fromRtu({ port, baudRate: 9600 }))
24
+ * ```
25
+ *
26
+ * @see requestSerialPort — Obtains the `port` handle both providers need (must be called from a user gesture).
27
+ */
28
+ export declare class WasmSerialTransportService extends WasmSerialTransportService_base {
29
+ /**
30
+ * Creates a {@link Layer} providing {@link WasmSerialTransportService}
31
+ * backed by an ASCII transport.
32
+ */
33
+ static fromAscii(options: WasmAsciiTransportOpenOptions): Layer.Layer<WasmSerialTransportService>;
34
+ /**
35
+ * Creates a {@link Layer} providing {@link WasmSerialTransportService}
36
+ * backed by an RTU transport.
37
+ */
38
+ static fromRtu(options: WasmRtuTransportOpenOptions): Layer.Layer<WasmSerialTransportService>;
39
+ /**
40
+ * Creates a mock {@link Layer} providing {@link WasmSerialTransportService}
41
+ * for testing or development.
42
+ *
43
+ * Accepts an array of {@link SlaveDeviceDefinition} describing the
44
+ * simulated Modbus slaves and their register/coil maps.
45
+ */
46
+ static makeMockTransport: (devices: SlaveDeviceDefinitions) => (options: WasmAsciiTransportOpenOptions | WasmRtuTransportOpenOptions) => Layer.Layer<WasmSerialTransportService>;
47
+ }
48
+ export {};
@@ -0,0 +1,38 @@
1
+ import { Layer } from 'effect';
2
+ import type { ServerHandlers } from 'modbus-rs';
3
+ import type { WasmTcpServerOptions } from 'modbus-rs/web';
4
+ import type { ModbusError } from './errors';
5
+ /**
6
+ * A scoped {@link Layer} that starts a browser Modbus server proxied over a
7
+ * WebSocket gateway (experimental upstream surface — browsers can't accept raw
8
+ * TCP connections, so this binds via `modbus-gateway` or an equivalent WS-to-TCP
9
+ * proxy).
10
+ *
11
+ * Unlike the native {@link tcpServerLayer}, the WASM server does not start
12
+ * serving on `bind()` — it requires an explicit, continuously-awaited `serve()`
13
+ * call to drive its request loop. This layer forks that call into the scope in
14
+ * the background so the returned `Layer` behaves the same as the native one
15
+ * from the consumer's perspective (no extra step needed).
16
+ *
17
+ * @param options - WebSocket gateway URL and unit ID.
18
+ * @param handlers - Callback functions that handle incoming Modbus requests
19
+ * (same {@link ServerHandlers} shape as the native TCP/serial servers).
20
+ * @returns A `Layer` that fails with {@link ModbusError} on bind failure.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import { Effect, Layer } from "effect";
25
+ * import { wasmWsServerLayer } from "@flux-control/effect-modbus-rs";
26
+ *
27
+ * const ServerLive = wasmWsServerLayer(
28
+ * { wsUrl: "ws://localhost:8080", unitId: 1 },
29
+ * { onReadCoils: (req) => [false, false] },
30
+ * );
31
+ *
32
+ * Layer.launch(ServerLive).pipe(Effect.runPromise);
33
+ * ```
34
+ *
35
+ * @see WasmTcpServerOptions — Options accepted by the upstream WASM WS server.
36
+ * @see ServerHandlers — Interface for request handler callbacks.
37
+ */
38
+ export declare const wasmWsServerLayer: (options: WasmTcpServerOptions, handlers: ServerHandlers) => Layer.Layer<never, ModbusError>;