node-osc 11.2.2 → 11.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.
- package/.github/dependabot.yml +19 -0
- package/.node-version +1 -0
- package/{agent.md → AGENTS.md} +11 -8
- package/README.md +4 -2
- package/dist/lib/Client.js +4 -41
- package/dist/lib/Server.js +65 -0
- package/dist/lib/internal/send.js +48 -0
- package/dist/test/test-promises.js +16 -0
- package/dist/test/test-server.js +61 -0
- package/docs/API.md +5 -5
- package/docs/GUIDE.md +5 -1
- package/docs/README.md +1 -1
- package/lib/Client.mjs +4 -41
- package/lib/Server.mjs +65 -0
- package/lib/internal/send.mjs +46 -0
- package/package.json +4 -4
- package/scripts/generate-docs.mjs +173 -167
- package/test/fixtures/types/test-cjs-types.ts +1 -0
- package/test/fixtures/types/test-esm-types.ts +1 -0
- package/test/test-promises.mjs +16 -0
- package/test/test-server.mjs +61 -0
- package/types/Client.d.mts +2 -3
- package/types/Client.d.mts.map +1 -1
- package/types/Server.d.mts +30 -2
- package/types/Server.d.mts.map +1 -1
- package/types/internal/send.d.mts +3 -0
- package/types/internal/send.d.mts.map +1 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { encode } from '../osc.mjs';
|
|
2
|
+
import Message from '../Message.mjs';
|
|
3
|
+
|
|
4
|
+
function normalizeMessage(message) {
|
|
5
|
+
if (message instanceof Array) {
|
|
6
|
+
return {
|
|
7
|
+
address: message[0],
|
|
8
|
+
args: message.slice(1)
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return message;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function performSend(sock, message, args, port, host, callback) {
|
|
16
|
+
let mes;
|
|
17
|
+
let buf;
|
|
18
|
+
const normalizedMessage = normalizeMessage(message);
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
switch (typeof normalizedMessage) {
|
|
22
|
+
case 'object':
|
|
23
|
+
buf = encode(normalizedMessage);
|
|
24
|
+
sock.send(buf, 0, buf.length, port, host, callback);
|
|
25
|
+
break;
|
|
26
|
+
case 'string':
|
|
27
|
+
mes = new Message(normalizedMessage);
|
|
28
|
+
for (const arg of args) {
|
|
29
|
+
mes.append(arg);
|
|
30
|
+
}
|
|
31
|
+
buf = encode(mes);
|
|
32
|
+
sock.send(buf, 0, buf.length, port, host, callback);
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
throw new TypeError('That Message Just Doesn\'t Seem Right');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
if (e.code !== 'ERR_SOCKET_DGRAM_NOT_RUNNING') throw e;
|
|
40
|
+
const error = new ReferenceError('Cannot send message on closed socket.');
|
|
41
|
+
error.code = e.code;
|
|
42
|
+
callback(error);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default performSend;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-osc",
|
|
3
3
|
"description": "pyOSC inspired library for sending and receiving OSC messages",
|
|
4
|
-
"version": "11.
|
|
4
|
+
"version": "11.3.0",
|
|
5
5
|
"exports": {
|
|
6
6
|
"types": "./types/index.d.mts",
|
|
7
7
|
"require": "./dist/lib/index.js",
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"url": "git+https://github.com/MylesBorins/node-osc.git"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@eslint/js": "^
|
|
51
|
-
"eslint": "^
|
|
52
|
-
"globals": "^
|
|
50
|
+
"@eslint/js": "^10.0.1",
|
|
51
|
+
"eslint": "^10.0.3",
|
|
52
|
+
"globals": "^17.4.0",
|
|
53
53
|
"jsdoc": "^4.0.5",
|
|
54
54
|
"rollup": "^4.46.2",
|
|
55
55
|
"tap": "^21.1.0",
|
|
@@ -5,120 +5,89 @@
|
|
|
5
5
|
* This script reads JSDoc JSON data and generates a formatted Markdown file.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { writeFileSync } from 'node:fs';
|
|
9
8
|
import { execSync } from 'node:child_process';
|
|
9
|
+
import { writeFileSync } from 'node:fs';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
jsdocJson = execSync('npx jsdoc -X -c jsdoc.json', {
|
|
15
|
-
encoding: 'utf8',
|
|
16
|
-
maxBuffer: 10 * 1024 * 1024
|
|
17
|
-
});
|
|
18
|
-
} catch (error) {
|
|
19
|
-
console.error('❌ Failed to run JSDoc:');
|
|
20
|
-
console.error(error.message);
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
11
|
+
const classOrder = ['Server', 'Client', 'Message', 'Bundle'];
|
|
12
|
+
const functionOrder = ['encode', 'decode'];
|
|
23
13
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
process.exit(1);
|
|
14
|
+
function githubAnchor(text) {
|
|
15
|
+
return text
|
|
16
|
+
.trim()
|
|
17
|
+
.toLowerCase()
|
|
18
|
+
.replace(/[^\w\- ]+/g, '')
|
|
19
|
+
.replace(/\s+/g, '-');
|
|
31
20
|
}
|
|
32
21
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (!classes[item.name]) {
|
|
42
|
-
classes[item.name] = {
|
|
43
|
-
desc: item.classdesc,
|
|
44
|
-
constructor: null,
|
|
45
|
-
methods: [],
|
|
46
|
-
examples: item.examples || [],
|
|
47
|
-
augments: item.augments || []
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
// Look for constructor params
|
|
51
|
-
if (item.params) {
|
|
52
|
-
classes[item.name].constructor = {
|
|
53
|
-
params: item.params,
|
|
54
|
-
examples: item.examples || []
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
} else if (item.kind === 'function' && item.memberof) {
|
|
58
|
-
// Method of a class
|
|
59
|
-
const className = item.memberof;
|
|
60
|
-
if (!classes[className]) {
|
|
61
|
-
classes[className] = {
|
|
62
|
-
desc: '',
|
|
63
|
-
constructor: null,
|
|
64
|
-
methods: [],
|
|
65
|
-
examples: []
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
classes[className].methods.push(item);
|
|
69
|
-
} else if (item.kind === 'function' && !item.memberof && item.scope === 'global') {
|
|
70
|
-
// Top-level function
|
|
71
|
-
functions[item.name] = item;
|
|
22
|
+
function runJsdoc() {
|
|
23
|
+
try {
|
|
24
|
+
return execSync('npx jsdoc -X -c jsdoc.json', {
|
|
25
|
+
encoding: 'utf8',
|
|
26
|
+
maxBuffer: 10 * 1024 * 1024
|
|
27
|
+
});
|
|
28
|
+
} catch (error) {
|
|
29
|
+
throw new Error(`Failed to run JSDoc: ${error.message}`, { cause: error });
|
|
72
30
|
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Generate Markdown
|
|
76
|
-
let markdown = `<!-- Generated by JSDoc. Update this documentation by updating the source code. -->
|
|
77
|
-
|
|
78
|
-
# API Reference
|
|
79
|
-
|
|
80
|
-
> **⚠️ This file is auto-generated from JSDoc comments in the source code.**
|
|
81
|
-
> To update this documentation, edit the JSDoc comments in the source files and run \`npm run docs\`.
|
|
82
|
-
|
|
83
|
-
This document provides detailed API reference for all classes, methods, and functions in node-osc.
|
|
31
|
+
}
|
|
84
32
|
|
|
85
|
-
|
|
33
|
+
function parseJsdocJson(jsdocJson) {
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(jsdocJson);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
throw new Error(`Failed to parse JSDoc JSON output: ${error.message}`, { cause: error });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
86
40
|
|
|
87
|
-
|
|
41
|
+
function collectDocs(docs) {
|
|
42
|
+
const classes = {};
|
|
43
|
+
const functions = {};
|
|
88
44
|
|
|
89
|
-
|
|
45
|
+
docs.forEach(item => {
|
|
46
|
+
if (item.undocumented || item.ignore) return;
|
|
90
47
|
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
48
|
+
if (item.kind === 'class' && item.classdesc) {
|
|
49
|
+
const classInfo = classes[item.name] || {
|
|
50
|
+
desc: '',
|
|
51
|
+
constructor: null,
|
|
52
|
+
methods: [],
|
|
53
|
+
examples: [],
|
|
54
|
+
augments: []
|
|
55
|
+
};
|
|
94
56
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
57
|
+
classInfo.desc = item.classdesc;
|
|
58
|
+
classInfo.examples = item.examples || [];
|
|
59
|
+
classInfo.augments = item.augments || [];
|
|
60
|
+
classes[item.name] = classInfo;
|
|
61
|
+
|
|
62
|
+
if (item.params) {
|
|
63
|
+
classes[item.name].constructor = {
|
|
64
|
+
params: item.params,
|
|
65
|
+
examples: item.examples || []
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
} else if (item.kind === 'function' && item.memberof) {
|
|
69
|
+
const className = item.memberof;
|
|
70
|
+
if (!classes[className]) {
|
|
71
|
+
classes[className] = {
|
|
72
|
+
desc: '',
|
|
73
|
+
constructor: null,
|
|
74
|
+
methods: [],
|
|
75
|
+
examples: [],
|
|
76
|
+
augments: []
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
classes[className].methods.push(item);
|
|
80
|
+
} else if (item.kind === 'function' && !item.memberof && item.scope === 'global') {
|
|
81
|
+
functions[item.name] = item;
|
|
101
82
|
}
|
|
102
|
-
|
|
103
|
-
markdown += ` - [${method.name}()](#${name.toLowerCase()}-${method.name.toLowerCase()})\n`;
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// Add functions to TOC
|
|
109
|
-
markdown += `- [Low Level Functions](#low-level-functions)\n`;
|
|
110
|
-
functionOrder.forEach(name => {
|
|
111
|
-
if (functions[name]) {
|
|
112
|
-
markdown += ` - [${name}()](#${name.toLowerCase()})\n`;
|
|
113
|
-
}
|
|
114
|
-
});
|
|
83
|
+
});
|
|
115
84
|
|
|
116
|
-
|
|
85
|
+
return { classes, functions };
|
|
86
|
+
}
|
|
117
87
|
|
|
118
|
-
// Helper function to format parameters
|
|
119
88
|
function formatParams(params) {
|
|
120
89
|
if (!params || params.length === 0) return '';
|
|
121
|
-
|
|
90
|
+
|
|
122
91
|
let result = '\n**Parameters:**\n\n';
|
|
123
92
|
params.forEach(param => {
|
|
124
93
|
const optional = param.optional ? ' (optional)' : '';
|
|
@@ -129,10 +98,9 @@ function formatParams(params) {
|
|
|
129
98
|
return result;
|
|
130
99
|
}
|
|
131
100
|
|
|
132
|
-
// Helper function to format examples
|
|
133
101
|
function formatExamples(examples) {
|
|
134
102
|
if (!examples || examples.length === 0) return '';
|
|
135
|
-
|
|
103
|
+
|
|
136
104
|
let result = '\n**Examples:**\n\n';
|
|
137
105
|
examples.forEach(example => {
|
|
138
106
|
result += '```javascript\n' + example + '\n```\n\n';
|
|
@@ -140,19 +108,17 @@ function formatExamples(examples) {
|
|
|
140
108
|
return result;
|
|
141
109
|
}
|
|
142
110
|
|
|
143
|
-
// Helper function to format returns
|
|
144
111
|
function formatReturns(returns) {
|
|
145
112
|
if (!returns || returns.length === 0) return '';
|
|
146
|
-
|
|
113
|
+
|
|
147
114
|
const ret = returns[0];
|
|
148
115
|
const types = ret.type ? ret.type.names.join(' | ') : 'any';
|
|
149
116
|
return `\n**Returns:** *{${types}}* - ${ret.description || ''}\n`;
|
|
150
117
|
}
|
|
151
118
|
|
|
152
|
-
// Helper function to format throws
|
|
153
119
|
function formatThrows(exceptions) {
|
|
154
120
|
if (!exceptions || exceptions.length === 0) return '';
|
|
155
|
-
|
|
121
|
+
|
|
156
122
|
let result = '\n**Throws:**\n\n';
|
|
157
123
|
exceptions.forEach(ex => {
|
|
158
124
|
const types = ex.type ? ex.type.names.join(' | ') : 'Error';
|
|
@@ -161,69 +127,109 @@ function formatThrows(exceptions) {
|
|
|
161
127
|
return result;
|
|
162
128
|
}
|
|
163
129
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
markdown += formatThrows(method.exceptions);
|
|
198
|
-
markdown += formatExamples(method.examples);
|
|
130
|
+
function generateMarkdown(classes, functions) {
|
|
131
|
+
let markdown = `<!-- Generated by JSDoc. Update this documentation by updating the source code. -->
|
|
132
|
+
|
|
133
|
+
# API Reference
|
|
134
|
+
|
|
135
|
+
> **⚠️ This file is auto-generated from JSDoc comments in the source code.**
|
|
136
|
+
> To update this documentation, edit the JSDoc comments in the source files and run \`npm run docs\`.
|
|
137
|
+
|
|
138
|
+
This document provides detailed API reference for all classes, methods, and functions in node-osc.
|
|
139
|
+
|
|
140
|
+
For usage guides, best practices, and troubleshooting, see the **[Guide](./GUIDE.md)**.
|
|
141
|
+
|
|
142
|
+
## Table of Contents
|
|
143
|
+
|
|
144
|
+
`;
|
|
145
|
+
|
|
146
|
+
classOrder.forEach(name => {
|
|
147
|
+
if (classes[name]) {
|
|
148
|
+
markdown += `- [${name}](#${githubAnchor(name)})\n`;
|
|
149
|
+
if (classes[name].constructor) {
|
|
150
|
+
markdown += ` - [Constructor](#${githubAnchor(`${name} Constructor`)})\n`;
|
|
151
|
+
}
|
|
152
|
+
classes[name].methods.forEach(method => {
|
|
153
|
+
markdown += ` - [${method.name}()](#${githubAnchor(`${name}.${method.name}()`)})\n`;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
markdown += `- [Low Level Functions](#${githubAnchor('Low Level Functions')})\n`;
|
|
159
|
+
functionOrder.forEach(name => {
|
|
160
|
+
if (functions[name]) {
|
|
161
|
+
markdown += ` - [${name}()](#${githubAnchor(`${name}()`)})\n`;
|
|
162
|
+
}
|
|
199
163
|
});
|
|
200
|
-
|
|
164
|
+
|
|
201
165
|
markdown += `\n---\n\n`;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
166
|
+
|
|
167
|
+
classOrder.forEach(className => {
|
|
168
|
+
const classInfo = classes[className];
|
|
169
|
+
if (!classInfo) return;
|
|
170
|
+
|
|
171
|
+
markdown += `## ${className}\n\n`;
|
|
172
|
+
|
|
173
|
+
if (classInfo.augments && classInfo.augments.length > 0) {
|
|
174
|
+
markdown += `**Extends:** ${classInfo.augments.join(', ')}\n\n`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
markdown += `${classInfo.desc}\n`;
|
|
178
|
+
|
|
179
|
+
if (classInfo.examples.length > 0 && !classInfo.constructor) {
|
|
180
|
+
markdown += formatExamples(classInfo.examples);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (classInfo.constructor) {
|
|
184
|
+
markdown += `\n### ${className} Constructor\n\n`;
|
|
185
|
+
markdown += `Creates a new ${className} instance.\n`;
|
|
186
|
+
markdown += formatParams(classInfo.constructor.params);
|
|
187
|
+
markdown += formatExamples(classInfo.constructor.examples);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
classInfo.methods.forEach(method => {
|
|
191
|
+
markdown += `\n### ${className}.${method.name}()\n\n`;
|
|
192
|
+
markdown += `${method.description || ''}\n`;
|
|
193
|
+
markdown += formatParams(method.params);
|
|
194
|
+
markdown += formatReturns(method.returns);
|
|
195
|
+
markdown += formatThrows(method.exceptions);
|
|
196
|
+
markdown += formatExamples(method.examples);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
markdown += `\n---\n\n`;
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
markdown += `## Low Level Functions\n\n`;
|
|
203
|
+
markdown += 'These functions provide low-level access to OSC encoding and decoding for advanced use cases.\n\n';
|
|
204
|
+
|
|
205
|
+
functionOrder.forEach(funcName => {
|
|
206
|
+
const func = functions[funcName];
|
|
207
|
+
if (!func) return;
|
|
208
|
+
|
|
209
|
+
markdown += `### ${funcName}()\n\n`;
|
|
210
|
+
markdown += `${func.description || ''}\n`;
|
|
211
|
+
markdown += formatParams(func.params);
|
|
212
|
+
markdown += formatReturns(func.returns);
|
|
213
|
+
markdown += formatThrows(func.exceptions);
|
|
214
|
+
markdown += formatExamples(func.examples);
|
|
215
|
+
markdown += '\n';
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
return markdown;
|
|
229
219
|
}
|
|
220
|
+
|
|
221
|
+
function main() {
|
|
222
|
+
try {
|
|
223
|
+
const jsdocJson = runJsdoc();
|
|
224
|
+
const docs = parseJsdocJson(jsdocJson);
|
|
225
|
+
const { classes, functions } = collectDocs(docs);
|
|
226
|
+
const markdown = generateMarkdown(classes, functions);
|
|
227
|
+
writeFileSync('docs/API.md', markdown, 'utf8');
|
|
228
|
+
console.log('✅ API documentation generated: docs/API.md');
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.error(`❌ ${error.message}`);
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
main();
|
|
@@ -4,6 +4,7 @@ const osc = require('node-osc');
|
|
|
4
4
|
|
|
5
5
|
// Create server first (typical usage pattern)
|
|
6
6
|
const server: Server = new osc.Server(3333, '0.0.0.0');
|
|
7
|
+
server.send(['/server-test', 1], 3334, '127.0.0.1', () => {});
|
|
7
8
|
|
|
8
9
|
// Create client after server
|
|
9
10
|
const client: Client = new osc.Client('127.0.0.1', 3333);
|
|
@@ -7,6 +7,7 @@ const server: Server = new Server(3333, '0.0.0.0');
|
|
|
7
7
|
|
|
8
8
|
// Wait for server to be ready (pattern from examples)
|
|
9
9
|
await once(server, 'listening');
|
|
10
|
+
await server.send(['/server-test', 1], 3334, '127.0.0.1');
|
|
10
11
|
|
|
11
12
|
server.on('message', (msg) => {
|
|
12
13
|
console.log('Received message:', msg);
|
package/test/test-promises.mjs
CHANGED
|
@@ -140,6 +140,22 @@ test('server: close with promise', async (t) => {
|
|
|
140
140
|
t.pass('Server closed successfully with promise');
|
|
141
141
|
});
|
|
142
142
|
|
|
143
|
+
test('server: send promise rejection on closed socket', async (t) => {
|
|
144
|
+
const oscServer = new Server(0, '127.0.0.1');
|
|
145
|
+
|
|
146
|
+
t.plan(1);
|
|
147
|
+
|
|
148
|
+
await once(oscServer, 'listening');
|
|
149
|
+
await oscServer.close();
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
await oscServer.send('/boom', 3333, '127.0.0.1');
|
|
153
|
+
t.fail('Should have thrown an error');
|
|
154
|
+
} catch (err) {
|
|
155
|
+
t.equal(err.code, 'ERR_SOCKET_DGRAM_NOT_RUNNING', 'Should reject with correct error code');
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
143
159
|
test('server: no callback still emits listening event', async (t) => {
|
|
144
160
|
const oscServer = new Server(0, '127.0.0.1');
|
|
145
161
|
|
package/test/test-server.mjs
CHANGED
|
@@ -88,6 +88,67 @@ test('server: callback as second arg', async (t) => {
|
|
|
88
88
|
});
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
+
test('server: send to remote port', async (t) => {
|
|
92
|
+
const sender = new Server(0, '127.0.0.1');
|
|
93
|
+
const receiver = new Server(0, '127.0.0.1');
|
|
94
|
+
await Promise.all([once(sender, 'listening'), once(receiver, 'listening')]);
|
|
95
|
+
|
|
96
|
+
t.plan(1);
|
|
97
|
+
|
|
98
|
+
t.teardown(async () => {
|
|
99
|
+
await Promise.all([sender.close(), receiver.close()]);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const receivedMessage = once(receiver, 'message');
|
|
103
|
+
await sender.send(['/test', 1], receiver.port, '127.0.0.1');
|
|
104
|
+
const [msg] = await receivedMessage;
|
|
105
|
+
|
|
106
|
+
t.same(msg, ['/test', 1], 'server should send a message from its bound socket');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('server: can receive and reply from within message handler', async (t) => {
|
|
110
|
+
const requester = new Server(0, '127.0.0.1');
|
|
111
|
+
const responder = new Server(0, '127.0.0.1');
|
|
112
|
+
await Promise.all([once(requester, 'listening'), once(responder, 'listening')]);
|
|
113
|
+
|
|
114
|
+
t.plan(3);
|
|
115
|
+
|
|
116
|
+
t.teardown(async () => {
|
|
117
|
+
await Promise.all([requester.close(), responder.close()]);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
responder.on('message', (msg, rinfo) => {
|
|
121
|
+
t.same(msg, ['/ping', 1], 'responder should receive the incoming message');
|
|
122
|
+
responder.send(['/ack', 1], rinfo.port, rinfo.address, (err) => {
|
|
123
|
+
t.error(err, 'responder should reply without error');
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const receivedReply = once(requester, 'message');
|
|
128
|
+
await requester.send(['/ping', 1], responder.port, '127.0.0.1');
|
|
129
|
+
const [reply] = await receivedReply;
|
|
130
|
+
|
|
131
|
+
t.same(reply, ['/ack', 1], 'requester should receive the reply on the same socket');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('server: send before listening returns a clear error', async (t) => {
|
|
135
|
+
t.plan(3);
|
|
136
|
+
|
|
137
|
+
const server = new Server(0, '127.0.0.1');
|
|
138
|
+
|
|
139
|
+
t.throws(() => {
|
|
140
|
+
server.send('/test', 3333, '127.0.0.1');
|
|
141
|
+
}, /before server is listening/i, 'send without callback should throw before listening');
|
|
142
|
+
|
|
143
|
+
server.send('/test', 3333, '127.0.0.1', (err) => {
|
|
144
|
+
t.ok(err instanceof Error, 'send should fail with an Error before listening');
|
|
145
|
+
t.match(err.message, /before server is listening/i, 'error message should explain the socket is not ready');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
await once(server, 'listening');
|
|
149
|
+
await server.close();
|
|
150
|
+
});
|
|
151
|
+
|
|
91
152
|
test('server: bad message', async (t) => {
|
|
92
153
|
t.plan(2);
|
|
93
154
|
const oscServer = new Server(0, '127.0.0.1');
|
package/types/Client.d.mts
CHANGED
|
@@ -23,7 +23,7 @@ export default Client;
|
|
|
23
23
|
* await client.send('/oscAddress', 200);
|
|
24
24
|
* await client.close();
|
|
25
25
|
*/
|
|
26
|
-
declare class Client extends EventEmitter<
|
|
26
|
+
declare class Client extends EventEmitter<any> {
|
|
27
27
|
/**
|
|
28
28
|
* Create an OSC Client.
|
|
29
29
|
*
|
|
@@ -36,7 +36,7 @@ declare class Client extends EventEmitter<[never]> {
|
|
|
36
36
|
constructor(host: string, port: number);
|
|
37
37
|
host: string;
|
|
38
38
|
port: number;
|
|
39
|
-
_sock: import("dgram").Socket;
|
|
39
|
+
_sock: import("node:dgram").Socket;
|
|
40
40
|
/**
|
|
41
41
|
* Close the client socket.
|
|
42
42
|
*
|
|
@@ -56,7 +56,6 @@ declare class Client extends EventEmitter<[never]> {
|
|
|
56
56
|
* await client.close();
|
|
57
57
|
*/
|
|
58
58
|
close(cb?: Function): Promise<void> | undefined;
|
|
59
|
-
_performSend(message: any, args: any, callback: any): void;
|
|
60
59
|
/**
|
|
61
60
|
* Send an OSC message or bundle to the server.
|
|
62
61
|
*
|
package/types/Client.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Client.d.mts","sourceRoot":"","sources":["../lib/Client.mjs"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"Client.d.mts","sourceRoot":"","sources":["../lib/Client.mjs"],"names":[],"mappings":";AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;IACE;;;;;;;;OAQG;IACH,kBANW,MAAM,QACN,MAAM,EAiBhB;IAVC,aAAgB;IAChB,aAAgB;IAChB,mCAGE;IAMJ;;;;;;;;;;;;;;;;;OAiBG;IACH,sBAZa,OAAO,CAAC,IAAI,CAAC,GAAC,SAAS,CAuBnC;IACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACH,cA7Bc,GAAC,EAAA,GAIF,OAAO,CAAC,IAAI,CAAC,GAAC,SAAS,CA2CnC;CACF;6BAzI4B,aAAa"}
|
package/types/Server.d.mts
CHANGED
|
@@ -46,7 +46,7 @@ export default Server;
|
|
|
46
46
|
* console.log(`Note: ${pitch}, Velocity: ${velocity}`);
|
|
47
47
|
* });
|
|
48
48
|
*/
|
|
49
|
-
declare class Server extends EventEmitter<
|
|
49
|
+
declare class Server extends EventEmitter<any> {
|
|
50
50
|
/**
|
|
51
51
|
* Create an OSC Server.
|
|
52
52
|
*
|
|
@@ -73,7 +73,35 @@ declare class Server extends EventEmitter<[never]> {
|
|
|
73
73
|
constructor(port: number, host?: string, cb?: Function);
|
|
74
74
|
port: number;
|
|
75
75
|
host: string;
|
|
76
|
-
|
|
76
|
+
_isListening: boolean;
|
|
77
|
+
_isClosed: boolean;
|
|
78
|
+
_sock: import("node:dgram").Socket;
|
|
79
|
+
/**
|
|
80
|
+
* Send an OSC message or bundle from the server's bound socket.
|
|
81
|
+
*
|
|
82
|
+
* This method can be used with either a callback or as a Promise.
|
|
83
|
+
*
|
|
84
|
+
* @param {import('./Message.mjs').default|import('./Bundle.mjs').default|Array|string} message - The message, bundle, address, or array to send.
|
|
85
|
+
* @param {number} port - The remote port to send to.
|
|
86
|
+
* @param {string} host - The remote host to send to.
|
|
87
|
+
* @param {Function} [cb] - Optional callback function called when send completes.
|
|
88
|
+
* @returns {Promise<void>|undefined} Returns a Promise if no callback is provided.
|
|
89
|
+
*
|
|
90
|
+
* @throws {Error} If the server socket is not yet listening.
|
|
91
|
+
* @throws {TypeError} If the message format is invalid.
|
|
92
|
+
* @throws {ReferenceError} If attempting to send on a closed socket.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* // Send an address-only message
|
|
96
|
+
* await server.send('/ping', 9000, '127.0.0.1');
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* // Send an array message
|
|
100
|
+
* server.send(['/ack', 1], 9000, '192.168.1.42', (err) => {
|
|
101
|
+
* if (err) console.error(err);
|
|
102
|
+
* });
|
|
103
|
+
*/
|
|
104
|
+
send(message: import("./Message.mjs").default | import("./Bundle.mjs").default | any[] | string, port: number, host: string, cb?: Function): Promise<void> | undefined;
|
|
77
105
|
/**
|
|
78
106
|
* Close the server socket.
|
|
79
107
|
*
|
package/types/Server.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Server.d.mts","sourceRoot":"","sources":["../lib/Server.mjs"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"Server.d.mts","sourceRoot":"","sources":["../lib/Server.mjs"],"names":[],"mappings":";AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH;IACE;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,kBApBW,MAAM,SACN,MAAM,iBAyEhB;IA9CC,aAAgB;IAChB,aAAgB;IAChB,sBAAyB;IACzB,mBAAsB;IACtB,mCAGE;IAwCJ;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,cApBW,OAAO,eAAe,EAAE,OAAO,GAAC,OAAO,cAAc,EAAE,OAAO,WAAO,MAAM,QAC3E,MAAM,QACN,MAAM,kBAEJ,OAAO,CAAC,IAAI,CAAC,GAAC,SAAS,CAyCnC;IACD;;;;;;;;;;;;;;;;;OAiBG;IACH,sBAZa,OAAO,CAAC,IAAI,CAAC,GAAC,SAAS,CAuBnC;CACF;6BAxN4B,aAAa"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send.d.mts","sourceRoot":"","sources":["../../lib/internal/send.mjs"],"names":[],"mappings":";AAcA,4GA6BC"}
|