node-osc 11.1.1 → 11.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +11 -0
- package/.github/workflows/bump-version.yml +2 -0
- package/.github/workflows/nodejs.yml +3 -0
- package/LICENSE +201 -165
- package/README.md +135 -42
- package/dist/lib/Bundle.js +66 -0
- package/dist/lib/Client.js +137 -22
- package/dist/lib/Message.js +87 -1
- package/dist/lib/Server.js +117 -6
- package/dist/lib/index.js +3 -0
- package/dist/lib/internal/decode.js +4 -4
- package/dist/lib/{internal/osc.js → osc.js} +70 -5
- package/dist/test/lib/osc.js +395 -0
- package/dist/test/test-client.js +152 -0
- package/dist/test/test-e2e.js +9 -3
- package/dist/test/test-encode-decode.js +849 -0
- package/dist/test/test-error-handling.js +116 -0
- package/dist/test/test-osc-internal.js +399 -41
- package/dist/test/test-promises.js +250 -0
- package/dist/test/test-types.js +42 -0
- package/dist/test/util.js +15 -8
- package/docs/API.md +477 -0
- package/docs/GUIDE.md +605 -0
- package/examples/README.md +119 -0
- package/examples/async-await.mjs +57 -0
- package/examples/bundle-example.mjs +92 -0
- package/examples/client.js +22 -5
- package/examples/error-handling.mjs +152 -0
- package/examples/esm.mjs +21 -0
- package/examples/server.js +16 -0
- package/jsdoc.json +16 -0
- package/lib/Bundle.mjs +66 -0
- package/lib/Client.mjs +137 -22
- package/lib/Message.mjs +87 -1
- package/lib/Server.mjs +117 -6
- package/lib/index.mjs +1 -0
- package/lib/internal/decode.mjs +4 -4
- package/lib/{internal/osc.mjs → osc.mjs} +71 -4
- package/package.json +12 -10
- package/rollup.config.mjs +48 -41
- package/scripts/generate-docs.mjs +229 -0
- package/test/fixtures/types/test-cjs-types.ts +19 -0
- package/test/fixtures/types/test-esm-types.ts +35 -0
- package/test/fixtures/types/tsconfig-cjs.test.json +17 -0
- package/test/fixtures/types/tsconfig-esm.test.json +17 -0
- package/test/test-bundle.mjs +0 -1
- package/test/test-client.mjs +152 -0
- package/test/test-e2e.mjs +9 -3
- package/test/test-encode-decode.mjs +847 -0
- package/test/test-error-handling.mjs +115 -0
- package/test/test-osc-internal.mjs +400 -42
- package/test/test-promises.mjs +249 -0
- package/test/test-types.mjs +39 -0
- package/test/util.mjs +15 -8
- package/tsconfig.json +45 -0
- package/types/Bundle.d.mts +70 -0
- package/types/Bundle.d.mts.map +1 -0
- package/types/Client.d.mts +101 -0
- package/types/Client.d.mts.map +1 -0
- package/types/Message.d.mts +84 -0
- package/types/Message.d.mts.map +1 -0
- package/types/Server.d.mts +98 -0
- package/types/Server.d.mts.map +1 -0
- package/types/index.d.mts +6 -0
- package/types/index.d.mts.map +1 -0
- package/types/internal/decode.d.mts +4 -0
- package/types/internal/decode.d.mts.map +1 -0
- package/types/osc.d.mts +66 -0
- package/types/osc.d.mts.map +1 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { once } from 'node:events';
|
|
2
|
+
import { beforeEach, test } from 'tap';
|
|
3
|
+
import { bootstrap } from './util.mjs';
|
|
4
|
+
|
|
5
|
+
import { Server, Client } from 'node-osc';
|
|
6
|
+
|
|
7
|
+
beforeEach(bootstrap);
|
|
8
|
+
|
|
9
|
+
test('client: send with promise - array', async (t) => {
|
|
10
|
+
const oscServer = new Server(t.context.port, '127.0.0.1');
|
|
11
|
+
const client = new Client('127.0.0.1', t.context.port);
|
|
12
|
+
|
|
13
|
+
t.plan(1);
|
|
14
|
+
|
|
15
|
+
oscServer.on('message', (msg) => {
|
|
16
|
+
oscServer.close();
|
|
17
|
+
t.same(msg, ['/test', 0, 1, 'testing', true], 'We should receive expected payload');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
await client.send(['/test', 0, 1, 'testing', true]);
|
|
21
|
+
await client.close();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('client: send with promise - string', async (t) => {
|
|
25
|
+
const oscServer = new Server(t.context.port, '127.0.0.1');
|
|
26
|
+
const client = new Client('127.0.0.1', t.context.port);
|
|
27
|
+
|
|
28
|
+
t.plan(1);
|
|
29
|
+
|
|
30
|
+
oscServer.on('message', (msg) => {
|
|
31
|
+
oscServer.close();
|
|
32
|
+
t.same(msg, ['/test'], 'We should receive expected payload');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
await client.send('/test');
|
|
36
|
+
await client.close();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('client: send with promise - message object', async (t) => {
|
|
40
|
+
const oscServer = new Server(t.context.port, '127.0.0.1');
|
|
41
|
+
const client = new Client('127.0.0.1', t.context.port);
|
|
42
|
+
|
|
43
|
+
t.plan(1);
|
|
44
|
+
|
|
45
|
+
oscServer.on('message', (msg) => {
|
|
46
|
+
oscServer.close();
|
|
47
|
+
t.same(msg, ['/test', 1, 2, 3, 'lol', false], 'we received the payload');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
await client.send({
|
|
51
|
+
address: '/test',
|
|
52
|
+
args: [1, 2, 3, 'lol', false]
|
|
53
|
+
});
|
|
54
|
+
await client.close();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('client: send with promise - multiple args', async (t) => {
|
|
58
|
+
const oscServer = new Server(t.context.port, '127.0.0.1');
|
|
59
|
+
const client = new Client('127.0.0.1', t.context.port);
|
|
60
|
+
|
|
61
|
+
t.plan(1);
|
|
62
|
+
|
|
63
|
+
oscServer.on('message', (msg) => {
|
|
64
|
+
oscServer.close();
|
|
65
|
+
t.same(msg, ['/test', 1, 2, 'testing'], 'We should receive expected payload');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await client.send('/test', 1, 2, 'testing');
|
|
69
|
+
await client.close();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('client: send promise rejection on closed socket', async (t) => {
|
|
73
|
+
const client = new Client('127.0.0.1', t.context.port);
|
|
74
|
+
|
|
75
|
+
t.plan(1);
|
|
76
|
+
|
|
77
|
+
await client.close();
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
await client.send('/boom');
|
|
81
|
+
t.fail('Should have thrown an error');
|
|
82
|
+
} catch (err) {
|
|
83
|
+
t.equal(err.code, 'ERR_SOCKET_DGRAM_NOT_RUNNING', 'Should reject with correct error code');
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('client: async/await usage', async (t) => {
|
|
88
|
+
const oscServer = new Server(t.context.port, '127.0.0.1');
|
|
89
|
+
const client = new Client('127.0.0.1', t.context.port);
|
|
90
|
+
|
|
91
|
+
t.plan(1);
|
|
92
|
+
|
|
93
|
+
const messagePromise = once(oscServer, 'message');
|
|
94
|
+
|
|
95
|
+
await client.send('/async-test', 42, 'hello');
|
|
96
|
+
const [receivedMessage] = await messagePromise;
|
|
97
|
+
|
|
98
|
+
t.same(receivedMessage, ['/async-test', 42, 'hello'], 'Message received via async/await');
|
|
99
|
+
|
|
100
|
+
await client.close();
|
|
101
|
+
await oscServer.close();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('server: close with promise', async (t) => {
|
|
105
|
+
const oscServer = new Server(t.context.port, '127.0.0.1');
|
|
106
|
+
|
|
107
|
+
t.plan(1);
|
|
108
|
+
|
|
109
|
+
await once(oscServer, 'listening');
|
|
110
|
+
|
|
111
|
+
await oscServer.close();
|
|
112
|
+
t.pass('Server closed successfully with promise');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('server: no callback still emits listening event', async (t) => {
|
|
116
|
+
const oscServer = new Server(t.context.port, '127.0.0.1');
|
|
117
|
+
|
|
118
|
+
t.plan(1);
|
|
119
|
+
|
|
120
|
+
await once(oscServer, 'listening');
|
|
121
|
+
t.pass('listening event emitted');
|
|
122
|
+
|
|
123
|
+
await oscServer.close();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('client and server: full async/await workflow', async (t) => {
|
|
127
|
+
const oscServer = new Server(t.context.port, '127.0.0.1');
|
|
128
|
+
const client = new Client('127.0.0.1', t.context.port);
|
|
129
|
+
|
|
130
|
+
t.plan(2);
|
|
131
|
+
|
|
132
|
+
// Wait for server to be ready
|
|
133
|
+
await once(oscServer, 'listening');
|
|
134
|
+
t.pass('Server started');
|
|
135
|
+
|
|
136
|
+
// Set up message handler
|
|
137
|
+
const messageReceived = once(oscServer, 'message');
|
|
138
|
+
|
|
139
|
+
// Send message and wait for it to be received
|
|
140
|
+
await client.send('/workflow', 'test', 123);
|
|
141
|
+
const [msg] = await messageReceived;
|
|
142
|
+
t.same(msg, ['/workflow', 'test', 123], 'Message received correctly');
|
|
143
|
+
|
|
144
|
+
// Clean up
|
|
145
|
+
await client.close();
|
|
146
|
+
await oscServer.close();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test('client: multiple sends with promises', async (t) => {
|
|
150
|
+
const oscServer = new Server(t.context.port, '127.0.0.1');
|
|
151
|
+
const client = new Client('127.0.0.1', t.context.port);
|
|
152
|
+
|
|
153
|
+
t.plan(3);
|
|
154
|
+
|
|
155
|
+
const messages = [];
|
|
156
|
+
oscServer.on('message', (msg) => {
|
|
157
|
+
messages.push(msg);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
await client.send('/msg1', 1);
|
|
161
|
+
await client.send('/msg2', 2);
|
|
162
|
+
await client.send('/msg3', 3);
|
|
163
|
+
|
|
164
|
+
// Give a little time for all messages to be received
|
|
165
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
166
|
+
|
|
167
|
+
t.equal(messages.length, 3, 'Received all three messages');
|
|
168
|
+
t.same(messages[0], ['/msg1', 1], 'First message correct');
|
|
169
|
+
t.same(messages[2], ['/msg3', 3], 'Last message correct');
|
|
170
|
+
|
|
171
|
+
await client.close();
|
|
172
|
+
await oscServer.close();
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test('client: close promise rejection on error', async (t) => {
|
|
176
|
+
const client = new Client('127.0.0.1', t.context.port);
|
|
177
|
+
|
|
178
|
+
t.plan(1);
|
|
179
|
+
|
|
180
|
+
// Mock the socket's close method to simulate an error
|
|
181
|
+
const originalClose = client._sock.close.bind(client._sock);
|
|
182
|
+
|
|
183
|
+
// Set up teardown to ensure socket is properly closed
|
|
184
|
+
t.teardown(() => {
|
|
185
|
+
// Restore original close method first
|
|
186
|
+
client._sock.close = originalClose;
|
|
187
|
+
// Then close the socket
|
|
188
|
+
try {
|
|
189
|
+
client._sock.close(() => {});
|
|
190
|
+
} catch {
|
|
191
|
+
// Socket might already be closed, that's ok
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
client._sock.close = function(cb) {
|
|
196
|
+
// Simulate an error being passed to callback
|
|
197
|
+
if (cb) {
|
|
198
|
+
const err = new Error('Mock close error');
|
|
199
|
+
err.code = 'MOCK_ERROR';
|
|
200
|
+
setImmediate(() => cb(err));
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
try {
|
|
205
|
+
await client.close();
|
|
206
|
+
t.fail('Should have thrown an error');
|
|
207
|
+
} catch (err) {
|
|
208
|
+
t.equal(err.code, 'MOCK_ERROR', 'Should reject with mock error');
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test('server: close promise rejection on error', async (t) => {
|
|
213
|
+
const oscServer = new Server(t.context.port, '127.0.0.1');
|
|
214
|
+
|
|
215
|
+
t.plan(1);
|
|
216
|
+
|
|
217
|
+
await once(oscServer, 'listening');
|
|
218
|
+
|
|
219
|
+
// Mock the socket's close method to simulate an error
|
|
220
|
+
const originalClose = oscServer._sock.close.bind(oscServer._sock);
|
|
221
|
+
|
|
222
|
+
// Set up teardown to ensure socket is properly closed
|
|
223
|
+
t.teardown(() => {
|
|
224
|
+
// Restore original close method first
|
|
225
|
+
oscServer._sock.close = originalClose;
|
|
226
|
+
// Then close the socket
|
|
227
|
+
try {
|
|
228
|
+
oscServer._sock.close(() => {});
|
|
229
|
+
} catch {
|
|
230
|
+
// Socket might already be closed, that's ok
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
oscServer._sock.close = function(cb) {
|
|
235
|
+
// Simulate an error being passed to callback
|
|
236
|
+
if (cb) {
|
|
237
|
+
const err = new Error('Mock close error');
|
|
238
|
+
err.code = 'MOCK_ERROR';
|
|
239
|
+
setImmediate(() => cb(err));
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
await oscServer.close();
|
|
245
|
+
t.fail('Should have thrown an error');
|
|
246
|
+
} catch (err) {
|
|
247
|
+
t.equal(err.code, 'MOCK_ERROR', 'Should reject with mock error');
|
|
248
|
+
}
|
|
249
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { test } from 'tap';
|
|
2
|
+
import { execSync } from 'node:child_process';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
7
|
+
|
|
8
|
+
// Only run in ESM mode (not when transpiled to CJS in dist/)
|
|
9
|
+
// Normalize path separators for cross-platform compatibility
|
|
10
|
+
const normalizedPath = __dirname.replace(/\\/g, '/');
|
|
11
|
+
const isESM = !normalizedPath.includes('/dist/');
|
|
12
|
+
|
|
13
|
+
test('types: TypeScript compilation', (t) => {
|
|
14
|
+
let tsconfigPath;
|
|
15
|
+
const testRoot = resolve(__dirname, isESM ? '.': '../../test');
|
|
16
|
+
if (isESM) {
|
|
17
|
+
tsconfigPath = join(testRoot, 'fixtures', 'types', 'tsconfig-esm.test.json');
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
tsconfigPath = join(testRoot, 'fixtures', 'types', 'tsconfig-cjs.test.json');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
// Run TypeScript compiler
|
|
25
|
+
const cmd = 'npx tsc --project "' + tsconfigPath + '"';
|
|
26
|
+
execSync(cmd, {
|
|
27
|
+
encoding: 'utf-8',
|
|
28
|
+
stdio: 'pipe',
|
|
29
|
+
cwd: join(testRoot, 'fixtures', 'types')
|
|
30
|
+
});
|
|
31
|
+
t.pass('TypeScript types compile successfully');
|
|
32
|
+
} catch (error) {
|
|
33
|
+
t.fail('TypeScript compilation failed: ' + error.message);
|
|
34
|
+
if (error.stdout) console.log('STDOUT:', error.stdout);
|
|
35
|
+
if (error.stderr) console.log('STDERR:', error.stderr);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
t.end();
|
|
39
|
+
});
|
package/test/util.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createServer } from 'node:net';
|
|
2
|
+
import { setImmediate } from 'node:timers/promises';
|
|
2
3
|
|
|
3
4
|
async function bootstrap(t) {
|
|
4
5
|
const port = await getPort();
|
|
@@ -7,18 +8,24 @@ async function bootstrap(t) {
|
|
|
7
8
|
};
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
function getPort() {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
async function getPort() {
|
|
12
|
+
const server = createServer();
|
|
13
|
+
server.unref();
|
|
14
|
+
|
|
15
|
+
const port = await new Promise((resolve, reject) => {
|
|
14
16
|
server.on('error', reject);
|
|
15
17
|
server.listen(() => {
|
|
16
|
-
|
|
17
|
-
server.close(() => {
|
|
18
|
-
resolve(port);
|
|
19
|
-
});
|
|
18
|
+
resolve(server.address().port);
|
|
20
19
|
});
|
|
21
20
|
});
|
|
21
|
+
|
|
22
|
+
await server.close();
|
|
23
|
+
|
|
24
|
+
// Allow the event loop to process and ensure port is fully released
|
|
25
|
+
// This prevents EACCES errors when immediately rebinding to the same port
|
|
26
|
+
await setImmediate();
|
|
27
|
+
|
|
28
|
+
return port;
|
|
22
29
|
}
|
|
23
30
|
|
|
24
31
|
export {
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Enable JSDoc type checking
|
|
4
|
+
"allowJs": true,
|
|
5
|
+
"checkJs": false,
|
|
6
|
+
|
|
7
|
+
// Generate declaration files only
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"emitDeclarationOnly": true,
|
|
10
|
+
"declarationMap": true,
|
|
11
|
+
|
|
12
|
+
// Output directory for declarations
|
|
13
|
+
"outDir": "./types",
|
|
14
|
+
|
|
15
|
+
// Module settings for ESM (will generate .d.mts files)
|
|
16
|
+
"module": "ES2022",
|
|
17
|
+
"moduleResolution": "node",
|
|
18
|
+
"target": "ES2022",
|
|
19
|
+
|
|
20
|
+
// Allow default imports from modules with no default export
|
|
21
|
+
"esModuleInterop": true,
|
|
22
|
+
"allowSyntheticDefaultImports": true,
|
|
23
|
+
|
|
24
|
+
// Strict options for better type inference
|
|
25
|
+
"strict": false,
|
|
26
|
+
"skipLibCheck": true,
|
|
27
|
+
|
|
28
|
+
// Resolve JSON modules
|
|
29
|
+
"resolveJsonModule": true,
|
|
30
|
+
|
|
31
|
+
// Base URL for paths
|
|
32
|
+
"baseUrl": ".",
|
|
33
|
+
"paths": {
|
|
34
|
+
"#decode": ["./lib/internal/decode.mjs"]
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"include": [
|
|
38
|
+
"lib/**/*.mjs"
|
|
39
|
+
],
|
|
40
|
+
"exclude": [
|
|
41
|
+
"node_modules",
|
|
42
|
+
"dist",
|
|
43
|
+
"test"
|
|
44
|
+
]
|
|
45
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export default Bundle;
|
|
2
|
+
/**
|
|
3
|
+
* Represents an OSC bundle containing multiple messages or nested bundles.
|
|
4
|
+
*
|
|
5
|
+
* OSC bundles allow multiple messages to be sent together, optionally with
|
|
6
|
+
* a timetag indicating when the bundle should be processed.
|
|
7
|
+
*
|
|
8
|
+
* @class
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // Create a bundle without a timetag
|
|
12
|
+
* const bundle = new Bundle(['/one', 1], ['/two', 2]);
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Create a bundle with a timetag
|
|
16
|
+
* const bundle = new Bundle(10, ['/one', 1], ['/two', 2]);
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // Nest bundles
|
|
20
|
+
* const bundle1 = new Bundle(['/one', 1]);
|
|
21
|
+
* const bundle2 = new Bundle(['/two', 2]);
|
|
22
|
+
* bundle1.append(bundle2);
|
|
23
|
+
*/
|
|
24
|
+
declare class Bundle {
|
|
25
|
+
/**
|
|
26
|
+
* Create an OSC Bundle.
|
|
27
|
+
*
|
|
28
|
+
* @param {number|Message|Bundle|Array} [timetagOrElement=0] - Timetag, or if not a number, the first element and timetag will default to 0.
|
|
29
|
+
* @param {...(Message|Bundle|Array)} elements - Messages or bundles to include.
|
|
30
|
+
* Arrays will be automatically converted to Message objects.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Bundle without timetag
|
|
34
|
+
* const bundle = new Bundle(['/test', 1], ['/test2', 2]);
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // Bundle with timetag of 10
|
|
38
|
+
* const bundle = new Bundle(10, ['/test', 1]);
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* // Bundle with Message objects
|
|
42
|
+
* const msg1 = new Message('/one', 1);
|
|
43
|
+
* const msg2 = new Message('/two', 2);
|
|
44
|
+
* const bundle = new Bundle(msg1, msg2);
|
|
45
|
+
*/
|
|
46
|
+
constructor(timetag: any, ...elements: (Message | Bundle | any[])[]);
|
|
47
|
+
oscType: string;
|
|
48
|
+
timetag: any;
|
|
49
|
+
elements: (Message | Bundle)[];
|
|
50
|
+
/**
|
|
51
|
+
* Append a message or bundle to this bundle.
|
|
52
|
+
*
|
|
53
|
+
* @param {Message|Bundle|Array} element - The message or bundle to append.
|
|
54
|
+
* Arrays will be automatically converted to Message objects.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* const bundle = new Bundle();
|
|
58
|
+
* bundle.append(['/test', 1]);
|
|
59
|
+
* bundle.append(new Message('/test2', 2));
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Append a nested bundle
|
|
63
|
+
* const bundle1 = new Bundle(['/one', 1]);
|
|
64
|
+
* const bundle2 = new Bundle(['/two', 2]);
|
|
65
|
+
* bundle1.append(bundle2);
|
|
66
|
+
*/
|
|
67
|
+
append(element: Message | Bundle | any[]): void;
|
|
68
|
+
}
|
|
69
|
+
import Message from './Message.mjs';
|
|
70
|
+
//# sourceMappingURL=Bundle.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Bundle.d.mts","sourceRoot":"","sources":["../lib/Bundle.mjs"],"names":[],"mappings":";AAaA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;IACE;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,uCAjBc,CAAC,OAAO,GAAC,MAAM,QAAM,CAAC,EAAA,EAyBnC;IAHC,gBAAuB;IACvB,aAAsB;IACtB,+BAAsC;IAGxC;;;;;;;;;;;;;;;;OAgBG;IACH,gBAdW,OAAO,GAAC,MAAM,QAAM,QAgB9B;CACF;oBAvFmB,eAAe"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export default Client;
|
|
2
|
+
/**
|
|
3
|
+
* OSC Client for sending messages and bundles over UDP.
|
|
4
|
+
*
|
|
5
|
+
* Extends EventEmitter and emits the following events:
|
|
6
|
+
* - 'error': Emitted when a socket error occurs
|
|
7
|
+
*
|
|
8
|
+
* @class
|
|
9
|
+
* @extends EventEmitter
|
|
10
|
+
* @example
|
|
11
|
+
* // Create a client
|
|
12
|
+
* const client = new Client('127.0.0.1', 3333);
|
|
13
|
+
*
|
|
14
|
+
* // Send a message with callback
|
|
15
|
+
* client.send('/oscAddress', 200, (err) => {
|
|
16
|
+
* if (err) console.error(err);
|
|
17
|
+
* client.close();
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Send a message with async/await
|
|
22
|
+
* const client = new Client('127.0.0.1', 3333);
|
|
23
|
+
* await client.send('/oscAddress', 200);
|
|
24
|
+
* await client.close();
|
|
25
|
+
*/
|
|
26
|
+
declare class Client extends EventEmitter<[never]> {
|
|
27
|
+
/**
|
|
28
|
+
* Create an OSC Client.
|
|
29
|
+
*
|
|
30
|
+
* @param {string} host - The hostname or IP address of the OSC server.
|
|
31
|
+
* @param {number} port - The port number of the OSC server.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* const client = new Client('127.0.0.1', 3333);
|
|
35
|
+
*/
|
|
36
|
+
constructor(host: string, port: number);
|
|
37
|
+
host: string;
|
|
38
|
+
port: number;
|
|
39
|
+
_sock: import("dgram").Socket;
|
|
40
|
+
/**
|
|
41
|
+
* Close the client socket.
|
|
42
|
+
*
|
|
43
|
+
* This method can be used with either a callback or as a Promise.
|
|
44
|
+
*
|
|
45
|
+
* @param {Function} [cb] - Optional callback function called when socket is closed.
|
|
46
|
+
* @returns {Promise<void>|undefined} Returns a Promise if no callback is provided.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* // With callback
|
|
50
|
+
* client.close((err) => {
|
|
51
|
+
* if (err) console.error(err);
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // With async/await
|
|
56
|
+
* await client.close();
|
|
57
|
+
*/
|
|
58
|
+
close(cb?: Function): Promise<void> | undefined;
|
|
59
|
+
_performSend(message: any, args: any, callback: any): void;
|
|
60
|
+
/**
|
|
61
|
+
* Send an OSC message or bundle to the server.
|
|
62
|
+
*
|
|
63
|
+
* This method can be used with either a callback or as a Promise.
|
|
64
|
+
* Messages can be sent in several formats:
|
|
65
|
+
* - As separate arguments: address followed by values
|
|
66
|
+
* - As a Message or Bundle object
|
|
67
|
+
* - As an array: [address, ...values]
|
|
68
|
+
*
|
|
69
|
+
* @param {...*} args - The message to send. Can be:
|
|
70
|
+
* - (address: string, ...values: any[], callback?: Function)
|
|
71
|
+
* - (message: Message|Bundle, callback?: Function)
|
|
72
|
+
* - (array: Array, callback?: Function)
|
|
73
|
+
* @returns {Promise<void>|undefined} Returns a Promise if no callback is provided.
|
|
74
|
+
*
|
|
75
|
+
* @throws {TypeError} If the message format is invalid.
|
|
76
|
+
* @throws {ReferenceError} If attempting to send on a closed socket.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // Send with address and arguments
|
|
80
|
+
* client.send('/oscAddress', 200, 'hello', (err) => {
|
|
81
|
+
* if (err) console.error(err);
|
|
82
|
+
* });
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* // Send with async/await
|
|
86
|
+
* await client.send('/oscAddress', 200, 'hello');
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* // Send a Message object
|
|
90
|
+
* const msg = new Message('/test', 1, 2, 3);
|
|
91
|
+
* await client.send(msg);
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* // Send a Bundle object
|
|
95
|
+
* const bundle = new Bundle(['/one', 1], ['/two', 2]);
|
|
96
|
+
* await client.send(bundle);
|
|
97
|
+
*/
|
|
98
|
+
send(...args: any[]): Promise<void> | undefined;
|
|
99
|
+
}
|
|
100
|
+
import { EventEmitter } from 'node:events';
|
|
101
|
+
//# sourceMappingURL=Client.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Client.d.mts","sourceRoot":"","sources":["../lib/Client.mjs"],"names":[],"mappings":";AAKA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;IACE;;;;;;;;OAQG;IACH,kBANW,MAAM,QACN,MAAM,EAiBhB;IAVC,aAAgB;IAChB,aAAgB;IAChB,8BAGE;IAMJ;;;;;;;;;;;;;;;;;OAiBG;IACH,sBAZa,OAAO,CAAC,IAAI,CAAC,GAAC,SAAS,CAuBnC;IACD,2DA2BC;IACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACH,cA7Bc,GAAC,EAAA,GAIF,OAAO,CAAC,IAAI,CAAC,GAAC,SAAS,CAmDnC;CACF;6BA9K4B,aAAa"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export default Message;
|
|
2
|
+
/**
|
|
3
|
+
* Represents an OSC message with an address and arguments.
|
|
4
|
+
*
|
|
5
|
+
* OSC messages consist of an address pattern (string starting with '/')
|
|
6
|
+
* and zero or more arguments of various types.
|
|
7
|
+
*
|
|
8
|
+
* @class
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // Create a message with constructor arguments
|
|
12
|
+
* const msg = new Message('/test', 1, 2, 'hello');
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Create a message and append arguments
|
|
16
|
+
* const msg = new Message('/test');
|
|
17
|
+
* msg.append(1);
|
|
18
|
+
* msg.append('hello');
|
|
19
|
+
* msg.append(3.14);
|
|
20
|
+
*/
|
|
21
|
+
declare class Message {
|
|
22
|
+
/**
|
|
23
|
+
* Create an OSC Message.
|
|
24
|
+
*
|
|
25
|
+
* @param {string} address - The OSC address pattern (e.g., '/oscillator/frequency').
|
|
26
|
+
* @param {...*} args - Optional arguments to include in the message.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* const msg = new Message('/test');
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* const msg = new Message('/test', 1, 2, 3);
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* const msg = new Message('/synth', 'note', 60, 0.5);
|
|
36
|
+
*/
|
|
37
|
+
constructor(address: string, ...args: any[]);
|
|
38
|
+
oscType: string;
|
|
39
|
+
address: string;
|
|
40
|
+
args: any[];
|
|
41
|
+
/**
|
|
42
|
+
* Append an argument to the message.
|
|
43
|
+
*
|
|
44
|
+
* Automatically detects the type based on the JavaScript type:
|
|
45
|
+
* - Integers are encoded as OSC integers
|
|
46
|
+
* - Floats are encoded as OSC floats
|
|
47
|
+
* - Strings are encoded as OSC strings
|
|
48
|
+
* - Booleans are encoded as OSC booleans
|
|
49
|
+
* - Buffers are encoded as OSC blobs
|
|
50
|
+
* - Arrays are recursively appended
|
|
51
|
+
* - Objects with a 'type' property are used as-is
|
|
52
|
+
*
|
|
53
|
+
* @param {*} arg - The argument to append. Can be:
|
|
54
|
+
* - A primitive value (number, string, boolean)
|
|
55
|
+
* - A Buffer (encoded as blob)
|
|
56
|
+
* - An array of values (will be recursively appended)
|
|
57
|
+
* - An object with 'type' and 'value' properties for explicit type control
|
|
58
|
+
*
|
|
59
|
+
* @throws {Error} If the argument type cannot be encoded.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* const msg = new Message('/test');
|
|
63
|
+
* msg.append(42); // Integer
|
|
64
|
+
* msg.append(3.14); // Float
|
|
65
|
+
* msg.append('hello'); // String
|
|
66
|
+
* msg.append(true); // Boolean
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* // Append multiple values at once
|
|
70
|
+
* msg.append([1, 2, 3]);
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* // Explicitly specify type
|
|
74
|
+
* msg.append({ type: 'float', value: 42 });
|
|
75
|
+
* msg.append({ type: 'blob', value: Buffer.from('data') });
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* // MIDI messages (4 bytes: port, status, data1, data2)
|
|
79
|
+
* msg.append({ type: 'midi', value: { port: 0, status: 144, data1: 60, data2: 127 } });
|
|
80
|
+
* msg.append({ type: 'm', value: Buffer.from([0, 144, 60, 127]) });
|
|
81
|
+
*/
|
|
82
|
+
append(arg: any): void;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=Message.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Message.d.mts","sourceRoot":"","sources":["../lib/Message.mjs"],"names":[],"mappings":";AAyBA;;;;;;;;;;;;;;;;;;GAkBG;AACH;IACE;;;;;;;;;;;;;;OAcG;IACH,qBAZW,MAAM,WACH,GAAC,EAAA,EAed;IAHC,gBAAwB;IACxB,gBAAsB;IACtB,YAAgB;IAGlB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwCG;IACH,YA7BW,GAAC,QA2DX;CACF"}
|