@evops/lightwaverf 1.0.4 → 1.0.5

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.
@@ -0,0 +1,39 @@
1
+ import { Debugger } from "debug";
2
+ export interface QueuedTransaction {
3
+ id: number;
4
+ originalMessage: string;
5
+ message: string;
6
+ resolve: (value: TransactionResponse) => void;
7
+ reject: (error: Error) => void;
8
+ timeoutId?: ReturnType<typeof setTimeout>;
9
+ retryTimeoutId?: ReturnType<typeof setTimeout>;
10
+ delay: number;
11
+ completed: boolean;
12
+ }
13
+ export interface TransactionResponse {
14
+ id: number;
15
+ [key: string]: unknown;
16
+ }
17
+ export interface LightwaveCommandQueueOptions {
18
+ debug: Debugger;
19
+ delay?: number;
20
+ timeout?: number;
21
+ onExecute: (message: string) => void;
22
+ }
23
+ export declare class LightwaveCommandQueue {
24
+ private queue;
25
+ private transactions;
26
+ private busy;
27
+ private debug;
28
+ private delay;
29
+ private timeout;
30
+ private onExecute;
31
+ constructor(options: LightwaveCommandQueueOptions);
32
+ send(message: string | Buffer): Promise<TransactionResponse>;
33
+ handleResponse(response: TransactionResponse): void;
34
+ handleRetryableError(transactionId: number): void;
35
+ destroy(): void;
36
+ private processQueue;
37
+ private completeTransaction;
38
+ private failTransaction;
39
+ }
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LightwaveCommandQueue = void 0;
4
+ class LightwaveCommandQueue {
5
+ queue = [];
6
+ transactions = new Map();
7
+ busy = false;
8
+ debug;
9
+ delay;
10
+ timeout;
11
+ onExecute;
12
+ constructor(options) {
13
+ this.debug = options.debug.extend("queue");
14
+ this.delay = options.delay ?? 800;
15
+ this.timeout = options.timeout ?? 10000;
16
+ this.onExecute = options.onExecute;
17
+ }
18
+ send(message) {
19
+ const transactionId = Math.round(Math.random() * Math.pow(10, 8));
20
+ const messageStr = typeof message === "string" ? message : message.toString("utf-8");
21
+ const messageWithTransaction = `${transactionId},${messageStr}`;
22
+ this.debug("[%d] Queueing message: %s", Date.now(), messageWithTransaction);
23
+ const { promise, resolve, reject } = Promise.withResolvers();
24
+ const transaction = {
25
+ id: transactionId,
26
+ originalMessage: messageStr,
27
+ message: messageWithTransaction,
28
+ resolve,
29
+ reject,
30
+ delay: this.delay,
31
+ completed: false,
32
+ };
33
+ this.queue.push(transaction);
34
+ this.transactions.set(transactionId, transaction);
35
+ this.processQueue();
36
+ return promise;
37
+ }
38
+ handleResponse(response) {
39
+ const transaction = this.transactions.get(response.id);
40
+ if (!transaction || transaction.completed) {
41
+ this.debug("No pending transaction found for id %d or already completed", response.id);
42
+ return;
43
+ }
44
+ this.debug("[%d] Transaction %d completed", Date.now(), response.id);
45
+ this.completeTransaction(transaction, response);
46
+ }
47
+ handleRetryableError(transactionId) {
48
+ const transaction = this.transactions.get(transactionId);
49
+ if (!transaction || transaction.completed) {
50
+ return;
51
+ }
52
+ // Clear existing timeout
53
+ if (transaction.timeoutId) {
54
+ clearTimeout(transaction.timeoutId);
55
+ transaction.timeoutId = undefined;
56
+ }
57
+ // Exponential backoff, max 10 seconds
58
+ transaction.delay = Math.min(transaction.delay * 2, 10000);
59
+ const retryMessage = `${transactionId},${transaction.originalMessage}`;
60
+ this.debug("Message errored, retrying: %s with delay: %d", retryMessage, transaction.delay);
61
+ // Set timeout for retry
62
+ transaction.timeoutId = setTimeout(() => {
63
+ if (transaction.completed)
64
+ return;
65
+ this.debug("Retry timeout expired for transaction %d", transactionId);
66
+ this.failTransaction(transaction, new Error(`Retry timeout expired ${transactionId}`));
67
+ }, 5000 + transaction.delay * 2);
68
+ // Schedule retry
69
+ transaction.retryTimeoutId = setTimeout(() => {
70
+ if (transaction.completed)
71
+ return;
72
+ this.onExecute(retryMessage);
73
+ }, Math.round(transaction.delay * 2));
74
+ }
75
+ destroy() {
76
+ for (const transaction of this.transactions.values()) {
77
+ if (transaction.timeoutId) {
78
+ clearTimeout(transaction.timeoutId);
79
+ }
80
+ if (transaction.retryTimeoutId) {
81
+ clearTimeout(transaction.retryTimeoutId);
82
+ }
83
+ if (!transaction.completed) {
84
+ transaction.reject(new Error("Queue destroyed"));
85
+ transaction.completed = true;
86
+ }
87
+ }
88
+ this.transactions.clear();
89
+ this.queue = [];
90
+ this.busy = false;
91
+ }
92
+ processQueue() {
93
+ if (this.busy) {
94
+ this.debug("Queue is busy, waiting to process");
95
+ return;
96
+ }
97
+ const transaction = this.queue.shift();
98
+ if (!transaction) {
99
+ return;
100
+ }
101
+ this.debug("Processing transaction: %d", transaction.id);
102
+ this.busy = true;
103
+ // Set timeout for response
104
+ transaction.timeoutId = setTimeout(() => {
105
+ if (transaction.completed)
106
+ return;
107
+ this.debug("Transaction %d timed out", transaction.id);
108
+ this.failTransaction(transaction, new Error(`Execution expired ${transaction.id}`));
109
+ }, this.timeout);
110
+ this.onExecute(transaction.message);
111
+ }
112
+ completeTransaction(transaction, response) {
113
+ if (transaction.completed)
114
+ return;
115
+ transaction.completed = true;
116
+ if (transaction.timeoutId) {
117
+ clearTimeout(transaction.timeoutId);
118
+ }
119
+ if (transaction.retryTimeoutId) {
120
+ clearTimeout(transaction.retryTimeoutId);
121
+ }
122
+ this.transactions.delete(transaction.id);
123
+ transaction.resolve(response);
124
+ this.debug("Transaction %d completed, scheduling next in %dms", transaction.id, this.delay);
125
+ setTimeout(() => {
126
+ this.busy = false;
127
+ this.processQueue();
128
+ }, this.delay);
129
+ }
130
+ failTransaction(transaction, error) {
131
+ if (transaction.completed)
132
+ return;
133
+ transaction.completed = true;
134
+ if (transaction.timeoutId) {
135
+ clearTimeout(transaction.timeoutId);
136
+ }
137
+ if (transaction.retryTimeoutId) {
138
+ clearTimeout(transaction.retryTimeoutId);
139
+ }
140
+ this.transactions.delete(transaction.id);
141
+ transaction.reject(error);
142
+ this.busy = false;
143
+ this.processQueue();
144
+ }
145
+ }
146
+ exports.LightwaveCommandQueue = LightwaveCommandQueue;
@@ -1,6 +1,6 @@
1
1
  import { Debugger } from "debug";
2
2
  import events from "events";
3
- import { LightwaveTransaction } from "./LightwaveTransaction";
3
+ import { TransactionResponse } from "./LightwaveCommandQueue";
4
4
  declare interface LightwaveRFClientInterface {
5
5
  on(event: "ready", listener: (client: LightwaveRFClient) => void): this;
6
6
  on(event: "deviceTurnedOn", listener: (room: number, device: number) => void): this;
@@ -15,7 +15,6 @@ export declare class LightwaveRFClient extends events.EventEmitter implements Li
15
15
  private commandQueue;
16
16
  private messageProcessors;
17
17
  private debug;
18
- private transactionListeners;
19
18
  delay: number;
20
19
  serial?: string;
21
20
  mac?: string;
@@ -29,8 +28,7 @@ export declare class LightwaveRFClient extends events.EventEmitter implements Li
29
28
  connect(): Promise<void>;
30
29
  disconnect(): Promise<[void, void]>;
31
30
  private checkRegistration;
32
- send(message: string | Buffer, callback?: (transaction: LightwaveTransaction | null, error: Error) => void): void;
33
- private processSendQueue;
31
+ send(message: string | Buffer): Promise<TransactionResponse>;
34
32
  private exec;
35
33
  private processRawMessage;
36
34
  private processLightwaveMessage;
@@ -6,19 +6,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.LightwaveRFClient = void 0;
7
7
  const dgram_1 = __importDefault(require("dgram"));
8
8
  const events_1 = __importDefault(require("events"));
9
+ const LightwaveCommandQueue_1 = require("./LightwaveCommandQueue");
9
10
  const LightwaveMessageProcessorForJson_1 = require("./LightwaveMessageProcessorForJson");
10
11
  const LightwaveMessageProcessorForText_1 = __importDefault(require("./LightwaveMessageProcessorForText"));
11
- const Queue_1 = require("./Queue");
12
12
  const LIGHTWAVE_LINK_SEND_PORT = 9760;
13
13
  const LIGHTWAVE_LINK_RECEIVE_PORT = 9761;
14
14
  class LightwaveRFClient extends events_1.default.EventEmitter {
15
15
  ip;
16
16
  senderSocket;
17
17
  receiverSocket;
18
- commandQueue = new Queue_1.Queue();
18
+ commandQueue;
19
19
  messageProcessors = [];
20
20
  debug;
21
- transactionListeners = new Map();
22
21
  delay = 800;
23
22
  serial;
24
23
  mac;
@@ -35,6 +34,11 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
35
34
  this.senderSocket.unref();
36
35
  this.receiverSocket = dgram_1.default.createSocket("udp4");
37
36
  this.receiverSocket.unref();
37
+ this.commandQueue = new LightwaveCommandQueue_1.LightwaveCommandQueue({
38
+ debug: this.debug,
39
+ delay: this.delay,
40
+ onExecute: (message) => this.exec(message),
41
+ });
38
42
  this.messageProcessors.push(new LightwaveMessageProcessorForJson_1.LightwaveMessageProcessorForJson(this.debug));
39
43
  this.messageProcessors.push(new LightwaveMessageProcessorForText_1.default(this.debug));
40
44
  }
@@ -63,74 +67,26 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
63
67
  async disconnect() {
64
68
  this.receiverSocket.removeAllListeners();
65
69
  this.senderSocket.removeAllListeners();
70
+ this.commandQueue.destroy();
66
71
  const { promise: senderPromise, resolve: senderResolve } = Promise.withResolvers();
67
72
  const { promise: receiverPromise, resolve: receiverResolve } = Promise.withResolvers();
68
73
  this.senderSocket.close(senderResolve);
69
74
  this.receiverSocket.close(receiverResolve);
70
75
  return Promise.all([senderPromise, receiverPromise]);
71
76
  }
72
- checkRegistration() {
77
+ async checkRegistration() {
73
78
  this.debug("Checking registration");
74
- this.send("@H", (transaction, error) => {
75
- if (error) {
76
- this.debug("Error: %o", error);
77
- }
79
+ try {
80
+ const transaction = await this.send("@H");
78
81
  this.debug(transaction);
79
- this.emit("ready", this);
80
- });
81
- }
82
- send(message, callback) {
83
- const transactionId = Math.round(Math.random() * Math.pow(10, 8));
84
- const messageWithTransaction = `${transactionId},${message}`;
85
- const transactionDebug = this.debug.extend("tx:" + transactionId);
86
- this.transactionListeners.set(transactionId, {
87
- message: message,
88
- debug: transactionDebug,
89
- delay: this.delay,
90
- callback: callback,
91
- });
92
- this.debug("[%d] Queueing message: %s", Date.now(), messageWithTransaction);
93
- this.commandQueue.add({
94
- id: transactionId,
95
- message: messageWithTransaction,
96
- debug: transactionDebug,
97
- callback,
98
- });
99
- this.processSendQueue();
100
- }
101
- async processSendQueue() {
102
- if (this.commandQueue.busy) {
103
- this.debug(`The queue is busy, will wait to process`);
104
- return;
105
82
  }
106
- const command = this.commandQueue.next();
107
- if (!command)
108
- return;
109
- this.debug(`Processing command: %o`, { command });
110
- this.commandQueue.busy = true;
111
- const transactionListener = this.transactionListeners.get(command.id);
112
- const originalCallback = transactionListener.callback;
113
- transactionListener.callback = (transaction, error) => {
114
- originalCallback?.(transaction, error);
115
- this.debug("Transaction %d completed, scheduling next processing in %dms !!!!!!!!!!", transaction.id, this.delay);
116
- setTimeout(() => {
117
- this.commandQueue.busy = false;
118
- this.processSendQueue();
119
- }, this.delay);
120
- };
121
- // If we didn't hear back within the timeout
122
- setTimeout(() => {
123
- const listener = this.transactionListeners.get(command.id);
124
- if (!listener)
125
- return;
126
- originalCallback?.(null, new Error("Execution expired " + command.id));
127
- this.commandQueue.busy = false;
128
- this.transactionListeners.delete(command.id);
129
- this.processSendQueue();
130
- }, 5000);
131
- const transactionDebug = this.debug.extend(`transaction:${command?.id}`);
132
- transactionDebug("Starting new transaction");
133
- this.exec(command.message);
83
+ catch (error) {
84
+ this.debug("Error: %o", error);
85
+ }
86
+ this.emit("ready", this);
87
+ }
88
+ send(message) {
89
+ return this.commandQueue.send(message);
134
90
  }
135
91
  exec(message) {
136
92
  if (message === undefined)
@@ -174,6 +130,7 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
174
130
  this.uptime = lightwaveMessage.uptime;
175
131
  }
176
132
  if (this.discoverLinkIp) {
133
+ this.debug(`Updating link ip to ${remoteInfo.address}`);
177
134
  this.ip = remoteInfo.address;
178
135
  }
179
136
  if (lightwaveMessage.fw) {
@@ -196,28 +153,14 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
196
153
  if (lightwaveMessage.fn === "dim") {
197
154
  this.emit("deviceDimmed", lightwaveMessage.room, lightwaveMessage.dev, Math.round((lightwaveMessage.param / 32) * 100));
198
155
  }
199
- const listener = this.transactionListeners.get(lightwaveMessage.id);
200
- if (!listener)
201
- return;
156
+ // Handle retryable errors (ERR,6 = device busy)
202
157
  if (lightwaveMessage.error?.match(/^ERR,6,/)) {
203
- // Storing delay on a message level provides the ability to implement
204
- // exponential backoff, here the maximum is 10 seconds
205
- listener.delay = Math.min(listener.delay * 2, 10000);
206
- const msg = `${lightwaveMessage.id},${listener.message}`;
207
- this.debug("message errorred, retrying: %o, %o with delay: %o", msg, listener, listener.delay);
208
- setTimeout(() => {
209
- this.exec(msg);
210
- }, Math.round(listener.delay * 2));
158
+ this.commandQueue.handleRetryableError(lightwaveMessage.id);
211
159
  return;
212
160
  }
213
- if (listener) {
214
- listener.debug("Found transaction listener");
215
- listener.debug("[%d] Transaction completed, removing listener", Date.now());
216
- this.transactionListeners.delete(lightwaveMessage.id);
217
- listener.callback(lightwaveMessage, null);
218
- }
219
- else {
220
- this.debug("Listener not found for message: %o", lightwaveMessage);
161
+ // Pass successful response to the queue
162
+ if (lightwaveMessage.id !== undefined) {
163
+ this.commandQueue.handleResponse(lightwaveMessage);
221
164
  }
222
165
  }
223
166
  }
package/.dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ declare class LightwaveRFConfiguration {
13
13
  email?: any;
14
14
  pin?: any;
15
15
  linkDisplayUpdates?: boolean;
16
+ discoverLinkIp?: boolean;
16
17
  }
17
18
  declare interface ILightwaveRF {
18
19
  on(event: "deviceTurnedOn", listener: (roomId: number, deviceId: number) => void): this;
@@ -44,7 +45,7 @@ export default class LightwaveRF extends EventEmitter<LightwaveEvents> implement
44
45
  lwAccount: LightwaveAccount;
45
46
  debug: debug.Debugger;
46
47
  private linkDisplayUpdates;
47
- constructor({ email, pin, ip, timeout, linkDisplayUpdates, }: LightwaveRFConfiguration);
48
+ constructor({ email, pin, ip, timeout, linkDisplayUpdates, discoverLinkIp, }: LightwaveRFConfiguration);
48
49
  get serial(): string | undefined;
49
50
  get mac(): string | undefined;
50
51
  get uptime(): number | undefined;
package/.dist/index.js CHANGED
@@ -18,6 +18,7 @@ class LightwaveRFConfiguration {
18
18
  email;
19
19
  pin;
20
20
  linkDisplayUpdates;
21
+ discoverLinkIp;
21
22
  }
22
23
  /** * LightwaveRF API
23
24
  *
@@ -39,13 +40,15 @@ class LightwaveRF extends events_1.EventEmitter {
39
40
  lwAccount;
40
41
  debug;
41
42
  linkDisplayUpdates;
42
- constructor({ email, pin, ip, timeout, linkDisplayUpdates = true, }) {
43
+ constructor({ email, pin, ip, timeout, linkDisplayUpdates = true, discoverLinkIp = true, }) {
43
44
  super();
44
45
  this.setMaxListeners(255);
45
46
  this.debug = (0, debug_1.default)("lightwave");
46
47
  this.linkDisplayUpdates = linkDisplayUpdates;
47
48
  this.debug("Initialising LightwaveRF Client");
48
- this.lwClient = new LightwaveRFClient_1.LightwaveRFClient(this.debug, ip);
49
+ this.lwClient = new LightwaveRFClient_1.LightwaveRFClient(this.debug, ip, {
50
+ discoverLinkIp,
51
+ });
49
52
  this.lwClient.once("ready", () => {
50
53
  this.debug("LightwaveRF ready");
51
54
  });
@@ -86,63 +89,41 @@ class LightwaveRF extends events_1.EventEmitter {
86
89
  }));
87
90
  }
88
91
  async turnOn({ roomId, deviceId, roomName, deviceName }) {
89
- const { promise, resolve, reject } = Promise.withResolvers();
90
92
  const linkDisplayUpdate = this.linkDisplayUpdates
91
93
  ? `|${roomName} ${deviceName}|Turn on|`
92
94
  : "";
93
- this.lwClient.send(`!F1R${roomId}D${deviceId}${linkDisplayUpdate}`, (_, error) => {
94
- if (error)
95
- return reject(error);
96
- resolve();
97
- });
98
- return promise;
95
+ await this.lwClient.send(`!F1R${roomId}D${deviceId}${linkDisplayUpdate}`);
99
96
  }
100
97
  async turnOff({ roomId, deviceId, roomName, deviceName }) {
101
- const { promise, resolve, reject } = Promise.withResolvers();
102
98
  const linkDisplayUpdate = this.linkDisplayUpdates
103
99
  ? `|${roomName} ${deviceName}|Turn off|`
104
100
  : "";
105
- this.lwClient.send(`!F0R${roomId}D${deviceId}${linkDisplayUpdate}`, (_, error) => {
106
- if (error)
107
- return reject(error);
108
- resolve();
109
- });
110
- return promise;
101
+ await this.lwClient.send(`!F0R${roomId}D${deviceId}${linkDisplayUpdate}`);
111
102
  }
112
103
  async dim({ roomId, deviceId, roomName, deviceName }, percentage) {
113
- const { promise, resolve, reject } = Promise.withResolvers();
114
104
  const lwDim = Math.round(percentage * 0.32);
115
105
  const linkDisplayUpdate = this.linkDisplayUpdates
116
106
  ? `|${roomName} ${deviceName}|Dim to ${percentage}%|`
117
107
  : "";
118
- this.lwClient.send(`!FdP${lwDim}R${roomId}D${deviceId}${linkDisplayUpdate}`, (_, error) => {
119
- if (error)
120
- return reject(error);
121
- resolve();
122
- });
123
- return promise;
108
+ await this.lwClient.send(`!FdP${lwDim}R${roomId}D${deviceId}${linkDisplayUpdate}`);
124
109
  }
125
110
  async connect() {
126
111
  return this.lwClient.connect();
127
112
  }
128
113
  async isRegistered() {
129
- return new Promise((resolve) => {
130
- const user = process.env.USER;
131
- this.lwClient.send(`@H|Check registration|user:${user}|`, (response) => {
132
- return resolve(!response?.error);
133
- });
134
- });
114
+ const user = process.env.USER;
115
+ const response = await this.lwClient.send(`@H|Check registration|user:${user}|`);
116
+ return !response?.error;
135
117
  }
136
118
  async ensureRegistration() {
119
+ const user = process.env.USER;
120
+ const response = await this.lwClient.send(`@H|Check registration|user:${user}|`);
121
+ if (!response?.error) {
122
+ return;
123
+ }
124
+ this.debug("We are not registered with the hub");
125
+ await this.lwClient.send("!F*p");
137
126
  return new Promise((resolve) => {
138
- const user = process.env.USER;
139
- this.lwClient.send(`@H|Check registration|user:${user}|`, (response) => {
140
- if (!response?.error) {
141
- return resolve();
142
- }
143
- this.debug("We are not registered with the hub");
144
- this.lwClient.send("!F*p");
145
- });
146
127
  this.lwClient.on("registered", resolve);
147
128
  });
148
129
  }
@@ -7,6 +7,7 @@ const fetch_vcr_1 = __importDefault(require("fetch-vcr"));
7
7
  const vitest_1 = require("vitest");
8
8
  const _1 = __importDefault(require("."));
9
9
  (0, vitest_1.describe)("LightwaveRF", () => {
10
+ let lw;
10
11
  (0, vitest_1.beforeAll)(() => {
11
12
  fetch_vcr_1.default.configure({
12
13
  fixturePath: __dirname + "/.fixtures",
@@ -14,8 +15,11 @@ const _1 = __importDefault(require("."));
14
15
  });
15
16
  global.fetch = fetch_vcr_1.default;
16
17
  });
18
+ (0, vitest_1.afterEach)(async () => {
19
+ await lw.lwClient.disconnect();
20
+ });
17
21
  (0, vitest_1.it)("should allow device linking", async () => {
18
- const lw = new _1.default({
22
+ lw = new _1.default({
19
23
  email: "some@user.com",
20
24
  pin: "1234",
21
25
  });
@@ -25,7 +29,7 @@ const _1 = __importDefault(require("."));
25
29
  await lw.lwClient.disconnect();
26
30
  });
27
31
  (0, vitest_1.it)("should turn device on", async () => {
28
- const lw = new _1.default({
32
+ lw = new _1.default({
29
33
  email: "some@user.com",
30
34
  pin: "1234",
31
35
  // Disabling link display updates as they cause buffer issues in the link
@@ -36,17 +40,19 @@ const _1 = __importDefault(require("."));
36
40
  await lw.connect();
37
41
  // await lw.ensureRegistration();
38
42
  const devices = await lw.getDevices();
39
- const wallLamps = devices?.find((d) => {
40
- return d.deviceName === "Table lamp";
43
+ const roomToInteractWith = "TV Room";
44
+ const lightToInteractWith = "Lights";
45
+ const light = devices?.find((d) => {
46
+ return (d.roomName === roomToInteractWith &&
47
+ d.deviceName === lightToInteractWith);
41
48
  });
42
- if (!wallLamps) {
43
- throw new Error("Could not find table lamp in the config");
49
+ if (!light) {
50
+ throw new Error(`Could not find ${lightToInteractWith} in the config`);
44
51
  }
45
52
  for (let i = 0; i < 5; i++) {
46
53
  console.debug("Turning device on and off", i);
47
- await lw.turnOn(wallLamps);
48
- await lw.turnOff(wallLamps);
54
+ await lw.turnOn(light);
55
+ await lw.turnOff(light);
49
56
  }
50
- await lw.lwClient.disconnect();
51
57
  }, 30000);
52
58
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@evops/lightwaverf",
3
3
  "description": "Lightwave RF client library",
4
- "version": "1.0.4",
4
+ "version": "1.0.5",
5
5
  "exports": {
6
6
  ".": {
7
7
  "types": "./.dist/index.d.ts",
package/vitest.config.ts CHANGED
@@ -6,7 +6,7 @@ export default defineConfig({
6
6
  environment: "node",
7
7
  printConsoleTrace: true,
8
8
  env: {
9
- // DEBUG: "lightwave*",
9
+ DEBUG: "lightwave*",
10
10
  },
11
11
  },
12
12
  });